1 /* libwmf ("ipa/ipa/bmp.h"): library for wmf conversion
2 Copyright (C) 2000 - various; see CREDITS, ChangeLog, and sources
3
4 The libwmf Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 The libwmf Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public
15 License along with the libwmf Library; see the file COPYING. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
18
19
20 #ifndef HAVE_GD
21 /* png stuff below adapted from stuff sent to me [fjf] by Lennard D. Rosenthal;
22 * probably used in ImageMagick and may not be covered, therefore, by the LGPL - (fjf)
23 *
24 * utility routine for saving a pixbuf to a png file.
25 * This was adapted from Iain Holmes' code in gnome-iconedit, and probably
26 * should be in a utility library, possibly in gdk-pixbuf itself.
27 */
ldr_bmp_png(wmfAPI * API,wmfBMP_Draw_t * bmp_draw,FILE * out)28 static void ldr_bmp_png (wmfAPI* API,wmfBMP_Draw_t* bmp_draw,FILE* out)
29 {
30 #ifdef HAVE_LIBPNG
31 wmfRGB rgb;
32
33 png_structp png_ptr = 0;
34 png_infop info_ptr = 0;
35 png_text text[2];
36
37 int i;
38 int j;
39 int x;
40 int y;
41 int width = (int) bmp_draw->crop.w;
42 int height = (int) bmp_draw->crop.h;
43 int depth = 8; /* ?? bit depth (bits per sample) */
44 int opacity;
45
46 char* ptr = 0;
47 char* buffer = (char*) wmf_malloc (API,4 * width);
48
49 if (ERR (API))
50 { WMF_DEBUG (API,"bailing...");
51 return;
52 }
53
54 png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,0,0,0);
55 if (png_ptr == 0)
56 { WMF_DEBUG (API,"Failed to write bitmap as PNG! (png_create_write_struct failed)");
57 wmf_free (API,buffer);
58 return;
59 }
60
61 info_ptr = png_create_info_struct (png_ptr);
62 if (info_ptr == 0)
63 { WMF_DEBUG (API,"Failed to write bitmap as PNG! (png_create_info_struct failed)");
64 png_destroy_write_struct (&png_ptr,0);
65 wmf_free (API,buffer);
66 return;
67 }
68
69 if (setjmp (png_ptr->jmpbuf))
70 { WMF_DEBUG (API,"Failed to write bitmap as PNG! (setjmp failed)");
71 png_destroy_write_struct (&png_ptr,&info_ptr);
72 wmf_free (API,buffer);
73 return;
74 }
75
76 png_init_io (png_ptr,out);
77
78 png_set_IHDR (png_ptr,info_ptr,width,height,depth,
79 PNG_COLOR_TYPE_RGB_ALPHA,PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
80
81 /* Some text to go with the png image */
82 text[0].key = "Title";
83 text[0].text = "A converted bitmap";
84 text[0].compression = PNG_TEXT_COMPRESSION_NONE;
85 text[1].key = "Software";
86 text[1].text = "libwmf2";
87 text[1].compression = PNG_TEXT_COMPRESSION_NONE;
88
89 png_set_text (png_ptr,info_ptr,text,2);
90
91 /* Write header data
92 */
93 png_write_info (png_ptr,info_ptr);
94
95 /* pump the raster data into libpng, one scan line at a time
96 */
97 x = (int) bmp_draw->crop.x;
98 y = (int) bmp_draw->crop.y;
99
100 for (j = 0; j < height; j++)
101 { ptr = buffer;
102 for (i = 0; i < width; i++)
103 { opacity = wmf_ipa_bmp_color (API,&(bmp_draw->bmp),&rgb,x+i,y+j);
104 *ptr++ = (char) rgb.r;
105 *ptr++ = (char) rgb.g;
106 *ptr++ = (char) rgb.b;
107 *ptr++ = (char) ((unsigned char) (opacity & 0xff));
108 }
109 png_write_row (png_ptr,(png_bytep) buffer);
110 }
111
112 png_write_end (png_ptr,info_ptr);
113 png_destroy_write_struct (&png_ptr,&info_ptr);
114
115 wmf_free (API,buffer);
116 #else /* HAVE_LIBPNG */
117 WMF_ERROR (API,"Glitch? No PNG support!");
118 API->err = wmf_E_Glitch;
119 #endif /* HAVE_LIBPNG */
120 return;
121 }
122 #endif /* ! HAVE_GD */
123 #ifdef HAVE_GD
ipa_b64_sink(void * context,const char * buffer,int length)124 static int ipa_b64_sink (void* context,const char* buffer,int length)
125 { ipa_b64_t* b64 = (ipa_b64_t*) context;
126
127 int i = 0;
128
129 while (i < length)
130 { // coverity[overrun-local : FALSE] - coverity seems to fail to see that ipa_b64_flush resets length to 0
131 b64->buffer[b64->length] = buffer[i];
132 i++;
133 b64->length++;
134 if (b64->length == IPA_B64_BUFLEN) ipa_b64_flush (context);
135 }
136
137 return (i);
138 }
139 #endif /* HAVE_GD */
140 #ifdef HAVE_GD
ipa_b64_flush(void * context)141 static void ipa_b64_flush (void* context)
142 { ipa_b64_t* b64 = (ipa_b64_t*) context;
143
144 static char B64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
145
146 char buffer[IPA_B64_LEQUIV];
147
148 unsigned long ulc1;
149 unsigned long ulc2;
150 unsigned long ulc3;
151 unsigned long ulc;
152
153 int triplets = (b64->length + 2) / 3;
154 int triplen;
155 int i;
156
157 char* ptr = b64->buffer;
158 char* btr = buffer;
159
160 if (b64->length == 0) return;
161
162 triplen = triplets * 3;
163 for (i = b64->length; i < triplen; i++) b64->buffer[i] = 0;
164
165 (*btr) = '\n';
166 btr++;
167
168 for (i = 0; i < triplets; i++)
169 { ulc1 = (unsigned long) ((unsigned char) (*ptr));
170 ptr++;
171 ulc2 = (unsigned long) ((unsigned char) (*ptr));
172 ptr++;
173 ulc3 = (unsigned long) ((unsigned char) (*ptr));
174 ptr++;
175
176 ulc = (ulc1 << 16) | (ulc2 << 8) | ulc3;
177
178 ulc1 = (ulc & (0x3f << 18)) >> 18;
179 ulc2 = (ulc & (0x3f << 12)) >> 12;
180 ulc3 = (ulc & (0x3f << 6)) >> 6;
181
182 ulc &= 0x3f;
183
184 (*btr) = B64[ulc1];
185 btr++;
186 (*btr) = B64[ulc2];
187 btr++;
188 (*btr) = B64[ulc3];
189 btr++;
190 (*btr) = B64[ulc ];
191 btr++;
192 }
193
194 if ((triplen - b64->length) > 1) (*(btr-2)) = '=';
195 if ((triplen - b64->length) > 0) (*(btr-1)) = '=';
196
197 (*btr) = '\0';
198
199 wmf_stream_printf (b64->API,b64->out,buffer);
200
201 b64->length = 0;
202 }
203 #endif /* HAVE_GD */
204
wmf_ipa_bmp_b64(wmfAPI * API,wmfBMP_Draw_t * bmp_draw,wmfStream * out)205 void wmf_ipa_bmp_b64 (wmfAPI* API,wmfBMP_Draw_t* bmp_draw,wmfStream* out)
206 {
207 #ifdef HAVE_GD
208 gdImage* image = 0;
209
210 gdSink sink;
211
212 ipa_b64_t b64;
213
214 WMF_DEBUG (API,"~~~~~~~~wmf_ipa_bmp_b64");
215 #ifndef HAVE_LIBPNG
216 WMF_DEBUG (API,"No support for PNG, sorry!");
217 API->err = wmf_E_DeviceError;
218 return;
219 #endif /* HAVE_LIBPNG */
220 image = ipa_bmp_gd (API,bmp_draw);
221
222 if (image == 0) return;
223
224 b64.API = API;
225 b64.out = out;
226
227 b64.length = 0;
228
229 sink.context = (void*) (&b64);
230 sink.sink = ipa_b64_sink;
231
232 gdImagePngToSink (image,&sink);
233 gdImageDestroy (image);
234
235 ipa_b64_flush (sink.context);
236 #endif /* HAVE_GD */
237 }
238
wmf_ipa_bmp_png(wmfAPI * API,wmfBMP_Draw_t * bmp_draw,char * name)239 void wmf_ipa_bmp_png (wmfAPI* API,wmfBMP_Draw_t* bmp_draw,char* name)
240 { FILE* file = 0;
241 #ifdef HAVE_GD
242 gdImage* image = 0;
243 #endif /* HAVE_GD */
244 WMF_DEBUG (API,"~~~~~~~~wmf_ipa_bmp_png");
245 #ifndef HAVE_LIBPNG
246 WMF_DEBUG (API,"No support for PNG, sorry!");
247 API->err = wmf_E_DeviceError;
248 return;
249 #endif /* HAVE_LIBPNG */
250 file = fopen (name,"wb");
251
252 if (file == 0)
253 { WMF_ERROR (API,"Failed to open file to write GD image!");
254 return;
255 }
256 #ifdef HAVE_GD
257 image = ipa_bmp_gd (API,bmp_draw);
258
259 if (image)
260 { gdImagePng (image,file);
261 gdImageDestroy (image);
262 }
263 #else /* HAVE_GD */
264 ldr_bmp_png (API,bmp_draw,file);
265 #endif /* HAVE_GD */
266
267 fclose (file);
268 }
269
wmf_ipa_bmp_jpg(wmfAPI * API,wmfBMP_Draw_t * bmp_draw,char * name)270 void wmf_ipa_bmp_jpg (wmfAPI* API,wmfBMP_Draw_t* bmp_draw,char* name)
271 {
272 #ifdef HAVE_GD
273 FILE* file = 0;
274
275 gdImage* image = 0;
276
277 WMF_DEBUG (API,"~~~~~~~~wmf_ipa_bmp_jpg");
278 #ifndef HAVE_LIBJPEG
279 WMF_DEBUG (API,"No support for JPEG, sorry!");
280 API->err = wmf_E_DeviceError;
281 return;
282 #endif /* HAVE_LIBJPEG */
283 file = fopen (name,"wb");
284
285 if (file == 0)
286 { WMF_ERROR (API,"Failed to open file to write GD image!");
287 return;
288 }
289
290 image = ipa_bmp_gd (API,bmp_draw);
291
292 if (image)
293 { gdImageJpeg (image,file,-1); /* Default quality. */
294 gdImageDestroy (image);
295 }
296
297 fclose (file);
298 #endif /* HAVE_GD */
299 }
300 #ifdef HAVE_GD
ipa_bmp_gd(wmfAPI * API,wmfBMP_Draw_t * bmp_draw)301 static gdImage* ipa_bmp_gd (wmfAPI* API,wmfBMP_Draw_t* bmp_draw)
302 { wmfRGB rgb;
303
304 int color;
305
306 unsigned int ui_x;
307 unsigned int ui_y;
308
309 unsigned int i;
310 unsigned int j;
311
312 gdImage* image = 0;
313
314 WMF_DEBUG (API,"~~~~~~~~ipa_bmp_gd");
315
316 if (bmp_draw->bmp.data == 0)
317 { WMF_ERROR (API,"Glitch! Attempt to write non-existant bitmap.");
318 API->err = wmf_E_Glitch;
319 return (0);
320 }
321
322 image = gdImageCreateTrueColor ((int) bmp_draw->crop.w,(int) bmp_draw->crop.h);
323
324 if (image == 0)
325 { WMF_ERROR (API,"Failed to create GD image!");
326 API->err = wmf_E_DeviceError;
327 return (0);
328 }
329
330 ui_x = (unsigned int) bmp_draw->crop.x;
331 ui_y = (unsigned int) bmp_draw->crop.y;
332
333 for (j = 0; j < (unsigned int) bmp_draw->crop.h; j++)
334 { for (i = 0; i < (unsigned int) bmp_draw->crop.w; i++)
335 { wmf_ipa_bmp_color (API,&(bmp_draw->bmp),&rgb,ui_x+i,ui_y+j);
336
337 color = gdImageColorResolve (image,rgb.r,rgb.g,rgb.b);
338
339 gdImageSetPixel (image,(int) i,(int) (bmp_draw->crop.h-1-j),color);
340 }
341 }
342
343 return (image);
344 }
345 #endif /* HAVE_GD */
wmf_ipa_bmp_eps(wmfAPI * API,wmfBMP_Draw_t * bmp_draw,char * name)346 void wmf_ipa_bmp_eps (wmfAPI* API,wmfBMP_Draw_t* bmp_draw,char* name)
347 { wmfRGB rgb;
348
349 unsigned int i;
350 unsigned int j;
351 unsigned int k;
352
353 unsigned int ui_x;
354 unsigned int ui_y;
355
356 unsigned int width;
357 unsigned int height;
358
359 static char hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
360
361 char buffer[80];
362
363 FILE* file = 0;
364
365 WMF_DEBUG (API,"~~~~~~~~wmf_ipa_bmp_eps");
366
367 if (bmp_draw->bmp.data == 0)
368 { WMF_ERROR (API,"Glitch! Attempt to write non-existant bitmap.");
369 API->err = wmf_E_Glitch;
370 return;
371 }
372
373 file = fopen (name,"w");
374
375 if (file == 0)
376 { WMF_ERROR (API,"Failed to open file to write EPS image!");
377 API->err = wmf_E_BadFile;
378 return;
379 }
380
381 ui_x = (unsigned int) bmp_draw->crop.x;
382 ui_y = (unsigned int) bmp_draw->crop.y;
383
384 width = (unsigned int) bmp_draw->crop.w;
385 height = (unsigned int) bmp_draw->crop.h;
386
387 /* Output as an embedded eps */
388
389 fputs ("%!PS-Adobe-2.0 EPSF-2.0\n",file);
390 fputs ("%%BoundingBox: ",file);
391 fprintf (file," 0 0 %u %u\n",width,height);
392
393 fprintf (file," 0 %d translate\n",1);
394 fprintf (file," %u %u scale\n",width,height);
395
396 /* I'm going to assume it's a color image - TODO: monochrome */
397
398 fprintf (file," /picstr %u 3 mul string def\n",width);
399
400 fprintf (file," %u %u 8\n",width,height);
401
402 fprintf (file," [ %u 0 0 %u 0 0 ]\n",width,height);
403
404 fputs (" { currentfile picstr readhexstring pop } false 3\n",file);
405
406 fputs (" colorimage\n",file);
407
408 for (j = 0; j < height; j++)
409 { k = 0;
410 for (i = 0; i < width; i++)
411 { if (k == 78)
412 { buffer[k++] = '\n';
413 buffer[k] = 0;
414 fputs (buffer,file);
415 k = 0;
416 }
417
418 wmf_ipa_bmp_color (API,&(bmp_draw->bmp),&rgb,ui_x+i,ui_y+j);
419
420 buffer[k++] = hex[(rgb.r & 0xf0) >> 4];
421 buffer[k++] = hex[ rgb.r & 0x0f ];
422 buffer[k++] = hex[(rgb.g & 0xf0) >> 4];
423 buffer[k++] = hex[ rgb.g & 0x0f ];
424 buffer[k++] = hex[(rgb.b & 0xf0) >> 4];
425 buffer[k++] = hex[ rgb.b & 0x0f ];
426 }
427 if (k > 0)
428 { buffer[k++] = '\n';
429 buffer[k] = 0;
430 fputs (buffer,file);
431 }
432 }
433
434 fputs ("showpage\n",file);
435
436 fclose (file);
437
438 return;
439 }
440
wmf_ipa_bmp_read(wmfAPI * API,wmfBMP_Read_t * bmp_read)441 void wmf_ipa_bmp_read (wmfAPI* API,wmfBMP_Read_t* bmp_read)
442 { wmfBMP* bmp = 0;
443
444 BMPSource source;
445
446 BMPData* data;
447
448 WMF_DEBUG (API,"~~~~~~~~wmf_[ipa_]bmp_read");
449
450 bmp = &(bmp_read->bmp);
451
452 bmp->data = 0;
453
454 data = (BMPData*) wmf_malloc (API,sizeof (BMPData));
455
456 if (ERR (API))
457 { if (API->flags & WMF_OPT_IGNORE_NONFATAL)
458 { API->err = wmf_E_None;
459 bmp->data = 0;
460 }
461 WMF_DEBUG (API,"bailing...");
462 return;
463 }
464
465 data->NColors = 0;
466 data->rgb = 0;
467 data->image = 0;
468
469 bmp->width = bmp_read->width;
470 bmp->height = bmp_read->height;
471
472 bmp->data = (void*) data;
473
474 source.begin = bmp_read->buffer;
475 source.end = bmp_read->buffer + bmp_read->length;
476 source.ptr = bmp_read->buffer;
477
478 ReadBMPImage (API,bmp,&source);
479
480 if (ERR (API))
481 { if (API->flags & WMF_OPT_IGNORE_NONFATAL)
482 { API->err = wmf_E_None;
483 bmp->data = 0;
484 }
485 }
486 }
487
wmf_ipa_bmp_free(wmfAPI * API,wmfBMP * bmp)488 void wmf_ipa_bmp_free (wmfAPI* API,wmfBMP* bmp)
489 { BMPData* data;
490
491 WMF_DEBUG (API,"~~~~~~~~wmf_[ipa_]bmp_free");
492
493 if (bmp->data == 0) return;
494
495 data = (BMPData*) bmp->data;
496
497 if (data->rgb) wmf_free (API,(void*) data->rgb );
498 if (data->image) wmf_free (API,(void*) data->image);
499
500 wmf_free (API,bmp->data);
501
502 bmp->data = 0;
503 }
504
wmf_ipa_bmp_copy(wmfAPI * API,wmfBMP * bmp,unsigned int width,unsigned int height)505 wmfBMP wmf_ipa_bmp_copy (wmfAPI* API,wmfBMP* bmp,unsigned int width,unsigned int height)
506 { wmfBMP copy;
507
508 wmfRGB rgb;
509
510 BMPData* copy_data = 0;
511 BMPData* data = 0;
512
513 float x;
514 float y;
515
516 unsigned int i;
517 unsigned int j;
518
519 int opacity;
520
521 size_t size;
522
523 WMF_DEBUG (API,"~~~~~~~~wmf_[ipa_]bmp_copy");
524
525 copy.width = width;
526 copy.height = height;
527
528 copy.data = 0;
529
530 if (bmp->data == 0) return (copy);
531
532 data = (BMPData*) bmp->data;
533
534 copy.data = wmf_malloc (API,sizeof (BMPData));
535
536 if (ERR (API))
537 { WMF_DEBUG (API,"bailing...");
538 return (copy);
539 }
540
541 copy_data = (BMPData*) copy.data;
542
543 if (data->rgb)
544 { copy_data->NColors = data->NColors;
545 copy_data->rgb = (wmfRGB*) wmf_malloc (API,data->NColors * sizeof (wmfRGB));
546
547 if (ERR (API))
548 { WMF_DEBUG (API,"bailing...");
549 wmf_free (API,copy.data);
550 copy.data = 0;
551 return (copy);
552 }
553 }
554 else
555 { copy_data->NColors = 0;
556 copy_data->rgb = 0;
557 }
558
559 copy_data->bits_per_pixel = data->bits_per_pixel;
560
561 copy_data->bytes_per_line = 4 * ((width * copy_data->bits_per_pixel + 31) / 32);
562
563 size = height * copy_data->bytes_per_line * sizeof (unsigned char);
564
565 copy_data->image = (unsigned char*) wmf_malloc (API,size);
566
567 if (ERR (API))
568 { WMF_DEBUG (API,"bailing...");
569 if (copy_data->rgb) wmf_free (API,copy_data->rgb);
570 wmf_free (API,copy.data);
571 copy.data = 0;
572 return (copy);
573 }
574
575 copy_data->masked = data->masked;
576 copy_data->flipped = data->flipped;
577
578 /* Data structure is complete, now to copy the image... */
579
580 for (j = 0; j < height; j++)
581 { y = (float) ((double) j * (double) bmp->height / (double) height);
582 for (i = 0; i < width; i++)
583 { x = (float) ((double) i * (double) bmp->width / (double) width);
584
585 opacity = wmf_ipa_bmp_interpolate (API,bmp,&rgb,x,y);
586
587 if (opacity < 0) break; /* Shouldn't occur, I think */
588
589 wmf_ipa_bmp_setcolor (API,©,&rgb,(unsigned char) opacity,i,j);
590 }
591 }
592
593 return (copy);
594 }
595
wmf_ipa_bmp_color(wmfAPI * API,wmfBMP * bmp,wmfRGB * rgb,unsigned int x,unsigned int y)596 int wmf_ipa_bmp_color (wmfAPI* API,wmfBMP* bmp,wmfRGB* rgb,unsigned int x,unsigned int y)
597 { int status = -1; /* error value */
598
599 /* WMF_DEBUG (API,"~~~~~~~~wmf_[ipa_]bmp_color"); */
600
601 rgb->r = 0;
602 rgb->g = 0;
603 rgb->b = 0;
604
605 if (bmp->data && x < bmp->width && y < bmp->height)
606 { status = ExtractColor (API,bmp,rgb,x,y);
607 }
608 else if ((API->flags & WMF_OPT_IGNORE_NONFATAL) == 0)
609 { WMF_ERROR (API,"Point outside bitmap");
610 API->err = wmf_E_Glitch;
611 }
612
613 return (status);
614 }
615
wmf_ipa_bmp_interpolate(wmfAPI * API,wmfBMP * bmp,wmfRGB * rgb,float x,float y)616 int wmf_ipa_bmp_interpolate (wmfAPI* API,wmfBMP* bmp,wmfRGB* rgb,float x,float y)
617 { int status = -1; /* error value */
618
619 unsigned int i1;
620 unsigned int i2;
621 unsigned int j1;
622 unsigned int j2;
623
624 unsigned char o_11;
625 unsigned char o_12;
626 unsigned char o_21;
627 unsigned char o_22;
628
629 float f_11;
630 float f_12;
631 float f_21;
632 float f_22;
633
634 wmfRGB rgb_11;
635 wmfRGB rgb_12;
636 wmfRGB rgb_21;
637 wmfRGB rgb_22;
638
639 /* WMF_DEBUG (API,"~~~~~~~~wmf_[ipa_]bmp_interpolate"); */
640
641 i1 = (unsigned int) floor (x);
642 i2 = (unsigned int) ceil (x);
643 j1 = (unsigned int) floor (y);
644 j2 = (unsigned int) ceil (y);
645
646 if (i1 >= (unsigned int)(bmp->width - 2))
647 { i1 = bmp->width - 2;
648 i2 = bmp->width - 1;
649 }
650
651 if (j1 >= (unsigned int)(bmp->height - 2))
652 { j1 = bmp->height - 2;
653 j2 = bmp->height - 1;
654 }
655
656 if ((i1 == i2) && (j1 == j2)) return (wmf_ipa_bmp_color (API,bmp,rgb,i1,j1));
657
658 i2 = i1 + 1;
659 j2 = j1 + 1;
660
661 rgb->r = 0;
662 rgb->g = 0;
663 rgb->b = 0;
664
665 status = wmf_ipa_bmp_color (API,bmp,&rgb_11,i1,j1);
666 if (status < 0) return (status);
667 o_11 = (unsigned char) status;
668
669 status = wmf_ipa_bmp_color (API,bmp,&rgb_12,i2,j1);
670 if (status < 0) return (status);
671 o_12 = (unsigned char) status;
672
673 status = wmf_ipa_bmp_color (API,bmp,&rgb_21,i1,j2);
674 if (status < 0) return (status);
675 o_21 = (unsigned char) status;
676
677 status = wmf_ipa_bmp_color (API,bmp,&rgb_22,i2,j2);
678 if (status < 0) return (status);
679 o_22 = (unsigned char) status;
680
681 x -= (float) i1;
682 y -= (float) j1;
683
684 f_11 = (1 - x) * (1 - y);
685 f_12 = x * (1 - y);
686 f_22 = x * y;
687 f_21 = (1 - x) * y;
688
689 status = (int) (rgb_11.r * f_11 + rgb_21.r * f_21 + rgb_22.r * f_22 + rgb_12.r * f_12);
690 rgb->r = (unsigned char) ((status < 0) ? 0 : ((status > 255) ? 255 : status));
691
692 status = (int) (rgb_11.g * f_11 + rgb_21.g * f_21 + rgb_22.g * f_22 + rgb_12.g * f_12);
693 rgb->g = (unsigned char) ((status < 0) ? 0 : ((status > 255) ? 255 : status));
694
695 status = (int) (rgb_11.b * f_11 + rgb_21.b * f_21 + rgb_22.b * f_22 + rgb_12.b * f_12);
696 rgb->b = (unsigned char) ((status < 0) ? 0 : ((status > 255) ? 255 : status));
697
698 status = (int) (o_11 * f_11 + o_21 * f_21 + o_22 * f_22 + o_12 * f_12);
699 status = ((status < 0) ? 0 : ((status > 255) ? 255 : status));
700
701 return (status);
702 }
703
wmf_ipa_bmp_setcolor(wmfAPI * API,wmfBMP * bmp,wmfRGB * rgb,unsigned char opacity,unsigned int x,unsigned int y)704 void wmf_ipa_bmp_setcolor (wmfAPI* API,wmfBMP* bmp,wmfRGB* rgb,unsigned char opacity,
705 unsigned int x,unsigned int y)
706 {
707 /* WMF_DEBUG (API,"~~~~~~~~wmf_[ipa_]bmp_setcolor"); */
708
709 if (bmp->data && x < bmp->width && y < bmp->height)
710 { SetColor (API,bmp,rgb,opacity,x,y);
711 }
712 else if ((API->flags & WMF_OPT_IGNORE_NONFATAL) == 0)
713 { WMF_ERROR (API,"Point outside bitmap");
714 API->err = wmf_E_Glitch;
715 }
716 }
717
718 /* Following source adapted from ImageMagick-5.2.7's coders/bmp.c, hence:
719 %
720 %
721 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
722 % %
723 % %
724 % %
725 % BBBB M M PPPP %
726 % B B MM MM P P %
727 % BBBB M M M PPPP %
728 % B B M M P %
729 % BBBB M M P %
730 % %
731 % %
732 % Read/Write ImageMagick Image Format. %
733 % %
734 % %
735 % Software Design %
736 % John Cristy %
737 % July 1992 %
738 % %
739 % %
740 % Copyright (C) 2001 ImageMagick Studio, a non-profit organization dedicated %
741 % to making software imaging solutions freely available. %
742 % %
743 % Permission is hereby granted, free of charge, to any person obtaining a %
744 % copy of this software and associated documentation files ("ImageMagick"), %
745 % to deal in ImageMagick without restriction, including without limitation %
746 % the rights to use, copy, modify, merge, publish, distribute, sublicense, %
747 % and/or sell copies of ImageMagick, and to permit persons to whom the %
748 % ImageMagick is furnished to do so, subject to the following conditions: %
749 % %
750 % The above copyright notice and this permission notice shall be included in %
751 % all copies or substantial portions of ImageMagick. %
752 % %
753 % The software is provided "as is", without warranty of any kind, express or %
754 % implied, including but not limited to the warranties of merchantability, %
755 % fitness for a particular purpose and noninfringement. In no event shall %
756 % ImageMagick Studio be liable for any claim, damages or other liability, %
757 % whether in an action of contract, tort or otherwise, arising from, out of %
758 % or in connection with ImageMagick or the use or other dealings in %
759 % ImageMagick. %
760 % %
761 % Except as contained in this notice, the name of the ImageMagick Studio %
762 % shall not be used in advertising or otherwise to promote the sale, use or %
763 % other dealings in ImageMagick without prior written authorization from the %
764 % ImageMagick Studio. %
765 % %
766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
767 %
768 %
769 */
770
ReadBlob(BMPSource * src,size_t length,unsigned char * buffer)771 static size_t ReadBlob (BMPSource* src,size_t length,unsigned char* buffer)
772 { size_t count = 0;
773
774 for (count = 0; count < length; count++)
775 { if (src->ptr >= src->end) break;
776
777 buffer[count] = (*(src->ptr));
778 src->ptr++;
779 }
780
781 return (count);
782 }
783
ReadBlobByte(BMPSource * src)784 static int ReadBlobByte (BMPSource* src)
785 { int byte;
786
787 if (src->ptr >= src->end) return (EOF);
788
789 byte = (int) (*(src->ptr));
790 src->ptr++;
791
792 return (byte);
793 }
794
ReadBlobLSBShort(BMPSource * src)795 static unsigned short ReadBlobLSBShort (BMPSource* src)
796 { unsigned short value;
797
798 unsigned char buffer[2];
799
800 value = ReadBlob (src,2,buffer);
801
802 if (value < 2) return (~value);
803
804 value = buffer[1] << 8;
805 value |= buffer[0];
806
807 return (value);
808 }
809
ReadBlobLSBLong(BMPSource * src)810 static unsigned int ReadBlobLSBLong (BMPSource* src)
811 { unsigned int value;
812
813 unsigned char buffer[4];
814
815 value = ReadBlob (src,4,buffer);
816
817 if (value < 4) return (~value); /* i.e., = -1 */
818
819 value = buffer[3] << 24;
820 value |= buffer[2] << 16;
821 value |= buffer[1] << 8;
822 value |= buffer[0];
823
824 return (value);
825 }
826
TellBlob(BMPSource * src)827 static long TellBlob (BMPSource* src)
828 { return ((long) (src->ptr - src->begin));
829 }
830
831 /*
832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 % %
834 % %
835 % %
836 % D e c o d e I m a g e %
837 % %
838 % %
839 % %
840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
841 %
842 % Method DecodeImage unpacks the packed image pixels into runlength-encoded
843 % pixel packets.
844 %
845 % A description of each parameter follows:
846 %
847 % o compression: A value of 1 means the compressed pixels are runlength
848 % encoded for a 256-color bitmap. A value of 2 means a 16-color bitmap.
849 %
850 % o pixels: The address of a byte (8 bits) array of pixel data created by
851 % the decoding process.
852 %
853 %
854 */
DecodeImage(wmfBMP * bmp,BMPSource * src,unsigned int compression,unsigned char * pixels)855 static int DecodeImage (wmfBMP* bmp,BMPSource* src,unsigned int compression,unsigned char* pixels)
856 { int byte;
857 int count;
858 int i;
859
860 U16 x;
861 U16 y;
862
863 U32 u;
864
865 unsigned char* q;
866 unsigned char* end;
867
868 for (u = 0; u < ((U32) bmp->width * (U32) bmp->height); u++) pixels[u] = 0;
869
870 byte = 0;
871 x = 0;
872 q = pixels;
873 end = pixels + bmp->width * bmp->height;
874
875 for (y = 0; y < bmp->height; )
876 { count = ReadBlobByte (src);
877 if (count == EOF) break;
878 if (count != 0)
879 { /* Encoded mode. */
880 byte = ReadBlobByte (src);
881 for (i = 0; i < count; i++)
882 {
883 if (q == end)
884 return 0;
885 if (compression == 1)
886 { (*(q++)) = (unsigned char) byte;
887 }
888 else
889 { (*(q++)) = ((i & 0x01) ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
890 x++;
891 }
892 }
893 }
894 else
895 { /* Escape mode. */
896 count = ReadBlobByte (src);
897 if (count == 0x01) return 1;
898 switch (count)
899 {
900 case 0x00:
901 { /* End of line. */
902 x = 0;
903 y++;
904 if (y >= bmp->height)
905 return 0;
906 q = pixels + y * bmp->width;
907 break;
908 }
909 case 0x02:
910 { /* Delta mode. */
911 x += ReadBlobByte (src);
912 y += ReadBlobByte (src);
913 if (y >= bmp->height)
914 return 0;
915 if (x >= bmp->width)
916 return 0;
917 q = pixels + y * bmp->width + x;
918 break;
919 }
920 default:
921 { /* Absolute mode. */
922 for (i = 0; i < count; i++)
923 {
924 if (q == end)
925 return 0;
926 if (compression == 1)
927 { (*(q++)) = ReadBlobByte (src);
928 }
929 else
930 { if ((i & 0x01) == 0) byte = ReadBlobByte (src);
931 (*(q++)) = ((i & 0x01) ? (byte & 0x0f) : ((byte >> 4) & 0x0f));
932 }
933 x++;
934 }
935 /* Read pad byte. */
936 if (compression == 1)
937 { if (count & 0x01) byte = ReadBlobByte (src);
938 }
939 else
940 { if (((count & 0x03) == 1) || ((count & 0x03) == 2))
941 { byte = ReadBlobByte (src);
942 }
943 }
944 break;
945 }
946 }
947 }
948 /* ?? TODO if (QuantumTick (y,image->rows)) MagickMonitor (LoadImageText,y,image->rows); */
949 }
950 ReadBlobByte (src); /* end of line */
951 ReadBlobByte (src);
952
953 return 1;
954 }
955
956 /*
957 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
958 % %
959 % %
960 % %
961 % R e a d B M P I m a g e %
962 % %
963 % %
964 % %
965 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
966 %
967 % Method ReadBMPImage reads a Microsoft Windows bitmap image file and
968 % returns it. It allocates the memory necessary for the new Image structure
969 % and returns a pointer to the new image.
970 %
971 % The format of the ReadBMPImage method is:
972 %
973 % image=ReadBMPImage(image_info)
974 %
975 % A description of each parameter follows:
976 %
977 % o image: Method ReadBMPImage returns a pointer to the image after
978 % reading. A null image is returned if there is a memory shortage or
979 % if the image cannot be read.
980 %
981 % o image_info: Specifies a pointer to an ImageInfo structure.
982 %
983 % o exception: return any errors or warnings in this structure.
984 %
985 %
986 */
ReadBMPImage(wmfAPI * API,wmfBMP * bmp,BMPSource * src)987 static void ReadBMPImage (wmfAPI* API,wmfBMP* bmp,BMPSource* src)
988 { BMPInfo bmp_info;
989
990 BMPData* data = 0;
991
992 long start_position = 0;
993
994 unsigned char packet[4];
995
996 unsigned int bytes_per_line;
997 unsigned int image_size;
998 unsigned int packet_size;
999 unsigned int i;
1000
1001 unsigned long u;
1002
1003 size_t bytes_read;
1004
1005 data = (BMPData*) bmp->data;
1006
1007 memset (&bmp_info,0,sizeof (BMPInfo));
1008
1009 bmp_info.ba_offset = 0;
1010
1011 bmp_info.size = ReadBlobLSBLong (src);
1012
1013 if (bmp_info.size == 12)
1014 { /* OS/2 BMP image file. */
1015 bmp_info.width = ReadBlobLSBShort (src);
1016 bmp_info.height = ReadBlobLSBShort (src);
1017 bmp_info.planes = ReadBlobLSBShort (src);
1018
1019 bmp_info.bits_per_pixel = ReadBlobLSBShort (src);
1020
1021 bmp_info.x_pixels = 0;
1022 bmp_info.y_pixels = 0;
1023 bmp_info.number_colors = 0;
1024 bmp_info.compression = 0;
1025 bmp_info.image_size = 0;
1026 }
1027 else
1028 { /* Microsoft Windows BMP image file. */
1029 bmp_info.width = ReadBlobLSBLong (src);
1030 bmp_info.height = ReadBlobLSBLong (src);
1031 bmp_info.planes = ReadBlobLSBShort (src);
1032
1033 bmp_info.bits_per_pixel = ReadBlobLSBShort (src);
1034
1035 bmp_info.compression = ReadBlobLSBLong (src);
1036 bmp_info.image_size = ReadBlobLSBLong (src);
1037
1038 bmp_info.x_pixels = ReadBlobLSBLong (src);
1039 bmp_info.y_pixels = ReadBlobLSBLong (src);
1040
1041 bmp_info.number_colors = ReadBlobLSBLong (src);
1042
1043 bmp_info.colors_important = ReadBlobLSBLong (src);
1044
1045 for (u = 0; u < (bmp_info.size - 40); u++) ReadBlobByte (src);
1046
1047 if ( (bmp_info.compression == 3)
1048 && ((bmp_info.bits_per_pixel == 16) || (bmp_info.bits_per_pixel == 32)) )
1049 { bmp_info.red_mask = ReadBlobLSBShort (src);
1050 bmp_info.green_mask = ReadBlobLSBShort (src);
1051 bmp_info.blue_mask = ReadBlobLSBShort (src);
1052
1053 if (bmp_info.size > 40)
1054 { /* Read color management information. */
1055 bmp_info.alpha_mask = ReadBlobLSBShort (src);
1056 bmp_info.colorspace = ReadBlobLSBLong (src);
1057
1058 bmp_info.red_primary.x = ReadBlobLSBLong (src);
1059 bmp_info.red_primary.y = ReadBlobLSBLong (src);
1060 bmp_info.red_primary.z = ReadBlobLSBLong (src);
1061
1062 bmp_info.green_primary.x = ReadBlobLSBLong (src);
1063 bmp_info.green_primary.y = ReadBlobLSBLong (src);
1064 bmp_info.green_primary.z = ReadBlobLSBLong (src);
1065
1066 bmp_info.blue_primary.x = ReadBlobLSBLong (src);
1067 bmp_info.blue_primary.y = ReadBlobLSBLong (src);
1068 bmp_info.blue_primary.z = ReadBlobLSBLong (src);
1069
1070 bmp_info.gamma_scale.x = ReadBlobLSBShort (src);
1071 bmp_info.gamma_scale.y = ReadBlobLSBShort (src);
1072 bmp_info.gamma_scale.z = ReadBlobLSBShort (src);
1073 }
1074 }
1075 }
1076
1077 if (bmp_info.height < 0)
1078 { bmp_info.height = - bmp_info.height;
1079 data->flipped = 1;
1080 }
1081 else
1082 { data->flipped = 0;
1083 }
1084
1085 /* WMF may change bitmap size without changing bitmap header
1086 */
1087 if (bmp->width == 0) bmp->width = (U16) bmp_info.width;
1088 if (bmp->height == 0) bmp->height = (U16) bmp_info.height;
1089
1090 data->NColors = 0;
1091 if ((bmp_info.number_colors != 0) || (bmp_info.bits_per_pixel < 16))
1092 { data->NColors = (unsigned int) bmp_info.number_colors;
1093 }
1094
1095 if (data->NColors > 0)
1096 { /* Read BMP raster colormap. */
1097 data->rgb = (wmfRGB*) wmf_malloc (API,data->NColors * sizeof (wmfRGB));
1098
1099 if (ERR (API))
1100 { WMF_DEBUG (API,"bailing...");
1101 return;
1102 }
1103
1104 if (bmp_info.size == 12) packet_size = 3;
1105 else packet_size = 4;
1106
1107 for (i = 0; i < data->NColors; i++)
1108 { bytes_read = ReadBlob (src,packet_size,packet);
1109 if (bytes_read < packet_size)
1110 { WMF_ERROR (API,"Unexpected EOF");
1111 API->err = wmf_E_EOF;
1112 break;
1113 }
1114 data->rgb[i].b = packet[0];
1115 data->rgb[i].g = packet[1];
1116 data->rgb[i].r = packet[2];
1117 }
1118
1119 if (ERR (API))
1120 { WMF_DEBUG (API,"bailing...");
1121 return;
1122 }
1123 }
1124
1125 while (TellBlob (src) < (long) (start_position + bmp_info.offset_bits))
1126 { ReadBlobByte (src);
1127 }
1128
1129 /* Read image data. */
1130 if (bmp_info.compression == 2) bmp_info.bits_per_pixel <<= 1;
1131
1132 bytes_per_line = 4 * ((bmp->width * bmp_info.bits_per_pixel + 31) / 32);
1133
1134 image_size = bytes_per_line * bmp->height;
1135
1136 data->image = (unsigned char*) wmf_malloc (API,image_size);
1137
1138 if (ERR (API))
1139 { WMF_DEBUG (API,"bailing...");
1140 return;
1141 }
1142
1143 if ((bmp_info.compression == 0) || (bmp_info.compression == 3))
1144 { bytes_read = ReadBlob (src,image_size,data->image);
1145 if (bytes_read < image_size)
1146 { WMF_ERROR (API,"Unexpected EOF");
1147 API->err = wmf_E_EOF;
1148 }
1149 }
1150 else
1151 {
1152 if (bmp_info.bits_per_pixel == 8) /* Convert run-length encoded raster pixels. */
1153 {
1154 if (!DecodeImage (bmp,src,(unsigned int) bmp_info.compression,data->image))
1155 { WMF_ERROR (API,"corrupt bmp");
1156 API->err = wmf_E_BadFormat;
1157 }
1158 }
1159 else
1160 { WMF_ERROR (API,"Unexpected pixel depth");
1161 API->err = wmf_E_BadFormat;
1162 }
1163 }
1164
1165 if (ERR (API))
1166 { WMF_DEBUG (API,"bailing...");
1167 return;
1168 }
1169
1170 data->bits_per_pixel = bmp_info.bits_per_pixel;
1171 data->bytes_per_line = bytes_per_line;
1172
1173 data->masked = bmp_info.red_mask;
1174 }
1175
ExtractColor(wmfAPI * API,wmfBMP * bmp,wmfRGB * rgb,unsigned int x,unsigned int y)1176 static int ExtractColor (wmfAPI* API,wmfBMP* bmp,wmfRGB* rgb,unsigned int x,unsigned int y)
1177 { int status = 0;
1178
1179 BMPData* data = 0;
1180
1181 int bit;
1182
1183 unsigned int color;
1184
1185 unsigned char opacity = WMF_BMP_OPAQUE;
1186
1187 unsigned char* p;
1188
1189 unsigned short word;
1190
1191 data = (BMPData*) bmp->data;
1192
1193 if (data->flipped) y = (bmp->height - 1) - y;
1194
1195 switch (data->bits_per_pixel)
1196 {
1197 case 1:
1198 { p = data->image + (y * data->bytes_per_line) + (x >> 3);
1199 bit = 0x80 >> (x & 0x07);
1200
1201 if ((*p) & bit) color = 1;
1202 else color = 0;
1203
1204 if (data->rgb && (color < data->NColors))
1205 { (*rgb) = data->rgb[color];
1206 }
1207 else
1208 { if (color)
1209 { rgb->r = 0;
1210 rgb->g = 0;
1211 rgb->b = 0;
1212 }
1213 else
1214 { rgb->r = 0xff;
1215 rgb->g = 0xff;
1216 rgb->b = 0xff;
1217 }
1218 }
1219 break;
1220 }
1221 case 4:
1222 { p = data->image + (y * data->bytes_per_line) + (x >> 1);
1223
1224 if (x & 1) color = (*p) & 0x0f;
1225 else color = ((*p) >> 4) & 0x0f;
1226
1227 if (data->rgb && (color < data->NColors))
1228 { (*rgb) = data->rgb[color];
1229 }
1230 else
1231 { rgb->r = color << 4;
1232 rgb->g = color << 4;
1233 rgb->b = color << 4;
1234 }
1235 break;
1236 }
1237 case 8:
1238 { p = data->image + (y * data->bytes_per_line) + x;
1239
1240 color = (*p);
1241
1242 if (data->rgb && (color < data->NColors))
1243 { (*rgb) = data->rgb[color];
1244 }
1245 else
1246 { rgb->r = color;
1247 rgb->g = color;
1248 rgb->b = color;
1249 }
1250 break;
1251 }
1252 case 16:
1253 { p = data->image + (y * data->bytes_per_line) + (x << 1);
1254
1255 word = (unsigned short) p[0] | (((unsigned short) p[1]) << 8);
1256
1257 if (data->masked == 0)
1258 { rgb->r = ((word >> 10) & 0x1f) << 3;
1259 rgb->g = ((word >> 5) & 0x1f) << 3;
1260 rgb->b = ( word & 0x1f) << 3;
1261 }
1262 else
1263 { rgb->r = ((word >> 11) & 0x1f) << 3;
1264 rgb->g = ((word >> 5) & 0x3f) << 2;
1265 rgb->b = ( word & 0x1f) << 3;
1266 }
1267 break;
1268 }
1269 case 24:
1270 { p = data->image + (y * data->bytes_per_line) + (x + (x << 1));
1271
1272 rgb->b = p[0];
1273 rgb->g = p[1];
1274 rgb->r = p[2];
1275
1276 break;
1277 }
1278 case 32:
1279 { p = data->image + (y * data->bytes_per_line) + (x << 2);
1280
1281 rgb->b = p[0];
1282 rgb->g = p[1];
1283 rgb->r = p[2];
1284
1285 opacity = p[3];
1286
1287 break;
1288 }
1289 default:
1290 if ((API->flags & WMF_OPT_IGNORE_NONFATAL) == 0)
1291 { WMF_ERROR (API,"Bitmap has bad format (illegal color depth)");
1292 API->err = wmf_E_BadFormat;
1293 }
1294 status = -1;
1295 break;
1296 }
1297
1298 if (status == 0) status = (int) opacity;
1299
1300 return (status);
1301 }
1302
SetColor(wmfAPI * API,wmfBMP * bmp,wmfRGB * rgb,unsigned char opacity,unsigned int x,unsigned int y)1303 static void SetColor (wmfAPI* API,wmfBMP* bmp,wmfRGB* rgb,unsigned char opacity,unsigned int x,unsigned int y)
1304 { BMPData* data = 0;
1305
1306 unsigned int i;
1307 unsigned int r_diff;
1308 unsigned int g_diff;
1309 unsigned int b_diff;
1310 unsigned int diff;
1311 unsigned int min_diff;
1312 unsigned int color;
1313
1314 unsigned char bit;
1315
1316 unsigned char* p;
1317
1318 unsigned short word;
1319
1320 data = (BMPData*) bmp->data;
1321
1322 if (data->flipped) y = (bmp->height - 1) - y;
1323
1324 switch (data->bits_per_pixel)
1325 {
1326 case 1:
1327 { p = data->image + (y * data->bytes_per_line) + (x >> 3);
1328 bit = 0x80 >> (x & 0x07);
1329
1330 if (rgb->r || rgb->g || rgb->b)
1331 { (*p) |= ( bit & 0xff);
1332 }
1333 else
1334 { (*p) &= (~bit & 0xff);
1335 }
1336
1337 break;
1338 }
1339 case 4:
1340 { p = data->image + (y * data->bytes_per_line) + (x >> 1);
1341
1342 if (data->rgb == 0) break;
1343
1344 min_diff = 766;
1345 color = 0;
1346 for (i = 0; i < data->NColors; i++)
1347 { r_diff = (unsigned int) ABS ((int) rgb->r - (int) data->rgb[i].r);
1348 g_diff = (unsigned int) ABS ((int) rgb->g - (int) data->rgb[i].g);
1349 b_diff = (unsigned int) ABS ((int) rgb->b - (int) data->rgb[i].b);
1350 diff = r_diff + g_diff + b_diff;
1351 if (min_diff > diff)
1352 { min_diff = diff;
1353 color = i;
1354 }
1355 }
1356
1357 if (x & 1)
1358 { (*p) = ( ((unsigned char) color) | ((*p) & 0x0f));
1359 }
1360 else
1361 { (*p) = ((((unsigned char) color) << 4) | ((*p) & 0xf0));
1362 }
1363
1364 break;
1365 }
1366 case 8:
1367 { p = data->image + (y * data->bytes_per_line) + x;
1368
1369 if (data->rgb == 0) break;
1370
1371 min_diff = 766;
1372 color = 0;
1373 for (i = 0; i < data->NColors; i++)
1374 { r_diff = (unsigned int) ABS ((int) rgb->r - (int) data->rgb[i].r);
1375 g_diff = (unsigned int) ABS ((int) rgb->g - (int) data->rgb[i].g);
1376 b_diff = (unsigned int) ABS ((int) rgb->b - (int) data->rgb[i].b);
1377 diff = r_diff + g_diff + b_diff;
1378 if (min_diff > diff)
1379 { min_diff = diff;
1380 color = i;
1381 }
1382 }
1383
1384 (*p) = (unsigned char) color;
1385
1386 break;
1387 }
1388 case 16:
1389 { p = data->image + (y * data->bytes_per_line) + (x << 1);
1390
1391 word = 0;
1392
1393 if (data->masked == 0)
1394 { word |= (rgb->r >> 3) << 10;
1395 word |= (rgb->g >> 3) << 5;
1396 word |= rgb->b >> 3;
1397 }
1398 else
1399 { word |= (rgb->r >> 3) << 11;
1400 word |= (rgb->g >> 2) << 5;
1401 word |= rgb->b >> 3;
1402 }
1403
1404 p[0] = (unsigned char) ( word & 0x00ff );
1405 p[1] = (unsigned char) ((word & 0xff00) >> 8);
1406
1407 break;
1408 }
1409 case 24:
1410 { p = data->image + (y * data->bytes_per_line) + (x + (x << 1));
1411
1412 p[0] = rgb->b;
1413 p[1] = rgb->g;
1414 p[2] = rgb->r;
1415
1416 break;
1417 }
1418 case 32:
1419 { p = data->image + (y * data->bytes_per_line) + (x << 2);
1420
1421 p[0] = rgb->b;
1422 p[1] = rgb->g;
1423 p[2] = rgb->r;
1424
1425 p[3] = opacity;
1426
1427 break;
1428 }
1429 default:
1430 if ((API->flags & WMF_OPT_IGNORE_NONFATAL) == 0)
1431 { WMF_ERROR (API,"Bitmap has bad format (illegal color depth)");
1432 API->err = wmf_E_BadFormat;
1433 }
1434 break;
1435 }
1436 }
1437
1438