home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / ppm / ppmtopict.c < prev    next >
C/C++ Source or Header  |  1993-10-04  |  11KB  |  483 lines

  1. /*
  2. ** ppmtopict.c - read a portable pixmap and produce a Macintosh PICT2 file.
  3. **
  4. ** Copyright (C) 1990 by Ken Yap <ken@cs.rochester.edu>.
  5. **
  6. ** Permission to use, copy, modify, and distribute this software and its
  7. ** documentation for any purpose and without fee is hereby granted, provided
  8. ** that the above copyright notice appear in all copies and that both that
  9. ** copyright notice and this permission notice appear in supporting
  10. ** documentation.  This software is provided "as is" without express or
  11. ** implied warranty.
  12. */
  13.  
  14. #include "ppm.h"
  15. #include "ppmcmap.h"
  16.  
  17. #define HEADER_SIZE        512
  18.  
  19. #define    RUN_THRESH        3
  20. #define    MAX_RUN            128        /* 0xff = 2, 0xfe = 3, etc */
  21. #define    MAX_COUNT        128        /* 0x00 = 1, 0x01 = 2, etc */
  22.  
  23. /* Opcodes */
  24. #define PICT_NOP        0x00
  25. #define PICT_clipRgn        0x01
  26. #define PICT_bkPat        0x02
  27. #define PICT_txFont        0x03
  28. #define PICT_txFace        0x04
  29. #define PICT_txMode        0x05
  30. #define PICT_spExtra        0x06
  31. #define PICT_pnSize        0x07
  32. #define PICT_pnMode        0x08
  33. #define PICT_pnPat        0x09
  34. #define PICT_thePat        0x0A
  35. #define PICT_ovSize        0x0B
  36. #define PICT_origin        0x0C
  37. #define PICT_txSize        0x0D
  38. #define PICT_fgColor        0x0E
  39. #define PICT_bkColor        0x0F
  40. #define PICT_txRatio        0x10
  41. #define PICT_picVersion        0x11
  42. #define    PICT_blPixPat        0x12
  43. #define    PICT_pnPixPat        0x13
  44. #define    PICT_fillPixPat        0x14
  45. #define    PICT_pnLocHFrac        0x15
  46. #define    PICT_chExtra        0x16
  47. #define    PICT_rgbFgCol        0x1A
  48. #define    PICT_rgbBkCol        0x1B
  49. #define    PICT_hiliteMode        0x1C
  50. #define    PICT_hiliteColor    0x1D
  51. #define    PICT_defHilite        0x1E
  52. #define    PICT_opColor        0x1F
  53. #define PICT_line        0x20
  54. #define PICT_line_from        0x21
  55. #define PICT_short_line        0x22
  56. #define PICT_short_line_from    0x23
  57. #define PICT_long_text        0x28
  58. #define PICT_DH_text        0x29
  59. #define PICT_DV_text        0x2A
  60. #define PICT_DHDV_text        0x2B
  61. #define PICT_frameRect        0x30
  62. #define PICT_paintRect        0x31
  63. #define PICT_eraseRect        0x32
  64. #define PICT_invertRect        0x33
  65. #define PICT_fillRect        0x34
  66. #define PICT_frameSameRect    0x38
  67. #define PICT_paintSameRect    0x39
  68. #define PICT_eraseSameRect    0x3A
  69. #define PICT_invertSameRect    0x3B
  70. #define PICT_fillSameRect    0x3C
  71. #define PICT_frameRRect        0x40
  72. #define PICT_paintRRect        0x41
  73. #define PICT_eraseRRect        0x42
  74. #define PICT_invertRRect    0x43
  75. #define PICT_fillRRect        0x44
  76. #define PICT_frameSameRRect    0x48
  77. #define PICT_paintSameRRect    0x49
  78. #define PICT_eraseSameRRect    0x4A
  79. #define PICT_invertSameRRect    0x4B
  80. #define PICT_fillSameRRect    0x4C
  81. #define PICT_frameOval        0x50
  82. #define PICT_paintOval        0x51
  83. #define PICT_eraseOval        0x52
  84. #define PICT_invertOval        0x53
  85. #define PICT_fillOval        0x54
  86. #define PICT_frameSameOval    0x58
  87. #define PICT_paintSameOval    0x59
  88. #define PICT_eraseSameOval    0x5A
  89. #define PICT_invertSameOval    0x5B
  90. #define PICT_fillSameOval    0x5C
  91. #define PICT_frameArc        0x60
  92. #define PICT_paintArc        0x61
  93. #define PICT_eraseArc        0x62
  94. #define PICT_invertArc        0x63
  95. #define PICT_fillArc        0x64
  96. #define PICT_frameSameArc    0x68
  97. #define PICT_paintSameArc    0x69
  98. #define PICT_eraseSameArc    0x6A
  99. #define PICT_invertSameArc    0x6B
  100. #define PICT_fillSameArc    0x6C
  101. #define PICT_framePoly        0x70
  102. #define PICT_paintPoly        0x71
  103. #define PICT_erasePoly        0x72
  104. #define PICT_invertPoly        0x73
  105. #define PICT_fillPoly        0x74
  106. #define PICT_frameSamePoly    0x78
  107. #define PICT_paintSamePoly    0x79
  108. #define PICT_eraseSamePoly    0x7A
  109. #define PICT_invertSamePoly    0x7B
  110. #define PICT_fillSamePoly    0x7C
  111. #define PICT_frameRgn        0x80
  112. #define PICT_paintRgn        0x81
  113. #define PICT_eraseRgn        0x82
  114. #define PICT_invertRgn        0x83
  115. #define PICT_fillRgn        0x84
  116. #define PICT_frameSameRgn    0x88
  117. #define PICT_paintSameRgn    0x89
  118. #define PICT_eraseSameRgn    0x8A
  119. #define PICT_invertSameRgn    0x8B
  120. #define PICT_fillSameRgn    0x8C
  121. #define PICT_BitsRect        0x90
  122. #define PICT_BitsRgn        0x91
  123. #define PICT_PackBitsRect    0x98
  124. #define PICT_PackBitsRgn    0x99
  125. #define PICT_shortComment    0xA0
  126. #define PICT_longComment    0xA1
  127. #define PICT_EndOfPicture    0xFF
  128. #define    PICT_headerOp        0x0C00
  129.  
  130. static void putFill ARGS(( FILE *fd, int n ));
  131. static void putShort ARGS(( FILE *fd, int i ));
  132. static void putLong ARGS(( FILE *fd, long i ));
  133. static void putFixed ARGS(( FILE *fd, int in, int frac ));
  134. static void putRect ARGS(( FILE *fd, int x1, int x2, int y1, int y2 ));
  135. static int putRow ARGS(( FILE *fd, int row, int cols, pixel *rowpixels, char *packed ));
  136.  
  137. #define MAXCOLORS 256
  138. static colorhash_table cht;
  139.  
  140. int
  141. main(argc, argv)
  142. int argc;
  143. char *argv[];
  144. {
  145.     FILE *ifp;
  146.     int argn, rows, cols, colors, i, row, oc;
  147.     register pixel **pixels;
  148.     char *packed;
  149.     pixval maxval;
  150.     long lmaxval, rval, gval, bval;
  151.     colorhist_vector chv;
  152.  
  153.  
  154.     ppm_init( &argc, argv );
  155.  
  156.     argn = 1;
  157.     if (argn < argc)
  158.     {
  159.         ifp = pm_openr(argv[1]);
  160.         argn++;
  161.     }
  162.     else
  163.         ifp = stdin;
  164.     if (argn != argc)
  165.         pm_usage("[ppmfile]");
  166.  
  167.     pixels = ppm_readppm(ifp, &cols, &rows, &maxval);
  168.     if (cols < 8)
  169.         pm_error("ppm input too narrow, must be >= 8 pixels wide" );
  170.     lmaxval = (long)maxval;
  171.     pm_close(ifp);
  172.  
  173.     /* Figure out the colormap. */
  174.     pm_message("computing colormap..." );
  175.     chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
  176.     if (chv == (colorhist_vector) 0)
  177.         pm_error("too many colors - try doing a 'ppmquant %d'", MAXCOLORS);
  178.     pm_message("%d colors found", colors );
  179.  
  180.     /* Make a hash table for fast color lookup. */
  181.     cht = ppm_colorhisttocolorhash(chv, colors);
  182.  
  183.     /* write the header */
  184.     putFill(stdout, HEADER_SIZE);
  185.  
  186.     /* write picSize and picFrame */
  187.     putShort(stdout, 0);
  188.     putRect(stdout, 0, 0, rows, cols);
  189.  
  190.     /* write version op and version */
  191.     putShort(stdout, PICT_picVersion);
  192.     putShort(stdout, 0x02FF);
  193.     putShort(stdout, PICT_headerOp);
  194.     putLong(stdout, -1L);
  195.     putFixed(stdout, 0, 0);
  196.     putFixed(stdout, 0, 0);
  197.     putFixed(stdout, cols, 0);
  198.     putFixed(stdout, rows, 0);
  199.     putFill(stdout, 4);
  200.  
  201.     /* seems to be needed by many PICT2 programs */
  202.     putShort(stdout, PICT_clipRgn);
  203.     putShort(stdout, 10);
  204.     putRect(stdout, 0, 0, rows, cols);
  205.  
  206.     /* write picture */
  207.     putShort(stdout, PICT_PackBitsRect);
  208.     putShort(stdout, cols | 0x8000);
  209.     putRect(stdout, 0, 0, rows, cols);
  210.     putShort(stdout, 0);    /* pmVersion */
  211.     putShort(stdout, 0);    /* packType */
  212.     putLong(stdout, 0L);    /* packSize */
  213.     putFixed(stdout, 72, 0);    /* hRes */
  214.     putFixed(stdout, 72, 0);    /* vRes */
  215.     putShort(stdout, 0);    /* pixelType */
  216.     putShort(stdout, 8);    /* pixelSize */
  217.     putShort(stdout, 1);    /* cmpCount */
  218.     putShort(stdout, 8);    /* cmpSize */
  219.     putLong(stdout, 0L);    /* planeBytes */
  220.     putLong(stdout, 0L);    /* pmTable */
  221.     putLong(stdout, 0L);    /* pmReserved */
  222.     putLong(stdout, 0L);    /* ctSeed */
  223.     putShort(stdout, 0);    /* ctFlags */
  224.     putShort(stdout, colors-1);    /* ctSize */
  225.  
  226.     /* Write out the colormap. */
  227.     for (i = 0; i < colors; i++)
  228.     {
  229.         putShort(stdout, i);
  230.         rval = PPM_GETR(chv[i].color);
  231.         gval = PPM_GETG(chv[i].color);
  232.         bval = PPM_GETB(chv[i].color);
  233.         if (lmaxval != 65535L)
  234.         {
  235.             rval = rval * 65535L / lmaxval;
  236.             gval = gval * 65535L / lmaxval;
  237.             bval = bval * 65535L / lmaxval;
  238.         }
  239.         putShort(stdout, (short)rval);
  240.         putShort(stdout, (short)gval);
  241.         putShort(stdout, (short)bval);
  242.     }
  243.  
  244.     putRect(stdout, 0, 0, rows, cols);    /* srcRect */
  245.     putRect(stdout, 0, 0, rows, cols);    /* dstRect */
  246.     putShort(stdout, 0);            /* mode */
  247.  
  248.     /* Finally, write out the data. */
  249.     packed = (char*) malloc((unsigned)(cols+cols/MAX_COUNT+1));
  250.     oc = 0;
  251.     for (row = 0; row < rows; row++)
  252.         oc += putRow(stdout, row, cols, pixels[row], packed);
  253.  
  254.     /* if we wrote an odd number of pixdata bytes, pad */
  255.     if (oc & 1)
  256.         (void) putc(0, stdout);
  257.     putShort(stdout, PICT_EndOfPicture);
  258.  
  259.     lmaxval = ftell(stdout) - HEADER_SIZE;
  260.     if (fseek(stdout, (long)HEADER_SIZE, 0) >= 0)
  261.         putShort(stdout, (short)(lmaxval & 0xffff));
  262.  
  263.     exit(0);
  264. }
  265.  
  266. static void
  267. putFill(fd, n)
  268. FILE *fd;
  269. int n;
  270. {
  271.     register int i;
  272.  
  273.     for (i = 0; i < n; i++)
  274.         (void) putc(0, fd);
  275. }
  276.  
  277. static void
  278. putShort(fd, i)
  279. FILE *fd;
  280. int i;
  281. {
  282.     (void) putc((i >> 8) & 0xff, fd);
  283.     (void) putc(i & 0xff, fd);
  284. }
  285.  
  286. #if __STDC__
  287. static void
  288. putLong( FILE *fd, long i )
  289. #else /*__STDC__*/
  290. static void
  291. putLong(fd, i)
  292. FILE *fd;
  293. long i;
  294. #endif /*__STDC__*/
  295. {
  296.     (void) putc((int)((i >> 24) & 0xff), fd);
  297.     (void) putc(((int)(i >> 16) & 0xff), fd);
  298.     (void) putc(((int)(i >> 8) & 0xff), fd);
  299.     (void) putc((int)(i & 0xff), fd);
  300. }
  301.  
  302. static void
  303. putFixed(fd, in, frac)
  304. FILE *fd;
  305. int in, frac;
  306. {
  307.     putShort(fd, in);
  308.     putShort(fd, frac);
  309. }
  310.  
  311. static void
  312. putRect(fd, x1, x2, y1, y2)
  313. FILE *fd;
  314. int x1, x2, y1, y2;
  315. {
  316.     putShort(fd, x1);
  317.     putShort(fd, x2);
  318.     putShort(fd, y1);
  319.     putShort(fd, y2);
  320. }
  321.  
  322. #define    RUNLENGTH
  323. #ifdef    RUNLENGTH
  324.  
  325. #define        runtochar(c)    (257-(c))
  326. #define        counttochar(c)    ((c)-1)
  327.  
  328. static int
  329. putRow(fd, row, cols, rowpixels, packed)
  330. FILE *fd;
  331. int row, cols;
  332. pixel *rowpixels;
  333. char *packed;
  334. {
  335.     register int i;
  336.     int packcols, count, run, rep, oc;
  337.     register pixel *pP;
  338.     pixel lastp;
  339.     register char *p;
  340.  
  341.     run = count = 0;
  342.     for (cols--, i = cols, pP = rowpixels + cols, p = packed, lastp = *pP;
  343.         i >= 0; i--, lastp = *pP, pP--)
  344.     {
  345.         if (PPM_EQUAL(lastp, *pP))
  346.             run++;
  347.         else if (run < RUN_THRESH)
  348.         {
  349.             while (run > 0)
  350.             {
  351.                 *p++ = ppm_lookupcolor(cht, &lastp);
  352.                 run--;
  353.                 count++;
  354.                 if (count == MAX_COUNT)
  355.                 {
  356.                     *p++ = counttochar(MAX_COUNT);
  357.                     count -= MAX_COUNT;
  358.                 }
  359.             }
  360.             run = 1;
  361.         }
  362.         else
  363.         {
  364.             if (count > 0)
  365.                 *p++ = counttochar(count);
  366.             count = 0;
  367.             while (run > 0)
  368.             {
  369.                 rep = run > MAX_RUN ? MAX_RUN : run;
  370.                 *p++ = ppm_lookupcolor(cht, &lastp);
  371.                 *p++ = runtochar(rep);
  372.                 run -= rep;
  373.             }
  374.             run = 1;
  375.         }
  376.     }
  377.     if (run < RUN_THRESH)
  378.     {
  379.         while (run > 0)
  380.         {
  381.             *p++ = ppm_lookupcolor(cht, &lastp);
  382.             run--;
  383.             count++;
  384.             if (count == MAX_COUNT)
  385.             {
  386.                 *p++ = counttochar(MAX_COUNT);
  387.                 count -= MAX_COUNT;
  388.             }
  389.         }
  390.     }
  391.     else
  392.     {
  393.         if (count > 0)
  394.             *p++ = counttochar(count);
  395.         count = 0;
  396.         while (run > 0)
  397.         {
  398.             rep = run > MAX_RUN ? MAX_RUN : run;
  399.             *p++ = ppm_lookupcolor(cht, &lastp);
  400.             *p++ = runtochar(rep);
  401.                 run -= rep;
  402.         }
  403.         run = 1;
  404.     }
  405.     if (count > 0)
  406.         *p++ = counttochar(count);
  407.  
  408.     packcols = p - packed;        /* how many did we write? */
  409.     if (cols > 250)
  410.     {
  411.         putShort(fd, packcols);
  412.         oc = packcols + 2;
  413.     }
  414.     else
  415.     {
  416.         (void) putc(packcols, fd);
  417.         oc = packcols + 1;
  418.     }
  419.  
  420.     /* now write out the packed row */
  421.     while(p != packed)
  422.     {
  423.         --p;
  424.         (void) putc(*p, fd);
  425.     }
  426.  
  427.     return (oc);
  428. }
  429.  
  430. #else    /* RUNLENGTH */
  431.  
  432. /* real dumb putRow with no compression */
  433. static int
  434. putRow(fd, row, cols, rowpixels, packed)
  435. FILE *fd;
  436. int row, cols;
  437. pixel *rowpixels;
  438. char *packed;
  439. {
  440.     register int i, j, bc, oc;
  441.     register pixel *pP;
  442.  
  443. #if notdef
  444.     bzero(aux, cols); /* aux?? */
  445. #endif /*notdef*/
  446.     bc = cols + (cols + MAX_COUNT - 1) / MAX_COUNT;
  447.     if (bc > 250)
  448.     {
  449.         putShort(fd, bc);
  450.         oc = bc + 2;
  451.     }
  452.     else
  453.     {
  454.         (void) putc(bc, fd);
  455.         oc = bc + 1;
  456.     }
  457.     for (i = 0, pP = rowpixels; i < cols;)
  458.     {
  459.         if (cols - i > MAX_COUNT)
  460.         {
  461.             (void) putc(MAX_COUNT - 1, fd);
  462.             for (j = 0; j < MAX_COUNT; j++)
  463.             {
  464.                 (void) putc(ppm_lookupcolor(cht, pP), fd);
  465.                 pP++;
  466.             }
  467.             i += MAX_COUNT;
  468.         }
  469.         else
  470.         {
  471.             (void) putc(cols - i - 1, fd);
  472.             for (j = 0; j < cols - i; j++)
  473.             {
  474.                 (void) putc(ppm_lookupcolor(cht, pP), fd);
  475.                 pP++;
  476.             }
  477.             i = cols;
  478.         }
  479.     }
  480.     return (oc);
  481. }
  482. #endif    /* RUNLENGTH */
  483.