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