~ubuntu-branches/ubuntu/intrepid/graphicsmagick/intrepid

« back to all changes in this revision

Viewing changes to coders/pict.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2006-05-06 16:28:08 UTC
  • Revision ID: james.westby@ubuntu.com-20060506162808-vt2ni3r5nytcszms
Tags: upstream-1.1.7
ImportĀ upstreamĀ versionĀ 1.1.7

Show diffs side-by-side

added added

removed removed

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