3 * Image handling tools, (c) AJK 2001-2005
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
36 unsigned char const bbc[] = {
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
38 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x00, // !
39 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, // "
40 0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00, // #
41 0x0C, 0x3F, 0x68, 0x3E, 0x0B, 0x7E, 0x18, 0x00, // $
42 0x60, 0x66, 0x0C, 0x18, 0x30, 0x66, 0x06, 0x00, // %
43 0x38, 0x6C, 0x6C, 0x38, 0x6D, 0x66, 0x3B, 0x00, // &
44 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, // '
45 0x0C, 0x18, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, // (
46 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, // )
47 0x00, 0x18, 0x7E, 0x3C, 0x7E, 0x18, 0x00, 0x00, // *
48 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, // +
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, // ,
50 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, // -
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, // .
52 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, // /
53 0x18, 0x24, 0x66, 0x66, 0x66, 0x24, 0x18, 0x00, // 0 (non crossed)
54 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, // 1
55 0x3C, 0x66, 0x06, 0x0C, 0x18, 0x30, 0x7E, 0x00, // 2
56 0x3C, 0x66, 0x06, 0x1C, 0x06, 0x66, 0x3C, 0x00, // 3
57 0x0C, 0x1C, 0x3C, 0x6C, 0x7E, 0x0C, 0x0C, 0x00, // 4
58 0x7E, 0x60, 0x7C, 0x06, 0x06, 0x66, 0x3C, 0x00, // 5
59 0x1C, 0x30, 0x60, 0x7C, 0x66, 0x66, 0x3C, 0x00, // 6
60 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x00, // 7
61 0x3C, 0x66, 0x66, 0x3C, 0x66, 0x66, 0x3C, 0x00, // 8
62 0x3C, 0x66, 0x66, 0x3E, 0x06, 0x0C, 0x38, 0x00, // 9
63 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, // :
64 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, // ;
65 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, // <
66 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, // =
67 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, // >
68 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, // ?
69 0x3C, 0x66, 0x6E, 0x6A, 0x6E, 0x60, 0x3C, 0x00, // @
70 0x3C, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, // A
71 0x7C, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x7C, 0x00, // B
72 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x00, // C
73 0x78, 0x6C, 0x66, 0x66, 0x66, 0x6C, 0x78, 0x00, // D
74 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x7E, 0x00, // E
75 0x7E, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x00, // F
76 0x3C, 0x66, 0x60, 0x6E, 0x66, 0x66, 0x3C, 0x00, // G
77 0x66, 0x66, 0x66, 0x7E, 0x66, 0x66, 0x66, 0x00, // H
78 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, // I
79 0x3E, 0x0C, 0x0C, 0x0C, 0x0C, 0x6C, 0x38, 0x00, // J
80 0x66, 0x6C, 0x78, 0x70, 0x78, 0x6C, 0x66, 0x00, // K
81 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7E, 0x00, // L
82 0x63, 0x77, 0x7F, 0x6B, 0x6B, 0x63, 0x63, 0x00, // M
83 0x66, 0x66, 0x76, 0x7E, 0x6E, 0x66, 0x66, 0x00, // N
84 0x3C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // O
85 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x00, // P
86 0x3C, 0x66, 0x66, 0x66, 0x6A, 0x6C, 0x36, 0x00, // Q
87 0x7C, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x00, // R
88 0x3C, 0x66, 0x60, 0x3C, 0x06, 0x66, 0x3C, 0x00, // S
89 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, // T
90 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // U
91 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, // V
92 0x63, 0x63, 0x6B, 0x6B, 0x7F, 0x77, 0x63, 0x00, // W
93 0x66, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x66, 0x00, // X
94 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x00, // Y
95 0x7E, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x7E, 0x00, // Z
96 0x7C, 0x60, 0x60, 0x60, 0x60, 0x60, 0x7C, 0x00, // [
97 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, //
98 0x3E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x3E, 0x00, // ]
99 0x18, 0x3C, 0x66, 0x42, 0x00, 0x00, 0x00, 0x00, // ^
100 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, // _
101 0x1C, 0x36, 0x30, 0x7C, 0x30, 0x30, 0x7E, 0x00, // `
102 0x00, 0x00, 0x3C, 0x06, 0x3E, 0x66, 0x3E, 0x00, // a
103 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x7C, 0x00, // b
104 0x00, 0x00, 0x3C, 0x66, 0x60, 0x66, 0x3C, 0x00, // c
105 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00, // d
106 0x00, 0x00, 0x3C, 0x66, 0x7E, 0x60, 0x3C, 0x00, // e
107 0x1C, 0x30, 0x30, 0x7C, 0x30, 0x30, 0x30, 0x00, // f
108 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x3C, // g
109 0x60, 0x60, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00, // h
110 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3C, 0x00, // i
111 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x70, // j
112 0x60, 0x60, 0x66, 0x6C, 0x78, 0x6C, 0x66, 0x00, // k
113 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, // l
114 0x00, 0x00, 0x36, 0x7F, 0x6B, 0x6B, 0x63, 0x00, // m
115 0x00, 0x00, 0x7C, 0x66, 0x66, 0x66, 0x66, 0x00, // n
116 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x00, // o
117 0x00, 0x00, 0x7C, 0x66, 0x66, 0x7C, 0x60, 0x60, // p
118 0x00, 0x00, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x07, // q
119 0x00, 0x00, 0x6C, 0x76, 0x60, 0x60, 0x60, 0x00, // r
120 0x00, 0x00, 0x3E, 0x60, 0x3C, 0x06, 0x7C, 0x00, // s
121 0x30, 0x30, 0x7C, 0x30, 0x30, 0x30, 0x1C, 0x00, // t
122 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3E, 0x00, // u
123 0x00, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, // v
124 0x00, 0x00, 0x63, 0x6B, 0x6B, 0x7F, 0x36, 0x00, // w
125 0x00, 0x00, 0x66, 0x3C, 0x18, 0x3C, 0x66, 0x00, // x
126 0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x3C, // y
127 0x00, 0x00, 0x7E, 0x0C, 0x18, 0x30, 0x7E, 0x00, // z
128 0x0C, 0x18, 0x18, 0x70, 0x18, 0x18, 0x0C, 0x00, // {
129 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, // |
130 0x30, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x30, 0x00, // }
131 0x31, 0x6B, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, // ~
132 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //
135 const char smallc[] = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-+&()/[];%";
136 unsigned char const small[] = {
138 0x1F, 0x11, 0x1F, //0
139 0x11, 0x1F, 0x10, //1
140 0x1D, 0x15, 0x17, //2
141 0x11, 0x15, 0x1F, //3
142 0x07, 0x04, 0x1F, //4
143 0x17, 0x15, 0x1D, //5
144 0x1F, 0x15, 0x1D, //6
145 0x01, 0x01, 0x1F, //7
146 0x1F, 0x15, 0x1F, //8
147 0x17, 0x15, 0x1F, //9
148 0x1E, 0x05, 0x1E, //A
149 0x1F, 0x15, 0x0A, //B
150 0x0E, 0x11, 0x11, //C
151 0x1F, 0x11, 0x0E, //D
152 0x1F, 0x15, 0x11, //E
153 0x1F, 0x05, 0x01, //F
154 0x0E, 0x11, 0x19, //G
155 0x1F, 0x04, 0x1F, //H
156 0x11, 0x1F, 0x11, //I
157 0x11, 0x0F, 0x01, //J
158 0x1F, 0x04, 0x1B, //K
159 0x1F, 0x10, 0x10, //L
160 0x1F, 0x03, 0x1F, //M
161 0x1F, 0x01, 0x1F, //N
162 0x0E, 0x11, 0x0E, //O
163 0x1F, 0x05, 0x02, //P
164 0x0E, 0x19, 0x1E, //Q
165 0x1F, 0x05, 0x1A, //R
166 0x12, 0x15, 0x09, //S
167 0x01, 0x1F, 0x01, //T
168 0x1F, 0x10, 0x1F, //U
169 0x0F, 0x10, 0x0F, //V
170 0x1F, 0x18, 0x1F, //W
171 0x1B, 0x04, 0x1B, //X
172 0x03, 0x1C, 0x03, //Y
173 0x19, 0x15, 0x13, //Z
174 0x04, 0x04, 0x04, //-
175 0x04, 0x0E, 0x04, //+
176 0x04, 0x0E, 0x04, //& (+)
177 0x00, 0x0E, 0x11, //(
178 0x11, 0x0E, 0x00, //)
179 0x08, 0x04, 0x02, ///
180 0x00, 0x1F, 0x11, //[
181 0x11, 0x1F, 0x00, //]
182 0x10, 0x0A, 0x00, //;
183 0x09, 0x04, 0x12, //%
187 ImageNew (int w, int h, int c)
188 { // create a new blank image
192 i = malloc (sizeof (*i));
195 memset (i, 0, sizeof (*i));
200 i->Image = malloc ((w + 1) * h);
206 memset (i->Image, 0, (w + 1) * h);
209 i->Colour = malloc (sizeof (Colour) * c);
216 memset (i->Colour, 0, sizeof (Colour) * c);
222 ImageFree (Image * i)
235 typedef short LZW[256];
236 typedef LZW LZWTree[MAXLZW];
237 typedef struct strPrivate
239 int cols; // number of colours, power of 2
240 unsigned char colbits; // number of bits for colours
241 int fh; // file handle
242 int lzwnext; // next code
243 int lzwlast; // last code in current bit size
244 int lzwbits; // current bit size
245 LZWTree lzw; // encode tree
246 unsigned char block[256]; // block so far, with count at start
247 int blockv; // pending value
248 int blockb; // bits used in pending value
249 short lzwcode; // which code we are on now
254 LZWFlush (Private * p)
255 { // flush this block
256 write (p->fh, p->block, *p->block + 1);
261 LZWOut (Private * p, short v)
263 p->blockv |= (v << p->blockb);
264 p->blockb += p->lzwbits;
265 while (p->blockb >= 8)
267 p->block[++*p->block] = p->blockv; // last partial byte
270 if (*p->block == 255)
276 LZWClear (Private * p)
279 p->lzwbits = p->colbits + 1;
280 p->lzwnext = p->cols + 2;
281 p->lzwlast = (1 << p->lzwbits) - 1;
282 p->lzwcode = p->cols; // starting point
283 for (c = 0; c < p->cols; c++)
285 p->lzw[p->cols][c] = c; // links to literal entries
286 memset (&p->lzw[c], -1, p->cols * 2); // links from literals, dead ends initially
291 ImageStart (Private * p)
293 unsigned char b = p->colbits;
294 write (p->fh, &b, 1);
299 LZWOut (p, p->cols); // clear code
303 ImageEnd (Private * p)
305 LZWOut (p, p->lzwcode); // last prefix
306 LZWOut (p, p->cols + 1); // end code
308 p->block[++*p->block] = p->blockv; // last partial byte
313 ImageOut (Private * p, unsigned char c)
315 short next = p->lzw[p->lzwcode][c];
318 LZWOut (p, p->lzwcode); // prefix
320 if (p->lzwnext + 1 == MAXLZW)
322 LZWOut (p, p->cols); // clear code
326 if (p->lzwnext < MAXLZW)
328 memset (p->lzw[p->lzwnext], -1, p->cols * 2); // init dead ends
329 p->lzw[p->lzwcode][c] = p->lzwnext;
330 if (p->lzwnext > p->lzwlast)
333 p->lzwlast = (1 << p->lzwbits) - 1;
339 p->lzwcode = next; // not a dead end
344 ImageWriteGif (Image * i, int fh, int back, int trans, char *comment)
348 for (p.colbits = 2, p.cols = 4; p.cols < i->C; p.cols *= 2, p.colbits++); // count colours, min 4
352 strcpy (buf, "GIF87a");
354 if (comment || trans >= 0)
356 buf[4] = '9'; // needs gif89 format
358 buf[n++] = (i->W & 255);
359 buf[n++] = (i->W >> 8);
360 buf[n++] = (i->H & 255);
361 buf[n++] = (i->H >> 8);
362 buf[n++] = (i->Colour ? 0x80 : 0) + 0x70 + (p.colbits - 1);
363 buf[n++] = back; // background
364 buf[n++] = 0; // aspect
368 for (c = 0; c < p.cols; c++)
372 buf[n++] = (i->Colour[c] >> 16 & 255);
373 buf[n++] = (i->Colour[c] >> 8 & 255);
374 buf[n++] = (i->Colour[c] & 255);
376 { // extra, unused, colour
384 if (comment && strlen (comment) < 256)
386 buf[n++] = 0x21; //extension
387 buf[n++] = 0xFE; //comment
388 buf[n++] = strlen (comment);
389 strcpy (buf + n, comment);
391 buf[n++] = 0; // end of block
395 buf[n++] = 0x21; // extension
396 buf[n++] = 0xF9; // graphic control
398 buf[n++] = 1; // transparrent
399 buf[n++] = 0; // delay
402 buf[n++] = 0; // terminator
406 buf[n++] = 0; // offset X
408 buf[n++] = 0; // offset Y
410 buf[n++] = (i->W & 255);
411 buf[n++] = (i->W >> 8);
412 buf[n++] = (i->H & 255);
413 buf[n++] = (i->H >> 8);
415 buf[n++] = 0x40; // interlaced, no local colour table
417 buf[n++] = 0x00; // non interlaced, no local colour table
428 for (y = 0; y < i->H; y += 8)
429 for (b = &ImagePixel (i, 0, y), x = 0; x < i->W; x++)
431 for (y = 4; y < i->H; y += 8)
432 for (b = &ImagePixel (i, 0, y), x = 0; x < i->W; x++)
434 for (y = 2; y < i->H; y += 4)
435 for (b = &ImagePixel (i, 0, y), x = 0; x < i->W; x++)
437 for (y = 1; y < i->H; y += 2)
438 for (b = &ImagePixel (i, 0, y), x = 0; x < i->W; x++)
441 for (y = 0; y < i->H; y++)
442 for (b = &ImagePixel (i, 0, y), x = 0; x < i->W; x++)
447 write (fh, "\0", 1); // end of image data
448 write (fh, "\x3B", 1); // trailer
452 ImageText (Image * i, int x, int y, int col, char *text)
457 if (*text >= ' ' && *text)
460 unsigned const char *b = bbc + (*text - ' ') * 8;
461 for (r = 0; r < 8; r++)
463 unsigned char v = *b++;
464 unsigned char *p = &ImagePixel (i, x, y + r);
466 for (m = 0x80; m; m >>= 1, p++)
477 ImageSmall (Image * i, int x, int y, int col, char *text)
478 { // writes 4x6 digits
482 char *p = strchr (smallc, toupper (*text));
487 unsigned const char *b = small + (p - smallc) * 3;
488 for (r = 0; r < 5; r++)
491 for (c = 0; c < 3; c++)
493 ImagePixel (i, x + c, y + r) = col;
497 } else if (*text == '.')
499 ImagePixel (i, x, y + 4) = col;
501 } else if (*text == ':')
503 ImagePixel (i, x, y + 1) = col;
504 ImagePixel (i, x, y + 3) = col;
512 ImageRect (Image * i, int x, int y, int w, int h, int c)
518 unsigned char *p = &ImagePixel (i, x, y);
529 /* Table of CRCs of all 8-bit messages. */
530 static unsigned int crc_table[256];
532 /* Make the table for a fast CRC. */
534 make_crc_table (void)
539 for (n = 0; n < 256; n++)
541 c = (unsigned int) n;
542 for (k = 0; k < 8; k++)
545 c = 0xedb88320L ^ (c >> 1);
553 /* Update a running CRC with the bytes buf[0..len-1]--the CRC
554 should be initialized to all 1's, and the transmitted value
555 is the 1's complement of the final running CRC (see the
556 crc() routine below)). */
559 update_crc (unsigned int crc, unsigned char *buf, int len)
561 unsigned int c = crc;
564 for (n = 0; n < len; n++)
565 c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
570 /* Return the CRC of the bytes buf[0..len-1]. */
572 crc (unsigned char *buf, int len)
574 return update_crc (0xffffffffL, buf, len) ^ 0xffffffffL;
578 writecrc (int fh, char *ptr, int len, unsigned int c)
580 write (fh, ptr, len);
582 c = crc_table[(c ^ *ptr++) & 0xff] ^ (c >> 8);
587 writechunk (int fh, char *typ, void *ptr, int len)
589 unsigned int v = htonl (len),
592 crc = writecrc (fh, typ, 4, ~0);
594 crc = writecrc (fh, ptr, len, crc);
601 adlersum (unsigned char *p, int l, unsigned int adler)
603 unsigned int s1 = (adler & 65535),
610 s1 %= 65521; // can be delayed due to sensible "l" values...
612 return (s2 << 16) + s1;
618 ImageWritePNG (Image * i, int fh, int back, int trans, char *comment)
621 write (fh, "\211PNG\r\n\032\n", 8); // PNG header
628 unsigned char colour;
629 unsigned char compress;
630 unsigned char filter;
631 unsigned char interlace;
636 ihdr.width = htonl (i->W);
637 ihdr.height = htonl (i->H);
638 writechunk (fh, "IHDR", &ihdr, 13);
641 unsigned int v = htonl (i->C * 3),
645 crc = writecrc (fh, "PLTE", 4, ~0);
646 for (n = 0; n < i->C; n++)
648 v = htonl (i->Colour[n] << 8);
649 crc = writecrc (fh, (void *) &v, 3, crc);
656 unsigned char b = back;
657 writechunk (fh, "bKGD", &b, 1);
661 char c[] = "Comment";
662 unsigned int v = htonl (strlen (c) + strlen (comment) + 1),
665 crc = writecrc (fh, "tEXt", 4, ~0);
666 crc = writecrc (fh, c, strlen (c) + 1, crc);
667 crc = writecrc (fh, comment, strlen (comment), crc);
672 unsigned char alpha[256];
674 for (n = 0; n < i->C; n++)
675 alpha[n] = 255 - (i->Colour[n] >> 24); // 4th palette byte treated as 0=opaque, 255-transparrent
676 if (trans >= 0 && trans < i->C)
677 alpha[trans] = 0; // manual set of specific transparrent colour
678 writechunk (fh, "tRNS", alpha, i->C);
682 unsigned int v = htonl (i->H * (i->L + 5) + 6),
686 unsigned char *p = i->Image;
688 crc = writecrc (fh, "IDAT", 4, ~0);
689 crc = writecrc (fh, "\170\001", 2, crc); // zlib header for deflate
694 h[0] = (n ? 0 : 1); // last chunk in deflate, un compressed
695 h[1] = (i->L & 255); // Len, LSB first as per deflate spec
697 h[3] = ~(i->L & 255); // Inverse of Len
698 h[4] = ~(i->L / 256);
699 *p = 0; // filter 0 (NONE)
700 crc = writecrc (fh, h, 5, crc);
701 crc = writecrc (fh, p, i->L, crc);
702 adler = adlersum (p, i->L, adler);
706 crc = writecrc (fh, (void *) &v, 4, crc);
714 for (n = 0; n < i->H; n++)
715 i->Image[n * i->L] = 0; // filter 0
716 n = i->H * i->L * 1001 / 1000 + 12;
718 if (compress2 (temp, &n, i->Image, i->L * i->H, 9) != Z_OK)
719 fprintf (stderr, "Deflate error\n");
721 writechunk (fh, "IDAT", temp, n);
725 writechunk (fh, "IEND", 0, 0); // IEND