1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % W W PPPP GGGG %
6 % W W P P G %
7 % W W W PPPP G GGG %
8 % WW WW P G G %
9 % W W P GGG %
10 % %
11 % %
12 % Read WordPerfect Image Format %
13 % %
14 % Software Design %
15 % Jaroslav Fojtik %
16 % June 2000 %
17 % %
18 % %
19 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
20 % dedicated to making software imaging solutions freely available. %
21 % %
22 % You may not use this file except in compliance with the License. You may %
23 % obtain a copy of the License at %
24 % %
25 % http://www.imagemagick.org/script/license.php %
26 % %
27 % Unless required by applicable law or agreed to in writing, software %
28 % distributed under the License is distributed on an "AS IS" BASIS, %
29 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
30 % See the License for the specific language governing permissions and %
31 % limitations under the License. %
32 % %
33 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
34 %
35 %
36 */
37
38 /*
39 Include declarations.
40 */
41 #include "MagickCore/studio.h"
42 #include "MagickCore/blob.h"
43 #include "MagickCore/blob-private.h"
44 #include "MagickCore/color-private.h"
45 #include "MagickCore/colormap.h"
46 #include "MagickCore/colormap-private.h"
47 #include "MagickCore/constitute.h"
48 #include "MagickCore/exception.h"
49 #include "MagickCore/exception-private.h"
50 #include "MagickCore/cache.h"
51 #include "MagickCore/distort.h"
52 #include "MagickCore/image.h"
53 #include "MagickCore/image-private.h"
54 #include "MagickCore/list.h"
55 #include "MagickCore/magic.h"
56 #include "MagickCore/magick.h"
57 #include "MagickCore/memory_.h"
58 #include "MagickCore/resource_.h"
59 #include "MagickCore/pixel-accessor.h"
60 #include "MagickCore/quantum-private.h"
61 #include "MagickCore/static.h"
62 #include "MagickCore/string_.h"
63 #include "MagickCore/module.h"
64 #include "MagickCore/transform.h"
65 #include "MagickCore/utility.h"
66 #include "MagickCore/utility-private.h"
67
68 typedef struct
69 {
70 unsigned char Red;
71 unsigned char Blue;
72 unsigned char Green;
73 } RGB_Record;
74
75 /* Default palette for WPG level 1 */
76 static const RGB_Record WPG1_Palette[256]={
77 { 0, 0, 0}, { 0, 0,168},
78 { 0,168, 0}, { 0,168,168},
79 {168, 0, 0}, {168, 0,168},
80 {168, 84, 0}, {168,168,168},
81 { 84, 84, 84}, { 84, 84,252},
82 { 84,252, 84}, { 84,252,252},
83 {252, 84, 84}, {252, 84,252},
84 {252,252, 84}, {252,252,252}, /*16*/
85 { 0, 0, 0}, { 20, 20, 20},
86 { 32, 32, 32}, { 44, 44, 44},
87 { 56, 56, 56}, { 68, 68, 68},
88 { 80, 80, 80}, { 96, 96, 96},
89 {112,112,112}, {128,128,128},
90 {144,144,144}, {160,160,160},
91 {180,180,180}, {200,200,200},
92 {224,224,224}, {252,252,252}, /*32*/
93 { 0, 0,252}, { 64, 0,252},
94 {124, 0,252}, {188, 0,252},
95 {252, 0,252}, {252, 0,188},
96 {252, 0,124}, {252, 0, 64},
97 {252, 0, 0}, {252, 64, 0},
98 {252,124, 0}, {252,188, 0},
99 {252,252, 0}, {188,252, 0},
100 {124,252, 0}, { 64,252, 0}, /*48*/
101 { 0,252, 0}, { 0,252, 64},
102 { 0,252,124}, { 0,252,188},
103 { 0,252,252}, { 0,188,252},
104 { 0,124,252}, { 0, 64,252},
105 {124,124,252}, {156,124,252},
106 {188,124,252}, {220,124,252},
107 {252,124,252}, {252,124,220},
108 {252,124,188}, {252,124,156}, /*64*/
109 {252,124,124}, {252,156,124},
110 {252,188,124}, {252,220,124},
111 {252,252,124}, {220,252,124},
112 {188,252,124}, {156,252,124},
113 {124,252,124}, {124,252,156},
114 {124,252,188}, {124,252,220},
115 {124,252,252}, {124,220,252},
116 {124,188,252}, {124,156,252}, /*80*/
117 {180,180,252}, {196,180,252},
118 {216,180,252}, {232,180,252},
119 {252,180,252}, {252,180,232},
120 {252,180,216}, {252,180,196},
121 {252,180,180}, {252,196,180},
122 {252,216,180}, {252,232,180},
123 {252,252,180}, {232,252,180},
124 {216,252,180}, {196,252,180}, /*96*/
125 {180,220,180}, {180,252,196},
126 {180,252,216}, {180,252,232},
127 {180,252,252}, {180,232,252},
128 {180,216,252}, {180,196,252},
129 {0,0,112}, {28,0,112},
130 {56,0,112}, {84,0,112},
131 {112,0,112}, {112,0,84},
132 {112,0,56}, {112,0,28}, /*112*/
133 {112,0,0}, {112,28,0},
134 {112,56,0}, {112,84,0},
135 {112,112,0}, {84,112,0},
136 {56,112,0}, {28,112,0},
137 {0,112,0}, {0,112,28},
138 {0,112,56}, {0,112,84},
139 {0,112,112}, {0,84,112},
140 {0,56,112}, {0,28,112}, /*128*/
141 {56,56,112}, {68,56,112},
142 {84,56,112}, {96,56,112},
143 {112,56,112}, {112,56,96},
144 {112,56,84}, {112,56,68},
145 {112,56,56}, {112,68,56},
146 {112,84,56}, {112,96,56},
147 {112,112,56}, {96,112,56},
148 {84,112,56}, {68,112,56}, /*144*/
149 {56,112,56}, {56,112,69},
150 {56,112,84}, {56,112,96},
151 {56,112,112}, {56,96,112},
152 {56,84,112}, {56,68,112},
153 {80,80,112}, {88,80,112},
154 {96,80,112}, {104,80,112},
155 {112,80,112}, {112,80,104},
156 {112,80,96}, {112,80,88}, /*160*/
157 {112,80,80}, {112,88,80},
158 {112,96,80}, {112,104,80},
159 {112,112,80}, {104,112,80},
160 {96,112,80}, {88,112,80},
161 {80,112,80}, {80,112,88},
162 {80,112,96}, {80,112,104},
163 {80,112,112}, {80,114,112},
164 {80,96,112}, {80,88,112}, /*176*/
165 {0,0,64}, {16,0,64},
166 {32,0,64}, {48,0,64},
167 {64,0,64}, {64,0,48},
168 {64,0,32}, {64,0,16},
169 {64,0,0}, {64,16,0},
170 {64,32,0}, {64,48,0},
171 {64,64,0}, {48,64,0},
172 {32,64,0}, {16,64,0}, /*192*/
173 {0,64,0}, {0,64,16},
174 {0,64,32}, {0,64,48},
175 {0,64,64}, {0,48,64},
176 {0,32,64}, {0,16,64},
177 {32,32,64}, {40,32,64},
178 {48,32,64}, {56,32,64},
179 {64,32,64}, {64,32,56},
180 {64,32,48}, {64,32,40}, /*208*/
181 {64,32,32}, {64,40,32},
182 {64,48,32}, {64,56,32},
183 {64,64,32}, {56,64,32},
184 {48,64,32}, {40,64,32},
185 {32,64,32}, {32,64,40},
186 {32,64,48}, {32,64,56},
187 {32,64,64}, {32,56,64},
188 {32,48,64}, {32,40,64}, /*224*/
189 {44,44,64}, {48,44,64},
190 {52,44,64}, {60,44,64},
191 {64,44,64}, {64,44,60},
192 {64,44,52}, {64,44,48},
193 {64,44,44}, {64,48,44},
194 {64,52,44}, {64,60,44},
195 {64,64,44}, {60,64,44},
196 {52,64,44}, {48,64,44}, /*240*/
197 {44,64,44}, {44,64,48},
198 {44,64,52}, {44,64,60},
199 {44,64,64}, {44,60,64},
200 {44,55,64}, {44,48,64},
201 {0,0,0}, {0,0,0},
202 {0,0,0}, {0,0,0},
203 {0,0,0}, {0,0,0},
204 {0,0,0}, {0,0,0} /*256*/
205 };
206
207 /*
208 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
209 % %
210 % %
211 % %
212 % I s W P G %
213 % %
214 % %
215 % %
216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
217 %
218 % IsWPG() returns True if the image format type, identified by the magick
219 % string, is WPG.
220 %
221 % The format of the IsWPG method is:
222 %
223 % unsigned int IsWPG(const unsigned char *magick,const size_t length)
224 %
225 % A description of each parameter follows:
226 %
227 % o status: Method IsWPG returns True if the image format type is WPG.
228 %
229 % o magick: compare image format pattern against these bytes.
230 %
231 % o length: Specifies the length of the magick string.
232 %
233 */
IsWPG(const unsigned char * magick,const size_t length)234 static unsigned int IsWPG(const unsigned char *magick,const size_t length)
235 {
236 if (length < 4)
237 return(MagickFalse);
238 if (memcmp(magick,"\377WPC",4) == 0)
239 return(MagickTrue);
240 return(MagickFalse);
241 }
242
243
Rd_WP_DWORD(Image * image,size_t * d)244 static void Rd_WP_DWORD(Image *image,size_t *d)
245 {
246 unsigned char
247 b;
248
249 b=ReadBlobByte(image);
250 *d=b;
251 if (b < 0xFFU)
252 return;
253 b=ReadBlobByte(image);
254 *d=(size_t) b;
255 b=ReadBlobByte(image);
256 *d+=(size_t) b*256l;
257 if (*d < 0x8000)
258 return;
259 *d=(*d & 0x7FFF) << 16;
260 b=ReadBlobByte(image);
261 *d+=(size_t) b;
262 b=ReadBlobByte(image);
263 *d+=(size_t) b*256l;
264 return;
265 }
266
InsertRow(Image * image,unsigned char * p,ssize_t y,int bpp,ExceptionInfo * exception)267 static void InsertRow(Image *image,unsigned char *p,ssize_t y,int bpp,
268 ExceptionInfo *exception)
269 {
270 int
271 bit;
272
273 Quantum
274 index;
275
276 register Quantum
277 *q;
278
279 ssize_t
280 x;
281
282 switch (bpp)
283 {
284 case 1: /* Convert bitmap scanline. */
285 {
286 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
287 if (q == (Quantum *) NULL)
288 break;
289 for (x=0; x < ((ssize_t) image->columns-7); x+=8)
290 {
291 for (bit=0; bit < 8; bit++)
292 {
293 index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
294 SetPixelIndex(image,index,q);
295 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
296 q+=GetPixelChannels(image);
297 }
298 p++;
299 }
300 if ((image->columns % 8) != 0)
301 {
302 for (bit=0; bit < (ssize_t) (image->columns % 8); bit++)
303 {
304 index=((*p) & (0x80 >> bit) ? 0x01 : 0x00);
305 SetPixelIndex(image,index,q);
306 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
307 q+=GetPixelChannels(image);
308 }
309 p++;
310 }
311 if (!SyncAuthenticPixels(image,exception))
312 break;
313 break;
314 }
315 case 2: /* Convert PseudoColor scanline. */
316 {
317 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
318 if (q == (Quantum *) NULL)
319 break;
320 for (x=0; x < ((ssize_t) image->columns-3); x+=4)
321 {
322 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
323 SetPixelIndex(image,index,q);
324 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
325 q+=GetPixelChannels(image);
326 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
327 SetPixelIndex(image,index,q);
328 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
329 q+=GetPixelChannels(image);
330 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,exception);
331 SetPixelIndex(image,index,q);
332 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
333 q+=GetPixelChannels(image);
334 index=ConstrainColormapIndex(image,(*p) & 0x3,exception);
335 SetPixelIndex(image,index,q);
336 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
337 q+=GetPixelChannels(image);
338 p++;
339 }
340 if ((image->columns % 4) != 0)
341 {
342 index=ConstrainColormapIndex(image,(*p >> 6) & 0x3,exception);
343 SetPixelIndex(image,index,q);
344 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
345 q+=GetPixelChannels(image);
346 if ((image->columns % 4) > 1)
347 {
348 index=ConstrainColormapIndex(image,(*p >> 4) & 0x3,exception);
349 SetPixelIndex(image,index,q);
350 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
351 q+=GetPixelChannels(image);
352 if ((image->columns % 4) > 2)
353 {
354 index=ConstrainColormapIndex(image,(*p >> 2) & 0x3,
355 exception);
356 SetPixelIndex(image,index,q);
357 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
358 q+=GetPixelChannels(image);
359 }
360 }
361 p++;
362 }
363 if (SyncAuthenticPixels(image,exception) == MagickFalse)
364 break;
365 break;
366 }
367
368 case 4: /* Convert PseudoColor scanline. */
369 {
370 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
371 if (q == (Quantum *) NULL)
372 break;
373 for (x=0; x < ((ssize_t) image->columns-1); x+=2)
374 {
375 index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
376 SetPixelIndex(image,index,q);
377 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
378 q+=GetPixelChannels(image);
379 index=ConstrainColormapIndex(image,(*p) & 0x0f,exception);
380 SetPixelIndex(image,index,q);
381 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
382 p++;
383 q+=GetPixelChannels(image);
384 }
385 if ((image->columns % 2) != 0)
386 {
387 index=ConstrainColormapIndex(image,(*p >> 4) & 0x0f,exception);
388 SetPixelIndex(image,index,q);
389 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
390 p++;
391 q+=GetPixelChannels(image);
392 }
393 if (SyncAuthenticPixels(image,exception) == MagickFalse)
394 break;
395 break;
396 }
397 case 8: /* Convert PseudoColor scanline. */
398 {
399 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
400 if (q == (Quantum *) NULL) break;
401
402 for (x=0; x < (ssize_t) image->columns; x++)
403 {
404 index=ConstrainColormapIndex(image,*p,exception);
405 SetPixelIndex(image,index,q);
406 SetPixelViaPixelInfo(image,image->colormap+(ssize_t) index,q);
407 p++;
408 q+=GetPixelChannels(image);
409 }
410 if (SyncAuthenticPixels(image,exception) == MagickFalse)
411 break;
412 }
413 break;
414
415 case 24: /* Convert DirectColor scanline. */
416 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
417 if (q == (Quantum *) NULL)
418 break;
419 for (x=0; x < (ssize_t) image->columns; x++)
420 {
421 SetPixelRed(image,ScaleCharToQuantum(*p++),q);
422 SetPixelGreen(image,ScaleCharToQuantum(*p++),q);
423 SetPixelBlue(image,ScaleCharToQuantum(*p++),q);
424 q+=GetPixelChannels(image);
425 }
426 if (!SyncAuthenticPixels(image,exception))
427 break;
428 break;
429 }
430 }
431
432
433 /* Helper for WPG1 raster reader. */
434 #define InsertByte(b) \
435 { \
436 BImgBuff[x]=b; \
437 x++; \
438 if((ssize_t) x>=ldblk) \
439 { \
440 InsertRow(image,BImgBuff,(ssize_t) y,bpp,exception); \
441 x=0; \
442 y++; \
443 } \
444 }
445 /* WPG1 raster reader. */
UnpackWPGRaster(Image * image,int bpp,ExceptionInfo * exception)446 static int UnpackWPGRaster(Image *image,int bpp,ExceptionInfo *exception)
447 {
448 int
449 x,
450 y,
451 i;
452
453 unsigned char
454 bbuf,
455 *BImgBuff,
456 RunCount;
457
458 ssize_t
459 ldblk;
460
461 x=0;
462 y=0;
463
464 ldblk=(ssize_t) ((bpp*image->columns+7)/8);
465 BImgBuff=(unsigned char *) AcquireQuantumMemory((size_t) ldblk,
466 8*sizeof(*BImgBuff));
467 if(BImgBuff==NULL) return(-2);
468
469 while(y<(ssize_t) image->rows)
470 {
471 int
472 c;
473
474 c=ReadBlobByte(image);
475 if (c == EOF)
476 break;
477 bbuf=(unsigned char) c;
478 RunCount=bbuf & 0x7F;
479 if(bbuf & 0x80)
480 {
481 if(RunCount) /* repeat next byte runcount * */
482 {
483 bbuf=ReadBlobByte(image);
484 for(i=0;i<(int) RunCount;i++) InsertByte(bbuf);
485 }
486 else { /* read next byte as RunCount; repeat 0xFF runcount* */
487 c=ReadBlobByte(image);
488 if (c < 0)
489 break;
490 RunCount=(unsigned char) c;
491 for(i=0;i<(int) RunCount;i++) InsertByte(0xFF);
492 }
493 }
494 else {
495 if(RunCount) /* next runcount byte are readed directly */
496 {
497 for(i=0;i < (int) RunCount;i++)
498 {
499 bbuf=ReadBlobByte(image);
500 InsertByte(bbuf);
501 }
502 }
503 else { /* repeat previous line runcount* */
504 c=ReadBlobByte(image);
505 if (c < 0)
506 break;
507 RunCount=(unsigned char) c;
508 if(x) { /* attempt to duplicate row from x position: */
509 /* I do not know what to do here */
510 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
511 return(-3);
512 }
513 for(i=0;i < (int) RunCount;i++)
514 {
515 x=0;
516 y++; /* Here I need to duplicate previous row RUNCOUNT* */
517 if(y<2) continue;
518 if(y>(ssize_t) image->rows)
519 {
520 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
521 return(-4);
522 }
523 InsertRow(image,BImgBuff,y-1,bpp,exception);
524 }
525 }
526 }
527 if (EOFBlob(image) != MagickFalse)
528 break;
529 }
530 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
531 return(y <(ssize_t) image->rows ? -5 : 0);
532 }
533
534
535 /* Helper for WPG2 reader. */
536 #define InsertByte6(b) \
537 { \
538 DisableMSCWarning(4310) \
539 if(XorMe)\
540 BImgBuff[x] = (unsigned char)~b;\
541 else\
542 BImgBuff[x] = b;\
543 RestoreMSCWarning \
544 x++; \
545 if((ssize_t) x >= ldblk) \
546 { \
547 InsertRow(image,BImgBuff,(ssize_t) y,bpp,exception); \
548 x=0; \
549 y++; \
550 } \
551 }
552 /* WPG2 raster reader. */
UnpackWPG2Raster(Image * image,int bpp,ExceptionInfo * exception)553 static int UnpackWPG2Raster(Image *image,int bpp,ExceptionInfo *exception)
554 {
555 int
556 RunCount,
557 XorMe = 0;
558
559 size_t
560 x,
561 y;
562
563 ssize_t
564 i,
565 ldblk;
566
567 unsigned int
568 SampleSize=1;
569
570 unsigned char
571 bbuf,
572 *BImgBuff,
573 SampleBuffer[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
574
575 x=0;
576 y=0;
577 ldblk=(ssize_t) ((bpp*image->columns+7)/8);
578 BImgBuff=(unsigned char *) AcquireQuantumMemory((size_t) ldblk,
579 sizeof(*BImgBuff));
580 if(BImgBuff==NULL)
581 return(-2);
582
583 while( y< image->rows)
584 {
585 bbuf=ReadBlobByte(image);
586
587 switch(bbuf)
588 {
589 case 0x7D:
590 SampleSize=ReadBlobByte(image); /* DSZ */
591 if(SampleSize>8)
592 return(-2);
593 if(SampleSize<1)
594 return(-2);
595 break;
596 case 0x7E:
597 (void) FormatLocaleFile(stderr,
598 "\nUnsupported WPG token XOR, please report!");
599 XorMe=!XorMe;
600 break;
601 case 0x7F:
602 RunCount=ReadBlobByte(image); /* BLK */
603 if (RunCount < 0)
604 break;
605 for(i=0; i < SampleSize*(RunCount+1); i++)
606 {
607 InsertByte6(0);
608 }
609 break;
610 case 0xFD:
611 RunCount=ReadBlobByte(image); /* EXT */
612 if (RunCount < 0)
613 break;
614 for(i=0; i<= RunCount;i++)
615 for(bbuf=0; bbuf < SampleSize; bbuf++)
616 InsertByte6(SampleBuffer[bbuf]);
617 break;
618 case 0xFE:
619 RunCount=ReadBlobByte(image); /* RST */
620 if (RunCount < 0)
621 break;
622 if(x!=0)
623 {
624 (void) FormatLocaleFile(stderr,
625 "\nUnsupported WPG2 unaligned token RST x=%.20g, please report!\n"
626 ,(double) x);
627 return(-3);
628 }
629 {
630 /* duplicate the previous row RunCount x */
631 for(i=0;i<=RunCount;i++)
632 {
633 InsertRow(image,BImgBuff,(ssize_t) (image->rows >= y ? y : image->rows-1),
634 bpp,exception);
635 y++;
636 }
637 }
638 break;
639 case 0xFF:
640 RunCount=ReadBlobByte(image); /* WHT */
641 if (RunCount < 0)
642 break;
643 for(i=0; i < SampleSize*(RunCount+1); i++)
644 {
645 InsertByte6(0xFF);
646 }
647 break;
648 default:
649 RunCount=bbuf & 0x7F;
650
651 if(bbuf & 0x80) /* REP */
652 {
653 for(i=0; i < SampleSize; i++)
654 SampleBuffer[i]=ReadBlobByte(image);
655 for(i=0;i<=RunCount;i++)
656 for(bbuf=0;bbuf<SampleSize;bbuf++)
657 InsertByte6(SampleBuffer[bbuf]);
658 }
659 else { /* NRP */
660 for(i=0; i< SampleSize*(RunCount+1);i++)
661 {
662 bbuf=ReadBlobByte(image);
663 InsertByte6(bbuf);
664 }
665 }
666 }
667 if (EOFBlob(image) != MagickFalse)
668 break;
669 }
670 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
671 return(0);
672 }
673
674
675 typedef float tCTM[3][3];
676
LoadWPG2Flags(Image * image,char Precision,float * Angle,tCTM * CTM)677 static unsigned LoadWPG2Flags(Image *image,char Precision,float *Angle,tCTM *CTM)
678 {
679 const unsigned char TPR=1,TRN=2,SKW=4,SCL=8,ROT=0x10,OID=0x20,LCK=0x80;
680 ssize_t x;
681 unsigned DenX;
682 unsigned Flags;
683
684 (void) memset(*CTM,0,sizeof(*CTM)); /*CTM.erase();CTM.resize(3,3);*/
685 (*CTM)[0][0]=1;
686 (*CTM)[1][1]=1;
687 (*CTM)[2][2]=1;
688
689 Flags=ReadBlobLSBShort(image);
690 if(Flags & LCK) (void) ReadBlobLSBLong(image); /*Edit lock*/
691 if(Flags & OID)
692 {
693 if(Precision==0)
694 {(void) ReadBlobLSBShort(image);} /*ObjectID*/
695 else
696 {(void) ReadBlobLSBLong(image);} /*ObjectID (Double precision)*/
697 }
698 if(Flags & ROT)
699 {
700 x=ReadBlobLSBLong(image); /*Rot Angle*/
701 if(Angle) *Angle=x/65536.0;
702 }
703 if(Flags & (ROT|SCL))
704 {
705 x=ReadBlobLSBLong(image); /*Sx*cos()*/
706 (*CTM)[0][0] = (float)x/0x10000;
707 x=ReadBlobLSBLong(image); /*Sy*cos()*/
708 (*CTM)[1][1] = (float)x/0x10000;
709 }
710 if(Flags & (ROT|SKW))
711 {
712 x=ReadBlobLSBLong(image); /*Kx*sin()*/
713 (*CTM)[1][0] = (float)x/0x10000;
714 x=ReadBlobLSBLong(image); /*Ky*sin()*/
715 (*CTM)[0][1] = (float)x/0x10000;
716 }
717 if(Flags & TRN)
718 {
719 x=ReadBlobLSBLong(image); DenX=ReadBlobLSBShort(image); /*Tx*/
720 if(x>=0) (*CTM)[0][2] = (float)x+(float)DenX/0x10000;
721 else (*CTM)[0][2] = (float)x-(float)DenX/0x10000;
722 x=ReadBlobLSBLong(image); DenX=ReadBlobLSBShort(image); /*Ty*/
723 (*CTM)[1][2]=(float)x + ((x>=0)?1:-1)*(float)DenX/0x10000;
724 if(x>=0) (*CTM)[1][2] = (float)x+(float)DenX/0x10000;
725 else (*CTM)[1][2] = (float)x-(float)DenX/0x10000;
726 }
727 if(Flags & TPR)
728 {
729 x=ReadBlobLSBShort(image); DenX=ReadBlobLSBShort(image); /*Px*/
730 (*CTM)[2][0] = x + (float)DenX/0x10000;;
731 x=ReadBlobLSBShort(image); DenX=ReadBlobLSBShort(image); /*Py*/
732 (*CTM)[2][1] = x + (float)DenX/0x10000;
733 }
734 return(Flags);
735 }
736
737
ExtractPostscript(Image * image,const ImageInfo * image_info,MagickOffsetType PS_Offset,ssize_t PS_Size,ExceptionInfo * exception)738 static Image *ExtractPostscript(Image *image,const ImageInfo *image_info,
739 MagickOffsetType PS_Offset,ssize_t PS_Size,ExceptionInfo *exception)
740 {
741 char
742 postscript_file[MagickPathExtent];
743
744 const MagicInfo
745 *magic_info;
746
747 FILE
748 *ps_file;
749
750 ImageInfo
751 *clone_info;
752
753 Image
754 *image2;
755
756 unsigned char
757 magick[2*MagickPathExtent];
758
759
760 if ((clone_info=CloneImageInfo(image_info)) == NULL)
761 return(image);
762 clone_info->blob=(void *) NULL;
763 clone_info->length=0;
764
765 /* Obtain temporary file */
766 (void) AcquireUniqueFilename(postscript_file);
767 ps_file=fopen_utf8(postscript_file,"wb");
768 if (ps_file == (FILE *) NULL)
769 goto FINISH;
770
771 /* Copy postscript to temporary file */
772 (void) SeekBlob(image,PS_Offset,SEEK_SET);
773 (void) ReadBlob(image, 2*MagickPathExtent, magick);
774
775 (void) SeekBlob(image,PS_Offset,SEEK_SET);
776 while(PS_Size-- > 0)
777 {
778 (void) fputc(ReadBlobByte(image),ps_file);
779 }
780 (void) fclose(ps_file);
781
782 /* Detect file format - Check magic.mgk configuration file. */
783 magic_info=GetMagicInfo(magick,2*MagickPathExtent,exception);
784 if(magic_info == (const MagicInfo *) NULL) goto FINISH_UNL;
785 /* printf("Detected:%s \n",magic_info->name); */
786 if(exception->severity != UndefinedException) goto FINISH_UNL;
787 if(magic_info->name == (char *) NULL) goto FINISH_UNL;
788
789 (void) strncpy(clone_info->magick,magic_info->name,MagickPathExtent);
790
791 /* Read nested image */
792 /*FormatString(clone_info->filename,"%s:%s",magic_info->name,postscript_file);*/
793 FormatLocaleString(clone_info->filename,MagickPathExtent,"%s",postscript_file);
794 image2=ReadImage(clone_info,exception);
795
796 if (!image2)
797 goto FINISH_UNL;
798
799 /*
800 Replace current image with new image while copying base image
801 attributes.
802 */
803 (void) CopyMagickString(image2->filename,image->filename,MagickPathExtent);
804 (void) CopyMagickString(image2->magick_filename,image->magick_filename,MagickPathExtent);
805 (void) CopyMagickString(image2->magick,image->magick,MagickPathExtent);
806 image2->depth=image->depth;
807 DestroyBlob(image2);
808 image2->blob=ReferenceBlob(image->blob);
809
810 if ((image->rows == 0) || (image->columns == 0))
811 DeleteImageFromList(&image);
812
813 AppendImageToList(&image,image2);
814
815 FINISH_UNL:
816 (void) RelinquishUniqueFileResource(postscript_file);
817 FINISH:
818 DestroyImageInfo(clone_info);
819 return(image);
820 }
821
822 /*
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
824 % %
825 % %
826 % %
827 % R e a d W P G I m a g e %
828 % %
829 % %
830 % %
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
832 %
833 % Method ReadWPGImage reads an WPG X image file and returns it. It
834 % allocates the memory necessary for the new Image structure and returns a
835 % pointer to the new image.
836 %
837 % The format of the ReadWPGImage method is:
838 %
839 % Image *ReadWPGImage(const ImageInfo *image_info,ExceptionInfo *exception)
840 %
841 % A description of each parameter follows:
842 %
843 % o image: Method ReadWPGImage returns a pointer to the image after
844 % reading. A null image is returned if there is a memory shortage or if
845 % the image cannot be read.
846 %
847 % o image_info: Specifies a pointer to a ImageInfo structure.
848 %
849 % o exception: return any errors or warnings in this structure.
850 %
851 */
ReadWPGImage(const ImageInfo * image_info,ExceptionInfo * exception)852 static Image *ReadWPGImage(const ImageInfo *image_info,
853 ExceptionInfo *exception)
854 {
855 typedef struct
856 {
857 size_t FileId;
858 MagickOffsetType DataOffset;
859 unsigned int ProductType;
860 unsigned int FileType;
861 unsigned char MajorVersion;
862 unsigned char MinorVersion;
863 unsigned int EncryptKey;
864 unsigned int Reserved;
865 } WPGHeader;
866
867 typedef struct
868 {
869 unsigned char RecType;
870 size_t RecordLength;
871 } WPGRecord;
872
873 typedef struct
874 {
875 unsigned char Class;
876 unsigned char RecType;
877 size_t Extension;
878 size_t RecordLength;
879 } WPG2Record;
880
881 typedef struct
882 {
883 unsigned HorizontalUnits;
884 unsigned VerticalUnits;
885 unsigned char PosSizePrecision;
886 } WPG2Start;
887
888 typedef struct
889 {
890 unsigned int Width;
891 unsigned int Height;
892 unsigned int Depth;
893 unsigned int HorzRes;
894 unsigned int VertRes;
895 } WPGBitmapType1;
896
897 typedef struct
898 {
899 unsigned int Width;
900 unsigned int Height;
901 unsigned char Depth;
902 unsigned char Compression;
903 } WPG2BitmapType1;
904
905 typedef struct
906 {
907 unsigned int RotAngle;
908 unsigned int LowLeftX;
909 unsigned int LowLeftY;
910 unsigned int UpRightX;
911 unsigned int UpRightY;
912 unsigned int Width;
913 unsigned int Height;
914 unsigned int Depth;
915 unsigned int HorzRes;
916 unsigned int VertRes;
917 } WPGBitmapType2;
918
919 typedef struct
920 {
921 unsigned int StartIndex;
922 unsigned int NumOfEntries;
923 } WPGColorMapRec;
924
925 /*
926 typedef struct {
927 size_t PS_unknown1;
928 unsigned int PS_unknown2;
929 unsigned int PS_unknown3;
930 } WPGPSl1Record;
931 */
932
933 Image
934 *image;
935
936 unsigned int
937 status;
938
939 WPGHeader
940 Header;
941
942 WPGRecord
943 Rec;
944
945 WPG2Record
946 Rec2;
947
948 WPG2Start StartWPG;
949
950 WPGBitmapType1
951 BitmapHeader1;
952
953 WPG2BitmapType1
954 Bitmap2Header1;
955
956 WPGBitmapType2
957 BitmapHeader2;
958
959 WPGColorMapRec
960 WPG_Palette;
961
962 int
963 i,
964 bpp,
965 WPG2Flags;
966
967 ssize_t
968 ldblk;
969
970 size_t
971 one;
972
973 unsigned char
974 *BImgBuff;
975
976 tCTM CTM; /*current transform matrix*/
977
978 /*
979 Open image file.
980 */
981 assert(image_info != (const ImageInfo *) NULL);
982 assert(image_info->signature == MagickCoreSignature);
983 assert(exception != (ExceptionInfo *) NULL);
984 assert(exception->signature == MagickCoreSignature);
985 one=1;
986 image=AcquireImage(image_info,exception);
987 image->depth=8;
988 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
989 if (status == MagickFalse)
990 {
991 image=DestroyImageList(image);
992 return((Image *) NULL);
993 }
994 /*
995 Read WPG image.
996 */
997 Header.FileId=ReadBlobLSBLong(image);
998 Header.DataOffset=(MagickOffsetType) ReadBlobLSBLong(image);
999 Header.ProductType=ReadBlobLSBShort(image);
1000 Header.FileType=ReadBlobLSBShort(image);
1001 Header.MajorVersion=ReadBlobByte(image);
1002 Header.MinorVersion=ReadBlobByte(image);
1003 Header.EncryptKey=ReadBlobLSBShort(image);
1004 Header.Reserved=ReadBlobLSBShort(image);
1005
1006 if (Header.FileId!=0x435057FF || (Header.ProductType>>8)!=0x16)
1007 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1008 if (Header.EncryptKey!=0)
1009 ThrowReaderException(CoderError,"EncryptedWPGImageFileNotSupported");
1010
1011 image->columns = 1;
1012 image->rows = 1;
1013 image->colors = 0;
1014 bpp=0;
1015 BitmapHeader2.RotAngle=0;
1016
1017 switch(Header.FileType)
1018 {
1019 case 1: /* WPG level 1 */
1020 while(!EOFBlob(image)) /* object parser loop */
1021 {
1022 (void) SeekBlob(image,Header.DataOffset,SEEK_SET);
1023 if(EOFBlob(image))
1024 break;
1025
1026 Rec.RecType=(i=ReadBlobByte(image));
1027 if(i==EOF)
1028 break;
1029 Rd_WP_DWORD(image,&Rec.RecordLength);
1030 if(EOFBlob(image))
1031 break;
1032
1033 Header.DataOffset=TellBlob(image)+Rec.RecordLength;
1034
1035 switch(Rec.RecType)
1036 {
1037 case 0x0B: /* bitmap type 1 */
1038 BitmapHeader1.Width=ReadBlobLSBShort(image);
1039 BitmapHeader1.Height=ReadBlobLSBShort(image);
1040 if ((BitmapHeader1.Width == 0) || (BitmapHeader1.Height == 0))
1041 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1042 BitmapHeader1.Depth=ReadBlobLSBShort(image);
1043 BitmapHeader1.HorzRes=ReadBlobLSBShort(image);
1044 BitmapHeader1.VertRes=ReadBlobLSBShort(image);
1045
1046 if(BitmapHeader1.HorzRes && BitmapHeader1.VertRes)
1047 {
1048 image->units=PixelsPerCentimeterResolution;
1049 image->resolution.x=BitmapHeader1.HorzRes/470.0;
1050 image->resolution.y=BitmapHeader1.VertRes/470.0;
1051 }
1052 image->columns=BitmapHeader1.Width;
1053 image->rows=BitmapHeader1.Height;
1054 bpp=BitmapHeader1.Depth;
1055
1056 goto UnpackRaster;
1057
1058 case 0x0E: /*Color palette */
1059 WPG_Palette.StartIndex=ReadBlobLSBShort(image);
1060 WPG_Palette.NumOfEntries=ReadBlobLSBShort(image);
1061
1062 image->colors=WPG_Palette.NumOfEntries;
1063 if (!AcquireImageColormap(image,image->colors,exception))
1064 goto NoMemory;
1065 for (i=WPG_Palette.StartIndex;
1066 i < (int)WPG_Palette.NumOfEntries; i++)
1067 {
1068 image->colormap[i].red=ScaleCharToQuantum((unsigned char)
1069 ReadBlobByte(image));
1070 image->colormap[i].green=ScaleCharToQuantum((unsigned char)
1071 ReadBlobByte(image));
1072 image->colormap[i].blue=ScaleCharToQuantum((unsigned char)
1073 ReadBlobByte(image));
1074 }
1075 break;
1076
1077 case 0x11: /* Start PS l1 */
1078 if(Rec.RecordLength > 8)
1079 image=ExtractPostscript(image,image_info,
1080 TellBlob(image)+8, /* skip PS header in the wpg */
1081 (ssize_t) Rec.RecordLength-8,exception);
1082 break;
1083
1084 case 0x14: /* bitmap type 2 */
1085 BitmapHeader2.RotAngle=ReadBlobLSBShort(image);
1086 BitmapHeader2.LowLeftX=ReadBlobLSBShort(image);
1087 BitmapHeader2.LowLeftY=ReadBlobLSBShort(image);
1088 BitmapHeader2.UpRightX=ReadBlobLSBShort(image);
1089 BitmapHeader2.UpRightY=ReadBlobLSBShort(image);
1090 BitmapHeader2.Width=ReadBlobLSBShort(image);
1091 BitmapHeader2.Height=ReadBlobLSBShort(image);
1092 if ((BitmapHeader2.Width == 0) || (BitmapHeader2.Height == 0))
1093 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1094 BitmapHeader2.Depth=ReadBlobLSBShort(image);
1095 BitmapHeader2.HorzRes=ReadBlobLSBShort(image);
1096 BitmapHeader2.VertRes=ReadBlobLSBShort(image);
1097
1098 image->units=PixelsPerCentimeterResolution;
1099 image->page.width=(unsigned int)
1100 ((BitmapHeader2.LowLeftX-BitmapHeader2.UpRightX)/470.0);
1101 image->page.height=(unsigned int)
1102 ((BitmapHeader2.LowLeftX-BitmapHeader2.UpRightY)/470.0);
1103 image->page.x=(int) (BitmapHeader2.LowLeftX/470.0);
1104 image->page.y=(int) (BitmapHeader2.LowLeftX/470.0);
1105 if(BitmapHeader2.HorzRes && BitmapHeader2.VertRes)
1106 {
1107 image->resolution.x=BitmapHeader2.HorzRes/470.0;
1108 image->resolution.y=BitmapHeader2.VertRes/470.0;
1109 }
1110 image->columns=BitmapHeader2.Width;
1111 image->rows=BitmapHeader2.Height;
1112 bpp=BitmapHeader2.Depth;
1113
1114 UnpackRaster:
1115 status=SetImageExtent(image,image->columns,image->rows,exception);
1116 if (status == MagickFalse)
1117 break;
1118 if ((image->colors == 0) && (bpp != 24))
1119 {
1120 image->colors=one << bpp;
1121 if (!AcquireImageColormap(image,image->colors,exception))
1122 {
1123 NoMemory:
1124 ThrowReaderException(ResourceLimitError,
1125 "MemoryAllocationFailed");
1126 }
1127 /* printf("Load default colormap \n"); */
1128 for (i=0; (i < (int) image->colors) && (i < 256); i++)
1129 {
1130 image->colormap[i].red=ScaleCharToQuantum(WPG1_Palette[i].Red);
1131 image->colormap[i].green=ScaleCharToQuantum(WPG1_Palette[i].Green);
1132 image->colormap[i].blue=ScaleCharToQuantum(WPG1_Palette[i].Blue);
1133 }
1134 }
1135 else
1136 {
1137 if (bpp < 24)
1138 if ( (image->colors < (one << bpp)) && (bpp != 24) )
1139 image->colormap=(PixelInfo *) ResizeQuantumMemory(
1140 image->colormap,(size_t) (one << bpp),
1141 sizeof(*image->colormap));
1142 }
1143
1144 if (bpp == 1)
1145 {
1146 if(image->colormap[0].red==0 &&
1147 image->colormap[0].green==0 &&
1148 image->colormap[0].blue==0 &&
1149 image->colormap[1].red==0 &&
1150 image->colormap[1].green==0 &&
1151 image->colormap[1].blue==0)
1152 { /* fix crippled monochrome palette */
1153 image->colormap[1].red =
1154 image->colormap[1].green =
1155 image->colormap[1].blue = QuantumRange;
1156 }
1157 }
1158
1159 if(UnpackWPGRaster(image,bpp,exception) < 0)
1160 /* The raster cannot be unpacked */
1161 {
1162 DecompressionFailed:
1163 ThrowReaderException(CoderError,"UnableToDecompressImage");
1164 }
1165
1166 if(Rec.RecType==0x14 && BitmapHeader2.RotAngle!=0 && !image_info->ping)
1167 {
1168 /* flop command */
1169 if(BitmapHeader2.RotAngle & 0x8000)
1170 {
1171 Image
1172 *flop_image;
1173
1174 flop_image = FlopImage(image, exception);
1175 if (flop_image != (Image *) NULL) {
1176 DuplicateBlob(flop_image,image);
1177 (void) RemoveLastImageFromList(&image);
1178 AppendImageToList(&image,flop_image);
1179 }
1180 }
1181 /* flip command */
1182 if(BitmapHeader2.RotAngle & 0x2000)
1183 {
1184 Image
1185 *flip_image;
1186
1187 flip_image = FlipImage(image, exception);
1188 if (flip_image != (Image *) NULL) {
1189 DuplicateBlob(flip_image,image);
1190 (void) RemoveLastImageFromList(&image);
1191 AppendImageToList(&image,flip_image);
1192 }
1193 }
1194 /* rotate command */
1195 if(BitmapHeader2.RotAngle & 0x0FFF)
1196 {
1197 Image
1198 *rotate_image;
1199
1200 rotate_image=RotateImage(image,(BitmapHeader2.RotAngle &
1201 0x0FFF), exception);
1202 if (rotate_image != (Image *) NULL) {
1203 DuplicateBlob(rotate_image,image);
1204 (void) RemoveLastImageFromList(&image);
1205 AppendImageToList(&image,rotate_image);
1206 }
1207 }
1208 }
1209
1210 /* Allocate next image structure. */
1211 AcquireNextImage(image_info,image,exception);
1212 image->depth=8;
1213 if (image->next == (Image *) NULL)
1214 goto Finish;
1215 image=SyncNextImageInList(image);
1216 image->columns=image->rows=1;
1217 image->colors=0;
1218 break;
1219
1220 case 0x1B: /* Postscript l2 */
1221 if(Rec.RecordLength>0x3C)
1222 image=ExtractPostscript(image,image_info,
1223 TellBlob(image)+0x3C, /* skip PS l2 header in the wpg */
1224 (ssize_t) Rec.RecordLength-0x3C,exception);
1225 break;
1226 }
1227 }
1228 break;
1229
1230 case 2: /* WPG level 2 */
1231 (void) memset(CTM,0,sizeof(CTM));
1232 StartWPG.PosSizePrecision = 0;
1233 while(!EOFBlob(image)) /* object parser loop */
1234 {
1235 (void) SeekBlob(image,Header.DataOffset,SEEK_SET);
1236 if(EOFBlob(image))
1237 break;
1238
1239 Rec2.Class=(i=ReadBlobByte(image));
1240 if(i==EOF)
1241 break;
1242 Rec2.RecType=(i=ReadBlobByte(image));
1243 if(i==EOF)
1244 break;
1245 Rd_WP_DWORD(image,&Rec2.Extension);
1246 Rd_WP_DWORD(image,&Rec2.RecordLength);
1247 if(EOFBlob(image))
1248 break;
1249
1250 Header.DataOffset=TellBlob(image)+Rec2.RecordLength;
1251
1252 switch(Rec2.RecType)
1253 {
1254 case 1:
1255 StartWPG.HorizontalUnits=ReadBlobLSBShort(image);
1256 StartWPG.VerticalUnits=ReadBlobLSBShort(image);
1257 StartWPG.PosSizePrecision=ReadBlobByte(image);
1258 break;
1259 case 0x0C: /* Color palette */
1260 WPG_Palette.StartIndex=ReadBlobLSBShort(image);
1261 WPG_Palette.NumOfEntries=ReadBlobLSBShort(image);
1262
1263 image->colors=WPG_Palette.NumOfEntries;
1264 if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
1265 ThrowReaderException(ResourceLimitError,
1266 "MemoryAllocationFailed");
1267 for (i=WPG_Palette.StartIndex;
1268 i < (int)WPG_Palette.NumOfEntries; i++)
1269 {
1270 image->colormap[i].red=ScaleCharToQuantum((char)
1271 ReadBlobByte(image));
1272 image->colormap[i].green=ScaleCharToQuantum((char)
1273 ReadBlobByte(image));
1274 image->colormap[i].blue=ScaleCharToQuantum((char)
1275 ReadBlobByte(image));
1276 (void) ReadBlobByte(image); /*Opacity??*/
1277 }
1278 break;
1279 case 0x0E:
1280 Bitmap2Header1.Width=ReadBlobLSBShort(image);
1281 Bitmap2Header1.Height=ReadBlobLSBShort(image);
1282 if ((Bitmap2Header1.Width == 0) || (Bitmap2Header1.Height == 0))
1283 ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1284 Bitmap2Header1.Depth=ReadBlobByte(image);
1285 Bitmap2Header1.Compression=ReadBlobByte(image);
1286
1287 if(Bitmap2Header1.Compression > 1)
1288 continue; /*Unknown compression method */
1289 switch(Bitmap2Header1.Depth)
1290 {
1291 case 1:
1292 bpp=1;
1293 break;
1294 case 2:
1295 bpp=2;
1296 break;
1297 case 3:
1298 bpp=4;
1299 break;
1300 case 4:
1301 bpp=8;
1302 break;
1303 case 8:
1304 bpp=24;
1305 break;
1306 default:
1307 continue; /*Ignore raster with unknown depth*/
1308 }
1309 image->columns=Bitmap2Header1.Width;
1310 image->rows=Bitmap2Header1.Height;
1311 status=SetImageExtent(image,image->columns,image->rows,exception);
1312 if (status == MagickFalse)
1313 break;
1314 if ((image->colors == 0) && (bpp != 24))
1315 {
1316 size_t
1317 one;
1318
1319 one=1;
1320 image->colors=one << bpp;
1321 if (!AcquireImageColormap(image,image->colors,exception))
1322 goto NoMemory;
1323 }
1324 else
1325 {
1326 if(bpp < 24)
1327 if( image->colors<(one << bpp) && bpp!=24 )
1328 image->colormap=(PixelInfo *) ResizeQuantumMemory(
1329 image->colormap,(size_t) (one << bpp),
1330 sizeof(*image->colormap));
1331 }
1332
1333
1334 switch(Bitmap2Header1.Compression)
1335 {
1336 case 0: /*Uncompressed raster*/
1337 {
1338 ldblk=(ssize_t) ((bpp*image->columns+7)/8);
1339 BImgBuff=(unsigned char *) AcquireQuantumMemory((size_t)
1340 ldblk+1,sizeof(*BImgBuff));
1341 if (BImgBuff == (unsigned char *) NULL)
1342 goto NoMemory;
1343
1344 for(i=0; i< (ssize_t) image->rows; i++)
1345 {
1346 (void) ReadBlob(image,ldblk,BImgBuff);
1347 InsertRow(image,BImgBuff,i,bpp,exception);
1348 }
1349
1350 if(BImgBuff)
1351 BImgBuff=(unsigned char *) RelinquishMagickMemory(BImgBuff);
1352 break;
1353 }
1354 case 1: /*RLE for WPG2 */
1355 {
1356 if( UnpackWPG2Raster(image,bpp,exception) < 0)
1357 goto DecompressionFailed;
1358 break;
1359 }
1360 }
1361
1362 if(CTM[0][0]<0 && !image_info->ping)
1363 { /*?? RotAngle=360-RotAngle;*/
1364 Image
1365 *flop_image;
1366
1367 flop_image = FlopImage(image, exception);
1368 if (flop_image != (Image *) NULL) {
1369 DuplicateBlob(flop_image,image);
1370 (void) RemoveLastImageFromList(&image);
1371 AppendImageToList(&image,flop_image);
1372 }
1373 /* Try to change CTM according to Flip - I am not sure, must be checked.
1374 Tx(0,0)=-1; Tx(1,0)=0; Tx(2,0)=0;
1375 Tx(0,1)= 0; Tx(1,1)=1; Tx(2,1)=0;
1376 Tx(0,2)=(WPG._2Rect.X_ur+WPG._2Rect.X_ll);
1377 Tx(1,2)=0; Tx(2,2)=1; */
1378 }
1379 if(CTM[1][1]<0 && !image_info->ping)
1380 { /*?? RotAngle=360-RotAngle;*/
1381 Image
1382 *flip_image;
1383
1384 flip_image = FlipImage(image, exception);
1385 if (flip_image != (Image *) NULL) {
1386 DuplicateBlob(flip_image,image);
1387 (void) RemoveLastImageFromList(&image);
1388 AppendImageToList(&image,flip_image);
1389 }
1390 /* Try to change CTM according to Flip - I am not sure, must be checked.
1391 float_matrix Tx(3,3);
1392 Tx(0,0)= 1; Tx(1,0)= 0; Tx(2,0)=0;
1393 Tx(0,1)= 0; Tx(1,1)=-1; Tx(2,1)=0;
1394 Tx(0,2)= 0; Tx(1,2)=(WPG._2Rect.Y_ur+WPG._2Rect.Y_ll);
1395 Tx(2,2)=1; */
1396 }
1397
1398
1399 /* Allocate next image structure. */
1400 AcquireNextImage(image_info,image,exception);
1401 image->depth=8;
1402 if (image->next == (Image *) NULL)
1403 goto Finish;
1404 image=SyncNextImageInList(image);
1405 image->columns=image->rows=1;
1406 image->colors=0;
1407 break;
1408
1409 case 0x12: /* Postscript WPG2*/
1410 i=ReadBlobLSBShort(image);
1411 if(Rec2.RecordLength > (unsigned int) i)
1412 image=ExtractPostscript(image,image_info,
1413 TellBlob(image)+i, /*skip PS header in the wpg2*/
1414 (ssize_t) (Rec2.RecordLength-i-2),exception);
1415 break;
1416
1417 case 0x1B: /*bitmap rectangle*/
1418 WPG2Flags = LoadWPG2Flags(image,StartWPG.PosSizePrecision,NULL,&CTM);
1419 (void) WPG2Flags;
1420 break;
1421 }
1422 }
1423
1424 break;
1425
1426 default:
1427 {
1428 ThrowReaderException(CoderError,"DataEncodingSchemeIsNotSupported");
1429 }
1430 }
1431
1432 Finish:
1433 (void) CloseBlob(image);
1434
1435 {
1436 Image
1437 *p;
1438
1439 ssize_t
1440 scene=0;
1441
1442 /*
1443 Rewind list, removing any empty images while rewinding.
1444 */
1445 p=image;
1446 image=NULL;
1447 while (p != (Image *) NULL)
1448 {
1449 Image *tmp=p;
1450 if ((p->rows == 0) || (p->columns == 0)) {
1451 p=p->previous;
1452 DeleteImageFromList(&tmp);
1453 } else {
1454 image=p;
1455 p=p->previous;
1456 }
1457 }
1458 /*
1459 Fix scene numbers.
1460 */
1461 for (p=image; p != (Image *) NULL; p=p->next)
1462 p->scene=(size_t) scene++;
1463 }
1464 if (image == (Image *) NULL)
1465 ThrowReaderException(CorruptImageError,
1466 "ImageFileDoesNotContainAnyImageData");
1467 return(image);
1468 }
1469
1470 /*
1471 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1472 % %
1473 % %
1474 % %
1475 % R e g i s t e r W P G I m a g e %
1476 % %
1477 % %
1478 % %
1479 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1480 %
1481 % Method RegisterWPGImage adds attributes for the WPG image format to
1482 % the list of supported formats. The attributes include the image format
1483 % tag, a method to read and/or write the format, whether the format
1484 % supports the saving of more than one frame to the same file or blob,
1485 % whether the format supports native in-memory I/O, and a brief
1486 % description of the format.
1487 %
1488 % The format of the RegisterWPGImage method is:
1489 %
1490 % size_t RegisterWPGImage(void)
1491 %
1492 */
RegisterWPGImage(void)1493 ModuleExport size_t RegisterWPGImage(void)
1494 {
1495 MagickInfo
1496 *entry;
1497
1498 entry=AcquireMagickInfo("WPG","WPG","Word Perfect Graphics");
1499 entry->decoder=(DecodeImageHandler *) ReadWPGImage;
1500 entry->magick=(IsImageFormatHandler *) IsWPG;
1501 entry->flags|=CoderSeekableStreamFlag;
1502 (void) RegisterMagickInfo(entry);
1503 return(MagickImageCoderSignature);
1504 }
1505
1506 /*
1507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1508 % %
1509 % %
1510 % %
1511 % U n r e g i s t e r W P G I m a g e %
1512 % %
1513 % %
1514 % %
1515 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1516 %
1517 % Method UnregisterWPGImage removes format registrations made by the
1518 % WPG module from the list of supported formats.
1519 %
1520 % The format of the UnregisterWPGImage method is:
1521 %
1522 % UnregisterWPGImage(void)
1523 %
1524 */
UnregisterWPGImage(void)1525 ModuleExport void UnregisterWPGImage(void)
1526 {
1527 (void) UnregisterMagickInfo("WPG");
1528 }
1529