1 /* ppmtopi1.c - read a portable pixmap and write a Degas PI1 file
2 **
3 ** Copyright (C) 1991 by Steve Belczyk and Jef Poskanzer.
4 **
5 ** Permission to use, copy, modify, and distribute this software and its
6 ** documentation for any purpose and without fee is hereby granted, provided
7 ** that the above copyright notice appear in all copies and that both that
8 ** copyright notice and this permission notice appear in supporting
9 ** documentation.  This software is provided "as is" without express or
10 ** implied warranty.
11 */
12 
13 #include "ppm.h"
14 
15 #define COLS 320
16 #define ROWS 200
17 #define MAXVAL 7
18 #define MAXCOLORS 16
19 
20 static short screen[ROWS*COLS/4];  /* simulate the ST's video RAM */
21 
22 int
main(argc,argv)23 main( argc, argv )
24     int argc;
25     char* argv[];
26     {
27     FILE* ifp;
28     pixel** pixels;
29     register pixel *pP;
30     colorhist_vector chv;
31     colorhash_table cht;
32     int rows, cols, row, colors, i;
33     register int col;
34     pixval maxval;
35 
36 
37     ppm_init( &argc, argv );
38 
39     if ( argc > 2 )
40         pm_usage( "[ppmfile]" );
41 
42     if ( argc == 2 )
43         ifp = pm_openr( argv[1] );
44     else
45         ifp = stdin;
46 
47     pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
48     pm_close( ifp );
49     if ( (cols > COLS) || (rows > ROWS) )
50         pm_error( "image is larger than %dx%d - sorry", COLS, ROWS );
51 
52     pm_message( "computing colormap..." );
53     chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
54     if ( chv == (colorhist_vector) 0 )
55         {
56         pm_message(
57             "too many colors - try doing a 'pnmquant %d'", MAXCOLORS );
58         exit( 1 );
59         }
60     pm_message( "%d colors found", colors );
61 
62     /* Write PI1 header - resolution and palette. */
63     (void) pm_writebigshort( stdout, (short) 0 );       /* low resolution */
64     for ( i = 0; i < 16; ++i )
65         {
66         short w;
67 
68         if ( i < colors )
69             {
70             pixel p;
71 
72             p = chv[i].color;
73             if ( maxval != MAXVAL )
74                 PPM_DEPTH( p, p, maxval, MAXVAL );
75             w  = ( (int) PPM_GETR( p ) ) << 8;
76             w |= ( (int) PPM_GETG( p ) ) << 4;
77             w |= ( (int) PPM_GETB( p ) );
78             }
79         else
80             w = 0;
81         (void) pm_writebigshort( stdout, w );
82         }
83     if ( maxval > MAXVAL )
84         pm_message(
85             "maxval is not %d - automatically rescaling colors", MAXVAL );
86 
87     /* Convert color vector to color hash table, for fast lookup. */
88     cht = ppm_colorhisttocolorhash( chv, colors );
89     ppm_freecolorhist( chv );
90 
91     /* Clear the screen buffer. */
92     for ( i = 0; i < ROWS*COLS/4; ++i )
93         screen[i] = 0;
94 
95     /* Convert. */
96     for ( row = 0; row < rows; ++row )
97         {
98         for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
99             {
100             register int color, ind, b, plane;
101 
102             color = ppm_lookupcolor( cht, pP );
103             if ( color == -1 )
104                 pm_error(
105                     "color not found?!?  row=%d col=%d  r=%d g=%d b=%d",
106                     row, col, PPM_GETR(*pP), PPM_GETG(*pP), PPM_GETB(*pP) );
107             ind = 80 * row + ( ( col >> 4 ) << 2 );
108             b = 0x8000 >> (col & 0xf);
109             for ( plane = 0; plane < 4; ++plane )
110                 if ( color & (1 << plane) )
111                     screen[ind+plane] |= b;
112             }
113         }
114 
115     /* And write out the screen buffer. */
116     for ( i = 0; i < ROWS*COLS/4; ++i )
117         (void) pm_writebigshort( stdout, screen[i] );
118 
119     exit( 0 );
120     }
121