home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / Graphics / ToyViewer-2.6a / src / ImageSave.bproj / ppmwrite.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-06  |  5.7 KB  |  259 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/file.h>
  4. #include <sys/wait.h>
  5. #include <bsd/libc.h>
  6. #include "../ppm.h"
  7. #include "../common.h"
  8. #include "../strfunc.h"
  9. #include "save.h"
  10.  
  11. FILE *openWPipe(FILE *fp, const char **list, int *err)
  12. {
  13.     int pfd[2];
  14.     int pid;
  15.  
  16.     /* if (*err != 0) then fork() didn't called successfully */
  17.     *err = 0;
  18.     if (list == NULL || access(list[0], X_OK) < 0) {
  19.         *err = Err_FLT_EXEC;
  20.         return NULL;    /* not executable */
  21.     }
  22.     (void)pipe(pfd);
  23.     if ((pid = fork()) == 0) { /* child process */
  24.         (void)close(0);
  25.         dup(pfd[0]);
  26.         (void)close(1);
  27.         dup(fileno(fp));
  28.         (void)fclose(fp);
  29.         (void)close(pfd[0]);
  30.         (void)close(pfd[1]);
  31.         execv(list[0], &list[1]);
  32.         exit(1);    /* Error */
  33.     }else if (pid < 0) {    /* ERROR */
  34.         *err = Err_FLT_EXEC;
  35.         (void)close(pfd[0]);
  36.         (void)close(pfd[1]);
  37.         (void)fclose(fp);
  38.         return NULL;
  39.     }
  40.     (void)close(pfd[0]);
  41.     (void)fclose(fp);
  42.     return fdopen(pfd[1], "w");
  43. }
  44.  
  45.  
  46. int ppmwrite(FILE *fp, const commonInfo *cinf, unsigned char **planes)
  47. {
  48.     int max = 255, sft = 0, n;
  49.     int r, g, b, a;
  50.  
  51.     switch (cinf->bits) {
  52.     case 1: max = 1;  sft = 7;  break;
  53.     case 2: max = 3;  sft = 6;  break;
  54.     case 4: max = 15;  sft = 4;  break;
  55.     case 8: max = 255;  sft = 0;  break;
  56.     }
  57.  
  58.     if (cinf->numcolors > 1) { /* color */
  59.         /* PPM Binary */
  60.         fprintf(fp, "P6\n# %s\n%d %d %d\n",
  61.             key_comm(cinf), cinf->width, cinf->height, max);
  62.         n = cinf->width * cinf->height;
  63.         if (sft)
  64.             while (n-- > 0) {
  65.                 (void) getPixel(&r, &g, &b, &a);
  66.                 putc(r >> sft, fp);
  67.                 putc(g >> sft, fp);
  68.                 putc(b >> sft, fp);
  69.             }
  70.         else
  71.             while (n-- > 0) {
  72.                 (void) getPixel(&r, &g, &b, &a);
  73.                 putc(r, fp);
  74.                 putc(g, fp);
  75.                 putc(b, fp);
  76.             }
  77.     }else if (max == 1) { /* Bi-Level */
  78.         /* PBM Binary */
  79.         int x = (cinf->width + 7) >> 3;
  80.         int y = cinf->height;
  81.         unsigned char *p = planes[0];
  82.         fprintf(fp, "P4\n# %s\n%d %d\n",
  83.             key_comm(cinf), cinf->width, cinf->height);
  84.         while (y-- > 0) {
  85.             if (cinf->cspace == NX_OneIsWhiteColorSpace)
  86.                 for (n = 0; n < x; n++)
  87.                     putc(p[n] ^ 0xff, fp);
  88.             else
  89.                 for (n = 0; n < x; n++)
  90.                     putc(p[n], fp);
  91.             p += cinf->xbytes;
  92.         }
  93.     }else { /* Gray */
  94.         /* PGM Binary */
  95.         fprintf(fp, "P5\n# %s\n%d %d %d\n",
  96.             key_comm(cinf), cinf->width, cinf->height, max);
  97.         n = cinf->width * cinf->height;
  98.         if (sft)
  99.             while (n-- > 0) {
  100.                 (void) getPixel(&r, &g, &b, &a);
  101.                 putc(r >> sft, fp);
  102.             }
  103.         else
  104.             while (n-- > 0) {
  105.                 (void) getPixel(&r, &g, &b, &a);
  106.                 putc(r, fp);
  107.             }
  108.     }
  109.     return 0;
  110. }
  111.  
  112.  
  113. int jpgwrite(FILE *fp, const commonInfo *cinf, const char *dir,
  114.         int quality, BOOL progressive)
  115. {
  116.     int r, g, b, a, n, argp, err;
  117.     char cjpegPath[MAXFILENAMELEN];
  118.     char cjpegQuality[16];
  119.     char comm_text[MAX_COMMENT];
  120.     const char *cmp;
  121.     static char *cjpegArg[10] = {
  122.         NULL,        /* 0: Tool Path */
  123.         CJPEG,
  124.         "-quality",
  125.         NULL,        /* 3: Quality (0-100) */
  126.         "-optimize",
  127.         NULL,        /* 5: -grayscale (maybe) */
  128.         NULL,        /* 6: -progressive (maybe) */
  129.         NULL,        /* 7: -comment (maybe) */
  130.         NULL, NULL };
  131.  
  132.     sprintf(cjpegPath, "%s/%s", dir, CJPEG);
  133.     cjpegArg[0] = cjpegPath;
  134.     sprintf(cjpegQuality, "%d", quality);
  135.     cjpegArg[3] = cjpegQuality;
  136.     argp = 5;
  137.     if (cinf->numcolors == 1) /* mono */
  138.         cjpegArg[argp++] = "-grayscale";
  139.     if (progressive)
  140.         cjpegArg[argp++] = "-progressive";
  141.     if ((cmp = begin_comm(cinf->memo, YES)) != NULL) {
  142.         int i, cc;
  143.         for (i = 0; cmp[i]; i++) {
  144.             if ((cc = cmp[i] & 0xff) < ' ') cc = ' ';
  145.             comm_text[i] = cc;
  146.         }
  147.         comm_text[i] = 0;
  148.         cjpegArg[argp++] = "-comment";
  149.         cjpegArg[argp++] = comm_text;
  150.     }
  151.     cjpegArg[argp] = NULL;
  152.  
  153.     if ((fp = openWPipe(fp, cjpegArg, &err)) == NULL)
  154.         return err;
  155.  
  156.     n = cinf->width * cinf->height;
  157.     if (cinf->numcolors > 1) { /* color */
  158.         /* PPM Binary */
  159.         fprintf(fp, "P6\n# %s\n%d %d 255\n",
  160.             key_comm(cinf), cinf->width, cinf->height);
  161.         while (n-- > 0) {
  162.             (void) getPixel(&r, &g, &b, &a);
  163.             putc(r, fp);
  164.             putc(g, fp);
  165.             putc(b, fp);
  166.         }
  167.     }else { /* Gray */
  168.         /* PGM Binary */
  169.         fprintf(fp, "P5\n# %s\n%d %d 255\n",
  170.             key_comm(cinf), cinf->width, cinf->height);
  171.         while (n-- > 0) {
  172.             (void) getPixel(&r, &g, &b, &a);
  173.             putc(r, fp);
  174.         }
  175.     }
  176.     (void)fclose(fp);
  177.     wait(0);    /* Don't forget */
  178.     return 0;
  179. }
  180.  
  181.  
  182. int jbigwrite(FILE *fp, const commonInfo *cinf, const char *map, const char *dir)
  183. {
  184.     int x, y, xb, xbytes, neg = 0, err = 0;
  185.     char jbigPath[MAXFILENAMELEN];
  186.     const unsigned char *pp, *pmap = NULL;
  187.     static char *jbigArg[4] = {
  188.         NULL,        /* 0: Tool Path */
  189.         PBM_JBIG,
  190.         NULL };
  191.  
  192.     sprintf(jbigPath, "%s/%s", dir, PBM_JBIG);
  193.     jbigArg[0] = jbigPath;
  194.  
  195.     if ((fp = openWPipe(fp, jbigArg, &err)) == NULL)
  196.         return err;
  197.  
  198.     xbytes = xb = (cinf->width + 7) >> 3;
  199.     if (cinf->alpha || cinf->bits != 1) {
  200.         pmap = pp = allocBilevelMap(cinf);
  201.         if (!pp) {
  202.             err = Err_MEMORY;
  203.             goto EXIT;
  204.         }
  205.     }else {
  206.         pp = map;
  207.         xbytes = cinf->xbytes;
  208.         neg = (cinf->cspace == NX_OneIsWhiteColorSpace);
  209.     }
  210.     fprintf(fp, "P4\n# %s\n%d %d\n",
  211.         key_comm(cinf), cinf->width, cinf->height);
  212.     for (y = 0; y < cinf->height; y++) {
  213.         if (neg)
  214.             for (x = 0; x < xb; x++)
  215.                 putc(*pp++ ^ 0xff, fp);
  216.         else
  217.             for (x = 0; x < xb; x++)
  218.                 putc(*pp++, fp);
  219.         for ( ; x < xbytes; x++) ++pp;
  220.     }
  221. EXIT:
  222.     (void)fclose(fp);
  223.     wait(0);    /* Don't forget */
  224.     if (pmap) free((void *)pmap);
  225.     return err;
  226. }
  227.  
  228. unsigned char *allocBilevelMap(const commonInfo *cinf)
  229. {
  230.     unsigned char *pp, *q;
  231.     int x, y, val, mask;
  232.     int r, g, b, a;
  233.     static unsigned short pattern[4][4]= {
  234.         { 102, 153, 102, 153 },
  235.         { 204,  51, 204,  51 },
  236.         { 102, 153, 102, 153 },
  237.         { 204,  51, 204,  51 } };
  238.  
  239.     pp = (unsigned char *)malloc(((cinf->width + 7) >> 3) * cinf->height);
  240.     if (!pp) return NULL;
  241.     q = pp;
  242.     val = 0;
  243.     mask = 0x80;
  244.     x = cinf->width;
  245.     for (y = 0; y < cinf->height; y++) {
  246.         for (x = cinf->width; x > 0; ) {
  247.             (void) getPixel(&r, &g, &b, &a);
  248.             if (pattern[x & 3][y & 3] > r) val |= mask;
  249.             --x;
  250.             if (!(mask >>= 1) || x <= 0) {
  251.                 *q++ = val;
  252.                 val = 0;
  253.                 mask = 0x80;
  254.             }
  255.         }
  256.     }
  257.     return pp;
  258. }
  259.