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