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