wpg.c revision aecd0ada163a4d6c769cec178955d5f3e9316f2f
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 68typedef 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 */ 76static 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*/ 234static 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 244static 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 267static 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. */ 446static 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{ \ 538DisableMSCWarning(4310) \ 539 if(XorMe)\ 540 BImgBuff[x] = (unsigned char)~b;\ 541 else\ 542 BImgBuff[x] = b;\ 543RestoreMSCWarning \ 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. */ 553static 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 675typedef float tCTM[3][3]; 676 677static unsigned LoadWPG2Flags(Image *image,char Precision,float *Angle,tCTM *CTM) 678{ 679const unsigned char TPR=1,TRN=2,SKW=4,SCL=8,ROT=0x10,OID=0x20,LCK=0x80; 680ssize_t x; 681unsigned DenX; 682unsigned 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 738static 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) CopyMagickMemory(image2->filename,image->filename,MagickPathExtent); 804 (void) CopyMagickMemory(image2->magick_filename,image->magick_filename,MagickPathExtent); 805 (void) CopyMagickMemory(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*/ 852static 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*/ 1493ModuleExport 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*/ 1525ModuleExport void UnregisterWPGImage(void) 1526{ 1527 (void) UnregisterMagickInfo("WPG"); 1528} 1529