home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / NETWORK / netpbm_src.lzh / NETPBM / PPM / ppmtoilbm.c < prev    next >
Text File  |  1996-11-18  |  61KB  |  1,856 lines

  1. /* ppmtoilbm.c - read a portable pixmap and produce an IFF ILBM file
  2. **
  3. ** Copyright (C) 1989 by Jef Poskanzer.
  4. ** Modified by Ingo Wilken (Ingo.Wilken@informatik.uni-oldenburg.de)
  5. **  20/Jun/93:
  6. **  - 24bit support (new options -24if, -24force)
  7. **  - HAM8 support (well, anything from HAM3 to HAM(MAXPLANES))
  8. **  - now writes up to 8 (16) planes (new options -maxplanes, -fixplanes)
  9. **  - colormap file (new option -map)
  10. **  - write colormap only (new option -cmaponly)
  11. **  - only writes CAMG chunk if it is a HAM-picture
  12. **  29/Aug/93:
  13. **  - operates row-by-row whenever possible
  14. **  - faster colorscaling with lookup-table (~20% faster on HAM pictures)
  15. **  - options -ham8 and -ham6 now imply -hamforce
  16. **  27/Nov/93:
  17. **  - byterun1 compression (this is now default) with new options:
  18. **    -compress, -nocompress, -cmethod, -savemem
  19. **  - floyd-steinberg error diffusion (for std+mapfile and HAM)
  20. **  - new options: -lace and -hires --> write CAMG chunk
  21. **  - LUT for luminance calculation (used by ppm_to_ham)
  22. **
  23. **
  24. **           std   HAM  24bit cmap  direct
  25. **  -------+-----+-----+-----+-----+-----
  26. **  BMHD     yes   yes   yes   yes   yes
  27. **  CMAP     yes   (1)   no    yes   no
  28. **  BODY     yes   yes   yes   no    yes
  29. **  CAMG     (2)   yes   (2)   no    (2)
  30. **  other    -     -     -     -     DCOL
  31. **  nPlanes  1-8   3-8   24    0     3-24   if configured without ILBM_BIGRAW
  32. **  nPlanes  1-16  3-16  24    0     3-48   if configured with ILBM_BIGRAW
  33. **
  34. **  (1): grayscale colormap
  35. **  (2): only if "-lace" or "-hires" option used
  36. **
  37. ** Permission to use, copy, modify, and distribute this software and its
  38. ** documentation for any purpose and without fee is hereby granted, provided
  39. ** that the above copyright notice appear in all copies and that both that
  40. ** copyright notice and this permission notice appear in supporting
  41. ** documentation.  This software is provided "as is" without express or
  42. ** implied warranty.
  43. */
  44.  
  45. #include "ppm.h"
  46. #include "ppmcmap.h"
  47. #include "ilbm.h"
  48.  
  49. /*#define DEBUG*/
  50.  
  51. #define MODE_DIRECT     4   /* direct color ILBM */
  52. #define MODE_CMAP       3   /* write normal file, but colormap only */
  53. #define MODE_24         2   /* write a 24bit (deep) ILBM */
  54. #define MODE_HAM        1   /* write a HAM */
  55. #define MODE_NONE       0   /* write a normal picture */
  56.  
  57. #define ECS_MAXPLANES   5
  58. #define ECS_HAMPLANES   6
  59. #define AGA_MAXPLANES   8
  60. #define AGA_HAMPLANES   8
  61.  
  62. #ifdef AMIGA_AGA
  63. #define DEF_MAXPLANES   AGA_MAXPLANES
  64. #define DEF_HAMPLANES   AGA_HAMPLANES
  65. #else
  66. #define DEF_MAXPLANES   ECS_MAXPLANES
  67. #define DEF_HAMPLANES   ECS_HAMPLANES
  68. #endif
  69. #define DEF_DCOLPLANES  5
  70. #define DEF_COMPRESSION cmpByteRun1
  71.  
  72.  
  73. typedef struct {
  74.     int             len;
  75.     unsigned char * row;
  76. } bodyrow;
  77. typedef struct {
  78.     long *thisrederr, *thisgreenerr, *thisblueerr;
  79.     long *nextrederr, *nextgreenerr, *nextblueerr;
  80.     int lefttoright;    /* 1 for left-to-right scan, 0 for right-to-left */
  81.     int cols;
  82.     pixel *pixrow;
  83.     pixval maxval;
  84.     int col, col_end;
  85.     int alternate;
  86.     pixval red, green, blue;    /* values of current pixel */
  87. } floydinfo;
  88.  
  89.  
  90. static int colorstobpp ARGS((int colors));
  91. #define put_fourchars(str)  (void)(fputs(str, stdout))
  92. static void put_big_short ARGS((short s));
  93. static void put_big_long ARGS((long l));
  94. #define put_byte(b)     (void)(putc((unsigned char)(b), stdout))
  95. static void ppm_to_ham ARGS((FILE *fp, int cols, int rows, int maxval, int hambits, int nocolor));
  96. static void ppm_to_24  ARGS((FILE *fp, int cols, int rows, int maxval));
  97. static void ppm_to_direct  ARGS((FILE *fp, int cols, int rows, int maxval, DirectColor *direct));
  98. static void ppm_to_std ARGS((FILE *fp, int cols, int rows, int maxval, colorhist_vector chv, int colors, int nPlanes));
  99. static void ppm_to_cmap ARGS((int maxval, colorhist_vector chv, int colors));
  100. static void write_form_ilbm ARGS((int size));
  101. static void write_bmhd ARGS((int cols, int rows, int nPlanes));
  102. static void write_std_cmap ARGS((colorhist_vector chv, int colors, int maxval));
  103. static int encode_row ARGS((FILE *outfile, rawtype *rawrow, int cols, int nPlanes));
  104. static int compress_row ARGS((int bytes));
  105. static int runbyte1 ARGS((int bytes));
  106. static pixel * next_pixrow ARGS((FILE *fp, int row));
  107. static pixval * make_val_table ARGS((pixval oldmaxval, pixval newmaxval));
  108. static void * xmalloc ARGS((int bytes));
  109. #define MALLOC(n, type)     (type *)xmalloc((n) * sizeof(type))
  110. static void init_read ARGS((FILE *fp, int *colsP, int *rowsP, pixval *maxvalP, int *formatP, int readall));
  111. static void write_body ARGS((void));
  112. static void write_camg ARGS((void));
  113. static void alloc_body_array ARGS((int rows, int nPlanes));
  114. static void free_body_array ARGS((void));
  115. #define PAD(n)      odd(n)  /* pad to a word */
  116. static int closest_color ARGS((colorhist_vector chv, int colors, pixval cmaxval, pixel *pP));
  117. static floydinfo *init_floyd ARGS((int cols, pixval maxval, int alternate));
  118. static void free_floyd ARGS((floydinfo *fi));
  119. static void begin_floyd_row ARGS((floydinfo *fi, pixel *prow));
  120. static pixel *next_floyd_pixel ARGS((floydinfo *fi));
  121. static void update_floyd_pixel ARGS((floydinfo *fi, int r, int g, int b));
  122. static void end_floyd_row ARGS((floydinfo *fi));
  123.  
  124. /* global data */
  125. static unsigned char *coded_rowbuf; /* buffer for uncompressed scanline */
  126. static unsigned char *compr_rowbuf; /* buffer for compressed scanline */
  127. static pixel **pixels;  /* PPM image (NULL for row-by-row operation) */
  128. static pixel *pixrow;   /* current row in PPM image (pointer into pixels array, or buffer for row-by-row operation) */
  129. static bodyrow *ilbm_body = NULL;   /* compressed ILBM BODY */
  130.  
  131. static long viewportmodes = 0;
  132. static int compr_type = DEF_COMPRESSION;
  133.  
  134. /* flags */
  135. static short savemem = 0;       /* slow operation, but uses less memory */
  136. static short compr_force = 0;   /* force compressed output, even if the image got larger  - NOT USED */
  137. static short floyd = 0;         /* apply floyd-steinberg error diffusion */
  138.  
  139. #define WORSTCOMPR(bytes)       ((bytes) + (bytes)/128 + 1)
  140. #define DO_COMPRESS             (compr_type != cmpNone)
  141. #define CAMGSIZE                (viewportmodes == 0 ? 0 : (4 + 4 + CAMGChunkSize))
  142.  
  143.  
  144.  
  145. /* Lookup tables for fast RGB -> luminance calculation. */
  146. /* taken from ppmtopgm.c   -IUW */
  147.  
  148. static int times77[256] = {
  149.             0,    77,   154,   231,   308,   385,   462,   539,
  150.           616,   693,   770,   847,   924,  1001,  1078,  1155,
  151.          1232,  1309,  1386,  1463,  1540,  1617,  1694,  1771,
  152.          1848,  1925,  2002,  2079,  2156,  2233,  2310,  2387,
  153.          2464,  2541,  2618,  2695,  2772,  2849,  2926,  3003,
  154.          3080,  3157,  3234,  3311,  3388,  3465,  3542,  3619,
  155.          3696,  3773,  3850,  3927,  4004,  4081,  4158,  4235,
  156.          4312,  4389,  4466,  4543,  4620,  4697,  4774,  4851,
  157.          4928,  5005,  5082,  5159,  5236,  5313,  5390,  5467,
  158.          5544,  5621,  5698,  5775,  5852,  5929,  6006,  6083,
  159.          6160,  6237,  6314,  6391,  6468,  6545,  6622,  6699,
  160.          6776,  6853,  6930,  7007,  7084,  7161,  7238,  7315,
  161.          7392,  7469,  7546,  7623,  7700,  7777,  7854,  7931,
  162.          8008,  8085,  8162,  8239,  8316,  8393,  8470,  8547,
  163.          8624,  8701,  8778,  8855,  8932,  9009,  9086,  9163,
  164.          9240,  9317,  9394,  9471,  9548,  9625,  9702,  9779,
  165.          9856,  9933, 10010, 10087, 10164, 10241, 10318, 10395,
  166.         10472, 10549, 10626, 10703, 10780, 10857, 10934, 11011,
  167.         11088, 11165, 11242, 11319, 11396, 11473, 11550, 11627,
  168.         11704, 11781, 11858, 11935, 12012, 12089, 12166, 12243,
  169.         12320, 12397, 12474, 12551, 12628, 12705, 12782, 12859,
  170.         12936, 13013, 13090, 13167, 13244, 13321, 13398, 13475,
  171.         13552, 13629, 13706, 13783, 13860, 13937, 14014, 14091,
  172.         14168, 14245, 14322, 14399, 14476, 14553, 14630, 14707,
  173.         14784, 14861, 14938, 15015, 15092, 15169, 15246, 15323,
  174.         15400, 15477, 15554, 15631, 15708, 15785, 15862, 15939,
  175.         16016, 16093, 16170, 16247, 16324, 16401, 16478, 16555,
  176.         16632, 16709, 16786, 16863, 16940, 17017, 17094, 17171,
  177.         17248, 17325, 17402, 17479, 17556, 17633, 17710, 17787,
  178.         17864, 17941, 18018, 18095, 18172, 18249, 18326, 18403,
  179.         18480, 18557, 18634, 18711, 18788, 18865, 18942, 19019,
  180.         19096, 19173, 19250, 19327, 19404, 19481, 19558, 19635 };
  181. static int times150[256] = {
  182.             0,   150,   300,   450,   600,   750,   900,  1050,
  183.          1200,  1350,  1500,  1650,  1800,  1950,  2100,  2250,
  184.          2400,  2550,  2700,  2850,  3000,  3150,  3300,  3450,
  185.          3600,  3750,  3900,  4050,  4200,  4350,  4500,  4650,
  186.          4800,  4950,  5100,  5250,  5400,  5550,  5700,  5850,
  187.          6000,  6150,  6300,  6450,  6600,  6750,  6900,  7050,
  188.          7200,  7350,  7500,  7650,  7800,  7950,  8100,  8250,
  189.          8400,  8550,  8700,  8850,  9000,  9150,  9300,  9450,
  190.          9600,  9750,  9900, 10050, 10200, 10350, 10500, 10650,
  191.         10800, 10950, 11100, 11250, 11400, 11550, 11700, 11850,
  192.         12000, 12150, 12300, 12450, 12600, 12750, 12900, 13050,
  193.         13200, 13350, 13500, 13650, 13800, 13950, 14100, 14250,
  194.         14400, 14550, 14700, 14850, 15000, 15150, 15300, 15450,
  195.         15600, 15750, 15900, 16050, 16200, 16350, 16500, 16650,
  196.         16800, 16950, 17100, 17250, 17400, 17550, 17700, 17850,
  197.         18000, 18150, 18300, 18450, 18600, 18750, 18900, 19050,
  198.         19200, 19350, 19500, 19650, 19800, 19950, 20100, 20250,
  199.         20400, 20550, 20700, 20850, 21000, 21150, 21300, 21450,
  200.         21600, 21750, 21900, 22050, 22200, 22350, 22500, 22650,
  201.         22800, 22950, 23100, 23250, 23400, 23550, 23700, 23850,
  202.         24000, 24150, 24300, 24450, 24600, 24750, 24900, 25050,
  203.         25200, 25350, 25500, 25650, 25800, 25950, 26100, 26250,
  204.         26400, 26550, 26700, 26850, 27000, 27150, 27300, 27450,
  205.         27600, 27750, 27900, 28050, 28200, 28350, 28500, 28650,
  206.         28800, 28950, 29100, 29250, 29400, 29550, 29700, 29850,
  207.         30000, 30150, 30300, 30450, 30600, 30750, 30900, 31050,
  208.         31200, 31350, 31500, 31650, 31800, 31950, 32100, 32250,
  209.         32400, 32550, 32700, 32850, 33000, 33150, 33300, 33450,
  210.         33600, 33750, 33900, 34050, 34200, 34350, 34500, 34650,
  211.         34800, 34950, 35100, 35250, 35400, 35550, 35700, 35850,
  212.         36000, 36150, 36300, 36450, 36600, 36750, 36900, 37050,
  213.         37200, 37350, 37500, 37650, 37800, 37950, 38100, 38250 };
  214. static int times29[256] = {
  215.             0,    29,    58,    87,   116,   145,   174,   203,
  216.           232,   261,   290,   319,   348,   377,   406,   435,
  217.           464,   493,   522,   551,   580,   609,   638,   667,
  218.           696,   725,   754,   783,   812,   841,   870,   899,
  219.           928,   957,   986,  1015,  1044,  1073,  1102,  1131,
  220.          1160,  1189,  1218,  1247,  1276,  1305,  1334,  1363,
  221.          1392,  1421,  1450,  1479,  1508,  1537,  1566,  1595,
  222.          1624,  1653,  1682,  1711,  1740,  1769,  1798,  1827,
  223.          1856,  1885,  1914,  1943,  1972,  2001,  2030,  2059,
  224.          2088,  2117,  2146,  2175,  2204,  2233,  2262,  2291,
  225.          2320,  2349,  2378,  2407,  2436,  2465,  2494,  2523,
  226.          2552,  2581,  2610,  2639,  2668,  2697,  2726,  2755,
  227.          2784,  2813,  2842,  2871,  2900,  2929,  2958,  2987,
  228.          3016,  3045,  3074,  3103,  3132,  3161,  3190,  3219,
  229.          3248,  3277,  3306,  3335,  3364,  3393,  3422,  3451,
  230.          3480,  3509,  3538,  3567,  3596,  3625,  3654,  3683,
  231.          3712,  3741,  3770,  3799,  3828,  3857,  3886,  3915,
  232.          3944,  3973,  4002,  4031,  4060,  4089,  4118,  4147,
  233.          4176,  4205,  4234,  4263,  4292,  4321,  4350,  4379,
  234.          4408,  4437,  4466,  4495,  4524,  4553,  4582,  4611,
  235.          4640,  4669,  4698,  4727,  4756,  4785,  4814,  4843,
  236.          4872,  4901,  4930,  4959,  4988,  5017,  5046,  5075,
  237.          5104,  5133,  5162,  5191,  5220,  5249,  5278,  5307,
  238.          5336,  5365,  5394,  5423,  5452,  5481,  5510,  5539,
  239.          5568,  5597,  5626,  5655,  5684,  5713,  5742,  5771,
  240.          5800,  5829,  5858,  5887,  5916,  5945,  5974,  6003,
  241.          6032,  6061,  6090,  6119,  6148,  6177,  6206,  6235,
  242.          6264,  6293,  6322,  6351,  6380,  6409,  6438,  6467,
  243.          6496,  6525,  6554,  6583,  6612,  6641,  6670,  6699,
  244.          6728,  6757,  6786,  6815,  6844,  6873,  6902,  6931,
  245.          6960,  6989,  7018,  7047,  7076,  7105,  7134,  7163,
  246.          7192,  7221,  7250,  7279,  7308,  7337,  7366,  7395 };
  247.  
  248.  
  249. /************ parse options and figure out what kind of ILBM to write ************/
  250.  
  251.  
  252. static int get_int_val ARGS((char *string, char *option, int bot, int top));
  253. static int get_compr_type ARGS((char *string));
  254. #define NEWDEPTH(pix, table)    PPM_ASSIGN((pix), (table)[PPM_GETR(pix)], (table)[PPM_GETG(pix)], (table)[PPM_GETB(pix)])
  255.  
  256.  
  257. int
  258. main(argc, argv)
  259.     int argc;
  260.     char *argv[];
  261. {
  262.     FILE *ifp;
  263.     int argn, rows, cols, format, colors, nPlanes;
  264.     int ifmode, forcemode, maxplanes, fixplanes, hambits, mode;
  265. #define MAXCOLORS       (1<<maxplanes)
  266.     pixval maxval;
  267.     colorhist_vector chv;
  268.     DirectColor dcol;
  269.     char *mapfile;
  270.     char *usage =
  271. "[-ecs|-aga] [-ham6|-ham8] [-maxplanes|-mp n] [-fixplanes|-fp n]\
  272.  [-normal|-hamif|-hamforce|-24if|-24force|-dcif|-dcforce|-cmaponly]\
  273.  [-hambits|-hamplanes n] [-dcbits|-dcplanes r g b] [-hires] [-lace]\
  274.  [-floyd|-fs] [-compress|-nocompress] [-cmethod none|byterun1]\
  275.  [-map ppmfile] [-savemem] [ppmfile]";
  276.  
  277.     ppm_init(&argc, argv);
  278.  
  279.     ifmode = MODE_NONE; forcemode = MODE_NONE;
  280.     maxplanes = DEF_MAXPLANES; fixplanes = 0;
  281.     hambits = DEF_HAMPLANES;
  282.     mapfile = NULL;
  283.     dcol.r = dcol.g = dcol.b = DEF_DCOLPLANES;
  284.  
  285.     argn = 1;
  286.     while( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) {
  287.         if( pm_keymatch(argv[argn], "-maxplanes", 4) || pm_keymatch(argv[argn], "-mp", 3) ) {
  288.             if( ++argn >= argc )
  289.                 pm_usage(usage);
  290.             maxplanes = get_int_val(argv[argn], argv[argn-1], 1, MAXPLANES);
  291.             fixplanes = 0;
  292.         }
  293.         else
  294.         if( pm_keymatch(argv[argn], "-fixplanes", 4) || pm_keymatch(argv[argn], "-fp", 3) ) {
  295.             if( ++argn >= argc )
  296.                 pm_usage(usage);
  297.             fixplanes = get_int_val(argv[argn], argv[argn-1], 1, MAXPLANES);
  298.             maxplanes = fixplanes;
  299.         }
  300.         else
  301.         if( pm_keymatch(argv[argn], "-map", 4) ) {
  302.             if( ++argn >= argc )
  303.                 pm_usage(usage);
  304.             mapfile = argv[argn];
  305.         }
  306.         else
  307.         if( pm_keymatch(argv[argn], "-cmaponly", 3) ) {
  308.             forcemode = MODE_CMAP;
  309.         }
  310.         else
  311.         if( pm_keymatch(argv[argn], "-hambits", 5) || pm_keymatch(argv[argn], "-hamplanes", 5) ) {
  312.             if( ++argn > argc )
  313.                 pm_usage(usage);
  314.             hambits = get_int_val(argv[argn], argv[argn-1], 3, MAXPLANES);
  315.         }
  316.         else
  317.         if( pm_keymatch(argv[argn], "-ham6", 5) ) {
  318.             hambits = ECS_HAMPLANES;
  319.             forcemode = MODE_HAM;
  320.         }
  321.         else
  322.         if( pm_keymatch(argv[argn], "-ham8", 5) ) {
  323.             hambits = AGA_HAMPLANES;
  324.             forcemode = MODE_HAM;
  325.         }
  326.         else
  327.         if( pm_keymatch(argv[argn], "-lace", 2) ) {
  328. #ifdef ILBM_PCHG
  329.             slicesize = 2;
  330. #endif
  331.             viewportmodes |= vmLACE;
  332.         }
  333.         else
  334.         if( pm_keymatch(argv[argn], "-nolace", 4) ) {
  335. #ifdef ILBM_PCHG
  336.             slicesize = 1;
  337. #endif
  338.             viewportmodes &= ~vmLACE;
  339.         }
  340.         else
  341.         if( pm_keymatch(argv[argn], "-hires", 3) )
  342.             viewportmodes |= vmHIRES;
  343.         else
  344.         if( pm_keymatch(argv[argn], "-nohires", 5) )
  345.             viewportmodes &= ~vmHIRES;
  346.         else
  347.         if( pm_keymatch(argv[argn], "-ecs", 2) ) {
  348.             maxplanes = ECS_MAXPLANES;
  349.             hambits = ECS_HAMPLANES;
  350.         }
  351.         else
  352.         if( pm_keymatch(argv[argn], "-aga", 2) ) {
  353.             maxplanes = AGA_MAXPLANES;
  354.             hambits = AGA_HAMPLANES;
  355.         }
  356.         else
  357.         if( pm_keymatch(argv[argn], "-hamif", 5) )
  358.             ifmode = MODE_HAM;
  359.         else
  360.         if( pm_keymatch(argv[argn], "-nohamif", 7) ) {
  361.             if( ifmode == MODE_HAM )
  362.                 ifmode = MODE_NONE;
  363.         }
  364.         else
  365.         if( pm_keymatch(argv[argn], "-hamforce", 5) )
  366.             forcemode = MODE_HAM;
  367.         else
  368.         if( pm_keymatch(argv[argn], "-nohamforce", 7) ) {
  369.             if( forcemode == MODE_HAM )
  370.                 forcemode = MODE_NONE;
  371.         }
  372.         else
  373.         if( pm_keymatch(argv[argn], "-24if", 4) )
  374.             ifmode = MODE_24;
  375.         else
  376.         if( pm_keymatch(argv[argn], "-no24if", 6) ) {
  377.             if( ifmode == MODE_24 )
  378.                 ifmode = MODE_NONE;
  379.         }
  380.         else
  381.         if( pm_keymatch(argv[argn], "-24force", 4) )
  382.             forcemode = MODE_24;
  383.         else
  384.         if( pm_keymatch(argv[argn], "-no24force", 6) ) {
  385.             if( forcemode == MODE_24 )
  386.                 forcemode = MODE_NONE;
  387.         }
  388.         else
  389.         if( pm_keymatch(argv[argn], "-dcif", 4) ) {
  390.             ifmode = MODE_DIRECT;
  391.         }
  392.         else
  393.         if( pm_keymatch(argv[argn], "-nodcif", 6) ) {
  394.             if( ifmode == MODE_DIRECT )
  395.                 ifmode = MODE_NONE;
  396.         }
  397.         else
  398.         if( pm_keymatch(argv[argn], "-dcforce", 4) ) {
  399.             forcemode = MODE_DIRECT;
  400.         }
  401.         else
  402.         if( pm_keymatch(argv[argn], "-nodcforce", 6) ) {
  403.             if( forcemode == MODE_DIRECT )
  404.                 forcemode = MODE_NONE;
  405.         }
  406.         else
  407.         if( pm_keymatch(argv[argn], "-dcbits", 4) || pm_keymatch(argv[argn], "-dcplanes", 4) ) {
  408.             char *option = argv[argn];
  409.  
  410.             if( ++argn >= argc )
  411.                 pm_usage(usage);
  412.             dcol.r = (unsigned char) get_int_val(argv[argn], option, 1, MAXPLANES);
  413.             if( ++argn >= argc )
  414.                 pm_usage(usage);
  415.             dcol.g = (unsigned char) get_int_val(argv[argn], option, 1, MAXPLANES);
  416.             if( ++argn >= argc )
  417.                 pm_usage(usage);
  418.             dcol.b = (unsigned char) get_int_val(argv[argn], option, 1, MAXPLANES);
  419.         }
  420.         else
  421.         if( pm_keymatch(argv[argn], "-normal", 4) ) {
  422.             ifmode = forcemode = MODE_NONE;
  423.             compr_type = DEF_COMPRESSION;
  424.         }
  425.         else
  426.         if( pm_keymatch(argv[argn], "-compress", 3) ) {
  427.             compr_force = 1;
  428.             if( compr_type == cmpNone )
  429.                 if( DEF_COMPRESSION == cmpNone )
  430.                     compr_type = cmpByteRun1;
  431.                 else
  432.                     compr_type = DEF_COMPRESSION;
  433.         }
  434.         else
  435.         if( pm_keymatch(argv[argn], "-nocompress", 4) ) {
  436.             compr_force = 0;
  437.             compr_type = cmpNone;
  438.         }
  439.         else
  440.         if( pm_keymatch(argv[argn], "-cmethod", 4) ) {
  441.             if( ++argn >= argc )
  442.                 pm_usage(usage);
  443.             compr_type = get_compr_type(argv[argn]);
  444.         }
  445.         else
  446.         if( pm_keymatch(argv[argn], "-savemem", 2) )
  447.             savemem = 1;
  448.         else
  449.         if( pm_keymatch(argv[argn], "-fs1", 4) )    /* EXPERIMENTAL */
  450.             floyd = 2;
  451.         else
  452.         if( pm_keymatch(argv[argn], "-floyd", 3) || pm_keymatch(argv[argn], "-fs", 3) )
  453.             floyd = 1;
  454.         else
  455.         if( pm_keymatch(argv[argn], "-nofloyd", 5) || pm_keymatch(argv[argn], "-nofs", 5) )
  456.             floyd = 0;
  457.         else
  458.             pm_usage(usage);
  459.         ++argn;
  460.     }
  461.  
  462.     if( argn < argc ) {
  463.         ifp = pm_openr(argv[argn]);
  464.         ++argn;
  465.     }
  466.     else
  467.         ifp = stdin;
  468.  
  469.     if( argn != argc )
  470.         pm_usage( usage );
  471.  
  472.     if( forcemode != MODE_NONE && mapfile != NULL )
  473.         pm_message("warning - mapfile only used for normal ILBMs");
  474.  
  475.     mode = forcemode;
  476.     switch( forcemode ) {
  477.         case MODE_HAM:
  478.             /* grayscale colormap for now - we don't need to read the whole
  479.                file into memory and can use row-by-row operation */
  480.             init_read(ifp, &cols, &rows, &maxval, &format, 0);
  481.             pm_message("hamforce option used - proceeding to write a HAM%d file", hambits);
  482.             break;
  483.         case MODE_24:
  484.             init_read(ifp, &cols, &rows, &maxval, &format, 0);
  485.             pm_message("24force option used - proceeding to write a 24bit file");
  486.             break;
  487.         case MODE_DIRECT:
  488.             init_read(ifp, &cols, &rows, &maxval, &format, 0);
  489.             pm_message("dcforce option used - proceeding to write a %d:%d:%d direct color file",
  490.                         dcol.r, dcol.g, dcol.b);
  491.             break;
  492.         case MODE_CMAP:
  493.             /* must read the whole file into memory */
  494.             init_read(ifp, &cols, &rows, &maxval, &format, 1);
  495.  
  496.             /* Figure out the colormap. */
  497.             pm_message("computing colormap...");
  498.             chv = ppm_computecolorhist(pixels, cols, rows, MAXCMAPCOLORS, &colors);
  499.             if( chv == (colorhist_vector)NULL )
  500.                 pm_error("too many colors - try doing a 'ppmquant %d'", MAXCMAPCOLORS);
  501.             pm_message("%d colors found", colors);
  502.             break;
  503.         default:
  504.             /* must read the whole file into memory */
  505.             init_read(ifp, &cols, &rows, &maxval, &format, 1);
  506.  
  507.             /* Figure out the colormap. */
  508.             if( mapfile ) {
  509.                 int mapcols, maprows, row, col;
  510.                 pixel **mappixels, *pP;
  511.                 pixval mapmaxval;
  512.                 FILE *mapfp;
  513.  
  514.                 pm_message("reading colormap file...");
  515.                 mapfp = pm_openr(mapfile);
  516.                 mappixels = ppm_readppm(mapfp, &mapcols, &maprows, &mapmaxval);
  517.                 pm_close(mapfp);
  518.                 if( mapcols == 0 || maprows == 0 )
  519.                     pm_error("null colormap??");
  520.  
  521.                 /* if the maxvals of the ppmfile and the mapfile are the same,
  522.                  * then the scaling to MAXCOLVAL (if necessary) will be done by
  523.                  * the write_std_cmap() function.
  524.                  * Otherwise scale them both to MAXCOLVAL.
  525.                  */
  526.                 if( maxval != mapmaxval ) {
  527.                     if( mapmaxval != MAXCOLVAL ) {
  528.                         pixval *table;
  529.                         pm_message("colormap maxval is not %d - rescaling colormap...", MAXCOLVAL);
  530.                         table = make_val_table(mapmaxval, MAXCOLVAL);
  531.                         for( row = 0; row < maprows; ++row )
  532.                             for( col = 0, pP = mappixels[row]; col < mapcols; ++col, ++pP )
  533.                                 NEWDEPTH(*pP, table);   /* was PPM_DEPTH( *pP, *pP, mapmaxval, MAXCOLVAL ); */
  534.                         mapmaxval = MAXCOLVAL;
  535.                         free(table);
  536.                     }
  537.  
  538.                     if( maxval != mapmaxval ) {
  539.                         pixval *table;
  540.                         pm_message("rescaling colors of picture...");
  541.                         table = make_val_table(maxval, mapmaxval);
  542.                         for( row = 0; row < rows; ++row )
  543.                             for( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
  544.                                 NEWDEPTH(*pP, table);   /* was PPM_DEPTH( *pP, *pP, maxval, mapmaxval ); */
  545.                         maxval = mapmaxval;
  546.                         free(table);
  547.                     }
  548.                 }
  549.  
  550.                 pm_message("computing colormap...");
  551.                 chv = ppm_computecolorhist(mappixels, mapcols, maprows, MAXCMAPCOLORS, &colors);
  552.                 ppm_freearray(mappixels, maprows);
  553.                 if( chv == (colorhist_vector)0 )
  554.                     pm_error("too many colors in colormap!");
  555.                 pm_message("%d colors found in colormap", colors);
  556.  
  557.                 nPlanes = fixplanes = maxplanes = colorstobpp(colors);
  558.             }
  559.             else {  /* no mapfile */
  560.                 pm_message("computing colormap...");
  561.                 chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors);
  562.                 if( chv == (colorhist_vector)0 ) {
  563.                     /* too many colors */
  564.                     mode = ifmode;
  565.                     switch( ifmode ) {
  566.                         case MODE_HAM:
  567.                             pm_message("too many colors - proceeding to write a HAM%d file", hambits);
  568.                             pm_message("if you want a non-HAM file, try doing a 'ppmquant %d'", MAXCOLORS);
  569.                             break;
  570.                         case MODE_24:
  571.                             pm_message("too many colors - proceeding to write a 24bit file" );
  572.                             pm_message("if you want a non-24bit file, try doing a 'ppmquant %d'", MAXCOLORS);
  573.                             break;
  574.                         case MODE_DIRECT:
  575.                             pm_message("too many colors - proceeding to write a %d:%d:%d direct color file",
  576.                                         dcol.r, dcol.g, dcol.b);
  577.                             pm_message("if you want a non-direct-color file, try doing a 'ppmquant %d'", MAXCOLORS);
  578.                             break;
  579.                         default:
  580.                             pm_message( "too many colors for %d planes", maxplanes );
  581.                             pm_message( "either use -hamif/-hamforce/-24if/-24force/-dcif/-dcforce/-maxplanes,");
  582.                             pm_error( "or try doing a 'ppmquant %d'", MAXCOLORS );
  583.                             break;
  584.                     }
  585.                 }
  586.                 else {
  587.                     pm_message("%d colors found", colors);
  588.                     nPlanes = colorstobpp(colors);
  589.                     if( fixplanes > nPlanes )
  590.                         nPlanes = fixplanes;
  591.                 }
  592.             }
  593.             break;
  594.     }
  595.  
  596.     if( mode != MODE_CMAP ) {
  597.         register int i;
  598.         coded_rowbuf = MALLOC(RowBytes(cols), unsigned char);
  599.         for( i = 0; i < RowBytes(cols); i++ )
  600.             coded_rowbuf[i] = 0;
  601.         if( DO_COMPRESS )
  602.             compr_rowbuf = MALLOC(WORSTCOMPR(RowBytes(cols)), unsigned char);
  603.     }
  604.  
  605.     switch( mode ) {
  606.         case MODE_HAM: {
  607.             int nocolor;
  608.  
  609.             nocolor = !(PPM_FORMAT_TYPE(format) == PPM_TYPE);
  610.             if( nocolor )
  611.                 floyd = 0;
  612.  
  613.             viewportmodes |= vmHAM;
  614.             ppm_to_ham(ifp, cols, rows, maxval, hambits, nocolor);
  615.             }
  616.             break;
  617.         case MODE_24:
  618.             ppm_to_24(ifp, cols, rows, maxval);
  619.             break;
  620.         case MODE_DIRECT:
  621.             ppm_to_direct(ifp, cols, rows, maxval, &dcol);
  622.             break;
  623.         case MODE_CMAP:
  624.             ppm_to_cmap(maxval, chv, colors);
  625.             break;
  626.         default:
  627.             if( mapfile == NULL )
  628.                 floyd = 0;          /* would only slow down conversion */
  629.             ppm_to_std(ifp, cols, rows, maxval, chv, colors, nPlanes);
  630.             break;
  631.     }
  632.     pm_close(ifp);
  633.     exit(0);
  634.     /*NOTREACHED*/
  635. }
  636.  
  637.  
  638. static int
  639. get_int_val(string, option, bot, top)
  640.     char *string, *option;
  641.     int bot, top;
  642. {
  643.     int val;
  644.  
  645.     if( sscanf(string, "%d", &val) != 1 )
  646.         pm_error("option \"%s\" needs integer argument", option);
  647.  
  648.     if( val < bot || val > top )
  649.         pm_error("option \"%s\" argument value out of range (%d..%d)", option, bot, top);
  650.  
  651.     return val;
  652. }
  653.  
  654.  
  655. static int
  656. get_compr_type(string)
  657.     char *string;
  658. {
  659.     int i;
  660.  
  661.     for( i = 0; i <= cmpMAXKNOWN; i++ ) {
  662.         if( strcmp(string, cmpNAME[i]) == 0 )
  663.             return i;
  664.     }
  665.     pm_message("unknown compression method: %s", string);
  666.     pm_message("using default compression (%s)", cmpNAME[DEF_COMPRESSION]);
  667.     return DEF_COMPRESSION;
  668. }
  669.  
  670.  
  671. /************ colormap file ************/
  672.  
  673. static void
  674. ppm_to_cmap(maxval, chv, colors)
  675.     int maxval;
  676.     colorhist_vector chv;
  677.     int colors;
  678. {
  679.     int formsize, cmapsize;
  680.  
  681.     cmapsize = colors * 3;
  682.  
  683.     formsize =
  684.         4 +                                 /* ILBM */
  685.         4 + 4 + BitMapHeaderSize +          /* BMHD size header */
  686.         4 + 4 + cmapsize + PAD(cmapsize);   /* CMAP size colormap */
  687.  
  688.     write_form_ilbm(formsize);
  689.     write_bmhd(0, 0, 0);
  690.     write_std_cmap(chv, colors, maxval);
  691. }
  692.  
  693. /************ HAM ************/
  694.  
  695. static long do_ham_body     ARGS((FILE *ifp, FILE *ofp, int cols, int rows, pixval maxval, pixval hammaxval, int nPlanes, int colbits, int no));
  696.  
  697. static void
  698. ppm_to_ham(fp, cols, rows, maxval, hambits, nocolor)
  699.     FILE *fp;
  700.     int cols, rows, maxval, hambits, nocolor;
  701. {
  702.     int colors, colbits, nPlanes, i, hammaxval;
  703.     long oldsize, bodysize, formsize, cmapsize;
  704.     pixval *table = NULL;
  705.  
  706.     colbits = hambits-2;
  707.     colors = 1 << colbits;
  708.     hammaxval = pm_bitstomaxval(colbits);
  709.     nPlanes = hambits;
  710.     cmapsize = colors * 3;
  711.  
  712.     bodysize = oldsize = rows * nPlanes * RowBytes(cols);
  713.     if( DO_COMPRESS ) {
  714.         alloc_body_array(rows, nPlanes);
  715.         bodysize = do_ham_body(fp, NULL, cols, rows, maxval, hammaxval, nPlanes, colbits, nocolor);
  716.         if( bodysize > oldsize )
  717.             pm_message("warning - %s compression increases BODY size by %d%%", cmpNAME[compr_type], 100*(bodysize-oldsize)/oldsize);
  718.         else
  719.             pm_message("BODY compression (%s): %d%%", cmpNAME[compr_type], 100*(oldsize-bodysize)/oldsize);
  720. #if 0
  721.         if( bodysize > oldsize && !compr_force ) {
  722.             pm_message("%s compression would increase body size by %d%%", cmpNAME[compr_type], 100*(bodysize-oldsize)/oldsize);
  723.             pm_message("writing uncompressed image");
  724.             free_body_array();
  725.             compr_type = cmpNone;
  726.             bodysize = oldsize;
  727.         }
  728. #endif
  729.     }
  730.  
  731.  
  732.     formsize =
  733.         4 +                                 /* ILBM */
  734.         4 + 4 + BitMapHeaderSize +          /* BMHD size header */
  735.         CAMGSIZE +                          /* 0 or CAMG size val */
  736.         4 + 4 + cmapsize + PAD(cmapsize) +  /* CMAP size colormap */
  737.         4 + 4 + bodysize + PAD(bodysize);   /* BODY size data */
  738.  
  739.     write_form_ilbm(formsize);
  740.     write_bmhd(cols, rows, nPlanes);
  741.     write_camg();
  742.  
  743.     /* write grayscale colormap */
  744.     put_fourchars("CMAP");
  745.     put_big_long(cmapsize);
  746.     table = make_val_table(hammaxval, MAXCOLVAL);
  747.     for( i = 0; i < colors; i++ ) {
  748.         put_byte( table[i] );   /* red */
  749.         put_byte( table[i] );   /* green */
  750.         put_byte( table[i] );   /* blue */
  751.     }
  752.     free(table);
  753.     if( odd(cmapsize) )
  754.         put_byte(0);
  755.  
  756.     /* write body */
  757.     put_fourchars("BODY");
  758.     put_big_long(bodysize);
  759.     if( DO_COMPRESS )
  760.         write_body();
  761.     else
  762.         do_ham_body(fp, stdout, cols, rows, maxval, hammaxval, nPlanes, colbits, nocolor);
  763.     if( odd(bodysize) )
  764.         put_byte(0);
  765. }
  766.  
  767.  
  768. static long
  769. do_ham_body(ifp, ofp, cols, rows, maxval, hammaxval, nPlanes, colbits, nocolor)
  770.     FILE *ifp, *ofp;
  771.     int cols, rows;
  772.     pixval maxval, hammaxval;
  773.     int nPlanes, colbits, nocolor;
  774. {
  775.     register int col, row;
  776.     pixel *pP;
  777.     pixval *table = NULL;
  778.     rawtype *raw_rowbuf;
  779.     floydinfo *fi;
  780.     long bodysize = 0;
  781.  
  782.     raw_rowbuf = MALLOC(cols, rawtype);
  783.  
  784.     if( hammaxval != maxval )
  785.         table = make_val_table(maxval, hammaxval);
  786.  
  787.     if( floyd ) {
  788.         fi = init_floyd(cols, maxval, 0);
  789.     }
  790.  
  791.     for( row = 0; row < rows; row++ ) {
  792.         register int noprev, pr, pg, pb, r, g, b, l;
  793.         int fpr, fpg, fpb;      /* unscaled previous color values, for floyd */
  794.  
  795.         pP = next_pixrow(ifp, row);
  796.         if( floyd )
  797.             begin_floyd_row(fi, pP);
  798.  
  799.         noprev = 1;
  800.         for( col = 0; col < cols; col++, pP++ ) {
  801.             int fr, fg, fb, fl;     /* unscaled color values, for floyd */
  802.             if( floyd )
  803.                 pP = next_floyd_pixel(fi);
  804.  
  805.             r = fr = PPM_GETR( *pP );
  806.             g = fg = PPM_GETG( *pP );
  807.             b = fb = PPM_GETB( *pP );
  808.             if( maxval <= 255 ) /* Use fast approximation to 0.299 r + 0.587 g + 0.114 b. */
  809.                 l = fl = (int)((times77[r] + times150[g] + times29[b] + 128) >> 8);
  810.             else /* Can't use fast approximation, so fall back on floats. */
  811.                 l = fl = (int)(PPM_LUMIN(*pP) + 0.5); /* -IUW added '+ 0.5' */
  812.  
  813.             if( table ) {
  814.                 r = table[r];
  815.                 g = table[g];
  816.                 b = table[b];
  817.                 l = table[l];
  818.             }
  819.  
  820.             if( noprev || nocolor ) {
  821.                 /* No previous pixels, gotta use the gray option. */
  822.                 raw_rowbuf[col] = l /* + (HAMCODE_CMAP << colbits) */;
  823.                 pr = pg = pb = l;
  824.                 fpr = fpg = fpb = fl;
  825.                 noprev = 0;
  826.             }
  827.             else {
  828.                 register int dred, dgreen, dblue, dgray;
  829.                 /* Compute distances for the four options. */
  830.                 dred = abs( g - pg ) + abs( b - pb );
  831.                 dgreen = abs( r - pr ) + abs( b - pb );
  832.                 dblue = abs( r - pr ) + abs( g - pg );
  833.                 dgray = abs( r - l ) + abs( g - l ) + abs( b - l );
  834.  
  835.                 /* simply doing  raw_rowbuf[col] = ...
  836.                  * is ok here because there is no fs-alternation performed
  837.                  * for HAM.  Otherwise we would have to do
  838.                  *     if( floyd )  raw_rowbuf[fi->col] = ...
  839.                  *     else         raw_rowbuf[col] = ...
  840.                  */
  841.                 if( dgray <= dred && dgray <= dgreen && dgray <= dblue ) {      /* -IUW  '<=' was '<'  */
  842.                     raw_rowbuf[col] = l /* + (HAMCODE_CMAP << colbits) */;
  843.                     pr = pg = pb = l;
  844.                     fpr = fpg = fpb = fl;
  845.                 }
  846.                 else
  847.                 if( dblue <= dred && dblue <= dgreen ) {
  848.                     raw_rowbuf[col] = b + (HAMCODE_BLUE << colbits);
  849.                     pb = b;
  850.                     fpb = fb;
  851.                 }
  852.                 else
  853.                 if( dred <= dgreen ) {
  854.                     raw_rowbuf[col] = r + (HAMCODE_RED << colbits);
  855.                     pr = r;
  856.                     fpr = fr;
  857.                 }
  858.                 else {
  859.                     raw_rowbuf[col] = g + (HAMCODE_GREEN << colbits);
  860.                     pg = g;
  861.                     fpg = fg;
  862.                 }
  863.             }
  864.             if( floyd )
  865.                 update_floyd_pixel(fi, fpr, fpg, fpb);
  866.         }
  867.         bodysize += encode_row(ofp, raw_rowbuf, cols, nPlanes);
  868.         if( floyd )
  869.             end_floyd_row(fi);
  870.     }
  871.     /* clean up */
  872.     if( table )
  873.         free(table);
  874.     free(raw_rowbuf);
  875.     if( floyd )
  876.         free_floyd(fi);
  877.  
  878.     return bodysize;
  879. }
  880.  
  881. /************ 24bit ************/
  882.  
  883. static long do_24_body      ARGS((FILE *ifp, FILE *ofp, int cols, int rows, pixval maxval));
  884.  
  885. static void
  886. ppm_to_24(fp, cols, rows, maxval)
  887.     FILE *fp;
  888.     int cols, rows, maxval;
  889. {
  890.     int nPlanes;
  891.     long bodysize, oldsize, formsize;
  892.  
  893.     nPlanes = 24;
  894.  
  895.     bodysize = oldsize = rows * nPlanes * RowBytes(cols);
  896.     if( DO_COMPRESS ) {
  897.         alloc_body_array(rows, nPlanes);
  898.         bodysize = do_24_body(fp, NULL, cols, rows, maxval);
  899.         if( bodysize > oldsize )
  900.             pm_message("warning - %s compression increases BODY size by %d%%", cmpNAME[compr_type], 100*(bodysize-oldsize)/oldsize);
  901.         else
  902.             pm_message("BODY compression (%s): %d%%", cmpNAME[compr_type], 100*(oldsize-bodysize)/oldsize);
  903. #if 0
  904.         if( bodysize > oldsize && !compr_force ) {
  905.             pm_message("%s compression would increase body size by %d%%", cmpNAME[compr_type], 100*(bodysize-oldsize)/oldsize);
  906.             pm_message("writing uncompressed image");
  907.             free_body_array();
  908.             compr_type = cmpNone;
  909.             bodysize = oldsize;
  910.         }
  911. #endif
  912.     }
  913.  
  914.  
  915.     formsize =
  916.         4 +                                 /* ILBM */
  917.         4 + 4 + BitMapHeaderSize +          /* BMHD size header */
  918.         CAMGSIZE +                          /* 0 or CAMG size val */
  919.         4 + 4 + bodysize + PAD(bodysize);   /* BODY size data */
  920.  
  921.     write_form_ilbm(formsize);
  922.     write_bmhd(cols, rows, nPlanes);
  923.     write_camg();
  924.  
  925.     /* write body */
  926.     put_fourchars("BODY");
  927.     put_big_long(bodysize);
  928.     if( DO_COMPRESS )
  929.         write_body();
  930.     else
  931.         do_24_body(fp, stdout, cols, rows, maxval);
  932.     if( odd(bodysize) )
  933.         put_byte(0);
  934. }
  935.  
  936.  
  937. static long
  938. do_24_body(ifp, ofp, cols, rows, maxval)
  939.     FILE *ifp, *ofp;
  940.     int cols, rows;
  941.     pixval maxval;
  942. {
  943.     register int row, col;
  944.     pixel *pP;
  945.     pixval *table = NULL;
  946.     long bodysize = 0;
  947.     rawtype *redbuf, *greenbuf, *bluebuf;
  948.  
  949.     redbuf   = MALLOC(cols, rawtype);
  950.     greenbuf = MALLOC(cols, rawtype);
  951.     bluebuf  = MALLOC(cols, rawtype);
  952.  
  953.     if( maxval != MAXCOLVAL ) {
  954.         pm_message("maxval is not %d - automatically rescaling colors", MAXCOLVAL);
  955.         table = make_val_table(maxval, MAXCOLVAL);
  956.     }
  957.  
  958.     for( row = 0; row < rows; row++ ) {
  959.         pP = next_pixrow(ifp, row);
  960.         if( table ) {
  961.             for( col = 0; col < cols; col++, pP++ ) {
  962.                 redbuf[col]     = table[PPM_GETR(*pP)];
  963.                 greenbuf[col]   = table[PPM_GETG(*pP)];
  964.                 bluebuf[col]    = table[PPM_GETB(*pP)];
  965.             }
  966.         }
  967.         else {
  968.             for( col = 0; col < cols; col++, pP++ ) {
  969.                 redbuf[col]     = PPM_GETR(*pP);
  970.                 greenbuf[col]   = PPM_GETG(*pP);
  971.                 bluebuf[col]    = PPM_GETB(*pP);
  972.             }
  973.         }
  974.         bodysize += encode_row(ofp, redbuf,   cols, 8);
  975.         bodysize += encode_row(ofp, greenbuf, cols, 8);
  976.         bodysize += encode_row(ofp, bluebuf,  cols, 8);
  977.     }
  978.     /* clean up */
  979.     if( table )
  980.         free(table);
  981.     free(redbuf);
  982.     free(greenbuf);
  983.     free(bluebuf);
  984.  
  985.     return bodysize;
  986. }
  987.  
  988.  
  989. /************ direct color ************/
  990.  
  991. static long do_direct_body  ARGS((FILE *ifp, FILE *ofp, int cols, int rows, pixval maxval, DirectColor *dcol));
  992.  
  993. static void
  994. ppm_to_direct(fp, cols, rows, maxval, dcol)
  995.     FILE *fp;
  996.     int cols, rows, maxval;
  997.     DirectColor *dcol;
  998. {
  999.     int nPlanes;
  1000.     long formsize, bodysize, oldsize;
  1001.  
  1002.     nPlanes = dcol->r + dcol->g + dcol->b;
  1003.  
  1004.     bodysize = oldsize = rows * nPlanes * RowBytes(cols);
  1005.     if( DO_COMPRESS ) {
  1006.         alloc_body_array(rows, nPlanes);
  1007.         bodysize = do_direct_body(fp, NULL, cols, rows, maxval, dcol);
  1008.         if( bodysize > oldsize )
  1009.             pm_message("warning - %s compression increases BODY size by %d%%", cmpNAME[compr_type], 100*(bodysize-oldsize)/oldsize);
  1010.         else
  1011.             pm_message("BODY compression (%s): %d%%", cmpNAME[compr_type], 100*(oldsize-bodysize)/oldsize);
  1012. #if 0
  1013.         if( bodysize > oldsize && !compr_force ) {
  1014.             pm_message("%s compression would increase body size by %d%%", cmpNAME[compr_type], 100*(bodysize-oldsize)/oldsize);
  1015.             pm_message("writing uncompressed image");
  1016.             free_body_array();
  1017.             compr_type = cmpNone;
  1018.             bodysize = oldsize;
  1019.         }
  1020. #endif
  1021.     }
  1022.  
  1023.     formsize =
  1024.         4 +                                 /* ILBM */
  1025.         4 + 4 + BitMapHeaderSize +          /* BMHD size header */
  1026.         CAMGSIZE +                          /* 0 or CAMG size val */
  1027.         4 + 4 + DirectColorSize +           /* DCOL size description */
  1028.         4 + 4 + bodysize + PAD(bodysize);   /* BODY size data */
  1029.  
  1030.     write_form_ilbm(formsize);
  1031.     write_bmhd(cols, rows, nPlanes);
  1032.     write_camg();
  1033.  
  1034.     /* write DCOL */
  1035.     put_fourchars("DCOL");
  1036.     put_big_long(DirectColorSize);
  1037.     put_byte(dcol->r);
  1038.     put_byte(dcol->g);
  1039.     put_byte(dcol->b);
  1040.     put_byte(0);    /* pad */
  1041.  
  1042.     /* write body */
  1043.     put_fourchars("BODY");
  1044.     put_big_long(bodysize);
  1045.     if( DO_COMPRESS )
  1046.         write_body();
  1047.     else
  1048.         do_direct_body(fp, stdout, cols, rows, maxval, dcol);
  1049.     if( odd(bodysize) )
  1050.         put_byte(0);
  1051. }
  1052.  
  1053.  
  1054. static long
  1055. do_direct_body(ifp, ofp, cols, rows, maxval, dcol)
  1056.     FILE *ifp, *ofp;
  1057.     int cols, rows;
  1058.     pixval maxval;
  1059.     DirectColor *dcol;
  1060. {
  1061.     register int row, col;
  1062.     pixel *pP;
  1063.     pixval *redtable = NULL, *greentable = NULL, *bluetable = NULL;
  1064.     pixval redmaxval, greenmaxval, bluemaxval;
  1065.     rawtype *redbuf, *greenbuf, *bluebuf;
  1066.     long bodysize = 0;
  1067.  
  1068.     redbuf   = MALLOC(cols, rawtype);
  1069.     greenbuf = MALLOC(cols, rawtype);
  1070.     bluebuf  = MALLOC(cols, rawtype);
  1071.  
  1072.     redmaxval   = pm_bitstomaxval(dcol->r);
  1073.     if( redmaxval != maxval ) {
  1074.         pm_message("rescaling reds to %d bits", dcol->r);
  1075.         redtable = make_val_table(maxval, redmaxval);
  1076.     }
  1077.     greenmaxval = pm_bitstomaxval(dcol->g);
  1078.     if( greenmaxval != maxval ) {
  1079.         pm_message("rescaling greens to %d bits", dcol->g);
  1080.         greentable = make_val_table(maxval, greenmaxval);
  1081.     }
  1082.     bluemaxval  = pm_bitstomaxval(dcol->b);
  1083.     if( bluemaxval != maxval ) {
  1084.         pm_message("rescaling blues to %d bits", dcol->b);
  1085.         bluetable = make_val_table(maxval, bluemaxval);
  1086.     }
  1087.  
  1088.     for( row = 0; row < rows; row++ ) {
  1089.         pP = next_pixrow(ifp, row);
  1090.         for( col = 0; col < cols; col++, pP++ ) {
  1091.             register pixval r, g, b;
  1092.  
  1093.             r = PPM_GETR(*pP); if( redtable ) r = redtable[r];
  1094.             g = PPM_GETG(*pP); if( greentable ) g = greentable[g];
  1095.             b = PPM_GETB(*pP); if( bluetable ) b = bluetable[b];
  1096.  
  1097.             redbuf[col] = r;
  1098.             greenbuf[col] = g;
  1099.             bluebuf[col] = b;
  1100.         }
  1101.         bodysize += encode_row(ofp, redbuf,   cols, dcol->r);
  1102.         bodysize += encode_row(ofp, greenbuf, cols, dcol->g);
  1103.         bodysize += encode_row(ofp, bluebuf,  cols, dcol->b);
  1104.     }
  1105.     /* clean up */
  1106.     if( redtable )
  1107.         free(redtable);
  1108.     if( greentable )
  1109.         free(greentable);
  1110.     if( bluetable )
  1111.         free(bluetable);
  1112.     free(redbuf);
  1113.     free(greenbuf);
  1114.     free(bluebuf);
  1115.  
  1116.     return bodysize;
  1117. }
  1118.  
  1119.  
  1120. /************ normal colormapped ************/
  1121.  
  1122. static long do_std_body     ARGS((FILE *ifp, FILE *ofp, int cols, int rows, pixval maxval, colorhist_vector chv, int colors, int nPlanes));
  1123.  
  1124. static void
  1125. ppm_to_std(fp, cols, rows, maxval, chv, colors, nPlanes)
  1126.     FILE *fp;
  1127.     int cols, rows, maxval;
  1128.     colorhist_vector chv;
  1129.     int colors, nPlanes;
  1130. {
  1131.     long formsize, cmapsize, bodysize, oldsize;
  1132.  
  1133.     bodysize = oldsize = rows * nPlanes * RowBytes(cols);
  1134.     if( DO_COMPRESS ) {
  1135.         alloc_body_array(rows, nPlanes);
  1136.         bodysize = do_std_body(fp, NULL, cols, rows, maxval, chv, colors, nPlanes);
  1137.         if( bodysize > oldsize )
  1138.             pm_message("warning - %s compression increases BODY size by %d%%", cmpNAME[compr_type], 100*(bodysize-oldsize)/oldsize);
  1139.         else
  1140.             pm_message("BODY compression (%s): %d%%", cmpNAME[compr_type], 100*(oldsize-bodysize)/oldsize);
  1141. #if 0
  1142.         if( bodysize > oldsize && !compr_force ) {
  1143.             pm_message("%s compression would increase body size by %d%%", cmpNAME[compr_type], 100*(bodysize-oldsize)/oldsize);
  1144.             pm_message("writing uncompressed image");
  1145.             free_body_array();
  1146.             compr_type = cmpNone;
  1147.             bodysize = oldsize;
  1148.         }
  1149. #endif
  1150.     }
  1151.  
  1152.     cmapsize = colors * 3;
  1153.  
  1154.     formsize =
  1155.         4 +                                 /* ILBM */
  1156.         4 + 4 + BitMapHeaderSize +          /* BMHD size header */
  1157.         CAMGSIZE +                          /* 0 or CAMG size val */
  1158.         4 + 4 + cmapsize + PAD(cmapsize) +  /* CMAP size colormap */
  1159.         4 + 4 + bodysize + PAD(bodysize);   /* BODY size data */
  1160.  
  1161.     write_form_ilbm(formsize);
  1162.     write_bmhd(cols, rows, nPlanes);
  1163.     write_camg();
  1164.     write_std_cmap(chv, colors, maxval);
  1165.  
  1166.     /* write body */
  1167.     put_fourchars("BODY");
  1168.     put_big_long(bodysize);
  1169.     if( DO_COMPRESS )
  1170.         write_body();
  1171.     else
  1172.         do_std_body(fp, stdout, cols, rows, maxval, chv, colors, nPlanes);
  1173.     if( odd(bodysize) )
  1174.         put_byte(0);
  1175. }
  1176.  
  1177.  
  1178. static long
  1179. do_std_body(ifp, ofp, cols, rows, maxval, chv, colors, nPlanes)
  1180.     FILE *ifp, *ofp;
  1181.     int cols, rows;
  1182.     pixval maxval;
  1183.     colorhist_vector chv;
  1184.     int colors, nPlanes;
  1185. {
  1186.     colorhash_table cht;
  1187.     register int row, col;
  1188.     pixel *pP;
  1189.     rawtype *raw_rowbuf;
  1190.     floydinfo *fi;
  1191.     long bodysize = 0;
  1192.     short usehash = !savemem;
  1193.  
  1194.     raw_rowbuf = MALLOC(cols, rawtype);
  1195.  
  1196.     /* Make a hash table for fast color lookup. */
  1197.     cht = ppm_colorhisttocolorhash(chv, colors);
  1198.  
  1199.     if( floyd )
  1200.         fi = init_floyd(cols, maxval, 1);
  1201.  
  1202.     for( row = 0; row < rows; row++ ) {
  1203.         pP = next_pixrow(ifp, row);
  1204.         if( floyd )
  1205.             begin_floyd_row(fi, pP);
  1206.  
  1207.         for( col = 0; col < cols; col++, pP++ ) {
  1208.             int ind;
  1209.  
  1210.             if( floyd )
  1211.                 pP = next_floyd_pixel(fi);
  1212.  
  1213.             /* Check hash table to see if we have already matched this color. */
  1214.             ind = ppm_lookupcolor(cht, pP);
  1215.             if( ind == -1 ) {
  1216.                 ind = closest_color(chv, colors, maxval, pP);   /* No; search colormap for closest match. */
  1217.                 if( usehash ) {
  1218.                     if( ppm_addtocolorhash(cht, pP, ind) < 0 ) {
  1219.                         pm_message("out of memory adding to hash table, proceeding without it");
  1220.                         usehash = 0;
  1221.                     }
  1222.                 }
  1223.             }
  1224.             if( floyd ) {
  1225.                 raw_rowbuf[fi->col] = ind;
  1226.                 update_floyd_pixel(fi, (int)PPM_GETR(chv[ind].color), (int)PPM_GETG(chv[ind].color), (int)PPM_GETB(chv[ind].color));
  1227.             }
  1228.             else
  1229.                 raw_rowbuf[col] = ind;
  1230.         }
  1231.         if( floyd )
  1232.             end_floyd_row(fi);
  1233.         bodysize += encode_row(ofp, raw_rowbuf, cols, nPlanes);
  1234.     }
  1235.     /* clean up */
  1236.     free(raw_rowbuf);
  1237.     ppm_freecolorhash(cht);
  1238.     if( floyd )
  1239.         free_floyd(fi);
  1240.  
  1241.     return bodysize;
  1242. }
  1243.  
  1244. /************ multipalette ************/
  1245.  
  1246. #ifdef ILBM_PCHG
  1247. static pixel *ppmslice[2];  /* need 2 for laced ILBMs, else 1 */
  1248.  
  1249. void ppm_to_pchg()
  1250. {
  1251. /*
  1252.     read first slice
  1253.     build a colormap from this slice
  1254.     select upto <maxcolors> colors
  1255.     build colormap from selected colors
  1256.     map slice to colormap
  1257.     write slice
  1258.     while( !finished ) {
  1259.         read next slice
  1260.         compute distances for each pixel and select upto
  1261.             <maxchangesperslice> unused colors in this slice
  1262.         modify selected colors to the ones with maximum(?) distance
  1263.         map slice to colormap
  1264.         write slice
  1265.     }
  1266.  
  1267.  
  1268.     for HAM use a different mapping:
  1269.         compute distance to closest color in colormap
  1270.         if( there is no matching color in colormap ) {
  1271.             compute distances for the three "modify" cases
  1272.             use the shortest distance from the four cases
  1273.         }
  1274. */
  1275. }
  1276. #endif
  1277.  
  1278. /************ ILBM functions ************/
  1279.  
  1280. static void
  1281. write_std_cmap(chv, colors, maxval)
  1282.     colorhist_vector chv;
  1283.     int colors, maxval;
  1284. {
  1285.     int cmapsize, i;
  1286.  
  1287.     cmapsize = 3 * colors;
  1288.  
  1289.     /* write colormap */
  1290.     put_fourchars("CMAP");
  1291.     put_big_long(cmapsize);
  1292.     if( maxval != MAXCOLVAL ) {
  1293.         pixval *table;
  1294.         pm_message("maxval is not %d - automatically rescaling colors", MAXCOLVAL);
  1295.         table = make_val_table(maxval, MAXCOLVAL);
  1296.         for( i = 0; i < colors; i++ ) {
  1297.             put_byte(table[PPM_GETR(chv[i].color)]);
  1298.             put_byte(table[PPM_GETG(chv[i].color)]);
  1299.             put_byte(table[PPM_GETB(chv[i].color)]);
  1300.         }
  1301.         free(table);
  1302.     }
  1303.     else {
  1304.         for( i = 0; i < colors; i++ ) {
  1305.             put_byte(PPM_GETR(chv[i].color));
  1306.             put_byte(PPM_GETG(chv[i].color));
  1307.             put_byte(PPM_GETB(chv[i].color));
  1308.         }
  1309.     }
  1310.     if( odd(cmapsize) )
  1311.         put_byte(0);
  1312. }
  1313.  
  1314.  
  1315. static void
  1316. write_form_ilbm(size)
  1317.     int size;
  1318. {
  1319.     put_fourchars("FORM");
  1320.     put_big_long(size);
  1321.     put_fourchars("ILBM");
  1322. }
  1323.  
  1324.  
  1325. static void
  1326. write_bmhd(cols, rows, nPlanes)
  1327.     int cols, rows, nPlanes;
  1328. {
  1329.     unsigned int xasp = 10, yasp = 10;
  1330.  
  1331.     if( viewportmodes & vmLACE )
  1332.         xasp *= 2;
  1333.     if( viewportmodes & vmHIRES )
  1334.         yasp *= 2;
  1335.  
  1336.     put_fourchars("BMHD");
  1337.     put_big_long(BitMapHeaderSize);
  1338.  
  1339.     put_big_short(cols);
  1340.     put_big_short(rows);
  1341.     put_big_short(0);                       /* x-offset */
  1342.     put_big_short(0);                       /* y-offset */
  1343.     put_byte(nPlanes);                      /* no of planes */
  1344.     put_byte(mskNone);                      /* masking type */
  1345.     put_byte((unsigned char)compr_type);    /* compression type */
  1346.     put_byte(0);                            /* pad1 */
  1347.     put_big_short(0);                       /* tranparentColor */
  1348.     put_byte(xasp);                         /* x-aspect */
  1349.     put_byte(yasp);                         /* y-aspect */
  1350.     put_big_short(cols);                    /* pageWidth */
  1351.     put_big_short(rows);                    /* pageHeight */
  1352. }
  1353.  
  1354.  
  1355. /* encode algorithm by Johan Widen (jw@jwdata.se) */
  1356. const unsigned char ppmtoilbm_bitmask[] = {1, 2, 4, 8, 16, 32, 64, 128};
  1357.  
  1358. static int
  1359. encode_row(outfile, rawrow, cols, nPlanes)
  1360.     FILE *outfile;  /* if non-NULL, write uncompressed row to this file */
  1361.     rawtype *rawrow;
  1362.     int cols, nPlanes;
  1363. {
  1364.     int plane, bytes;
  1365.     long retbytes = 0;
  1366.  
  1367.     bytes = RowBytes(cols);
  1368.  
  1369.     /* Encode and write raw bytes in plane-interleaved form. */
  1370.     for( plane = 0; plane < nPlanes; plane++ ) {
  1371.         register int col, cbit;
  1372.         register rawtype *rp;
  1373.         register unsigned char *cp;
  1374.         int mask;
  1375.  
  1376.         mask = 1 << plane;
  1377.         cbit = -1;
  1378.         cp = coded_rowbuf-1;
  1379.         rp = rawrow;
  1380.         for( col = 0; col < cols; col++, cbit--, rp++ ) {
  1381.             if( cbit < 0 ) {
  1382.                 cbit = 7;
  1383.                 *++cp = 0;
  1384.             }
  1385.             if( *rp & mask )
  1386.                 *cp |= ppmtoilbm_bitmask[cbit];
  1387.         }
  1388.         if( outfile ) {
  1389.             retbytes += bytes;
  1390.             if( fwrite(coded_rowbuf, 1, bytes, stdout) != bytes )
  1391.                 pm_error("write error");
  1392.         }
  1393.         else
  1394.             retbytes += compress_row(bytes);
  1395.     }
  1396.     return retbytes;
  1397. }
  1398.  
  1399.  
  1400. static int
  1401. compress_row(bytes)
  1402.     int bytes;
  1403. {
  1404.     static int count;
  1405.     int newbytes;
  1406.  
  1407.     /* if new compression methods are defined, do a switch here */
  1408.     newbytes = runbyte1(bytes);
  1409.  
  1410.     if( savemem ) {
  1411.         ilbm_body[count].row = MALLOC(newbytes, unsigned char);
  1412.         bcopy(compr_rowbuf, ilbm_body[count].row, newbytes);
  1413.     }
  1414.     else {
  1415.         ilbm_body[count].row = compr_rowbuf;
  1416.         compr_rowbuf = MALLOC(WORSTCOMPR(bytes), unsigned char);
  1417.     }
  1418.     ilbm_body[count].len = newbytes;
  1419.     ++count;
  1420.  
  1421.     return newbytes;
  1422. }
  1423.  
  1424.  
  1425. static void
  1426. write_body ARGS((void))
  1427. {
  1428.     bodyrow *p;
  1429.  
  1430.     for( p = ilbm_body; p->row != NULL; p++ ) {
  1431.         if( fwrite(p->row, 1, p->len, stdout) != p->len )
  1432.             pm_error("write error");
  1433.     }
  1434.     /* pad byte (if neccessary) is written by do_xxx_body() function */
  1435. }
  1436.  
  1437.  
  1438. static void
  1439. write_camg ARGS((void))
  1440. {
  1441.     if( viewportmodes ) {
  1442.         put_fourchars("CAMG");
  1443.         put_big_long(CAMGChunkSize);
  1444.         put_big_long(viewportmodes);
  1445.     }
  1446. }
  1447.  
  1448.  
  1449. /************ compression ************/
  1450.  
  1451.  
  1452. /* runbyte1 algorithm by Robert A. Knop (rknop@mop.caltech.edu) */
  1453. static int
  1454. runbyte1(size)
  1455.    int size;
  1456. {
  1457.     int in,out,count,hold;
  1458.     register unsigned char *inbuf = coded_rowbuf;
  1459.     register unsigned char *outbuf = compr_rowbuf;
  1460.  
  1461.  
  1462.     in=out=0;
  1463.     while( in<size ) {
  1464.         if( (in<size-1) && (inbuf[in]==inbuf[in+1]) ) {     /*Begin replicate run*/
  1465.             for( count=0,hold=in; in<size && inbuf[in]==inbuf[hold] && count<128; in++,count++)
  1466.                 ;
  1467.             outbuf[out++]=(unsigned char)(char)(-count+1);
  1468.             outbuf[out++]=inbuf[hold];
  1469.         }
  1470.         else {  /*Do a literal run*/
  1471.             hold=out; out++; count=0;
  1472.             while( ((in>=size-2)&&(in<size)) || ((in<size-2) && ((inbuf[in]!=inbuf[in+1])||(inbuf[in]!=inbuf[in+2]))) ) {
  1473.                 outbuf[out++]=inbuf[in++];
  1474.                 if( ++count>=128 )
  1475.                     break;
  1476.             }
  1477.             outbuf[hold]=count-1;
  1478.         }
  1479.     }
  1480.     return(out);
  1481. }
  1482.  
  1483.  
  1484. /************ PPM functions ************/
  1485.  
  1486.  
  1487. static int
  1488. closest_color(chv, colors, cmaxval, pP)
  1489.     colorhist_vector chv;
  1490.     int colors;
  1491.     pixval cmaxval;
  1492.     pixel *pP;
  1493. {
  1494.     /* Search colormap for closest match.       */
  1495.     /* algorithm taken from ppmquant.c   -IUW   */
  1496.     register int i, r1, g1, b1;
  1497.     int ind;
  1498.     long dist;
  1499.  
  1500.     r1 = PPM_GETR(*pP);
  1501.     g1 = PPM_GETG(*pP);
  1502.     b1 = PPM_GETB(*pP);
  1503.     dist = 2000000000;
  1504.     for( i = 0; i < colors; i++ ) {
  1505.         register int r2, g2, b2;
  1506.         long newdist;
  1507.  
  1508.         r2 = PPM_GETR(chv[i].color);
  1509.         g2 = PPM_GETG(chv[i].color);
  1510.         b2 = PPM_GETB(chv[i].color);
  1511.         newdist = ( r1 - r2 ) * ( r1 - r2 ) +
  1512.                   ( g1 - g2 ) * ( g1 - g2 ) +
  1513.                   ( b1 - b2 ) * ( b1 - b2 );
  1514.  
  1515.         if( newdist < dist ) {
  1516.             ind = i;
  1517.             dist = newdist;
  1518.         }
  1519.     }
  1520.     return ind;
  1521. }
  1522.  
  1523.  
  1524. /************ floyd-steinberg error diffusion ************/
  1525.  
  1526. static floydinfo *
  1527. init_floyd(cols, maxval, alternate)
  1528.     int cols;
  1529.     pixval maxval;
  1530.     int alternate;
  1531. {
  1532.     register int i;
  1533.     floydinfo *fi;
  1534.  
  1535.     fi = MALLOC(1, floydinfo);
  1536.  
  1537.     fi->thisrederr  = MALLOC(cols + 2, long);
  1538.     fi->thisgreenerr= MALLOC(cols + 2, long);
  1539.     fi->thisblueerr = MALLOC(cols + 2, long);
  1540.     fi->nextrederr  = MALLOC(cols + 2, long);
  1541.     fi->nextgreenerr= MALLOC(cols + 2, long);
  1542.     fi->nextblueerr = MALLOC(cols + 2, long);
  1543.     fi->lefttoright = 1;
  1544.     fi->cols = cols;
  1545.     fi->maxval = maxval;
  1546.     fi->alternate = alternate;
  1547.  
  1548.     for( i = 0; i < cols + 2; i++ )
  1549.         fi->thisrederr[i] = fi->thisgreenerr[i] = fi->thisblueerr[i] = 0;
  1550.  
  1551.     return fi;
  1552. }
  1553.  
  1554.  
  1555. static void
  1556. free_floyd(fi)
  1557.     floydinfo *fi;
  1558. {
  1559.     free(fi->thisrederr); free(fi->thisgreenerr); free(fi->thisblueerr);
  1560.     free(fi->nextrederr); free(fi->nextgreenerr); free(fi->nextblueerr);
  1561.     free(fi);
  1562. }
  1563.  
  1564.  
  1565. static void
  1566. begin_floyd_row(fi, prow)
  1567.     floydinfo *fi;
  1568.     pixel *prow;
  1569. {
  1570.     register int i;
  1571.  
  1572.     fi->pixrow = prow;
  1573.  
  1574.     for( i = 0; i < fi->cols + 2; i++ )
  1575.         fi->nextrederr[i] = fi->nextgreenerr[i] = fi->nextblueerr[i] = 0;
  1576.  
  1577.     if( fi->lefttoright ) {
  1578.         fi->col = 0;
  1579.         fi->col_end = fi->cols;
  1580.     }
  1581.     else {
  1582.         fi->col = fi->cols - 1;
  1583.         fi->col_end = -1;
  1584.     }
  1585. }
  1586.  
  1587.  
  1588. #define FS_GREEN_WEIGHT     1
  1589. #define FS_RED_WEIGHT       2   /* luminance of component relative to green */
  1590. #define FS_BLUE_WEIGHT      5
  1591.  
  1592. static pixel *
  1593. next_floyd_pixel(fi)
  1594.     floydinfo *fi;
  1595. {
  1596.     register long r, g, b;
  1597.     register pixel *pP;
  1598.     int errcol = fi->col+1;
  1599.     pixval maxval = fi->maxval;
  1600.  
  1601. #ifdef DEBUG
  1602.     if( fi->col == fi->col_end )
  1603.         pm_error("fs - access out of array bounds");    /* should never happen */
  1604. #endif
  1605.  
  1606.     pP = &(fi->pixrow[fi->col]);
  1607.  
  1608.     /* Use Floyd-Steinberg errors to adjust actual color. */
  1609.     r = fi->thisrederr  [errcol]; if( r < 0 ) r -= 8; else r += 8; r /= 16;
  1610.     g = fi->thisgreenerr[errcol]; if( g < 0 ) g -= 8; else g += 8; g /= 16;
  1611.     b = fi->thisblueerr [errcol]; if( b < 0 ) b -= 8; else b += 8; b /= 16;
  1612.  
  1613.     if( floyd == 2 ) {       /* EXPERIMENTAL */
  1614.         r /= FS_RED_WEIGHT;  b /= FS_BLUE_WEIGHT;
  1615.     }
  1616.  
  1617.     r += PPM_GETR(*pP); if ( r < 0 ) r = 0; else if ( r > maxval ) r = maxval;
  1618.     g += PPM_GETG(*pP); if ( g < 0 ) g = 0; else if ( g > maxval ) g = maxval;
  1619.     b += PPM_GETB(*pP); if ( b < 0 ) b = 0; else if ( b > maxval ) b = maxval;
  1620.  
  1621.     PPM_ASSIGN(*pP, r, g, b);
  1622.  
  1623.     fi->red = r;
  1624.     fi->green = g;
  1625.     fi->blue = b;
  1626.  
  1627.     return pP;
  1628. }
  1629.  
  1630.  
  1631. static void
  1632. update_floyd_pixel(fi, r, g, b)
  1633.     floydinfo *fi;
  1634.     int r, g, b;
  1635. {
  1636.     register long rerr, gerr, berr, err;
  1637.     int col = fi->col;
  1638.     int errcol = col+1;
  1639.     long two_err;
  1640.  
  1641.     rerr = (long)(fi->red)   - r;
  1642.     gerr = (long)(fi->green) - g;
  1643.     berr = (long)(fi->blue)  - b;
  1644.  
  1645.     if( fi->lefttoright ) {
  1646.         two_err = 2*rerr;
  1647.         err = rerr;     fi->nextrederr[errcol+1] += err;    /* 1/16 */
  1648.         err += two_err; fi->nextrederr[errcol-1] += err;    /* 3/16 */
  1649.         err += two_err; fi->nextrederr[errcol  ] += err;    /* 5/16 */
  1650.         err += two_err; fi->thisrederr[errcol+1] += err;    /* 7/16 */
  1651.  
  1652.         two_err = 2*gerr;
  1653.         err = gerr;     fi->nextgreenerr[errcol+1] += err;    /* 1/16 */
  1654.         err += two_err; fi->nextgreenerr[errcol-1] += err;    /* 3/16 */
  1655.         err += two_err; fi->nextgreenerr[errcol  ] += err;    /* 5/16 */
  1656.         err += two_err; fi->thisgreenerr[errcol+1] += err;    /* 7/16 */
  1657.  
  1658.         two_err = 2*berr;
  1659.         err = berr;     fi->nextblueerr[errcol+1] += err;    /* 1/16 */
  1660.         err += two_err; fi->nextblueerr[errcol-1] += err;    /* 3/16 */
  1661.         err += two_err; fi->nextblueerr[errcol  ] += err;    /* 5/16 */
  1662.         err += two_err; fi->thisblueerr[errcol+1] += err;    /* 7/16 */
  1663.  
  1664.         fi->col++;
  1665.     }
  1666.     else {
  1667.         two_err = 2*rerr;
  1668.         err = rerr;     fi->nextrederr[errcol-1] += err;    /* 1/16 */
  1669.         err += two_err; fi->nextrederr[errcol+1] += err;    /* 3/16 */
  1670.         err += two_err; fi->nextrederr[errcol  ] += err;    /* 5/16 */
  1671.         err += two_err; fi->thisrederr[errcol-1] += err;    /* 7/16 */
  1672.  
  1673.         two_err = 2*gerr;
  1674.         err = gerr;     fi->nextgreenerr[errcol-1] += err;    /* 1/16 */
  1675.         err += two_err; fi->nextgreenerr[errcol+1] += err;    /* 3/16 */
  1676.         err += two_err; fi->nextgreenerr[errcol  ] += err;    /* 5/16 */
  1677.         err += two_err; fi->thisgreenerr[errcol-1] += err;    /* 7/16 */
  1678.  
  1679.         two_err = 2*berr;
  1680.         err = berr;     fi->nextblueerr[errcol-1] += err;    /* 1/16 */
  1681.         err += two_err; fi->nextblueerr[errcol+1] += err;    /* 3/16 */
  1682.         err += two_err; fi->nextblueerr[errcol  ] += err;    /* 5/16 */
  1683.         err += two_err; fi->thisblueerr[errcol-1] += err;    /* 7/16 */
  1684.  
  1685.         fi->col--;
  1686.     }
  1687. }
  1688.  
  1689.  
  1690. static void
  1691. end_floyd_row(fi)
  1692.     floydinfo *fi;
  1693. {
  1694.     long *tmp;
  1695.  
  1696.     tmp = fi->thisrederr;   fi->thisrederr   = fi->nextrederr;   fi->nextrederr   = tmp;
  1697.     tmp = fi->thisgreenerr; fi->thisgreenerr = fi->nextgreenerr; fi->nextgreenerr = tmp;
  1698.     tmp = fi->thisblueerr;  fi->thisblueerr  = fi->nextblueerr;  fi->nextblueerr  = tmp;
  1699.     if( fi->alternate )
  1700.         fi->lefttoright = !(fi->lefttoright);
  1701. }
  1702.  
  1703.  
  1704. /************ other utility functions ************/
  1705.  
  1706. static void
  1707. alloc_body_array(rows, nPlanes)
  1708.     int rows, nPlanes;
  1709. {
  1710.     ilbm_body = MALLOC(rows * nPlanes + 1, bodyrow);
  1711.     ilbm_body[rows * nPlanes].row = NULL;
  1712. }
  1713.  
  1714. #if 0   /* not used for now */
  1715. static void
  1716. free_body_array ARGS((void))
  1717. {
  1718.     bodyrow *p;
  1719.  
  1720.     for( p = ilbm_body; p->row != NULL; p++ )
  1721.         free(p->row);
  1722.     free(ilbm_body);
  1723. }
  1724. #endif
  1725.  
  1726. static int
  1727. colorstobpp(colors)
  1728.     int colors;
  1729. {
  1730.     int i;
  1731.  
  1732.     for( i = 1; i <= MAXPLANES; i++ ) {
  1733.         if( colors <= (1 << i) )
  1734.             return i;
  1735.     }
  1736.     pm_error("too many planes (max %d)", MAXPLANES);
  1737.     /*NOTREACHED*/
  1738. }
  1739.  
  1740.  
  1741. #if 0
  1742. static void
  1743. put_fourchars(str)
  1744.     char* str;
  1745. {
  1746.     fputs( str, stdout );
  1747. }
  1748. #endif
  1749.  
  1750.  
  1751. static void
  1752. put_big_short(s)
  1753.     short s;
  1754. {
  1755.     if ( pm_writebigshort( stdout, s ) == -1 )
  1756.         pm_error( "write error" );
  1757. }
  1758.  
  1759.  
  1760. static void
  1761. put_big_long(l)
  1762.     long l;
  1763. {
  1764.     if ( pm_writebiglong( stdout, l ) == -1 )
  1765.         pm_error( "write error" );
  1766. }
  1767.  
  1768.  
  1769. #if 0
  1770. static void
  1771. put_byte(b)
  1772.     unsigned char b;
  1773. {
  1774.     (void) putc( b, stdout );
  1775. }
  1776. #endif
  1777.  
  1778.  
  1779. static pixval *
  1780. make_val_table(oldmaxval, newmaxval)
  1781.     pixval oldmaxval, newmaxval;
  1782. {
  1783.     int i;
  1784.     pixval *table;
  1785.  
  1786.     table = MALLOC(oldmaxval + 1, pixval);
  1787.     for(i = 0; i <= oldmaxval; i++ )
  1788.         table[i] = (i * newmaxval + oldmaxval/2) / oldmaxval;
  1789.  
  1790.     return table;
  1791. }
  1792.  
  1793.  
  1794. static void *
  1795. xmalloc(bytes)
  1796.     int bytes;
  1797. {
  1798.     void *mem;
  1799.  
  1800.     mem = malloc(bytes);
  1801.     if( mem == NULL )
  1802.         pm_error("out of memory allocating %d bytes", bytes);
  1803.     return mem;
  1804. }
  1805.  
  1806.  
  1807. static int  gFormat;
  1808. static int  gCols;
  1809. static int  gMaxval;
  1810.  
  1811. static void
  1812. init_read(fp, colsP, rowsP, maxvalP, formatP, readall)
  1813.     FILE *fp;
  1814.     int *colsP, *rowsP;
  1815.     pixval *maxvalP;
  1816.     int *formatP;
  1817.     int readall;
  1818. {
  1819.     ppm_readppminit(fp, colsP, rowsP, maxvalP, formatP);
  1820.     if( readall ) {
  1821.         int row;
  1822.  
  1823.         pixels = ppm_allocarray(*colsP, *rowsP);
  1824.         for( row = 0; row < *rowsP; row++ )
  1825.             ppm_readppmrow(fp, pixels[row], *colsP, *maxvalP, *formatP);
  1826.         /* pixels = ppm_readppm(fp, colsP, rowsP, maxvalP); */
  1827.     }
  1828.     else {
  1829.         pixrow = ppm_allocrow(*colsP);
  1830.     }
  1831.     gCols = *colsP;
  1832.     gMaxval = *maxvalP;
  1833.     gFormat = *formatP;
  1834. }
  1835.  
  1836.  
  1837. static pixel *
  1838. next_pixrow(fp, row)
  1839.     FILE *fp;
  1840.     int row;
  1841. {
  1842.     if( pixels )
  1843.         pixrow = pixels[row];
  1844.     else {
  1845. #ifdef DEBUG
  1846.         static int rowcnt;
  1847.         if( row != rowcnt )
  1848.             pm_error("big mistake");
  1849.         rowcnt++;
  1850. #endif
  1851.         ppm_readppmrow(fp, pixrow, gCols, gMaxval, gFormat);
  1852.     }
  1853.     return pixrow;
  1854. }
  1855.  
  1856.