home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stdlib.h>
- #include <libc.h>
- #include "ppm.h"
-
- /* PPM Format
- Px : Header
- Width Height
- MAX : pbm does not have this field
- Bitmap : in ASCII / Binary
- */
-
- #define PXOF 0xff
- #define UnknownHD 0
- /* PX original Format
- PX : Header
- Width Height Colors : Colors := Number of colors in palette - 1
- Palette : Binary
- Bitmap : Binary
- */
-
- static int ppmkind = 0, ppmmax = 0;
- static char ppmcomm[MAX_COMMENT];
-
- static void ppm_skip(FILE *fp)
- {
- int c;
-
- while ((c = getc(fp)) != EOF) {
- if (c == '\n') {
- c = getc(fp);
- while (c == '#') {
- while ((c = getc(fp)) != '\n')
- if (c == EOF)
- return;
- c = getc(fp);
- }
- }
- if (c > ' ') {
- ungetc(c, fp);
- return;
- }
- }
- }
-
- static int ppm_head(FILE *fp)
- {
- int c, i, kind = UnknownHD;
-
- if ((c = getc(fp)) != 'P')
- return UnknownHD;
- c = getc(fp);
- if (c >= '0' && c <= '9')
- kind = c - '0';
- else if (c == 'X')
- kind = PXOF;
- ppmcomm[0] = 0;
- while ((c = getc(fp)) <= ' ') ;
- if (c == '#') {
- for (i = 0; (c = getc(fp)) != '\n'; i++)
- if (i < MAX_COMMENT-1) ppmcomm[i] = c;
- ppmcomm[i] = 0;
- ungetc('\n', fp);
- ppm_skip(fp);
- }else
- ungetc(c, fp);
- return kind;
- }
-
- static int ppm_getint(FILE *fp)
- {
- int c;
- int v = 0;
-
- c = getc(fp);
- while (c < '0' || c > '9') {
- if (c == EOF) return -1;
- c = getc(fp);
- }
- while (c >= '0' && c <= '9') {
- v = (v * 10) + c - '0';
- c = getc(fp);
- }
- if (c != EOF && c < ' ')
- ungetc(c, fp);
- return v;
- }
-
-
- commonInfo *loadPpmHeader(FILE *fp, int *errcode)
- {
- int w, err;
- commonInfo *cinf;
-
- *errcode = err = 0;
- ppmkind = ppm_head(fp);
- if (ppmkind == UnknownHD) {
- *errcode = Err_FORMAT;
- return NULL;
- }
- if ((w = ppm_getint(fp)) >= MAXWidth) {
- *errcode = Err_IMPLEMENT;
- return NULL;
- }
- if ((cinf = (commonInfo *)malloc(sizeof(commonInfo))) == NULL) {
- *errcode = Err_MEMORY;
- return NULL;
- }
- cinf->width = w;
- cinf->alpha = NO;
- cinf->type = Type_ppm;
- cinf->isplanar = YES;
- cinf->palsteps = 0;
- cinf->palette = NULL;
- cinf->memo[0] = 0;
- ppm_skip(fp);
- cinf->height = ppm_getint(fp);
- if (ppmkind == PBMa || ppmkind == PBMb) {
- ppmmax = 2;
- cinf->numcolors = 1;
- (void)getc(fp);
- }else {
- ppm_skip(fp);
- ppmmax = ppm_getint(fp) + 1;
- (void)getc(fp);
- if (ppmkind == PXOF) {
- cinf->numcolors = 3;
- cinf->xbytes = cinf->width;
- cinf->bits = 8;
- cinf->cspace = NX_RGBColorSpace;
- return cinf;
- }
- cinf->numcolors = (ppmkind == PPMa || ppmkind == PPMb) ? 3 : 1;
- }
-
- cinf->bits = (ppmmax > 16) ? 8
- : ((ppmmax > 4) ? 4 : ((ppmmax > 2) ? 2 : 1));
- cinf->xbytes = byte_length(cinf->bits, cinf->width);
- cinf->cspace = (cinf->numcolors > 1) ? NX_RGBColorSpace
- : ((ppmkind == PBMa || ppmkind == PBMb)
- ? NX_OneIsBlackColorSpace
- : NX_OneIsWhiteColorSpace);
- return cinf;
- }
-
-
- static int isGrayPPM(unsigned char **planes, int length)
- {
- int i;
- unsigned char *rr, *gg, *bb;
-
- rr = planes[0];
- gg = planes[1];
- bb = planes[2];
- for (i = 0; i < length; i++) {
- if (rr[i] != gg[i] || gg[i] != bb[i]) return 0;
- }
- return 1;
- }
-
- static int bitsOfPPM(unsigned char **planes, commonInfo *cinf)
- {
- unsigned char *p, buf[256];
- int i, pn, w, num;
-
- w = cinf->width * cinf->height;
- for (i = 0; i < 256; i++) buf[i] = 0;
- num = 0;
- for (pn = 0; pn < cinf->numcolors; pn++) {
- p = planes[pn];
- for (i = 0; i < w; i++)
- if (buf[p[i]] == 0) {
- buf[p[i]] = 1;
- if (++num > 16) return 8;
- }
- }
- return optimalBits(buf, num);
- }
-
- static int getPXOF(FILE *fp, commonInfo *cinf, unsigned char **planes)
- {
- int i, x, y;
- unsigned char *p, *rr, *gg, *bb;
-
- cinf->palette = (paltype *)malloc(sizeof(paltype) * ppmmax);
- if (cinf->palette == NULL)
- return Err_MEMORY;
- cinf->palsteps = ppmmax;
- for (i = 0; i < ppmmax; i++) {
- p = cinf->palette[i];
- for (x = 0; x < 3; x++)
- p[x] = getc(fp);
- }
- rr = planes[0];
- gg = planes[1];
- bb = planes[2];
- for (y = 0; y < cinf->height; y++) {
- for (x = 0; x < cinf->width; x++) {
- p = cinf->palette[getc(fp)];
- *rr++ = p[RED];
- *gg++ = p[GREEN];
- *bb++ = p[BLUE];
- }
- }
- return 0;
- }
-
- static int PPMplanes(FILE *fp,
- commonInfo *cinf, int pn, unsigned char **planes)
- {
- int i, x, y;
- unsigned char work[3][MAXWidth];
- int width = cinf->width;
-
- for (y = 0; y < cinf->height; y++) {
- if (feof(fp))
- return Err_SHORT;
- if (isPPMascii(ppmkind)) {
- for (x = 0; x < width; x++)
- for (i = 0; i < pn; i++) {
- ppm_skip(stdin);
- work[i][x] = (ppm_getint(fp) << 8) / ppmmax;
- }
- }else if (ppmkind == PBMb) {
- int mask, cc;
- for (x = 0; x < width; ) {
- cc = getc(fp);
- for (mask = 0x80; mask; mask >>= 1) {
- work[0][x] = (cc & mask) ? 0xff : 0;
- if (++x >= width) break;
- }
- }
- }else {
- for (x = 0; x < width; x++) {
- for (i = 0; i < pn; i++)
- work[i][x] = (getc(fp) << 8) / ppmmax;
- }
- }
- for (i = 0; i < pn; i++) {
- unsigned char *pp = planes[i] + y * cinf->xbytes;
- packImage(pp, work[i], width, cinf->bits);
- }
- }
- return 0;
- }
-
- int ppmGetImage(FILE *fp,
- commonInfo *cinf, unsigned char **planes, const char *fkind)
- {
- int i, y, pn, bits, err;
- int width, xbyte;
- const char *kp;
-
- width = cinf->width;
- pn = cinf->numcolors;
- err = allocImage(planes, width, cinf->height, cinf->bits, (pn == 1));
- if (err) return err;
- if (ppmkind == PXOF)
- err = getPXOF(fp, cinf, planes);
- else
- err = PPMplanes(fp, cinf, pn, planes);
- if (err) return err;
-
- /* Is the image Gray ? */
- if (pn == 3 && isGrayPPM(planes, cinf->xbytes * cinf->height)) {
- size_t newsize = planes[1] - planes[0];
- planes[0] = (unsigned char *)realloc(planes[0], newsize);
- planes[1] = planes[2] = NULL;
- pn = cinf->numcolors = 1;
- cinf->cspace = NX_OneIsWhiteColorSpace;
- }
- /* How many bits are needed ? */
- if (cinf->bits == 8 && (bits = bitsOfPPM(planes, cinf)) < 8) {
- unsigned char *src, *dst, *newmap[3];
- err = allocImage(newmap, width, cinf->height, bits, (pn == 1));
- if (err) return 0; /* Error */
- xbyte = byte_length(bits, width);
- for (i = 0; i < pn; i++) {
- src = planes[i];
- dst = newmap[i];
- for (y = 0; y < cinf->height; y++) {
- packImage(dst, src, width, bits);
- src += width;
- dst += xbyte;
- }
- }
- free((void *)planes[0]);
- for (i = 0; i < 3; i++)
- planes[i] = newmap[i];
- cinf->xbytes = xbyte;
- cinf->bits = bits;
- }
-
- sprintf(cinf->memo, "%d x %d ", cinf->width, cinf->height);
- kp = fkind ? fkind
- : ((ppmkind == PXOF) ? "PXOF" : PPMname(ppmkind));
- strcat(cinf->memo, kp);
- if ((bits = cinf->bits) == 1)
- strcat(cinf->memo, " 1bit");
- else {
- i = strlen(cinf->memo);
- sprintf(cinf->memo + i, " %dbits%s", bits,
- (planes[1] ? "" : ", gray"));
- }
- if (ppmcomm[0]) {
- strcat(cinf->memo, " : ");
- i = strlen(cinf->memo);
- strncat(cinf->memo, ppmcomm, MAX_COMMENT - i - 2);
- }
-
- return 0;
- }
-
- #ifdef _TEST
- main()
- {
- printf("kind=P%d\n", ppm_head(stdin));
- while (!feof(stdin)) {
- ppm_skip(stdin);
- printf("%d\n", ppm_getint(stdin));
- }
- }
- #endif
-