ftp.nice.ch/pub/next/graphics/viewer/ToyViewer.2.6a.s.tar.gz#/ToyViewer2.6a/src/ImageSave.bproj/ppmwrite.c

This is ppmwrite.c in view mode; [Download] [Up]

#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <bsd/libc.h>
#include "../ppm.h"
#include "../common.h"
#include "../strfunc.h"
#include "save.h"

FILE *openWPipe(FILE *fp, const char **list, int *err)
{
	int pfd[2];
	int pid;

	/* if (*err != 0) then fork() didn't called successfully */
	*err = 0;
	if (list == NULL || access(list[0], X_OK) < 0) {
		*err = Err_FLT_EXEC;
		return NULL;	/* not executable */
	}
	(void)pipe(pfd);
	if ((pid = fork()) == 0) { /* child process */
		(void)close(0);
		dup(pfd[0]);
		(void)close(1);
		dup(fileno(fp));
		(void)fclose(fp);
		(void)close(pfd[0]);
		(void)close(pfd[1]);
		execv(list[0], &list[1]);
		exit(1);	/* Error */
	}else if (pid < 0) {	/* ERROR */
		*err = Err_FLT_EXEC;
		(void)close(pfd[0]);
		(void)close(pfd[1]);
		(void)fclose(fp);
		return NULL;
	}
	(void)close(pfd[0]);
	(void)fclose(fp);
	return fdopen(pfd[1], "w");
}


int ppmwrite(FILE *fp, const commonInfo *cinf, unsigned char **planes)
{
	int max = 255, sft = 0, n;
	int r, g, b, a;

	switch (cinf->bits) {
	case 1: max = 1;  sft = 7;  break;
	case 2: max = 3;  sft = 6;  break;
	case 4: max = 15;  sft = 4;  break;
	case 8: max = 255;  sft = 0;  break;
	}

	if (cinf->numcolors > 1) { /* color */
		/* PPM Binary */
		fprintf(fp, "P6\n# %s\n%d %d %d\n",
			key_comm(cinf), cinf->width, cinf->height, max);
		n = cinf->width * cinf->height;
		if (sft)
			while (n-- > 0) {
				(void) getPixel(&r, &g, &b, &a);
				putc(r >> sft, fp);
				putc(g >> sft, fp);
				putc(b >> sft, fp);
			}
		else
			while (n-- > 0) {
				(void) getPixel(&r, &g, &b, &a);
				putc(r, fp);
				putc(g, fp);
				putc(b, fp);
			}
	}else if (max == 1) { /* Bi-Level */
		/* PBM Binary */
		int x = (cinf->width + 7) >> 3;
		int y = cinf->height;
		unsigned char *p = planes[0];
		fprintf(fp, "P4\n# %s\n%d %d\n",
			key_comm(cinf), cinf->width, cinf->height);
		while (y-- > 0) {
			if (cinf->cspace == NX_OneIsWhiteColorSpace)
				for (n = 0; n < x; n++)
					putc(p[n] ^ 0xff, fp);
			else
				for (n = 0; n < x; n++)
					putc(p[n], fp);
			p += cinf->xbytes;
		}
	}else { /* Gray */
		/* PGM Binary */
		fprintf(fp, "P5\n# %s\n%d %d %d\n",
			key_comm(cinf), cinf->width, cinf->height, max);
		n = cinf->width * cinf->height;
		if (sft)
			while (n-- > 0) {
				(void) getPixel(&r, &g, &b, &a);
				putc(r >> sft, fp);
			}
		else
			while (n-- > 0) {
				(void) getPixel(&r, &g, &b, &a);
				putc(r, fp);
			}
	}
	return 0;
}


int jpgwrite(FILE *fp, const commonInfo *cinf, const char *dir,
		int quality, BOOL progressive)
{
	int r, g, b, a, n, argp, err;
	char cjpegPath[MAXFILENAMELEN];
	char cjpegQuality[16];
	char comm_text[MAX_COMMENT];
	const char *cmp;
	static char *cjpegArg[10] = {
		NULL,		/* 0: Tool Path */
		CJPEG,
		"-quality",
		NULL,		/* 3: Quality (0-100) */
		"-optimize",
		NULL,		/* 5: -grayscale (maybe) */
		NULL,		/* 6: -progressive (maybe) */
		NULL,		/* 7: -comment (maybe) */
		NULL, NULL };

	sprintf(cjpegPath, "%s/%s", dir, CJPEG);
	cjpegArg[0] = cjpegPath;
	sprintf(cjpegQuality, "%d", quality);
	cjpegArg[3] = cjpegQuality;
	argp = 5;
	if (cinf->numcolors == 1) /* mono */
		cjpegArg[argp++] = "-grayscale";
	if (progressive)
		cjpegArg[argp++] = "-progressive";
	if ((cmp = begin_comm(cinf->memo, YES)) != NULL) {
		int i, cc;
		for (i = 0; cmp[i]; i++) {
			if ((cc = cmp[i] & 0xff) < ' ') cc = ' ';
			comm_text[i] = cc;
		}
		comm_text[i] = 0;
		cjpegArg[argp++] = "-comment";
		cjpegArg[argp++] = comm_text;
	}
	cjpegArg[argp] = NULL;

	if ((fp = openWPipe(fp, cjpegArg, &err)) == NULL)
		return err;

	n = cinf->width * cinf->height;
	if (cinf->numcolors > 1) { /* color */
		/* PPM Binary */
		fprintf(fp, "P6\n# %s\n%d %d 255\n",
			key_comm(cinf), cinf->width, cinf->height);
		while (n-- > 0) {
			(void) getPixel(&r, &g, &b, &a);
			putc(r, fp);
			putc(g, fp);
			putc(b, fp);
		}
	}else { /* Gray */
		/* PGM Binary */
		fprintf(fp, "P5\n# %s\n%d %d 255\n",
			key_comm(cinf), cinf->width, cinf->height);
		while (n-- > 0) {
			(void) getPixel(&r, &g, &b, &a);
			putc(r, fp);
		}
	}
	(void)fclose(fp);
	wait(0);	/* Don't forget */
	return 0;
}


int jbigwrite(FILE *fp, const commonInfo *cinf, const char *map, const char *dir)
{
	int x, y, xb, xbytes, neg = 0, err = 0;
	char jbigPath[MAXFILENAMELEN];
	const unsigned char *pp, *pmap = NULL;
	static char *jbigArg[4] = {
		NULL,		/* 0: Tool Path */
		PBM_JBIG,
		NULL };

	sprintf(jbigPath, "%s/%s", dir, PBM_JBIG);
	jbigArg[0] = jbigPath;

	if ((fp = openWPipe(fp, jbigArg, &err)) == NULL)
		return err;

	xbytes = xb = (cinf->width + 7) >> 3;
	if (cinf->alpha || cinf->bits != 1) {
		pmap = pp = allocBilevelMap(cinf);
		if (!pp) {
			err = Err_MEMORY;
			goto EXIT;
		}
	}else {
		pp = map;
		xbytes = cinf->xbytes;
		neg = (cinf->cspace == NX_OneIsWhiteColorSpace);
	}
	fprintf(fp, "P4\n# %s\n%d %d\n",
		key_comm(cinf), cinf->width, cinf->height);
	for (y = 0; y < cinf->height; y++) {
		if (neg)
			for (x = 0; x < xb; x++)
				putc(*pp++ ^ 0xff, fp);
		else
			for (x = 0; x < xb; x++)
				putc(*pp++, fp);
		for ( ; x < xbytes; x++) ++pp;
	}
EXIT:
	(void)fclose(fp);
	wait(0);	/* Don't forget */
	if (pmap) free((void *)pmap);
	return err;
}

unsigned char *allocBilevelMap(const commonInfo *cinf)
{
	unsigned char *pp, *q;
	int x, y, val, mask;
	int r, g, b, a;
	static unsigned short pattern[4][4]= {
		{ 102, 153, 102, 153 },
		{ 204,  51, 204,  51 },
		{ 102, 153, 102, 153 },
		{ 204,  51, 204,  51 } };

	pp = (unsigned char *)malloc(((cinf->width + 7) >> 3) * cinf->height);
	if (!pp) return NULL;
	q = pp;
	val = 0;
	mask = 0x80;
	x = cinf->width;
	for (y = 0; y < cinf->height; y++) {
		for (x = cinf->width; x > 0; ) {
			(void) getPixel(&r, &g, &b, &a);
			if (pattern[x & 3][y & 3] > r) val |= mask;
			--x;
			if (!(mask >>= 1) || x <= 0) {
				*q++ = val;
				val = 0;
				mask = 0x80;
			}
		}
	}
	return pp;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.