1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % PPPP IIIII CCCC TTTTT % 7 % P P I C T % 8 % PPPP I C T % 9 % P I C T % 10 % P IIIII CCCC T % 11 % % 12 % % 13 % Read/Write Apple Macintosh QuickDraw/PICT Format % 14 % % 15 % Software Design % 16 % Cristy % 17 % July 1992 % 18 % % 19 % % 20 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization % 21 % dedicated to making software imaging solutions freely available. % 22 % % 23 % You may not use this file except in compliance with the License. You may % 24 % obtain a copy of the License at % 25 % % 26 % http://www.imagemagick.org/script/license.php % 27 % % 28 % Unless required by applicable law or agreed to in writing, software % 29 % distributed under the License is distributed on an "AS IS" BASIS, % 30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31 % See the License for the specific language governing permissions and % 32 % limitations under the License. % 33 % % 34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35 % 36 % 37 */ 38 39 /* 41 Include declarations. 42 */ 43 #include "MagickCore/studio.h" 44 #include "MagickCore/blob.h" 45 #include "MagickCore/blob-private.h" 46 #include "MagickCore/cache.h" 47 #include "MagickCore/color-private.h" 48 #include "MagickCore/colormap.h" 49 #include "MagickCore/colormap-private.h" 50 #include "MagickCore/colorspace.h" 51 #include "MagickCore/colorspace-private.h" 52 #include "MagickCore/composite.h" 53 #include "MagickCore/constitute.h" 54 #include "MagickCore/exception.h" 55 #include "MagickCore/exception-private.h" 56 #include "MagickCore/image.h" 57 #include "MagickCore/image-private.h" 58 #include "MagickCore/list.h" 59 #include "MagickCore/log.h" 60 #include "MagickCore/magick.h" 61 #include "MagickCore/memory_.h" 62 #include "MagickCore/monitor.h" 63 #include "MagickCore/monitor-private.h" 64 #include "MagickCore/pixel-accessor.h" 65 #include "MagickCore/profile.h" 66 #include "MagickCore/resource_.h" 67 #include "MagickCore/quantum-private.h" 68 #include "MagickCore/static.h" 69 #include "MagickCore/string_.h" 70 #include "MagickCore/module.h" 71 #include "MagickCore/transform.h" 72 #include "MagickCore/utility.h" 73 74 /* 76 ImageMagick Macintosh PICT Methods. 77 */ 78 #define ReadPixmap(pixmap) \ 79 { \ 80 pixmap.version=(short) ReadBlobMSBShort(image); \ 81 pixmap.pack_type=(short) ReadBlobMSBShort(image); \ 82 pixmap.pack_size=ReadBlobMSBLong(image); \ 83 pixmap.horizontal_resolution=1UL*ReadBlobMSBShort(image); \ 84 (void) ReadBlobMSBShort(image); \ 85 pixmap.vertical_resolution=1UL*ReadBlobMSBShort(image); \ 86 (void) ReadBlobMSBShort(image); \ 87 pixmap.pixel_type=(short) ReadBlobMSBShort(image); \ 88 pixmap.bits_per_pixel=(short) ReadBlobMSBShort(image); \ 89 pixmap.component_count=(short) ReadBlobMSBShort(image); \ 90 pixmap.component_size=(short) ReadBlobMSBShort(image); \ 91 pixmap.plane_bytes=ReadBlobMSBLong(image); \ 92 pixmap.table=ReadBlobMSBLong(image); \ 93 pixmap.reserved=ReadBlobMSBLong(image); \ 94 if ((EOFBlob(image) != MagickFalse) || (pixmap.bits_per_pixel <= 0) || \ 95 (pixmap.bits_per_pixel > 32) || (pixmap.component_count <= 0) || \ 96 (pixmap.component_count > 4) || (pixmap.component_size <= 0)) \ 97 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); \ 98 } 99 100 typedef struct _PICTCode 101 { 102 const char 103 *name; 104 105 ssize_t 106 length; 107 108 const char 109 *description; 110 } PICTCode; 111 112 typedef struct _PICTPixmap 113 { 114 short 115 version, 116 pack_type; 117 118 size_t 119 pack_size, 120 horizontal_resolution, 121 vertical_resolution; 122 123 short 124 pixel_type, 125 bits_per_pixel, 126 component_count, 127 component_size; 128 129 size_t 130 plane_bytes, 131 table, 132 reserved; 133 } PICTPixmap; 134 135 typedef struct _PICTRectangle 136 { 137 short 138 top, 139 left, 140 bottom, 141 right; 142 } PICTRectangle; 143 144 static const PICTCode 145 codes[] = 146 { 147 /* 0x00 */ { "NOP", 0, "nop" }, 148 /* 0x01 */ { "Clip", 0, "clip" }, 149 /* 0x02 */ { "BkPat", 8, "background pattern" }, 150 /* 0x03 */ { "TxFont", 2, "text font (word)" }, 151 /* 0x04 */ { "TxFace", 1, "text face (byte)" }, 152 /* 0x05 */ { "TxMode", 2, "text mode (word)" }, 153 /* 0x06 */ { "SpExtra", 4, "space extra (fixed point)" }, 154 /* 0x07 */ { "PnSize", 4, "pen size (point)" }, 155 /* 0x08 */ { "PnMode", 2, "pen mode (word)" }, 156 /* 0x09 */ { "PnPat", 8, "pen pattern" }, 157 /* 0x0a */ { "FillPat", 8, "fill pattern" }, 158 /* 0x0b */ { "OvSize", 4, "oval size (point)" }, 159 /* 0x0c */ { "Origin", 4, "dh, dv (word)" }, 160 /* 0x0d */ { "TxSize", 2, "text size (word)" }, 161 /* 0x0e */ { "FgColor", 4, "foreground color (ssize_tword)" }, 162 /* 0x0f */ { "BkColor", 4, "background color (ssize_tword)" }, 163 /* 0x10 */ { "TxRatio", 8, "numerator (point), denominator (point)" }, 164 /* 0x11 */ { "Version", 1, "version (byte)" }, 165 /* 0x12 */ { "BkPixPat", 0, "color background pattern" }, 166 /* 0x13 */ { "PnPixPat", 0, "color pen pattern" }, 167 /* 0x14 */ { "FillPixPat", 0, "color fill pattern" }, 168 /* 0x15 */ { "PnLocHFrac", 2, "fractional pen position" }, 169 /* 0x16 */ { "ChExtra", 2, "extra for each character" }, 170 /* 0x17 */ { "reserved", 0, "reserved for Apple use" }, 171 /* 0x18 */ { "reserved", 0, "reserved for Apple use" }, 172 /* 0x19 */ { "reserved", 0, "reserved for Apple use" }, 173 /* 0x1a */ { "RGBFgCol", 6, "RGB foreColor" }, 174 /* 0x1b */ { "RGBBkCol", 6, "RGB backColor" }, 175 /* 0x1c */ { "HiliteMode", 0, "hilite mode flag" }, 176 /* 0x1d */ { "HiliteColor", 6, "RGB hilite color" }, 177 /* 0x1e */ { "DefHilite", 0, "Use default hilite color" }, 178 /* 0x1f */ { "OpColor", 6, "RGB OpColor for arithmetic modes" }, 179 /* 0x20 */ { "Line", 8, "pnLoc (point), newPt (point)" }, 180 /* 0x21 */ { "LineFrom", 4, "newPt (point)" }, 181 /* 0x22 */ { "ShortLine", 6, "pnLoc (point, dh, dv (-128 .. 127))" }, 182 /* 0x23 */ { "ShortLineFrom", 2, "dh, dv (-128 .. 127)" }, 183 /* 0x24 */ { "reserved", -1, "reserved for Apple use" }, 184 /* 0x25 */ { "reserved", -1, "reserved for Apple use" }, 185 /* 0x26 */ { "reserved", -1, "reserved for Apple use" }, 186 /* 0x27 */ { "reserved", -1, "reserved for Apple use" }, 187 /* 0x28 */ { "LongText", 0, "txLoc (point), count (0..255), text" }, 188 /* 0x29 */ { "DHText", 0, "dh (0..255), count (0..255), text" }, 189 /* 0x2a */ { "DVText", 0, "dv (0..255), count (0..255), text" }, 190 /* 0x2b */ { "DHDVText", 0, "dh, dv (0..255), count (0..255), text" }, 191 /* 0x2c */ { "reserved", -1, "reserved for Apple use" }, 192 /* 0x2d */ { "reserved", -1, "reserved for Apple use" }, 193 /* 0x2e */ { "reserved", -1, "reserved for Apple use" }, 194 /* 0x2f */ { "reserved", -1, "reserved for Apple use" }, 195 /* 0x30 */ { "frameRect", 8, "rect" }, 196 /* 0x31 */ { "paintRect", 8, "rect" }, 197 /* 0x32 */ { "eraseRect", 8, "rect" }, 198 /* 0x33 */ { "invertRect", 8, "rect" }, 199 /* 0x34 */ { "fillRect", 8, "rect" }, 200 /* 0x35 */ { "reserved", 8, "reserved for Apple use" }, 201 /* 0x36 */ { "reserved", 8, "reserved for Apple use" }, 202 /* 0x37 */ { "reserved", 8, "reserved for Apple use" }, 203 /* 0x38 */ { "frameSameRect", 0, "rect" }, 204 /* 0x39 */ { "paintSameRect", 0, "rect" }, 205 /* 0x3a */ { "eraseSameRect", 0, "rect" }, 206 /* 0x3b */ { "invertSameRect", 0, "rect" }, 207 /* 0x3c */ { "fillSameRect", 0, "rect" }, 208 /* 0x3d */ { "reserved", 0, "reserved for Apple use" }, 209 /* 0x3e */ { "reserved", 0, "reserved for Apple use" }, 210 /* 0x3f */ { "reserved", 0, "reserved for Apple use" }, 211 /* 0x40 */ { "frameRRect", 8, "rect" }, 212 /* 0x41 */ { "paintRRect", 8, "rect" }, 213 /* 0x42 */ { "eraseRRect", 8, "rect" }, 214 /* 0x43 */ { "invertRRect", 8, "rect" }, 215 /* 0x44 */ { "fillRRrect", 8, "rect" }, 216 /* 0x45 */ { "reserved", 8, "reserved for Apple use" }, 217 /* 0x46 */ { "reserved", 8, "reserved for Apple use" }, 218 /* 0x47 */ { "reserved", 8, "reserved for Apple use" }, 219 /* 0x48 */ { "frameSameRRect", 0, "rect" }, 220 /* 0x49 */ { "paintSameRRect", 0, "rect" }, 221 /* 0x4a */ { "eraseSameRRect", 0, "rect" }, 222 /* 0x4b */ { "invertSameRRect", 0, "rect" }, 223 /* 0x4c */ { "fillSameRRect", 0, "rect" }, 224 /* 0x4d */ { "reserved", 0, "reserved for Apple use" }, 225 /* 0x4e */ { "reserved", 0, "reserved for Apple use" }, 226 /* 0x4f */ { "reserved", 0, "reserved for Apple use" }, 227 /* 0x50 */ { "frameOval", 8, "rect" }, 228 /* 0x51 */ { "paintOval", 8, "rect" }, 229 /* 0x52 */ { "eraseOval", 8, "rect" }, 230 /* 0x53 */ { "invertOval", 8, "rect" }, 231 /* 0x54 */ { "fillOval", 8, "rect" }, 232 /* 0x55 */ { "reserved", 8, "reserved for Apple use" }, 233 /* 0x56 */ { "reserved", 8, "reserved for Apple use" }, 234 /* 0x57 */ { "reserved", 8, "reserved for Apple use" }, 235 /* 0x58 */ { "frameSameOval", 0, "rect" }, 236 /* 0x59 */ { "paintSameOval", 0, "rect" }, 237 /* 0x5a */ { "eraseSameOval", 0, "rect" }, 238 /* 0x5b */ { "invertSameOval", 0, "rect" }, 239 /* 0x5c */ { "fillSameOval", 0, "rect" }, 240 /* 0x5d */ { "reserved", 0, "reserved for Apple use" }, 241 /* 0x5e */ { "reserved", 0, "reserved for Apple use" }, 242 /* 0x5f */ { "reserved", 0, "reserved for Apple use" }, 243 /* 0x60 */ { "frameArc", 12, "rect, startAngle, arcAngle" }, 244 /* 0x61 */ { "paintArc", 12, "rect, startAngle, arcAngle" }, 245 /* 0x62 */ { "eraseArc", 12, "rect, startAngle, arcAngle" }, 246 /* 0x63 */ { "invertArc", 12, "rect, startAngle, arcAngle" }, 247 /* 0x64 */ { "fillArc", 12, "rect, startAngle, arcAngle" }, 248 /* 0x65 */ { "reserved", 12, "reserved for Apple use" }, 249 /* 0x66 */ { "reserved", 12, "reserved for Apple use" }, 250 /* 0x67 */ { "reserved", 12, "reserved for Apple use" }, 251 /* 0x68 */ { "frameSameArc", 4, "rect, startAngle, arcAngle" }, 252 /* 0x69 */ { "paintSameArc", 4, "rect, startAngle, arcAngle" }, 253 /* 0x6a */ { "eraseSameArc", 4, "rect, startAngle, arcAngle" }, 254 /* 0x6b */ { "invertSameArc", 4, "rect, startAngle, arcAngle" }, 255 /* 0x6c */ { "fillSameArc", 4, "rect, startAngle, arcAngle" }, 256 /* 0x6d */ { "reserved", 4, "reserved for Apple use" }, 257 /* 0x6e */ { "reserved", 4, "reserved for Apple use" }, 258 /* 0x6f */ { "reserved", 4, "reserved for Apple use" }, 259 /* 0x70 */ { "framePoly", 0, "poly" }, 260 /* 0x71 */ { "paintPoly", 0, "poly" }, 261 /* 0x72 */ { "erasePoly", 0, "poly" }, 262 /* 0x73 */ { "invertPoly", 0, "poly" }, 263 /* 0x74 */ { "fillPoly", 0, "poly" }, 264 /* 0x75 */ { "reserved", 0, "reserved for Apple use" }, 265 /* 0x76 */ { "reserved", 0, "reserved for Apple use" }, 266 /* 0x77 */ { "reserved", 0, "reserved for Apple use" }, 267 /* 0x78 */ { "frameSamePoly", 0, "poly (NYI)" }, 268 /* 0x79 */ { "paintSamePoly", 0, "poly (NYI)" }, 269 /* 0x7a */ { "eraseSamePoly", 0, "poly (NYI)" }, 270 /* 0x7b */ { "invertSamePoly", 0, "poly (NYI)" }, 271 /* 0x7c */ { "fillSamePoly", 0, "poly (NYI)" }, 272 /* 0x7d */ { "reserved", 0, "reserved for Apple use" }, 273 /* 0x7e */ { "reserved", 0, "reserved for Apple use" }, 274 /* 0x7f */ { "reserved", 0, "reserved for Apple use" }, 275 /* 0x80 */ { "frameRgn", 0, "region" }, 276 /* 0x81 */ { "paintRgn", 0, "region" }, 277 /* 0x82 */ { "eraseRgn", 0, "region" }, 278 /* 0x83 */ { "invertRgn", 0, "region" }, 279 /* 0x84 */ { "fillRgn", 0, "region" }, 280 /* 0x85 */ { "reserved", 0, "reserved for Apple use" }, 281 /* 0x86 */ { "reserved", 0, "reserved for Apple use" }, 282 /* 0x87 */ { "reserved", 0, "reserved for Apple use" }, 283 /* 0x88 */ { "frameSameRgn", 0, "region (NYI)" }, 284 /* 0x89 */ { "paintSameRgn", 0, "region (NYI)" }, 285 /* 0x8a */ { "eraseSameRgn", 0, "region (NYI)" }, 286 /* 0x8b */ { "invertSameRgn", 0, "region (NYI)" }, 287 /* 0x8c */ { "fillSameRgn", 0, "region (NYI)" }, 288 /* 0x8d */ { "reserved", 0, "reserved for Apple use" }, 289 /* 0x8e */ { "reserved", 0, "reserved for Apple use" }, 290 /* 0x8f */ { "reserved", 0, "reserved for Apple use" }, 291 /* 0x90 */ { "BitsRect", 0, "copybits, rect clipped" }, 292 /* 0x91 */ { "BitsRgn", 0, "copybits, rgn clipped" }, 293 /* 0x92 */ { "reserved", -1, "reserved for Apple use" }, 294 /* 0x93 */ { "reserved", -1, "reserved for Apple use" }, 295 /* 0x94 */ { "reserved", -1, "reserved for Apple use" }, 296 /* 0x95 */ { "reserved", -1, "reserved for Apple use" }, 297 /* 0x96 */ { "reserved", -1, "reserved for Apple use" }, 298 /* 0x97 */ { "reserved", -1, "reserved for Apple use" }, 299 /* 0x98 */ { "PackBitsRect", 0, "packed copybits, rect clipped" }, 300 /* 0x99 */ { "PackBitsRgn", 0, "packed copybits, rgn clipped" }, 301 /* 0x9a */ { "DirectBitsRect", 0, "PixMap, srcRect, dstRect, mode, PixData" }, 302 /* 0x9b */ { "DirectBitsRgn", 0, "PixMap, srcRect, dstRect, mode, maskRgn, PixData" }, 303 /* 0x9c */ { "reserved", -1, "reserved for Apple use" }, 304 /* 0x9d */ { "reserved", -1, "reserved for Apple use" }, 305 /* 0x9e */ { "reserved", -1, "reserved for Apple use" }, 306 /* 0x9f */ { "reserved", -1, "reserved for Apple use" }, 307 /* 0xa0 */ { "ShortComment", 2, "kind (word)" }, 308 /* 0xa1 */ { "LongComment", 0, "kind (word), size (word), data" } 309 }; 310 311 /* 312 Forward declarations. 313 */ 314 static MagickBooleanType 315 WritePICTImage(const ImageInfo *,Image *,ExceptionInfo *); 316 317 /* 319 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 320 % % 321 % % 322 % % 323 % D e c o d e I m a g e % 324 % % 325 % % 326 % % 327 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 328 % 329 % DecodeImage decompresses an image via Macintosh pack bits decoding for 330 % Macintosh PICT images. 331 % 332 % The format of the DecodeImage method is: 333 % 334 % unsigned char *DecodeImage(Image *blob,Image *image, 335 % size_t bytes_per_line,const int bits_per_pixel, 336 % unsigned size_t extent) 337 % 338 % A description of each parameter follows: 339 % 340 % o image_info: the image info. 341 % 342 % o blob,image: the address of a structure of type Image. 343 % 344 % o bytes_per_line: This integer identifies the number of bytes in a 345 % scanline. 346 % 347 % o bits_per_pixel: the number of bits in a pixel. 348 % 349 % o extent: the number of pixels allocated. 350 % 351 */ 352 353 static unsigned char *ExpandBuffer(unsigned char *pixels, 354 MagickSizeType *bytes_per_line,const unsigned int bits_per_pixel) 355 { 356 register ssize_t 357 i; 358 359 register unsigned char 360 *p, 361 *q; 362 363 static unsigned char 364 scanline[8*256]; 365 366 p=pixels; 367 q=scanline; 368 switch (bits_per_pixel) 369 { 370 case 8: 371 case 16: 372 case 32: 373 return(pixels); 374 case 4: 375 { 376 for (i=0; i < (ssize_t) *bytes_per_line; i++) 377 { 378 *q++=(*p >> 4) & 0xff; 379 *q++=(*p & 15); 380 p++; 381 } 382 *bytes_per_line*=2; 383 break; 384 } 385 case 2: 386 { 387 for (i=0; i < (ssize_t) *bytes_per_line; i++) 388 { 389 *q++=(*p >> 6) & 0x03; 390 *q++=(*p >> 4) & 0x03; 391 *q++=(*p >> 2) & 0x03; 392 *q++=(*p & 3); 393 p++; 394 } 395 *bytes_per_line*=4; 396 break; 397 } 398 case 1: 399 { 400 for (i=0; i < (ssize_t) *bytes_per_line; i++) 401 { 402 *q++=(*p >> 7) & 0x01; 403 *q++=(*p >> 6) & 0x01; 404 *q++=(*p >> 5) & 0x01; 405 *q++=(*p >> 4) & 0x01; 406 *q++=(*p >> 3) & 0x01; 407 *q++=(*p >> 2) & 0x01; 408 *q++=(*p >> 1) & 0x01; 409 *q++=(*p & 0x01); 410 p++; 411 } 412 *bytes_per_line*=8; 413 break; 414 } 415 default: 416 break; 417 } 418 return(scanline); 419 } 420 421 static unsigned char *DecodeImage(Image *blob,Image *image, 422 size_t bytes_per_line,const unsigned int bits_per_pixel,size_t *extent, 423 ExceptionInfo *exception) 424 { 425 MagickSizeType 426 number_pixels; 427 428 register ssize_t 429 i; 430 431 register unsigned char 432 *p, 433 *q; 434 435 size_t 436 bytes_per_pixel, 437 length, 438 row_bytes, 439 scanline_length, 440 width; 441 442 ssize_t 443 count, 444 j, 445 y; 446 447 unsigned char 448 *pixels, 449 *scanline; 450 451 /* 452 Determine pixel buffer size. 453 */ 454 if (bits_per_pixel <= 8) 455 bytes_per_line&=0x7fff; 456 width=image->columns; 457 bytes_per_pixel=1; 458 if (bits_per_pixel == 16) 459 { 460 bytes_per_pixel=2; 461 width*=2; 462 } 463 else 464 if (bits_per_pixel == 32) 465 width*=image->alpha_trait ? 4 : 3; 466 if (bytes_per_line == 0) 467 bytes_per_line=width; 468 row_bytes=(size_t) (image->columns | 0x8000); 469 if (image->storage_class == DirectClass) 470 row_bytes=(size_t) ((4*image->columns) | 0x8000); 471 /* 472 Allocate pixel and scanline buffer. 473 */ 474 pixels=(unsigned char *) AcquireQuantumMemory(image->rows,row_bytes* 475 sizeof(*pixels)); 476 if (pixels == (unsigned char *) NULL) 477 return((unsigned char *) NULL); 478 *extent=row_bytes*image->rows*sizeof(*pixels); 479 (void) ResetMagickMemory(pixels,0,*extent); 480 scanline=(unsigned char *) AcquireQuantumMemory(row_bytes,2* 481 sizeof(*scanline)); 482 if (scanline == (unsigned char *) NULL) 483 return((unsigned char *) NULL); 484 if (bytes_per_line < 8) 485 { 486 /* 487 Pixels are already uncompressed. 488 */ 489 for (y=0; y < (ssize_t) image->rows; y++) 490 { 491 q=pixels+y*width*GetPixelChannels(image);; 492 number_pixels=bytes_per_line; 493 count=ReadBlob(blob,(size_t) number_pixels,scanline); 494 if (count != (ssize_t) number_pixels) 495 { 496 (void) ThrowMagickException(exception,GetMagickModule(), 497 CorruptImageError,"UnableToUncompressImage","`%s'", 498 image->filename); 499 break; 500 } 501 p=ExpandBuffer(scanline,&number_pixels,bits_per_pixel); 502 if ((q+number_pixels) > (pixels+(*extent))) 503 { 504 (void) ThrowMagickException(exception,GetMagickModule(), 505 CorruptImageError,"UnableToUncompressImage","`%s'", 506 image->filename); 507 break; 508 } 509 (void) CopyMagickMemory(q,p,(size_t) number_pixels); 510 } 511 scanline=(unsigned char *) RelinquishMagickMemory(scanline); 512 return(pixels); 513 } 514 /* 515 Uncompress RLE pixels into uncompressed pixel buffer. 516 */ 517 for (y=0; y < (ssize_t) image->rows; y++) 518 { 519 q=pixels+y*width; 520 if (bytes_per_line > 200) 521 scanline_length=ReadBlobMSBShort(blob); 522 else 523 scanline_length=1UL*ReadBlobByte(blob); 524 if (scanline_length >= row_bytes) 525 { 526 (void) ThrowMagickException(exception,GetMagickModule(), 527 CorruptImageError,"UnableToUncompressImage","`%s'",image->filename); 528 break; 529 } 530 count=ReadBlob(blob,scanline_length,scanline); 531 if (count != (ssize_t) scanline_length) 532 { 533 (void) ThrowMagickException(exception,GetMagickModule(), 534 CorruptImageError,"UnableToUncompressImage","`%s'",image->filename); 535 break; 536 } 537 for (j=0; j < (ssize_t) scanline_length; ) 538 if ((scanline[j] & 0x80) == 0) 539 { 540 length=(size_t) ((scanline[j] & 0xff)+1); 541 number_pixels=length*bytes_per_pixel; 542 p=ExpandBuffer(scanline+j+1,&number_pixels,bits_per_pixel); 543 if ((q-pixels+number_pixels) <= *extent) 544 (void) CopyMagickMemory(q,p,(size_t) number_pixels); 545 q+=number_pixels; 546 j+=(ssize_t) (length*bytes_per_pixel+1); 547 } 548 else 549 { 550 length=(size_t) (((scanline[j] ^ 0xff) & 0xff)+2); 551 number_pixels=bytes_per_pixel; 552 p=ExpandBuffer(scanline+j+1,&number_pixels,bits_per_pixel); 553 for (i=0; i < (ssize_t) length; i++) 554 { 555 if ((q-pixels+number_pixels) <= *extent) 556 (void) CopyMagickMemory(q,p,(size_t) number_pixels); 557 q+=number_pixels; 558 } 559 j+=(ssize_t) bytes_per_pixel+1; 560 } 561 } 562 scanline=(unsigned char *) RelinquishMagickMemory(scanline); 563 return(pixels); 564 } 565 566 /* 568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 569 % % 570 % % 571 % % 572 % E n c o d e I m a g e % 573 % % 574 % % 575 % % 576 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 577 % 578 % EncodeImage compresses an image via Macintosh pack bits encoding 579 % for Macintosh PICT images. 580 % 581 % The format of the EncodeImage method is: 582 % 583 % size_t EncodeImage(Image *image,const unsigned char *scanline, 584 % const size_t bytes_per_line,unsigned char *pixels) 585 % 586 % A description of each parameter follows: 587 % 588 % o image: the address of a structure of type Image. 589 % 590 % o scanline: A pointer to an array of characters to pack. 591 % 592 % o bytes_per_line: the number of bytes in a scanline. 593 % 594 % o pixels: A pointer to an array of characters where the packed 595 % characters are stored. 596 % 597 */ 598 static size_t EncodeImage(Image *image,const unsigned char *scanline, 599 const size_t bytes_per_line,unsigned char *pixels) 600 { 601 #define MaxCount 128 602 #define MaxPackbitsRunlength 128 603 604 register const unsigned char 605 *p; 606 607 register ssize_t 608 i; 609 610 register unsigned char 611 *q; 612 613 size_t 614 length; 615 616 ssize_t 617 count, 618 repeat_count, 619 runlength; 620 621 unsigned char 622 index; 623 624 /* 625 Pack scanline. 626 */ 627 assert(image != (Image *) NULL); 628 assert(image->signature == MagickCoreSignature); 629 if (image->debug != MagickFalse) 630 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 631 assert(scanline != (unsigned char *) NULL); 632 assert(pixels != (unsigned char *) NULL); 633 count=0; 634 runlength=0; 635 p=scanline+(bytes_per_line-1); 636 q=pixels; 637 index=(*p); 638 for (i=(ssize_t) bytes_per_line-1; i >= 0; i--) 639 { 640 if (index == *p) 641 runlength++; 642 else 643 { 644 if (runlength < 3) 645 while (runlength > 0) 646 { 647 *q++=(unsigned char) index; 648 runlength--; 649 count++; 650 if (count == MaxCount) 651 { 652 *q++=(unsigned char) (MaxCount-1); 653 count-=MaxCount; 654 } 655 } 656 else 657 { 658 if (count > 0) 659 *q++=(unsigned char) (count-1); 660 count=0; 661 while (runlength > 0) 662 { 663 repeat_count=runlength; 664 if (repeat_count > MaxPackbitsRunlength) 665 repeat_count=MaxPackbitsRunlength; 666 *q++=(unsigned char) index; 667 *q++=(unsigned char) (257-repeat_count); 668 runlength-=repeat_count; 669 } 670 } 671 runlength=1; 672 } 673 index=(*p); 674 p--; 675 } 676 if (runlength < 3) 677 while (runlength > 0) 678 { 679 *q++=(unsigned char) index; 680 runlength--; 681 count++; 682 if (count == MaxCount) 683 { 684 *q++=(unsigned char) (MaxCount-1); 685 count-=MaxCount; 686 } 687 } 688 else 689 { 690 if (count > 0) 691 *q++=(unsigned char) (count-1); 692 count=0; 693 while (runlength > 0) 694 { 695 repeat_count=runlength; 696 if (repeat_count > MaxPackbitsRunlength) 697 repeat_count=MaxPackbitsRunlength; 698 *q++=(unsigned char) index; 699 *q++=(unsigned char) (257-repeat_count); 700 runlength-=repeat_count; 701 } 702 } 703 if (count > 0) 704 *q++=(unsigned char) (count-1); 705 /* 706 Write the number of and the packed length. 707 */ 708 length=(size_t) (q-pixels); 709 if (bytes_per_line > 200) 710 { 711 (void) WriteBlobMSBShort(image,(unsigned short) length); 712 length+=2; 713 } 714 else 715 { 716 (void) WriteBlobByte(image,(unsigned char) length); 717 length++; 718 } 719 while (q != pixels) 720 { 721 q--; 722 (void) WriteBlobByte(image,*q); 723 } 724 return(length); 725 } 726 727 /* 729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 730 % % 731 % % 732 % % 733 % I s P I C T % 734 % % 735 % % 736 % % 737 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 738 % 739 % IsPICT()() returns MagickTrue if the image format type, identified by the 740 % magick string, is PICT. 741 % 742 % The format of the ReadPICTImage method is: 743 % 744 % MagickBooleanType IsPICT(const unsigned char *magick,const size_t length) 745 % 746 % A description of each parameter follows: 747 % 748 % o magick: compare image format pattern against these bytes. 749 % 750 % o length: Specifies the length of the magick string. 751 % 752 */ 753 static MagickBooleanType IsPICT(const unsigned char *magick,const size_t length) 754 { 755 if (length < 12) 756 return(MagickFalse); 757 /* 758 Embedded OLE2 macintosh have "PICT" instead of 512 platform header. 759 */ 760 if (memcmp(magick,"PICT",4) == 0) 761 return(MagickTrue); 762 if (length < 528) 763 return(MagickFalse); 764 if (memcmp(magick+522,"\000\021\002\377\014\000",6) == 0) 765 return(MagickTrue); 766 return(MagickFalse); 767 } 768 769 #if !defined(macintosh) 771 /* 772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 773 % % 774 % % 775 % % 776 % R e a d P I C T I m a g e % 777 % % 778 % % 779 % % 780 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 781 % 782 % ReadPICTImage() reads an Apple Macintosh QuickDraw/PICT image file 783 % and returns it. It allocates the memory necessary for the new Image 784 % structure and returns a pointer to the new image. 785 % 786 % The format of the ReadPICTImage method is: 787 % 788 % Image *ReadPICTImage(const ImageInfo *image_info, 789 % ExceptionInfo *exception) 790 % 791 % A description of each parameter follows: 792 % 793 % o image_info: the image info. 794 % 795 % o exception: return any errors or warnings in this structure. 796 % 797 */ 798 799 static MagickBooleanType ReadRectangle(Image *image,PICTRectangle *rectangle) 800 { 801 rectangle->top=(short) ReadBlobMSBShort(image); 802 rectangle->left=(short) ReadBlobMSBShort(image); 803 rectangle->bottom=(short) ReadBlobMSBShort(image); 804 rectangle->right=(short) ReadBlobMSBShort(image); 805 if ((EOFBlob(image) != MagickFalse) || (rectangle->left > rectangle->right) || 806 (rectangle->top > rectangle->bottom)) 807 return(MagickFalse); 808 return(MagickTrue); 809 } 810 811 static Image *ReadPICTImage(const ImageInfo *image_info, 812 ExceptionInfo *exception) 813 { 814 char 815 geometry[MagickPathExtent], 816 header_ole[4]; 817 818 Image 819 *image; 820 821 int 822 c, 823 code; 824 825 MagickBooleanType 826 jpeg, 827 status; 828 829 PICTRectangle 830 frame; 831 832 PICTPixmap 833 pixmap; 834 835 Quantum 836 index; 837 838 register Quantum 839 *q; 840 841 register ssize_t 842 i, 843 x; 844 845 size_t 846 extent, 847 length; 848 849 ssize_t 850 count, 851 flags, 852 j, 853 version, 854 y; 855 856 StringInfo 857 *profile; 858 859 /* 860 Open image file. 861 */ 862 assert(image_info != (const ImageInfo *) NULL); 863 assert(image_info->signature == MagickCoreSignature); 864 if (image_info->debug != MagickFalse) 865 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 866 image_info->filename); 867 assert(exception != (ExceptionInfo *) NULL); 868 assert(exception->signature == MagickCoreSignature); 869 image=AcquireImage(image_info,exception); 870 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 871 if (status == MagickFalse) 872 { 873 image=DestroyImageList(image); 874 return((Image *) NULL); 875 } 876 /* 877 Read PICT header. 878 */ 879 pixmap.bits_per_pixel=0; 880 pixmap.component_count=0; 881 /* 882 Skip header : 512 for standard PICT and 4, ie "PICT" for OLE2. 883 */ 884 header_ole[0]=ReadBlobByte(image); 885 header_ole[1]=ReadBlobByte(image); 886 header_ole[2]=ReadBlobByte(image); 887 header_ole[3]=ReadBlobByte(image); 888 if (!((header_ole[0] == 0x50) && (header_ole[1] == 0x49) && 889 (header_ole[2] == 0x43) && (header_ole[3] == 0x54 ))) 890 for (i=0; i < 508; i++) 891 if (ReadBlobByte(image) == EOF) 892 break; 893 (void) ReadBlobMSBShort(image); /* skip picture size */ 894 if (ReadRectangle(image,&frame) == MagickFalse) 895 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 896 while ((c=ReadBlobByte(image)) == 0) ; 897 if (c != 0x11) 898 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 899 version=ReadBlobByte(image); 900 if (version == 2) 901 { 902 c=ReadBlobByte(image); 903 if (c != 0xff) 904 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 905 } 906 else 907 if (version != 1) 908 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 909 if ((frame.left < 0) || (frame.right < 0) || (frame.top < 0) || 910 (frame.bottom < 0) || (frame.left >= frame.right) || 911 (frame.top >= frame.bottom)) 912 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 913 /* 914 Create black canvas. 915 */ 916 flags=0; 917 image->depth=8; 918 image->columns=1UL*(frame.right-frame.left); 919 image->rows=1UL*(frame.bottom-frame.top); 920 image->resolution.x=DefaultResolution; 921 image->resolution.y=DefaultResolution; 922 image->units=UndefinedResolution; 923 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) 924 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 925 { 926 (void) CloseBlob(image); 927 return(GetFirstImageInList(image)); 928 } 929 status=SetImageExtent(image,image->columns,image->rows,exception); 930 if (status == MagickFalse) 931 return(DestroyImageList(image)); 932 /* 933 Interpret PICT opcodes. 934 */ 935 jpeg=MagickFalse; 936 for (code=0; EOFBlob(image) == MagickFalse; ) 937 { 938 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) 939 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 940 break; 941 if ((version == 1) || ((TellBlob(image) % 2) != 0)) 942 code=ReadBlobByte(image); 943 if (version == 2) 944 code=ReadBlobMSBSignedShort(image); 945 if (code < 0) 946 break; 947 if (code > 0xa1) 948 { 949 if (image->debug != MagickFalse) 950 (void) LogMagickEvent(CoderEvent,GetMagickModule(),"%04X:",code); 951 } 952 else 953 { 954 if (image->debug != MagickFalse) 955 (void) LogMagickEvent(CoderEvent,GetMagickModule(), 956 " %04X %s: %s",code,codes[code].name,codes[code].description); 957 switch (code) 958 { 959 case 0x01: 960 { 961 /* 962 Clipping rectangle. 963 */ 964 length=ReadBlobMSBShort(image); 965 if (length != 0x000a) 966 { 967 for (i=0; i < (ssize_t) (length-2); i++) 968 if (ReadBlobByte(image) == EOF) 969 break; 970 break; 971 } 972 if (ReadRectangle(image,&frame) == MagickFalse) 973 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 974 if (((frame.left & 0x8000) != 0) || ((frame.top & 0x8000) != 0)) 975 break; 976 image->columns=1UL*(frame.right-frame.left); 977 image->rows=1UL*(frame.bottom-frame.top); 978 status=SetImageExtent(image,image->columns,image->rows,exception); 979 if (status == MagickFalse) 980 return(DestroyImageList(image)); 981 (void) SetImageBackgroundColor(image,exception); 982 break; 983 } 984 case 0x12: 985 case 0x13: 986 case 0x14: 987 { 988 ssize_t 989 pattern; 990 991 size_t 992 height, 993 width; 994 995 /* 996 Skip pattern definition. 997 */ 998 pattern=1L*ReadBlobMSBShort(image); 999 for (i=0; i < 8; i++) 1000 if (ReadBlobByte(image) == EOF) 1001 break; 1002 if (pattern == 2) 1003 { 1004 for (i=0; i < 5; i++) 1005 if (ReadBlobByte(image) == EOF) 1006 break; 1007 break; 1008 } 1009 if (pattern != 1) 1010 ThrowReaderException(CorruptImageError,"UnknownPatternType"); 1011 length=ReadBlobMSBShort(image); 1012 if (ReadRectangle(image,&frame) == MagickFalse) 1013 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 1014 ReadPixmap(pixmap); 1015 image->depth=1UL*pixmap.component_size; 1016 image->resolution.x=1.0*pixmap.horizontal_resolution; 1017 image->resolution.y=1.0*pixmap.vertical_resolution; 1018 image->units=PixelsPerInchResolution; 1019 (void) ReadBlobMSBLong(image); 1020 flags=1L*ReadBlobMSBShort(image); 1021 length=ReadBlobMSBShort(image); 1022 for (i=0; i <= (ssize_t) length; i++) 1023 (void) ReadBlobMSBLong(image); 1024 width=1UL*(frame.bottom-frame.top); 1025 height=1UL*(frame.right-frame.left); 1026 if (pixmap.bits_per_pixel <= 8) 1027 length&=0x7fff; 1028 if (pixmap.bits_per_pixel == 16) 1029 width<<=1; 1030 if (length == 0) 1031 length=width; 1032 if (length < 8) 1033 { 1034 for (i=0; i < (ssize_t) (length*height); i++) 1035 if (ReadBlobByte(image) == EOF) 1036 break; 1037 } 1038 else 1039 for (j=0; j < (int) height; j++) 1040 if (length > 200) 1041 { 1042 for (j=0; j < (ssize_t) ReadBlobMSBShort(image); j++) 1043 if (ReadBlobByte(image) == EOF) 1044 break; 1045 } 1046 else 1047 for (j=0; j < (ssize_t) ReadBlobByte(image); j++) 1048 if (ReadBlobByte(image) == EOF) 1049 break; 1050 break; 1051 } 1052 case 0x1b: 1053 { 1054 /* 1055 Initialize image background color. 1056 */ 1057 image->background_color.red=(Quantum) 1058 ScaleShortToQuantum(ReadBlobMSBShort(image)); 1059 image->background_color.green=(Quantum) 1060 ScaleShortToQuantum(ReadBlobMSBShort(image)); 1061 image->background_color.blue=(Quantum) 1062 ScaleShortToQuantum(ReadBlobMSBShort(image)); 1063 break; 1064 } 1065 case 0x70: 1066 case 0x71: 1067 case 0x72: 1068 case 0x73: 1069 case 0x74: 1070 case 0x75: 1071 case 0x76: 1072 case 0x77: 1073 { 1074 /* 1075 Skip polygon or region. 1076 */ 1077 length=ReadBlobMSBShort(image); 1078 for (i=0; i < (ssize_t) (length-2); i++) 1079 if (ReadBlobByte(image) == EOF) 1080 break; 1081 break; 1082 } 1083 case 0x90: 1084 case 0x91: 1085 case 0x98: 1086 case 0x99: 1087 case 0x9a: 1088 case 0x9b: 1089 { 1090 Image 1091 *tile_image; 1092 1093 PICTRectangle 1094 source, 1095 destination; 1096 1097 register unsigned char 1098 *p; 1099 1100 size_t 1101 j; 1102 1103 ssize_t 1104 bytes_per_line; 1105 1106 unsigned char 1107 *pixels; 1108 1109 /* 1110 Pixmap clipped by a rectangle. 1111 */ 1112 bytes_per_line=0; 1113 if ((code != 0x9a) && (code != 0x9b)) 1114 bytes_per_line=1L*ReadBlobMSBShort(image); 1115 else 1116 { 1117 (void) ReadBlobMSBShort(image); 1118 (void) ReadBlobMSBShort(image); 1119 (void) ReadBlobMSBShort(image); 1120 } 1121 if (ReadRectangle(image,&frame) == MagickFalse) 1122 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 1123 /* 1124 Initialize tile image. 1125 */ 1126 tile_image=CloneImage(image,1UL*(frame.right-frame.left), 1127 1UL*(frame.bottom-frame.top),MagickTrue,exception); 1128 if (tile_image == (Image *) NULL) 1129 return((Image *) NULL); 1130 if ((code == 0x9a) || (code == 0x9b) || 1131 ((bytes_per_line & 0x8000) != 0)) 1132 { 1133 ReadPixmap(pixmap); 1134 tile_image->depth=1UL*pixmap.component_size; 1135 tile_image->alpha_trait=pixmap.component_count == 4 ? 1136 BlendPixelTrait : UndefinedPixelTrait; 1137 tile_image->resolution.x=(double) pixmap.horizontal_resolution; 1138 tile_image->resolution.y=(double) pixmap.vertical_resolution; 1139 tile_image->units=PixelsPerInchResolution; 1140 if (tile_image->alpha_trait != UndefinedPixelTrait) 1141 image->alpha_trait=tile_image->alpha_trait; 1142 } 1143 if ((code != 0x9a) && (code != 0x9b)) 1144 { 1145 /* 1146 Initialize colormap. 1147 */ 1148 tile_image->colors=2; 1149 if ((bytes_per_line & 0x8000) != 0) 1150 { 1151 (void) ReadBlobMSBLong(image); 1152 flags=1L*ReadBlobMSBShort(image); 1153 tile_image->colors=1UL*ReadBlobMSBShort(image)+1; 1154 } 1155 status=AcquireImageColormap(tile_image,tile_image->colors, 1156 exception); 1157 if (status == MagickFalse) 1158 { 1159 tile_image=DestroyImage(tile_image); 1160 ThrowReaderException(ResourceLimitError, 1161 "MemoryAllocationFailed"); 1162 } 1163 if ((bytes_per_line & 0x8000) != 0) 1164 { 1165 for (i=0; i < (ssize_t) tile_image->colors; i++) 1166 { 1167 j=ReadBlobMSBShort(image) % tile_image->colors; 1168 if ((flags & 0x8000) != 0) 1169 j=(size_t) i; 1170 tile_image->colormap[j].red=(Quantum) 1171 ScaleShortToQuantum(ReadBlobMSBShort(image)); 1172 tile_image->colormap[j].green=(Quantum) 1173 ScaleShortToQuantum(ReadBlobMSBShort(image)); 1174 tile_image->colormap[j].blue=(Quantum) 1175 ScaleShortToQuantum(ReadBlobMSBShort(image)); 1176 } 1177 } 1178 else 1179 { 1180 for (i=0; i < (ssize_t) tile_image->colors; i++) 1181 { 1182 tile_image->colormap[i].red=(Quantum) (QuantumRange- 1183 tile_image->colormap[i].red); 1184 tile_image->colormap[i].green=(Quantum) (QuantumRange- 1185 tile_image->colormap[i].green); 1186 tile_image->colormap[i].blue=(Quantum) (QuantumRange- 1187 tile_image->colormap[i].blue); 1188 } 1189 } 1190 } 1191 if (ReadRectangle(image,&source) == MagickFalse) 1192 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 1193 if (ReadRectangle(image,&destination) == MagickFalse) 1194 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 1195 (void) ReadBlobMSBShort(image); 1196 if ((code == 0x91) || (code == 0x99) || (code == 0x9b)) 1197 { 1198 /* 1199 Skip region. 1200 */ 1201 length=ReadBlobMSBShort(image); 1202 for (i=0; i < (ssize_t) (length-2); i++) 1203 if (ReadBlobByte(image) == EOF) 1204 break; 1205 } 1206 if ((code != 0x9a) && (code != 0x9b) && 1207 (bytes_per_line & 0x8000) == 0) 1208 pixels=DecodeImage(image,tile_image,1UL*bytes_per_line,1,&extent, 1209 exception); 1210 else 1211 pixels=DecodeImage(image,tile_image,1UL*bytes_per_line,1U* 1212 pixmap.bits_per_pixel,&extent,exception); 1213 if (pixels == (unsigned char *) NULL) 1214 { 1215 tile_image=DestroyImage(tile_image); 1216 ThrowReaderException(ResourceLimitError, 1217 "MemoryAllocationFailed"); 1218 } 1219 /* 1220 Convert PICT tile image to pixel packets. 1221 */ 1222 p=pixels; 1223 for (y=0; y < (ssize_t) tile_image->rows; y++) 1224 { 1225 if (p > (pixels+extent+image->columns)) 1226 ThrowReaderException(CorruptImageError,"NotEnoughPixelData"); 1227 q=QueueAuthenticPixels(tile_image,0,y,tile_image->columns,1, 1228 exception); 1229 if (q == (Quantum *) NULL) 1230 break; 1231 for (x=0; x < (ssize_t) tile_image->columns; x++) 1232 { 1233 if (tile_image->storage_class == PseudoClass) 1234 { 1235 index=ConstrainColormapIndex(tile_image,*p,exception); 1236 SetPixelIndex(tile_image,index,q); 1237 SetPixelRed(tile_image, 1238 tile_image->colormap[(ssize_t) index].red,q); 1239 SetPixelGreen(tile_image, 1240 tile_image->colormap[(ssize_t) index].green,q); 1241 SetPixelBlue(tile_image, 1242 tile_image->colormap[(ssize_t) index].blue,q); 1243 } 1244 else 1245 { 1246 if (pixmap.bits_per_pixel == 16) 1247 { 1248 i=(*p++); 1249 j=(*p); 1250 SetPixelRed(tile_image,ScaleCharToQuantum( 1251 (unsigned char) ((i & 0x7c) << 1)),q); 1252 SetPixelGreen(tile_image,ScaleCharToQuantum( 1253 (unsigned char) (((i & 0x03) << 6) | 1254 ((j & 0xe0) >> 2))),q); 1255 SetPixelBlue(tile_image,ScaleCharToQuantum( 1256 (unsigned char) ((j & 0x1f) << 3)),q); 1257 } 1258 else 1259 if (tile_image->alpha_trait == UndefinedPixelTrait) 1260 { 1261 if (p > (pixels+extent+2*image->columns)) 1262 ThrowReaderException(CorruptImageError, 1263 "NotEnoughPixelData"); 1264 SetPixelRed(tile_image,ScaleCharToQuantum(*p),q); 1265 SetPixelGreen(tile_image,ScaleCharToQuantum( 1266 *(p+tile_image->columns)),q); 1267 SetPixelBlue(tile_image,ScaleCharToQuantum( 1268 *(p+2*tile_image->columns)),q); 1269 } 1270 else 1271 { 1272 if (p > (pixels+extent+3*image->columns)) 1273 ThrowReaderException(CorruptImageError, 1274 "NotEnoughPixelData"); 1275 SetPixelAlpha(tile_image,ScaleCharToQuantum(*p),q); 1276 SetPixelRed(tile_image,ScaleCharToQuantum( 1277 *(p+tile_image->columns)),q); 1278 SetPixelGreen(tile_image,ScaleCharToQuantum( 1279 *(p+2*tile_image->columns)),q); 1280 SetPixelBlue(tile_image,ScaleCharToQuantum( 1281 *(p+3*tile_image->columns)),q); 1282 } 1283 } 1284 p++; 1285 q+=GetPixelChannels(tile_image); 1286 } 1287 if (SyncAuthenticPixels(tile_image,exception) == MagickFalse) 1288 break; 1289 if ((tile_image->storage_class == DirectClass) && 1290 (pixmap.bits_per_pixel != 16)) 1291 { 1292 p+=(pixmap.component_count-1)*tile_image->columns; 1293 if (p < pixels) 1294 break; 1295 } 1296 status=SetImageProgress(image,LoadImageTag,y,tile_image->rows); 1297 if (status == MagickFalse) 1298 break; 1299 } 1300 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 1301 if (jpeg == MagickFalse) 1302 if ((code == 0x9a) || (code == 0x9b) || 1303 ((bytes_per_line & 0x8000) != 0)) 1304 (void) CompositeImage(image,tile_image,CopyCompositeOp, 1305 MagickTrue,destination.left,destination.top,exception); 1306 tile_image=DestroyImage(tile_image); 1307 break; 1308 } 1309 case 0xa1: 1310 { 1311 unsigned char 1312 *info; 1313 1314 size_t 1315 type; 1316 1317 /* 1318 Comment. 1319 */ 1320 type=ReadBlobMSBShort(image); 1321 length=ReadBlobMSBShort(image); 1322 if (length == 0) 1323 break; 1324 (void) ReadBlobMSBLong(image); 1325 length-=4; 1326 if (length == 0) 1327 break; 1328 info=(unsigned char *) AcquireQuantumMemory(length,sizeof(*info)); 1329 if (info == (unsigned char *) NULL) 1330 break; 1331 count=ReadBlob(image,length,info); 1332 if (count != (ssize_t) length) 1333 ThrowReaderException(ResourceLimitError,"UnableToReadImageData"); 1334 switch (type) 1335 { 1336 case 0xe0: 1337 { 1338 profile=BlobToStringInfo((const void *) NULL,length); 1339 SetStringInfoDatum(profile,info); 1340 status=SetImageProfile(image,"icc",profile,exception); 1341 profile=DestroyStringInfo(profile); 1342 if (status == MagickFalse) 1343 ThrowReaderException(ResourceLimitError, 1344 "MemoryAllocationFailed"); 1345 break; 1346 } 1347 case 0x1f2: 1348 { 1349 profile=BlobToStringInfo((const void *) NULL,length); 1350 SetStringInfoDatum(profile,info); 1351 status=SetImageProfile(image,"iptc",profile,exception); 1352 if (status == MagickFalse) 1353 ThrowReaderException(ResourceLimitError, 1354 "MemoryAllocationFailed"); 1355 profile=DestroyStringInfo(profile); 1356 break; 1357 } 1358 default: 1359 break; 1360 } 1361 info=(unsigned char *) RelinquishMagickMemory(info); 1362 break; 1363 } 1364 default: 1365 { 1366 /* 1367 Skip to next op code. 1368 */ 1369 if (codes[code].length == -1) 1370 (void) ReadBlobMSBShort(image); 1371 else 1372 for (i=0; i < (ssize_t) codes[code].length; i++) 1373 if (ReadBlobByte(image) == EOF) 1374 break; 1375 } 1376 } 1377 } 1378 if (code == 0xc00) 1379 { 1380 /* 1381 Skip header. 1382 */ 1383 for (i=0; i < 24; i++) 1384 if (ReadBlobByte(image) == EOF) 1385 break; 1386 continue; 1387 } 1388 if (((code >= 0xb0) && (code <= 0xcf)) || 1389 ((code >= 0x8000) && (code <= 0x80ff))) 1390 continue; 1391 if (code == 0x8200) 1392 { 1393 FILE 1394 *file; 1395 1396 Image 1397 *tile_image; 1398 1399 ImageInfo 1400 *read_info; 1401 1402 int 1403 unique_file; 1404 1405 /* 1406 Embedded JPEG. 1407 */ 1408 jpeg=MagickTrue; 1409 read_info=CloneImageInfo(image_info); 1410 SetImageInfoBlob(read_info,(void *) NULL,0); 1411 file=(FILE *) NULL; 1412 unique_file=AcquireUniqueFileResource(read_info->filename); 1413 if (unique_file != -1) 1414 file=fdopen(unique_file,"wb"); 1415 if ((unique_file == -1) || (file == (FILE *) NULL)) 1416 { 1417 (void) RelinquishUniqueFileResource(read_info->filename); 1418 (void) CopyMagickString(image->filename,read_info->filename, 1419 MagickPathExtent); 1420 ThrowFileException(exception,FileOpenError, 1421 "UnableToCreateTemporaryFile",image->filename); 1422 image=DestroyImageList(image); 1423 return((Image *) NULL); 1424 } 1425 length=ReadBlobMSBLong(image); 1426 if (length > 154) 1427 { 1428 for (i=0; i < 6; i++) 1429 (void) ReadBlobMSBLong(image); 1430 if (ReadRectangle(image,&frame) == MagickFalse) 1431 { 1432 (void) fclose(file); 1433 (void) RelinquishUniqueFileResource(read_info->filename); 1434 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 1435 } 1436 for (i=0; i < 122; i++) 1437 if (ReadBlobByte(image) == EOF) 1438 break; 1439 for (i=0; i < (ssize_t) (length-154); i++) 1440 { 1441 c=ReadBlobByte(image); 1442 if (c == EOF) 1443 break; 1444 (void) fputc(c,file); 1445 } 1446 } 1447 (void) fclose(file); 1448 (void) close(unique_file); 1449 tile_image=ReadImage(read_info,exception); 1450 (void) RelinquishUniqueFileResource(read_info->filename); 1451 read_info=DestroyImageInfo(read_info); 1452 if (tile_image == (Image *) NULL) 1453 continue; 1454 (void) FormatLocaleString(geometry,MagickPathExtent,"%.20gx%.20g", 1455 (double) MagickMax(image->columns,tile_image->columns), 1456 (double) MagickMax(image->rows,tile_image->rows)); 1457 (void) SetImageExtent(image, 1458 MagickMax(image->columns,tile_image->columns), 1459 MagickMax(image->rows,tile_image->rows),exception); 1460 (void) TransformImageColorspace(image,tile_image->colorspace,exception); 1461 (void) CompositeImage(image,tile_image,CopyCompositeOp,MagickTrue, 1462 frame.left,frame.right,exception); 1463 image->compression=tile_image->compression; 1464 tile_image=DestroyImage(tile_image); 1465 continue; 1466 } 1467 if ((code == 0xff) || (code == 0xffff)) 1468 break; 1469 if (((code >= 0xd0) && (code <= 0xfe)) || 1470 ((code >= 0x8100) && (code <= 0xffff))) 1471 { 1472 /* 1473 Skip reserved. 1474 */ 1475 length=ReadBlobMSBShort(image); 1476 for (i=0; i < (ssize_t) length; i++) 1477 if (ReadBlobByte(image) == EOF) 1478 break; 1479 continue; 1480 } 1481 if ((code >= 0x100) && (code <= 0x7fff)) 1482 { 1483 /* 1484 Skip reserved. 1485 */ 1486 length=(size_t) ((code >> 7) & 0xff); 1487 for (i=0; i < (ssize_t) length; i++) 1488 if (ReadBlobByte(image) == EOF) 1489 break; 1490 continue; 1491 } 1492 } 1493 (void) CloseBlob(image); 1494 return(GetFirstImageInList(image)); 1495 } 1496 #endif 1497 1498 /* 1500 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1501 % % 1502 % % 1503 % % 1504 % R e g i s t e r P I C T I m a g e % 1505 % % 1506 % % 1507 % % 1508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1509 % 1510 % RegisterPICTImage() adds attributes for the PICT image format to 1511 % the list of supported formats. The attributes include the image format 1512 % tag, a method to read and/or write the format, whether the format 1513 % supports the saving of more than one frame to the same file or blob, 1514 % whether the format supports native in-memory I/O, and a brief 1515 % description of the format. 1516 % 1517 % The format of the RegisterPICTImage method is: 1518 % 1519 % size_t RegisterPICTImage(void) 1520 % 1521 */ 1522 ModuleExport size_t RegisterPICTImage(void) 1523 { 1524 MagickInfo 1525 *entry; 1526 1527 entry=AcquireMagickInfo("PICT","PCT","Apple Macintosh QuickDraw/PICT"); 1528 entry->decoder=(DecodeImageHandler *) ReadPICTImage; 1529 entry->encoder=(EncodeImageHandler *) WritePICTImage; 1530 entry->flags^=CoderAdjoinFlag; 1531 entry->flags|=CoderSeekableStreamFlag; 1532 entry->magick=(IsImageFormatHandler *) IsPICT; 1533 (void) RegisterMagickInfo(entry); 1534 entry=AcquireMagickInfo("PICT","PICT","Apple Macintosh QuickDraw/PICT"); 1535 entry->decoder=(DecodeImageHandler *) ReadPICTImage; 1536 entry->encoder=(EncodeImageHandler *) WritePICTImage; 1537 entry->flags^=CoderAdjoinFlag; 1538 entry->flags|=CoderSeekableStreamFlag; 1539 entry->magick=(IsImageFormatHandler *) IsPICT; 1540 (void) RegisterMagickInfo(entry); 1541 return(MagickImageCoderSignature); 1542 } 1543 1544 /* 1546 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1547 % % 1548 % % 1549 % % 1550 % U n r e g i s t e r P I C T I m a g e % 1551 % % 1552 % % 1553 % % 1554 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1555 % 1556 % UnregisterPICTImage() removes format registrations made by the 1557 % PICT module from the list of supported formats. 1558 % 1559 % The format of the UnregisterPICTImage method is: 1560 % 1561 % UnregisterPICTImage(void) 1562 % 1563 */ 1564 ModuleExport void UnregisterPICTImage(void) 1565 { 1566 (void) UnregisterMagickInfo("PCT"); 1567 (void) UnregisterMagickInfo("PICT"); 1568 } 1569 1570 /* 1572 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1573 % % 1574 % % 1575 % % 1576 % W r i t e P I C T I m a g e % 1577 % % 1578 % % 1579 % % 1580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1581 % 1582 % WritePICTImage() writes an image to a file in the Apple Macintosh 1583 % QuickDraw/PICT image format. 1584 % 1585 % The format of the WritePICTImage method is: 1586 % 1587 % MagickBooleanType WritePICTImage(const ImageInfo *image_info, 1588 % Image *image,ExceptionInfo *exception) 1589 % 1590 % A description of each parameter follows. 1591 % 1592 % o image_info: the image info. 1593 % 1594 % o image: The image. 1595 % 1596 % o exception: return any errors or warnings in this structure. 1597 % 1598 */ 1599 static MagickBooleanType WritePICTImage(const ImageInfo *image_info, 1600 Image *image,ExceptionInfo *exception) 1601 { 1602 #define MaxCount 128 1603 #define PictCropRegionOp 0x01 1604 #define PictEndOfPictureOp 0xff 1605 #define PictJPEGOp 0x8200 1606 #define PictInfoOp 0x0C00 1607 #define PictInfoSize 512 1608 #define PictPixmapOp 0x9A 1609 #define PictPICTOp 0x98 1610 #define PictVersion 0x11 1611 1612 const StringInfo 1613 *profile; 1614 1615 double 1616 x_resolution, 1617 y_resolution; 1618 1619 MagickBooleanType 1620 status; 1621 1622 MagickOffsetType 1623 offset; 1624 1625 PICTPixmap 1626 pixmap; 1627 1628 PICTRectangle 1629 bounds, 1630 crop_rectangle, 1631 destination_rectangle, 1632 frame_rectangle, 1633 size_rectangle, 1634 source_rectangle; 1635 1636 register const Quantum 1637 *p; 1638 1639 register ssize_t 1640 i, 1641 x; 1642 1643 size_t 1644 bytes_per_line, 1645 count, 1646 row_bytes, 1647 storage_class; 1648 1649 ssize_t 1650 y; 1651 1652 unsigned char 1653 *buffer, 1654 *packed_scanline, 1655 *scanline; 1656 1657 unsigned short 1658 base_address, 1659 transfer_mode; 1660 1661 /* 1662 Open output image file. 1663 */ 1664 assert(image_info != (const ImageInfo *) NULL); 1665 assert(image_info->signature == MagickCoreSignature); 1666 assert(image != (Image *) NULL); 1667 assert(image->signature == MagickCoreSignature); 1668 if (image->debug != MagickFalse) 1669 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1670 if ((image->columns > 65535L) || (image->rows > 65535L)) 1671 ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit"); 1672 assert(exception != (ExceptionInfo *) NULL); 1673 assert(exception->signature == MagickCoreSignature); 1674 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 1675 if (status == MagickFalse) 1676 return(status); 1677 (void) TransformImageColorspace(image,sRGBColorspace,exception); 1678 /* 1679 Initialize image info. 1680 */ 1681 size_rectangle.top=0; 1682 size_rectangle.left=0; 1683 size_rectangle.bottom=(short) image->rows; 1684 size_rectangle.right=(short) image->columns; 1685 frame_rectangle=size_rectangle; 1686 crop_rectangle=size_rectangle; 1687 source_rectangle=size_rectangle; 1688 destination_rectangle=size_rectangle; 1689 base_address=0xff; 1690 row_bytes=image->columns; 1691 bounds.top=0; 1692 bounds.left=0; 1693 bounds.bottom=(short) image->rows; 1694 bounds.right=(short) image->columns; 1695 pixmap.version=0; 1696 pixmap.pack_type=0; 1697 pixmap.pack_size=0; 1698 pixmap.pixel_type=0; 1699 pixmap.bits_per_pixel=8; 1700 pixmap.component_count=1; 1701 pixmap.component_size=8; 1702 pixmap.plane_bytes=0; 1703 pixmap.table=0; 1704 pixmap.reserved=0; 1705 transfer_mode=0; 1706 x_resolution=image->resolution.x != 0.0 ? image->resolution.x : 1707 DefaultResolution; 1708 y_resolution=image->resolution.y != 0.0 ? image->resolution.y : 1709 DefaultResolution; 1710 storage_class=image->storage_class; 1711 if (image_info->compression == JPEGCompression) 1712 storage_class=DirectClass; 1713 if (storage_class == DirectClass) 1714 { 1715 pixmap.component_count=image->alpha_trait != UndefinedPixelTrait ? 4 : 3; 1716 pixmap.pixel_type=16; 1717 pixmap.bits_per_pixel=32; 1718 pixmap.pack_type=0x04; 1719 transfer_mode=0x40; 1720 row_bytes=4*image->columns; 1721 } 1722 /* 1723 Allocate memory. 1724 */ 1725 bytes_per_line=image->columns; 1726 if (storage_class == DirectClass) 1727 bytes_per_line*=image->alpha_trait != UndefinedPixelTrait ? 4 : 3; 1728 buffer=(unsigned char *) AcquireQuantumMemory(PictInfoSize,sizeof(*buffer)); 1729 packed_scanline=(unsigned char *) AcquireQuantumMemory((size_t) 1730 (row_bytes+MaxCount),sizeof(*packed_scanline)); 1731 scanline=(unsigned char *) AcquireQuantumMemory(row_bytes,sizeof(*scanline)); 1732 if ((buffer == (unsigned char *) NULL) || 1733 (packed_scanline == (unsigned char *) NULL) || 1734 (scanline == (unsigned char *) NULL)) 1735 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 1736 (void) ResetMagickMemory(scanline,0,row_bytes); 1737 (void) ResetMagickMemory(packed_scanline,0,(size_t) (row_bytes+MaxCount)); 1738 /* 1739 Write header, header size, size bounding box, version, and reserved. 1740 */ 1741 (void) ResetMagickMemory(buffer,0,PictInfoSize); 1742 (void) WriteBlob(image,PictInfoSize,buffer); 1743 (void) WriteBlobMSBShort(image,0); 1744 (void) WriteBlobMSBShort(image,(unsigned short) size_rectangle.top); 1745 (void) WriteBlobMSBShort(image,(unsigned short) size_rectangle.left); 1746 (void) WriteBlobMSBShort(image,(unsigned short) size_rectangle.bottom); 1747 (void) WriteBlobMSBShort(image,(unsigned short) size_rectangle.right); 1748 (void) WriteBlobMSBShort(image,PictVersion); 1749 (void) WriteBlobMSBShort(image,0x02ff); /* version #2 */ 1750 (void) WriteBlobMSBShort(image,PictInfoOp); 1751 (void) WriteBlobMSBLong(image,0xFFFE0000UL); 1752 /* 1753 Write full size of the file, resolution, frame bounding box, and reserved. 1754 */ 1755 (void) WriteBlobMSBShort(image,(unsigned short) x_resolution); 1756 (void) WriteBlobMSBShort(image,0x0000); 1757 (void) WriteBlobMSBShort(image,(unsigned short) y_resolution); 1758 (void) WriteBlobMSBShort(image,0x0000); 1759 (void) WriteBlobMSBShort(image,(unsigned short) frame_rectangle.top); 1760 (void) WriteBlobMSBShort(image,(unsigned short) frame_rectangle.left); 1761 (void) WriteBlobMSBShort(image,(unsigned short) frame_rectangle.bottom); 1762 (void) WriteBlobMSBShort(image,(unsigned short) frame_rectangle.right); 1763 (void) WriteBlobMSBLong(image,0x00000000L); 1764 profile=GetImageProfile(image,"iptc"); 1765 if (profile != (StringInfo *) NULL) 1766 { 1767 (void) WriteBlobMSBShort(image,0xa1); 1768 (void) WriteBlobMSBShort(image,0x1f2); 1769 (void) WriteBlobMSBShort(image,(unsigned short) 1770 (GetStringInfoLength(profile)+4)); 1771 (void) WriteBlobString(image,"8BIM"); 1772 (void) WriteBlob(image,GetStringInfoLength(profile), 1773 GetStringInfoDatum(profile)); 1774 } 1775 profile=GetImageProfile(image,"icc"); 1776 if (profile != (StringInfo *) NULL) 1777 { 1778 (void) WriteBlobMSBShort(image,0xa1); 1779 (void) WriteBlobMSBShort(image,0xe0); 1780 (void) WriteBlobMSBShort(image,(unsigned short) 1781 (GetStringInfoLength(profile)+4)); 1782 (void) WriteBlobMSBLong(image,0x00000000UL); 1783 (void) WriteBlob(image,GetStringInfoLength(profile), 1784 GetStringInfoDatum(profile)); 1785 (void) WriteBlobMSBShort(image,0xa1); 1786 (void) WriteBlobMSBShort(image,0xe0); 1787 (void) WriteBlobMSBShort(image,4); 1788 (void) WriteBlobMSBLong(image,0x00000002UL); 1789 } 1790 /* 1791 Write crop region opcode and crop bounding box. 1792 */ 1793 (void) WriteBlobMSBShort(image,PictCropRegionOp); 1794 (void) WriteBlobMSBShort(image,0xa); 1795 (void) WriteBlobMSBShort(image,(unsigned short) crop_rectangle.top); 1796 (void) WriteBlobMSBShort(image,(unsigned short) crop_rectangle.left); 1797 (void) WriteBlobMSBShort(image,(unsigned short) crop_rectangle.bottom); 1798 (void) WriteBlobMSBShort(image,(unsigned short) crop_rectangle.right); 1799 if (image_info->compression == JPEGCompression) 1800 { 1801 Image 1802 *jpeg_image; 1803 1804 ImageInfo 1805 *jpeg_info; 1806 1807 size_t 1808 length; 1809 1810 unsigned char 1811 *blob; 1812 1813 jpeg_image=CloneImage(image,0,0,MagickTrue,exception); 1814 if (jpeg_image == (Image *) NULL) 1815 { 1816 (void) CloseBlob(image); 1817 return(MagickFalse); 1818 } 1819 jpeg_info=CloneImageInfo(image_info); 1820 (void) CopyMagickString(jpeg_info->magick,"JPEG",MagickPathExtent); 1821 length=0; 1822 blob=(unsigned char *) ImageToBlob(jpeg_info,jpeg_image,&length, 1823 exception); 1824 jpeg_info=DestroyImageInfo(jpeg_info); 1825 if (blob == (unsigned char *) NULL) 1826 return(MagickFalse); 1827 jpeg_image=DestroyImage(jpeg_image); 1828 (void) WriteBlobMSBShort(image,PictJPEGOp); 1829 (void) WriteBlobMSBLong(image,(unsigned int) length+154); 1830 (void) WriteBlobMSBShort(image,0x0000); 1831 (void) WriteBlobMSBLong(image,0x00010000UL); 1832 (void) WriteBlobMSBLong(image,0x00000000UL); 1833 (void) WriteBlobMSBLong(image,0x00000000UL); 1834 (void) WriteBlobMSBLong(image,0x00000000UL); 1835 (void) WriteBlobMSBLong(image,0x00010000UL); 1836 (void) WriteBlobMSBLong(image,0x00000000UL); 1837 (void) WriteBlobMSBLong(image,0x00000000UL); 1838 (void) WriteBlobMSBLong(image,0x00000000UL); 1839 (void) WriteBlobMSBLong(image,0x40000000UL); 1840 (void) WriteBlobMSBLong(image,0x00000000UL); 1841 (void) WriteBlobMSBLong(image,0x00000000UL); 1842 (void) WriteBlobMSBLong(image,0x00000000UL); 1843 (void) WriteBlobMSBLong(image,0x00400000UL); 1844 (void) WriteBlobMSBShort(image,0x0000); 1845 (void) WriteBlobMSBShort(image,(unsigned short) image->rows); 1846 (void) WriteBlobMSBShort(image,(unsigned short) image->columns); 1847 (void) WriteBlobMSBShort(image,0x0000); 1848 (void) WriteBlobMSBShort(image,768); 1849 (void) WriteBlobMSBShort(image,0x0000); 1850 (void) WriteBlobMSBLong(image,0x00000000UL); 1851 (void) WriteBlobMSBLong(image,0x00566A70UL); 1852 (void) WriteBlobMSBLong(image,0x65670000UL); 1853 (void) WriteBlobMSBLong(image,0x00000000UL); 1854 (void) WriteBlobMSBLong(image,0x00000001UL); 1855 (void) WriteBlobMSBLong(image,0x00016170UL); 1856 (void) WriteBlobMSBLong(image,0x706C0000UL); 1857 (void) WriteBlobMSBLong(image,0x00000000UL); 1858 (void) WriteBlobMSBShort(image,768); 1859 (void) WriteBlobMSBShort(image,(unsigned short) image->columns); 1860 (void) WriteBlobMSBShort(image,(unsigned short) image->rows); 1861 (void) WriteBlobMSBShort(image,(unsigned short) x_resolution); 1862 (void) WriteBlobMSBShort(image,0x0000); 1863 (void) WriteBlobMSBShort(image,(unsigned short) y_resolution); 1864 (void) WriteBlobMSBLong(image,0x00000000UL); 1865 (void) WriteBlobMSBLong(image,0x87AC0001UL); 1866 (void) WriteBlobMSBLong(image,0x0B466F74UL); 1867 (void) WriteBlobMSBLong(image,0x6F202D20UL); 1868 (void) WriteBlobMSBLong(image,0x4A504547UL); 1869 (void) WriteBlobMSBLong(image,0x00000000UL); 1870 (void) WriteBlobMSBLong(image,0x00000000UL); 1871 (void) WriteBlobMSBLong(image,0x00000000UL); 1872 (void) WriteBlobMSBLong(image,0x00000000UL); 1873 (void) WriteBlobMSBLong(image,0x00000000UL); 1874 (void) WriteBlobMSBLong(image,0x0018FFFFUL); 1875 (void) WriteBlob(image,length,blob); 1876 if ((length & 0x01) != 0) 1877 (void) WriteBlobByte(image,'\0'); 1878 blob=(unsigned char *) RelinquishMagickMemory(blob); 1879 } 1880 /* 1881 Write picture opcode, row bytes, and picture bounding box, and version. 1882 */ 1883 if (storage_class == PseudoClass) 1884 (void) WriteBlobMSBShort(image,PictPICTOp); 1885 else 1886 { 1887 (void) WriteBlobMSBShort(image,PictPixmapOp); 1888 (void) WriteBlobMSBLong(image,(size_t) base_address); 1889 } 1890 (void) WriteBlobMSBShort(image,(unsigned short) (row_bytes | 0x8000)); 1891 (void) WriteBlobMSBShort(image,(unsigned short) bounds.top); 1892 (void) WriteBlobMSBShort(image,(unsigned short) bounds.left); 1893 (void) WriteBlobMSBShort(image,(unsigned short) bounds.bottom); 1894 (void) WriteBlobMSBShort(image,(unsigned short) bounds.right); 1895 /* 1896 Write pack type, pack size, resolution, pixel type, and pixel size. 1897 */ 1898 (void) WriteBlobMSBShort(image,(unsigned short) pixmap.version); 1899 (void) WriteBlobMSBShort(image,(unsigned short) pixmap.pack_type); 1900 (void) WriteBlobMSBLong(image,(unsigned int) pixmap.pack_size); 1901 (void) WriteBlobMSBShort(image,(unsigned short) (x_resolution+0.5)); 1902 (void) WriteBlobMSBShort(image,0x0000); 1903 (void) WriteBlobMSBShort(image,(unsigned short) (y_resolution+0.5)); 1904 (void) WriteBlobMSBShort(image,0x0000); 1905 (void) WriteBlobMSBShort(image,(unsigned short) pixmap.pixel_type); 1906 (void) WriteBlobMSBShort(image,(unsigned short) pixmap.bits_per_pixel); 1907 /* 1908 Write component count, size, plane bytes, table size, and reserved. 1909 */ 1910 (void) WriteBlobMSBShort(image,(unsigned short) pixmap.component_count); 1911 (void) WriteBlobMSBShort(image,(unsigned short) pixmap.component_size); 1912 (void) WriteBlobMSBLong(image,(unsigned int) pixmap.plane_bytes); 1913 (void) WriteBlobMSBLong(image,(unsigned int) pixmap.table); 1914 (void) WriteBlobMSBLong(image,(unsigned int) pixmap.reserved); 1915 if (storage_class == PseudoClass) 1916 { 1917 /* 1918 Write image colormap. 1919 */ 1920 (void) WriteBlobMSBLong(image,0x00000000L); /* color seed */ 1921 (void) WriteBlobMSBShort(image,0L); /* color flags */ 1922 (void) WriteBlobMSBShort(image,(unsigned short) (image->colors-1)); 1923 for (i=0; i < (ssize_t) image->colors; i++) 1924 { 1925 (void) WriteBlobMSBShort(image,(unsigned short) i); 1926 (void) WriteBlobMSBShort(image,ScaleQuantumToShort( 1927 image->colormap[i].red)); 1928 (void) WriteBlobMSBShort(image,ScaleQuantumToShort( 1929 image->colormap[i].green)); 1930 (void) WriteBlobMSBShort(image,ScaleQuantumToShort( 1931 image->colormap[i].blue)); 1932 } 1933 } 1934 /* 1935 Write source and destination rectangle. 1936 */ 1937 (void) WriteBlobMSBShort(image,(unsigned short) source_rectangle.top); 1938 (void) WriteBlobMSBShort(image,(unsigned short) source_rectangle.left); 1939 (void) WriteBlobMSBShort(image,(unsigned short) source_rectangle.bottom); 1940 (void) WriteBlobMSBShort(image,(unsigned short) source_rectangle.right); 1941 (void) WriteBlobMSBShort(image,(unsigned short) destination_rectangle.top); 1942 (void) WriteBlobMSBShort(image,(unsigned short) destination_rectangle.left); 1943 (void) WriteBlobMSBShort(image,(unsigned short) destination_rectangle.bottom); 1944 (void) WriteBlobMSBShort(image,(unsigned short) destination_rectangle.right); 1945 (void) WriteBlobMSBShort(image,(unsigned short) transfer_mode); 1946 /* 1947 Write picture data. 1948 */ 1949 count=0; 1950 if (storage_class == PseudoClass) 1951 for (y=0; y < (ssize_t) image->rows; y++) 1952 { 1953 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1954 if (p == (const Quantum *) NULL) 1955 break; 1956 for (x=0; x < (ssize_t) image->columns; x++) 1957 { 1958 scanline[x]=(unsigned char) GetPixelIndex(image,p); 1959 p+=GetPixelChannels(image); 1960 } 1961 count+=EncodeImage(image,scanline,(size_t) (row_bytes & 0x7FFF), 1962 packed_scanline); 1963 if (image->previous == (Image *) NULL) 1964 { 1965 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 1966 image->rows); 1967 if (status == MagickFalse) 1968 break; 1969 } 1970 } 1971 else 1972 if (image_info->compression == JPEGCompression) 1973 { 1974 (void) ResetMagickMemory(scanline,0,row_bytes); 1975 for (y=0; y < (ssize_t) image->rows; y++) 1976 count+=EncodeImage(image,scanline,(size_t) (row_bytes & 0x7FFF), 1977 packed_scanline); 1978 } 1979 else 1980 { 1981 register unsigned char 1982 *blue, 1983 *green, 1984 *opacity, 1985 *red; 1986 1987 red=scanline; 1988 green=scanline+image->columns; 1989 blue=scanline+2*image->columns; 1990 opacity=scanline+3*image->columns; 1991 for (y=0; y < (ssize_t) image->rows; y++) 1992 { 1993 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 1994 if (p == (const Quantum *) NULL) 1995 break; 1996 red=scanline; 1997 green=scanline+image->columns; 1998 blue=scanline+2*image->columns; 1999 if (image->alpha_trait != UndefinedPixelTrait) 2000 { 2001 opacity=scanline; 2002 red=scanline+image->columns; 2003 green=scanline+2*image->columns; 2004 blue=scanline+3*image->columns; 2005 } 2006 for (x=0; x < (ssize_t) image->columns; x++) 2007 { 2008 *red++=ScaleQuantumToChar(GetPixelRed(image,p)); 2009 *green++=ScaleQuantumToChar(GetPixelGreen(image,p)); 2010 *blue++=ScaleQuantumToChar(GetPixelBlue(image,p)); 2011 if (image->alpha_trait != UndefinedPixelTrait) 2012 *opacity++=ScaleQuantumToChar((Quantum) (GetPixelAlpha(image,p))); 2013 p+=GetPixelChannels(image); 2014 } 2015 count+=EncodeImage(image,scanline,bytes_per_line,packed_scanline); 2016 if (image->previous == (Image *) NULL) 2017 { 2018 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 2019 image->rows); 2020 if (status == MagickFalse) 2021 break; 2022 } 2023 } 2024 } 2025 if ((count & 0x01) != 0) 2026 (void) WriteBlobByte(image,'\0'); 2027 (void) WriteBlobMSBShort(image,PictEndOfPictureOp); 2028 offset=TellBlob(image); 2029 offset=SeekBlob(image,512,SEEK_SET); 2030 (void) WriteBlobMSBShort(image,(unsigned short) offset); 2031 scanline=(unsigned char *) RelinquishMagickMemory(scanline); 2032 packed_scanline=(unsigned char *) RelinquishMagickMemory(packed_scanline); 2033 buffer=(unsigned char *) RelinquishMagickMemory(buffer); 2034 (void) CloseBlob(image); 2035 return(MagickTrue); 2036 } 2037