~cosme/ubuntu/precise/freeimage/freeimage-3.15.1

« back to all changes in this revision

Viewing changes to Source/FreeImage/PluginPICT.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cosme Domínguez Díaz
  • Date: 2010-07-20 13:42:15 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100720134215-xt1454zaedv3b604
Tags: 3.13.1-0ubuntu1
* New upstream release. Closes: (LP: #607800)
 - Updated debian/freeimage-get-orig-source script.
 - Removing no longer necessary debian/patches/* and
   the patch system in debian/rules.
 - Updated debian/rules to work with the new Makefiles.
 - Drop from -O3 to -O2 and use lzma compression saves
   ~10 MB of free space. 
* lintian stuff
 - fixed debhelper-but-no-misc-depends
 - fixed ldconfig-symlink-missing-for-shlib

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ==========================================================
 
2
// Apple Macintosh QuickDraw/PICT Loader
 
3
//
 
4
// Design and implementation by
 
5
// - Amir Ebrahimi (amir@unity3d.com)
 
6
//
 
7
// Based on PICT loading code from paintlib (http://www.paintlib.de/paintlib/).
 
8
//
 
9
// Paintlib License:
 
10
// The paintlib source code and all documentation are copyright (c) 1996-2002 
 
11
// Ulrich von Zadow and other contributors.
 
12
//
 
13
// The paintlib source code is supplied "AS IS". Ulrich von Zadow and other 
 
14
// contributors disclaim all warranties, expressed or implied, including, without
 
15
// limitation, the warranties of merchantability and of fitness for any purpose. 
 
16
// The authors assume no liability for direct, indirect, incidental, special, 
 
17
// exemplary, or consequential damages, which may result from the use of paintlib, 
 
18
// even if advised of the possibility of such damage.
 
19
//
 
20
// Permission is hereby granted to use, copy, modify, and distribute this source 
 
21
// code, or portions hereof, for any purpose, without fee, subject to the following 
 
22
// restrictions:
 
23
//
 
24
// 1. The origin of this source code must not be misrepresented.
 
25
// 2. Altered versions must be plainly marked as such and must not be misrepresented
 
26
//    as being the original source.
 
27
// 3. This Copyright notice may not be removed or altered from any source or altered 
 
28
//    source distribution.
 
29
// 4. Executables containing paintlib or parts of it must state that the software 
 
30
//    "contains paintlib code. paintlib is copyright (c) 1996-2002 Ulrich von Zadow
 
31
//    and other contributors.". This notice must be displayed in at least one place
 
32
//    where the copyright for the software itself is displayed. The documentation must 
 
33
//    also contain this notice.
 
34
//
 
35
// Bug fixes were made to the original code to support version 2 PICT files
 
36
// properly.
 
37
// 
 
38
// Additional resources:
 
39
// http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-458.html
 
40
// http://www.fileformat.info/format/macpict/egff.htm
 
41
// 
 
42
// Notes (http://lists.apple.com/archives/java-dev/2006/Apr/msg00588.html):
 
43
// There are three main types of PICT files:
 
44
//  - Version 1
 
45
//  - Version 2
 
46
//  - Extended Version 2
 
47
//
 
48
// Some things to look out for:
 
49
//  - The bounds and target DPI are stored in a different place in all three.
 
50
//  - Some of the values are fixed-point shorts ( short / 65536f )
 
51
//  - Values are big endian 
 
52
//  - All of this may be *preceded* by a 512 byte header--sometimes it is
 
53
//    there, and sometimes it isn't. You just have to check for the magic
 
54
//        values in both places.
 
55
//
 
56
// This file is part of FreeImage 3
 
57
//
 
58
// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
 
59
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
 
60
// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
 
61
// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
 
62
// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
 
63
// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
 
64
// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
 
65
// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
 
66
// THIS DISCLAIMER.
 
67
//
 
68
// Use at your own risk!
 
69
// ==========================================================
 
70
 
 
71
#include "FreeImage.h"
 
72
#include "Utilities.h"
 
73
 
 
74
// ==========================================================
 
75
// Plugin Interface
 
76
// ==========================================================
 
77
static int s_format_id;
 
78
 
 
79
static const int outputMessageSize = 256;
 
80
 
 
81
// ==========================================================
 
82
// Internal functions
 
83
// ==========================================================
 
84
 
 
85
static unsigned
 
86
Read8(FreeImageIO *io, fi_handle handle) {
 
87
        unsigned char i = 0;
 
88
        io->read_proc(&i, 1, 1, handle);
 
89
        return i;
 
90
}
 
91
 
 
92
static unsigned
 
93
Read16(FreeImageIO *io, fi_handle handle) {
 
94
        // reads a two-byte big-endian integer from the given file and returns its value.
 
95
        // assumes unsigned.
 
96
        
 
97
        unsigned hi = Read8(io, handle);
 
98
        unsigned lo = Read8(io, handle);
 
99
        return lo + (hi << 8);
 
100
}
 
101
 
 
102
static unsigned
 
103
Read32(FreeImageIO *io, fi_handle handle) {
 
104
        // reads a four-byte big-endian integer from the given file and returns its value.
 
105
        // assumes unsigned.
 
106
        
 
107
        unsigned b3 = Read8(io, handle);
 
108
        unsigned b2 = Read8(io, handle);
 
109
        unsigned b1 = Read8(io, handle);
 
110
        unsigned b0 = Read8(io, handle);
 
111
        return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
 
112
}
 
113
 
 
114
// ----------------------------------------------------------
 
115
 
 
116
struct OpDef
 
117
{
 
118
        char * name;
 
119
        int    len;
 
120
        char * description;
 
121
};
 
122
 
 
123
// for reserved opcodes
 
124
#define res(length) { "reserved", (length), "reserved for Apple use" }
 
125
#define RGB_LEN 6
 
126
#define WORD_LEN -1
 
127
#define NA 0
 
128
 
 
129
static OpDef optable[] =
 
130
{
 
131
/* 0x00 */  { "NOP",               0, "nop" },
 
132
/* 0x01 */  { "Clip",             NA, "clip" },
 
133
/* 0x02 */  { "BkPat",             8, "background pattern" },
 
134
/* 0x03 */  { "TxFont",            2, "text font (word)" },
 
135
/* 0x04 */  { "TxFace",            1, "text face (byte)" },
 
136
/* 0x05 */  { "TxMode",            2, "text mode (word)" },
 
137
/* 0x06 */  { "SpExtra",           4, "space extra (fixed point)" },
 
138
/* 0x07 */  { "PnSize",            4, "pen size (point)" },
 
139
/* 0x08 */  { "PnMode",            2, "pen mode (word)" },
 
140
/* 0x09 */  { "PnPat",             8, "pen pattern" },
 
141
/* 0x0a */  { "FillPat",           8, "fill pattern" },
 
142
/* 0x0b */  { "OvSize",            4, "oval size (point)" },
 
143
/* 0x0c */  { "Origin",            4, "dh, dv (word)" },
 
144
/* 0x0d */  { "TxSize",            2, "text size (word)" },
 
145
/* 0x0e */  { "FgColor",           4, "foreground color (longword)" },
 
146
/* 0x0f */  { "BkColor",           4, "background color (longword)" },
 
147
/* 0x10 */  { "TxRatio",           8, "numerator (point), denominator (point)" },
 
148
/* 0x11 */  { "Version",           1, "version (byte)" },
 
149
/* 0x12 */  { "BkPixPat",         NA, "color background pattern" },
 
150
/* 0x13 */  { "PnPixPat",         NA, "color pen pattern" },
 
151
/* 0x14 */  { "FillPixPat",       NA, "color fill pattern" },
 
152
/* 0x15 */  { "PnLocHFrac",        2, "fractional pen position" },
 
153
/* 0x16 */  { "ChExtra",           2, "extra for each character" },
 
154
/* 0x17 */  res(0),
 
155
/* 0x18 */  res(0),
 
156
/* 0x19 */  res(0),
 
157
/* 0x1a */  { "RGBFgCol",    RGB_LEN, "RGB foreColor" },
 
158
/* 0x1b */  { "RGBBkCol",    RGB_LEN, "RGB backColor" },
 
159
/* 0x1c */  { "HiliteMode",        0, "hilite mode flag" },
 
160
/* 0x1d */  { "HiliteColor", RGB_LEN, "RGB hilite color" },
 
161
/* 0x1e */  { "DefHilite",         0, "Use default hilite color" },
 
162
/* 0x1f */  { "OpColor",           6, "RGB OpColor for arithmetic modes" },
 
163
/* 0x20 */  { "Line",              8, "pnLoc (point), newPt (point)" },
 
164
/* 0x21 */  { "LineFrom",          4, "newPt (point)" },
 
165
/* 0x22 */  { "ShortLine",         6, "pnLoc (point, dh, dv (-128 .. 127))" },
 
166
/* 0x23 */  { "ShortLineFrom",     2, "dh, dv (-128 .. 127)" },
 
167
/* 0x24 */  res(WORD_LEN),
 
168
/* 0x25 */  res(WORD_LEN),
 
169
/* 0x26 */  res(WORD_LEN),
 
170
/* 0x27 */  res(WORD_LEN),
 
171
/* 0x28 */  { "LongText",         NA, "txLoc (point), count (0..255), text" },
 
172
/* 0x29 */  { "DHText",           NA, "dh (0..255), count (0..255), text" },
 
173
/* 0x2a */  { "DVText",           NA, "dv (0..255), count (0..255), text" },
 
174
/* 0x2b */  { "DHDVText",         NA, "dh, dv (0..255), count (0..255), text" },
 
175
/* 0x2c */  res(WORD_LEN),
 
176
/* 0x2d */  res(WORD_LEN),
 
177
/* 0x2e */  res(WORD_LEN),
 
178
/* 0x2f */  res(WORD_LEN),
 
179
/* 0x30 */  { "frameRect",         8, "rect" },
 
180
/* 0x31 */  { "paintRect",         8, "rect" },
 
181
/* 0x32 */  { "eraseRect",         8, "rect" },
 
182
/* 0x33 */  { "invertRect",        8, "rect" },
 
183
/* 0x34 */  { "fillRect",          8, "rect" },
 
184
/* 0x35 */  res(8),
 
185
/* 0x36 */  res(8),
 
186
/* 0x37 */  res(8),
 
187
/* 0x38 */  { "frameSameRect",     0, "rect" },
 
188
/* 0x39 */  { "paintSameRect",     0, "rect" },
 
189
/* 0x3a */  { "eraseSameRect",     0, "rect" },
 
190
/* 0x3b */  { "invertSameRect",    0, "rect" },
 
191
/* 0x3c */  { "fillSameRect",      0, "rect" },
 
192
/* 0x3d */  res(0),
 
193
/* 0x3e */  res(0),
 
194
/* 0x3f */  res(0),
 
195
/* 0x40 */  { "frameRRect",        8, "rect" },
 
196
/* 0x41 */  { "paintRRect",        8, "rect" },
 
197
/* 0x42 */  { "eraseRRect",        8, "rect" },
 
198
/* 0x43 */  { "invertRRect",       8, "rect" },
 
199
/* 0x44 */  { "fillRRrect",        8, "rect" },
 
200
/* 0x45 */  res(8),
 
201
/* 0x46 */  res(8),
 
202
/* 0x47 */  res(8),
 
203
/* 0x48 */  { "frameSameRRect",    0, "rect" },
 
204
/* 0x49 */  { "paintSameRRect",    0, "rect" },
 
205
/* 0x4a */  { "eraseSameRRect",    0, "rect" },
 
206
/* 0x4b */  { "invertSameRRect",   0, "rect" },
 
207
/* 0x4c */  { "fillSameRRect",     0, "rect" },
 
208
/* 0x4d */  res(0),
 
209
/* 0x4e */  res(0),
 
210
/* 0x4f */  res(0),
 
211
/* 0x50 */  { "frameOval",         8, "rect" },
 
212
/* 0x51 */  { "paintOval",         8, "rect" },
 
213
/* 0x52 */  { "eraseOval",         8, "rect" },
 
214
/* 0x53 */  { "invertOval",        8, "rect" },
 
215
/* 0x54 */  { "fillOval",          8, "rect" },
 
216
/* 0x55 */  res(8),
 
217
/* 0x56 */  res(8),
 
218
/* 0x57 */  res(8),
 
219
/* 0x58 */  { "frameSameOval",     0, "rect" },
 
220
/* 0x59 */  { "paintSameOval",     0, "rect" },
 
221
/* 0x5a */  { "eraseSameOval",     0, "rect" },
 
222
/* 0x5b */  { "invertSameOval",    0, "rect" },
 
223
/* 0x5c */  { "fillSameOval",      0, "rect" },
 
224
/* 0x5d */  res(0),
 
225
/* 0x5e */  res(0),
 
226
/* 0x5f */  res(0),
 
227
/* 0x60 */  { "frameArc",         12, "rect, startAngle, arcAngle" },
 
228
/* 0x61 */  { "paintArc",         12, "rect, startAngle, arcAngle" },
 
229
/* 0x62 */  { "eraseArc",         12, "rect, startAngle, arcAngle" },
 
230
/* 0x63 */  { "invertArc",        12, "rect, startAngle, arcAngle" },
 
231
/* 0x64 */  { "fillArc",          12, "rect, startAngle, arcAngle" },
 
232
/* 0x65 */  res(12),
 
233
/* 0x66 */  res(12),
 
234
/* 0x67 */  res(12),
 
235
/* 0x68 */  { "frameSameArc",      4, "rect, startAngle, arcAngle" },
 
236
/* 0x69 */  { "paintSameArc",      4, "rect, startAngle, arcAngle" },
 
237
/* 0x6a */  { "eraseSameArc",      4, "rect, startAngle, arcAngle" },
 
238
/* 0x6b */  { "invertSameArc",     4, "rect, startAngle, arcAngle" },
 
239
/* 0x6c */  { "fillSameArc",       4, "rect, startAngle, arcAngle" },
 
240
/* 0x6d */  res(4),
 
241
/* 0x6e */  res(4),
 
242
/* 0x6f */  res(4),
 
243
/* 0x70 */  { "framePoly",        NA, "poly" },
 
244
/* 0x71 */  { "paintPoly",        NA, "poly" },
 
245
/* 0x72 */  { "erasePoly",        NA, "poly" },
 
246
/* 0x73 */  { "invertPoly",       NA, "poly" },
 
247
/* 0x74 */  { "fillPoly",         NA, "poly" },
 
248
/* 0x75 */  res(NA),
 
249
/* 0x76 */  res(NA),
 
250
/* 0x77 */  res(NA),
 
251
/* 0x78 */  { "frameSamePoly",     0, "poly (NYI)" },
 
252
/* 0x79 */  { "paintSamePoly",     0, "poly (NYI)" },
 
253
/* 0x7a */  { "eraseSamePoly",     0, "poly (NYI)" },
 
254
/* 0x7b */  { "invertSamePoly",    0, "poly (NYI)" },
 
255
/* 0x7c */  { "fillSamePoly",      0, "poly (NYI)" },
 
256
/* 0x7d */  res(0),
 
257
/* 0x7e */  res(0),
 
258
/* 0x7f */  res(0),
 
259
/* 0x80 */  { "frameRgn",         NA, "region" },
 
260
/* 0x81 */  { "paintRgn",         NA, "region" },
 
261
/* 0x82 */  { "eraseRgn",         NA, "region" },
 
262
/* 0x83 */  { "invertRgn",        NA, "region" },
 
263
/* 0x84 */  { "fillRgn",          NA, "region" },
 
264
/* 0x85 */  res(NA),
 
265
/* 0x86 */  res(NA),
 
266
/* 0x87 */  res(NA),
 
267
/* 0x88 */  { "frameSameRgn",      0, "region (NYI)" },
 
268
/* 0x89 */  { "paintSameRgn",      0, "region (NYI)" },
 
269
/* 0x8a */  { "eraseSameRgn",      0, "region (NYI)" },
 
270
/* 0x8b */  { "invertSameRgn",     0, "region (NYI)" },
 
271
/* 0x8c */  { "fillSameRgn",       0, "region (NYI)" },
 
272
/* 0x8d */  res(0),
 
273
/* 0x8e */  res(0),
 
274
/* 0x8f */  res(0),
 
275
/* 0x90 */  { "BitsRect",         NA, "copybits, rect clipped" },
 
276
/* 0x91 */  { "BitsRgn",          NA, "copybits, rgn clipped" },
 
277
/* 0x92 */  res(WORD_LEN),
 
278
/* 0x93 */  res(WORD_LEN),
 
279
/* 0x94 */  res(WORD_LEN),
 
280
/* 0x95 */  res(WORD_LEN),
 
281
/* 0x96 */  res(WORD_LEN),
 
282
/* 0x97 */  res(WORD_LEN),
 
283
/* 0x98 */  { "PackBitsRect",     NA, "packed copybits, rect clipped" },
 
284
/* 0x99 */  { "PackBitsRgn",      NA, "packed copybits, rgn clipped" },
 
285
/* 0x9a */  { "Opcode_9A",        NA, "the mysterious opcode 9A" },
 
286
/* 0x9b */  res(WORD_LEN),
 
287
/* 0x9c */  res(WORD_LEN),
 
288
/* 0x9d */  res(WORD_LEN),
 
289
/* 0x9e */  res(WORD_LEN),
 
290
/* 0x9f */  res(WORD_LEN),
 
291
/* 0xa0 */  { "ShortComment",      2, "kind (word)" },
 
292
/* 0xa1 */  { "LongComment",      NA, "kind (word), size (word), data" }
 
293
};
 
294
 
 
295
// ----------------------------------------------------------
 
296
 
 
297
struct MacRect
 
298
{
 
299
        WORD top;
 
300
        WORD left;
 
301
        WORD bottom;
 
302
        WORD right;
 
303
};
 
304
 
 
305
struct MacpixMap
 
306
{
 
307
        // Ptr baseAddr              // Not used in file.
 
308
        // short rowBytes            // read in seperatly.
 
309
        struct MacRect Bounds;
 
310
        WORD version;
 
311
        WORD packType;
 
312
        LONG packSize;
 
313
        LONG hRes;
 
314
        LONG vRes;
 
315
        WORD pixelType;
 
316
        WORD pixelSize;
 
317
        WORD cmpCount;
 
318
        WORD cmpSize;
 
319
        LONG planeBytes;
 
320
        LONG pmTable;
 
321
        LONG pmReserved;
 
322
};
 
323
 
 
324
struct MacRGBColour
 
325
{
 
326
        WORD red;
 
327
        WORD green;
 
328
        WORD blue;
 
329
};
 
330
 
 
331
struct MacPoint
 
332
{
 
333
        WORD x;
 
334
        WORD y;
 
335
};
 
336
 
 
337
struct MacPattern // Klaube
 
338
{
 
339
        BYTE pix[64];
 
340
};
 
341
 
 
342
// ----------------------------------------------------------
 
343
 
 
344
static void 
 
345
ReadRect( FreeImageIO *io, fi_handle handle, MacRect* rect ) {
 
346
        rect->top = Read16( io, handle );
 
347
        rect->left = Read16( io, handle );
 
348
        rect->bottom = Read16( io, handle );
 
349
        rect->right = Read16( io, handle );
 
350
}
 
351
 
 
352
static void 
 
353
ReadPixmap( FreeImageIO *io, fi_handle handle, MacpixMap* pPixMap ) {
 
354
        pPixMap->version = Read16( io, handle );
 
355
        pPixMap->packType = Read16( io, handle );
 
356
        pPixMap->packSize = Read32( io, handle );
 
357
        pPixMap->hRes = Read16( io, handle );
 
358
        Read16( io, handle );
 
359
        pPixMap->vRes = Read16( io, handle );
 
360
        Read16( io, handle );
 
361
        pPixMap->pixelType = Read16( io, handle );
 
362
        pPixMap->pixelSize = Read16( io, handle );
 
363
        pPixMap->cmpCount = Read16( io, handle );
 
364
        pPixMap->cmpSize = Read16( io, handle );
 
365
        pPixMap->planeBytes = Read32( io, handle );
 
366
        pPixMap->pmTable = Read32( io, handle );
 
367
        pPixMap->pmReserved = Read32( io, handle );
 
368
}
 
369
 
 
370
/**
 
371
Reads a mac color table into a bitmap palette.
 
372
*/
 
373
static void 
 
374
ReadColorTable( FreeImageIO *io, fi_handle handle, WORD* pNumColors, RGBQUAD* pPal ) {
 
375
        LONG        ctSeed;
 
376
        WORD        ctFlags;
 
377
        WORD        val;
 
378
        int         i;
 
379
        
 
380
        ctSeed = Read32( io, handle );
 
381
        ctFlags = Read16( io, handle );
 
382
        WORD numColors = Read16( io, handle )+1;
 
383
        *pNumColors = numColors;
 
384
        
 
385
        for (i = 0; i < numColors; i++) {
 
386
                val = Read16( io, handle );
 
387
                if (ctFlags & 0x8000) {
 
388
                        // The indicies in a device colour table are bogus and
 
389
                        // usually == 0, so I assume we allocate up the list of
 
390
                        // colours in order.
 
391
                        val = i;
 
392
                }
 
393
                if (val >= numColors) {
 
394
                        throw "pixel value greater than color table size.";
 
395
                }
 
396
                // Mac colour tables contain 16-bit values for R, G, and B...
 
397
                pPal[val].rgbRed = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF));
 
398
                pPal[val].rgbGreen = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF));
 
399
                pPal[val].rgbBlue = ((BYTE) (((WORD) (Read16( io, handle )) >> 8) & 0xFF));
 
400
        }
 
401
}
 
402
 
 
403
/**
 
404
skips unneeded packbits.
 
405
pixelSize == Source bits per pixel.
 
406
*/
 
407
static void 
 
408
SkipBits( FreeImageIO *io, fi_handle handle, MacRect* bounds, WORD rowBytes, int pixelSize ) {
 
409
        int    i;
 
410
        WORD   pixwidth;           // bytes per row when uncompressed.
 
411
        
 
412
        int height = bounds->bottom - bounds->top;
 
413
        int width = bounds->right - bounds->left;
 
414
        
 
415
        // High bit of rowBytes is flag.
 
416
        if (pixelSize <= 8) {
 
417
                rowBytes &= 0x7fff;
 
418
        }
 
419
        pixwidth = width;
 
420
        
 
421
        if (pixelSize == 16) {
 
422
                pixwidth *= 2;
 
423
        }
 
424
        if (rowBytes == 0) {
 
425
                rowBytes = pixwidth;
 
426
        }
 
427
        if (rowBytes < 8) {
 
428
                io->seek_proc( handle, rowBytes*height, SEEK_CUR );
 
429
        }
 
430
        else {
 
431
                for (i = 0; i < height; i++) {
 
432
                        int lineLen;            // length of source line in bytes.
 
433
                        if (rowBytes > 250) {
 
434
                                lineLen = Read16( io, handle );
 
435
                        } else {
 
436
                                lineLen = Read8( io, handle );
 
437
                        }
 
438
                        io->seek_proc( handle, lineLen, SEEK_CUR );
 
439
                }
 
440
        }
 
441
}
 
442
 
 
443
/**
 
444
Skip polygon or region
 
445
*/
 
446
static void 
 
447
SkipPolyOrRegion( FreeImageIO *io, fi_handle handle ) {
 
448
        WORD len = Read16( io, handle ) - 2;
 
449
        io->seek_proc(handle, len, SEEK_CUR);   
 
450
}
 
451
 
 
452
/**
 
453
Width in bytes for 8 bpp or less.
 
454
Width in pixels for 16 bpp.
 
455
Expands Width units to 32-bit pixel data.
 
456
*/
 
457
static void 
 
458
expandBuf( FreeImageIO *io, fi_handle handle, int width, int bpp, BYTE* dst ) { 
 
459
        switch (bpp) {
 
460
                case 16:
 
461
                        for ( int i=0; i<width; i++) {
 
462
                                WORD src = Read16( io, handle );
 
463
                                dst[ FI_RGBA_BLUE ] = (src & 31)*8;                             // Blue
 
464
                                dst[ FI_RGBA_GREEN ] = ((src >> 5) & 31)*8;             // Green
 
465
                                dst[ FI_RGBA_RED ] = ((src >> 10) & 31)*8;              // Red
 
466
                                dst[ FI_RGBA_ALPHA ] = 0xFF;                                    // Alpha
 
467
                                dst += 4;
 
468
                        }
 
469
                        break;
 
470
                default:
 
471
                        throw "Bad bits per pixel in expandBuf.";
 
472
        }
 
473
}
 
474
 
 
475
/**
 
476
Expands Width units to 8-bit pixel data.
 
477
Max. 8 bpp source format.
 
478
*/
 
479
static void 
 
480
expandBuf8( FreeImageIO *io, fi_handle handle, int width, int bpp, BYTE* dst )
 
481
{
 
482
        switch (bpp) {
 
483
                case 8:
 
484
                        io->read_proc( dst, width, 1, handle );
 
485
                        break;
 
486
                case 4:
 
487
                        for (int i = 0; i < width; i++) {
 
488
                                WORD src = Read8( io, handle );
 
489
                                *dst = (src >> 4) & 15;
 
490
                                *(dst+1) = (src & 15);
 
491
                                dst += 2;
 
492
                        }
 
493
                        if (width & 1) { // Odd Width?
 
494
                                WORD src = Read8( io, handle );
 
495
                                *dst = (src >> 4) & 15;
 
496
                                dst++;
 
497
                        }
 
498
                        break;
 
499
                case 2:
 
500
                        for (int i = 0; i < width; i++) {
 
501
                                WORD src = Read8( io, handle );
 
502
                                *dst = (src >> 6) & 3;
 
503
                                *(dst+1) = (src >> 4) & 3;
 
504
                                *(dst+2) = (src >> 2) & 3;
 
505
                                *(dst+3) = (src & 3);
 
506
                                dst += 4;
 
507
                        }
 
508
                        if (width & 3)  { // Check for leftover pixels
 
509
                                for (int i = 6; i > 8 - (width & 3) * 2; i -= 2) {
 
510
                                        WORD src = Read8( io, handle );
 
511
                                        *dst = (src >> i) & 3;
 
512
                                        dst++;
 
513
                                }
 
514
                        }
 
515
                        break;
 
516
                case 1:
 
517
                        for (int i = 0; i < width; i++) {
 
518
                                WORD src = Read8( io, handle );
 
519
                                *dst = (src >> 7) & 1;
 
520
                                *(dst+1) = (src >> 6) & 1;
 
521
                                *(dst+2) = (src >> 5) & 1;
 
522
                                *(dst+3) = (src >> 4) & 1;
 
523
                                *(dst+4) = (src >> 3) & 1;
 
524
                                *(dst+5) = (src >> 2) & 1;
 
525
                                *(dst+6) = (src >> 1) & 1;
 
526
                                *(dst+7) = (src  & 1);
 
527
                                dst += 8;
 
528
                        }
 
529
                        if (width & 7) {  // Check for leftover pixels
 
530
                                for (int i = 7; i > (8-width & 7); i--) {
 
531
                                        WORD src = Read8( io, handle );
 
532
                                        *dst = (src >> i) & 1;
 
533
                                        dst++;
 
534
                                }
 
535
                        }
 
536
                        break;
 
537
                default:
 
538
                        throw "Bad bits per pixel in expandBuf8.";
 
539
        }
 
540
}
 
541
 
 
542
static BYTE* 
 
543
UnpackPictRow( FreeImageIO *io, fi_handle handle, BYTE* pLineBuf, int width, int rowBytes, int srcBytes ) {     
 
544
        if (rowBytes < 8) { // Ah-ha!  The bits aren't actually packed.  This will be easy.
 
545
                io->read_proc( pLineBuf, rowBytes, 1, handle );
 
546
        }
 
547
        else {
 
548
                BYTE* pCurPixel = pLineBuf;
 
549
                
 
550
                // Unpack RLE. The data is packed bytewise.
 
551
                for (int j = 0; j < srcBytes; ) {
 
552
                        BYTE FlagCounter = Read8( io, handle );
 
553
                        if (FlagCounter & 0x80) {
 
554
                                if (FlagCounter == 0x80) {
 
555
                                        // Special case: repeat value of 0.
 
556
                                        // Apple says ignore.
 
557
                                        j++;
 
558
                                } else { 
 
559
                                        // Packed data.
 
560
                                        int len = ((FlagCounter ^ 255) & 255) + 2;                                      
 
561
                                        BYTE p = Read8( io, handle );
 
562
                                        memset( pCurPixel, p, len);
 
563
                                        pCurPixel += len;
 
564
                                        j += 2;
 
565
                                }
 
566
                        }
 
567
                        else { 
 
568
                                // Unpacked data
 
569
                                int len = (FlagCounter & 255) + 1;
 
570
                                io->read_proc( pCurPixel, len, 1, handle );
 
571
                                pCurPixel += len;
 
572
                                j += len + 1;
 
573
                        }
 
574
                }
 
575
        }
 
576
        
 
577
        return pLineBuf;
 
578
}
 
579
 
 
580
/**
 
581
This routine decompresses BitsRects with a packType of 4 (and 32 bits per pixel). 
 
582
In this format, each line is separated into 8-bit-bitplanes and then compressed via RLE. 
 
583
To decode, the routine decompresses each line & then juggles the bytes around to get pixel-oriented data.
 
584
NumBitPlanes == 3 if RGB, 4 if RGBA
 
585
*/
 
586
static void 
 
587
Unpack32Bits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes, int numPlanes ) {
 
588
        int height = bounds->bottom - bounds->top;
 
589
        int width = bounds->right - bounds->left;
 
590
        
 
591
        if (rowBytes == 0) {
 
592
                rowBytes = width*4;
 
593
        }
 
594
        
 
595
        BYTE* pLineBuf = (BYTE*)malloc( rowBytes ); // Let's allocate enough for 4 bit planes
 
596
        if ( pLineBuf ) {
 
597
                try     {
 
598
                        for ( int i = 0; i < height; i++ ) { 
 
599
                                // for each line do...
 
600
                                int linelen;            // length of source line in bytes.
 
601
                                if (rowBytes > 250) {
 
602
                                        linelen = Read16( io, handle );
 
603
                                } else {
 
604
                                        linelen = Read8( io, handle);
 
605
                                }
 
606
                                
 
607
                                BYTE* pBuf = UnpackPictRow( io, handle, pLineBuf, width, rowBytes, linelen );
 
608
                                
 
609
                                // Convert plane-oriented data into pixel-oriented data &
 
610
                                // copy into destination bitmap.
 
611
                                BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);
 
612
                                
 
613
                                if ( numPlanes == 3 ) {
 
614
                                        for ( int j = 0; j < width; j++ ) { 
 
615
                                                // For each pixel in line...
 
616
                                                dst[ FI_RGBA_BLUE ] = (*(pBuf+width*2));     // Blue
 
617
                                                dst[ FI_RGBA_GREEN ] = (*(pBuf+width));       // Green
 
618
                                                dst[ FI_RGBA_RED ] = (*pBuf);             // Red
 
619
                                                dst[ FI_RGBA_ALPHA ] = (0xFF);
 
620
                                                dst += 4;
 
621
                                                pBuf++;
 
622
                                        }
 
623
                                } else {
 
624
                                        for ( int j = 0; j < width; j++ ) { 
 
625
                                                // For each pixel in line...
 
626
                                                dst[ FI_RGBA_BLUE ] = (*(pBuf+width*3));     // Blue
 
627
                                                dst[ FI_RGBA_GREEN ] = (*(pBuf+width*2));     // Green
 
628
                                                dst[ FI_RGBA_RED ] = (*(pBuf+width));       // Red
 
629
                                                dst[ FI_RGBA_ALPHA ] = (*pBuf);
 
630
                                                dst += 4;
 
631
                                                pBuf++;
 
632
                                        }
 
633
                                }
 
634
                        }
 
635
                }
 
636
                catch( ... ) {
 
637
                        free( pLineBuf );
 
638
                        throw;
 
639
                }
 
640
        }
 
641
        free( pLineBuf );
 
642
}
 
643
 
 
644
/**
 
645
Decompression routine for 8 bpp. 
 
646
rowBytes is the number of bytes each source row would take if it were uncompressed.
 
647
This _isn't_ equal to the number of pixels in the row - it seems apple pads the data to a word boundary and then compresses it. 
 
648
Of course, we have to decompress the excess data and then throw it away.
 
649
*/
 
650
static void 
 
651
Unpack8Bits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes ) {       
 
652
        int height = bounds->bottom - bounds->top;
 
653
        int width = bounds->right - bounds->left;
 
654
        
 
655
        // High bit of rowBytes is flag.
 
656
        rowBytes &= 0x7fff;
 
657
        
 
658
        if (rowBytes == 0) {
 
659
                rowBytes = width;
 
660
        }
 
661
        
 
662
        for ( int i = 0; i < height; i++ ) {
 
663
                int linelen;            // length of source line in bytes.
 
664
                if (rowBytes > 250) {
 
665
                        linelen = Read16( io, handle );
 
666
                } else {
 
667
                        linelen = Read8( io, handle );
 
668
                }
 
669
                BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);                         
 
670
                dst = UnpackPictRow( io, handle, dst, width, rowBytes, linelen );
 
671
        }
 
672
}
 
673
 
 
674
/**
 
675
Decompression routine for everything but 8 & 32 bpp. 
 
676
This routine is slower than the two routines above since it has to deal with a lot of special cases :-(.
 
677
It's also a bit chaotic because of these special cases...
 
678
unpack8bits is basically a dumber version of unpackbits.
 
679
pixelSize == Source bits per pixel.
 
680
*/
 
681
static void 
 
682
UnpackBits( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacRect* bounds, WORD rowBytes, int pixelSize ) {
 
683
        WORD   pixwidth;           // bytes per row when uncompressed.
 
684
        int    pkpixsize;
 
685
        int    PixelPerRLEUnit;
 
686
 
 
687
        char outputMessage[ outputMessageSize ] = "";
 
688
        
 
689
        int height = bounds->bottom - bounds->top;
 
690
        int width = bounds->right - bounds->left;
 
691
        
 
692
        // High bit of rowBytes is flag.
 
693
        if (pixelSize <= 8) {
 
694
                rowBytes &= 0x7fff;
 
695
        }
 
696
        
 
697
        pixwidth = width;
 
698
        pkpixsize = 1;          // RLE unit: one byte for everything...
 
699
        if (pixelSize == 16) {    // ...except 16 bpp.
 
700
                pkpixsize = 2;
 
701
                pixwidth *= 2;
 
702
        }
 
703
        
 
704
        if (rowBytes == 0) {
 
705
                rowBytes = pixwidth;
 
706
        }
 
707
        
 
708
        {
 
709
                // I allocate the temporary line buffer here. I allocate too
 
710
                // much memory to compensate for sloppy (& hence fast) decompression.
 
711
                switch (pixelSize) {
 
712
                        case 1:
 
713
                                PixelPerRLEUnit = 8;
 
714
                                break;
 
715
                        case 2:
 
716
                                PixelPerRLEUnit = 4;
 
717
                                break;
 
718
                        case 4:
 
719
                                PixelPerRLEUnit = 2;
 
720
                                break;
 
721
                        case 8:
 
722
                                PixelPerRLEUnit = 1;
 
723
                                break;
 
724
                        case 16:
 
725
                                PixelPerRLEUnit = 1;
 
726
                                break;
 
727
                        default:
 
728
                                sprintf( outputMessage, "Illegal bpp value in unpackbits: %d\n", pixelSize );
 
729
                                throw outputMessage;
 
730
                }
 
731
                
 
732
                if (rowBytes < 8) { 
 
733
                        // ah-ha!  The bits aren't actually packed.  This will be easy.
 
734
                        for ( int i = 0; i < height; i++ ) {
 
735
                                BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);
 
736
                                if (pixelSize == 16) {
 
737
                                        expandBuf( io, handle, width, pixelSize, dst );
 
738
                                } else {
 
739
                                        expandBuf8( io, handle, width, pixelSize, dst );
 
740
                                }
 
741
                        }
 
742
                }
 
743
                else {
 
744
                        for ( int i = 0; i < height; i++ ) { 
 
745
                                // For each line do...
 
746
                                int    linelen;            // length of source line in bytes.
 
747
                                if (rowBytes > 250) {
 
748
                                        linelen = Read16( io, handle );
 
749
                                } else {
 
750
                                        linelen = Read8( io, handle );
 
751
                                }
 
752
                                
 
753
                                BYTE* dst = (BYTE*)FreeImage_GetScanLine( dib, height - 1 - i);
 
754
                                BYTE FlagCounter;
 
755
                                
 
756
                                // Unpack RLE. The data is packed bytewise - except for
 
757
                                // 16 bpp data, which is packed per pixel :-(.
 
758
                                for ( int j = 0; j < linelen; ) {
 
759
                                        FlagCounter = Read8( io, handle );
 
760
                                        if (FlagCounter & 0x80) {
 
761
                                                if (FlagCounter == 0x80) {
 
762
                                                        // Special case: repeat value of 0.
 
763
                                                        // Apple says ignore.
 
764
                                                        j++;
 
765
                                                }
 
766
                                                else { 
 
767
                                                        // Packed data.
 
768
                                                        int len = ((FlagCounter ^ 255) & 255) + 2;
 
769
                                                        
 
770
                                                        // This is slow for some formats...
 
771
                                                        if (pixelSize == 16) {
 
772
                                                                expandBuf( io, handle, 1, pixelSize, dst );
 
773
                                                                for ( int k = 1; k < len; k++ ) { 
 
774
                                                                        // Repeat the pixel len times.
 
775
                                                                        memcpy( dst+(k*4*PixelPerRLEUnit), dst, 4*PixelPerRLEUnit);
 
776
                                                                }
 
777
                                                                dst += len*4*PixelPerRLEUnit;
 
778
                                                        }
 
779
                                                        else {
 
780
                                                                expandBuf8( io, handle, 1, pixelSize, dst );
 
781
                                                                for ( int k = 1; k < len; k++ ) { 
 
782
                                                                        // Repeat the expanded byte len times.
 
783
                                                                        memcpy( dst+(k*PixelPerRLEUnit), dst, PixelPerRLEUnit);
 
784
                                                                }
 
785
                                                                dst += len*PixelPerRLEUnit;
 
786
                                                        }
 
787
                                                        j += pkpixsize + 1;
 
788
                                                }
 
789
                                        }
 
790
                                        else { 
 
791
                                                // Unpacked data
 
792
                                                int len = (FlagCounter & 255) + 1;
 
793
                                                if (pixelSize == 16) {
 
794
                                                        expandBuf( io, handle, len, pixelSize, dst );
 
795
                                                        dst += len*4*PixelPerRLEUnit;
 
796
                                                }
 
797
                                                else {
 
798
                                                        expandBuf8( io, handle, len, pixelSize, dst );
 
799
                                                        dst += len*PixelPerRLEUnit;
 
800
                                                }
 
801
                                                j += ( len * pkpixsize ) + 1;
 
802
                                        }
 
803
                                }
 
804
                        }
 
805
                }
 
806
        }
 
807
}
 
808
 
 
809
static void 
 
810
DecodeOp9a( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, MacpixMap* pixMap ) {
 
811
        // Do the actual unpacking.
 
812
        switch ( pixMap->pixelSize ) {
 
813
                case 32:
 
814
                        Unpack32Bits( io, handle, dib, &pixMap->Bounds, 0, pixMap->cmpCount );
 
815
                        break;
 
816
                case 8:
 
817
                        Unpack8Bits( io, handle, dib, &pixMap->Bounds, 0 );
 
818
                        break;
 
819
                default:
 
820
                        UnpackBits( io, handle, dib, &pixMap->Bounds, 0, pixMap->pixelSize );
 
821
        }
 
822
}
 
823
 
 
824
static void 
 
825
DecodeBitmap( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, BOOL isRegion, MacRect* bounds, WORD rowBytes ) {
 
826
        WORD mode = Read16( io, handle );
 
827
        
 
828
        if ( isRegion ) {
 
829
                SkipPolyOrRegion( io, handle );
 
830
        }
 
831
        
 
832
        RGBQUAD* pal = FreeImage_GetPalette( dib );
 
833
        if ( !pal ) {
 
834
                throw "No palette for bitmap!";
 
835
        }
 
836
        
 
837
        for (int i = 0; i < 2; i++) {
 
838
                unsigned char val = i ? 0xFF : 0x0;
 
839
                pal[i].rgbRed = val;
 
840
                pal[i].rgbGreen = val;
 
841
                pal[i].rgbBlue = val;
 
842
        }
 
843
        
 
844
        UnpackBits( io, handle, dib, bounds, rowBytes, 1 );
 
845
}
 
846
 
 
847
static void 
 
848
DecodePixmap( FreeImageIO *io, fi_handle handle, FIBITMAP* dib, BOOL isRegion, MacpixMap* pixMap, WORD rowBytes ) {
 
849
        // Read mac colour table into windows palette.
 
850
        WORD numColors;    // Palette size.
 
851
        RGBQUAD ct[256];
 
852
        
 
853
        ReadColorTable( io, handle, &numColors, ct );
 
854
        if ( FreeImage_GetBPP( dib ) == 8 ) {
 
855
                RGBQUAD* pal = FreeImage_GetPalette( dib );
 
856
                if ( !pal ) {
 
857
                        throw "No palette for bitmap!";
 
858
                }
 
859
                
 
860
                for (int i = 0; i < numColors; i++) {
 
861
                        pal[i].rgbRed = ct[ i ].rgbRed;
 
862
                        pal[i].rgbGreen = ct[ i ].rgbGreen;
 
863
                        pal[i].rgbBlue = ct[ i ].rgbBlue;
 
864
                }
 
865
        }
 
866
        
 
867
        // Ignore source & destination rectangle as well as transfer mode.
 
868
        MacRect tempRect;
 
869
        ReadRect( io, handle, &tempRect );
 
870
        ReadRect( io, handle, &tempRect );
 
871
        WORD mode = Read16( io, handle );
 
872
        
 
873
        if ( isRegion) {
 
874
                SkipPolyOrRegion( io, handle );
 
875
        }
 
876
        
 
877
        switch ( pixMap->pixelSize ) {
 
878
                case 32:
 
879
                        Unpack32Bits( io, handle, dib, &pixMap->Bounds, rowBytes, pixMap->cmpCount );
 
880
                        break;
 
881
                case 8:
 
882
                        Unpack8Bits( io, handle, dib, &pixMap->Bounds, rowBytes );
 
883
                        break;
 
884
                default:
 
885
                        UnpackBits( io, handle, dib, &pixMap->Bounds, rowBytes, pixMap->pixelSize );
 
886
        }
 
887
}
 
888
 
 
889
// ==========================================================
 
890
// Plugin Implementation
 
891
// ==========================================================
 
892
 
 
893
static const char * DLL_CALLCONV
 
894
Format() {
 
895
        return "PICT";
 
896
}
 
897
 
 
898
static const char * DLL_CALLCONV
 
899
Description() {
 
900
        return "Macintosh PICT";
 
901
}
 
902
 
 
903
static const char * DLL_CALLCONV
 
904
Extension() {
 
905
        return "pct,pict,pic";
 
906
}
 
907
 
 
908
static const char * DLL_CALLCONV
 
909
MimeType() {
 
910
        return "image/x-pict";
 
911
}
 
912
 
 
913
static BOOL DLL_CALLCONV
 
914
Validate(FreeImageIO *io, fi_handle handle) {
 
915
        if(io->seek_proc(handle, 522, SEEK_SET) == 0) {
 
916
                BYTE pict_signature[] = { 0x00, 0x11, 0x02, 0xFF, 0x0C, 0X00 };
 
917
                BYTE signature[6];
 
918
 
 
919
                if(io->read_proc(signature, 1, sizeof(pict_signature), handle)) {
 
920
                        // v1.0 files have 0x11 (version operator) followed by 0x01 (version number)
 
921
                        // v2.0 files have 0x0011 (version operator) followed by 0x02ff (version number)
 
922
                        //   and additionally 0x0c00 as a header opcode
 
923
                        // Currently, we are only supporting v2.0
 
924
                        return (memcmp(pict_signature, signature, sizeof(pict_signature)) == 0);
 
925
                } else {
 
926
                        return FALSE;
 
927
                }
 
928
        }
 
929
 
 
930
        return FALSE;
 
931
}
 
932
 
 
933
static BOOL DLL_CALLCONV
 
934
SupportsExportDepth(int depth) {
 
935
        return FALSE;
 
936
}
 
937
 
 
938
static BOOL DLL_CALLCONV 
 
939
SupportsExportType(FREE_IMAGE_TYPE type) {
 
940
        return FALSE;
 
941
}
 
942
 
 
943
static BOOL DLL_CALLCONV
 
944
SupportsICCProfiles() {
 
945
        return FALSE;
 
946
}
 
947
 
 
948
/**
 
949
This plugin decodes macintosh PICT files with 1,2,4,8,16 and 32 bits per pixel as well as PICT/JPEG. 
 
950
If an alpha channel is present in a 32-bit-PICT, it is decoded as well. 
 
951
The PICT format is a general picture file format and can contain a lot of other elements besides bitmaps. 
 
952
These elements are ignored.     
 
953
*/
 
954
static FIBITMAP * DLL_CALLCONV
 
955
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
 
956
        char outputMessage[ outputMessageSize ] = "";
 
957
        FIBITMAP* dib = NULL;
 
958
        try {           
 
959
                // Skip empty 512 byte header.
 
960
                if ( !io->seek_proc(handle, 512, SEEK_CUR) == 0 )
 
961
                        return NULL;
 
962
                
 
963
                // Read PICT header
 
964
                Read16( io, handle ); // Skip version 1 picture size
 
965
                
 
966
                MacRect frame;
 
967
                ReadRect( io, handle, &frame );
 
968
 
 
969
                BYTE b = 0;
 
970
                while ((b = Read8(io, handle)) == 0);
 
971
                if ( b != 0x11 ) {
 
972
                        throw "invalid header: version number missing.";
 
973
                }
 
974
                
 
975
                int version = Read8( io, handle );
 
976
                if ( version == 2 && Read8( io, handle ) != 0xff ) {
 
977
                        throw "invalid header: illegal version number.";
 
978
                }
 
979
                
 
980
                enum PICTType {none, op9a, jpeg, pixmap, bitmap};
 
981
                PICTType pictType = none;
 
982
                
 
983
                MacRect bounds;
 
984
                MacpixMap pixMap;
 
985
                int hRes = 0x480000; // in pixels/inch (72 by default == 0x480000 in fixed point)
 
986
                int vRes = 0x480000; // in pixels/inch (72 by default == 0x480000 in fixed point)
 
987
                WORD rowBytes = 0;
 
988
                BOOL isRegion = FALSE;
 
989
                BOOL done = FALSE;
 
990
                while ( !done ) {
 
991
                        WORD opcode = 0;
 
992
                        
 
993
                        if ((version == 1) || ((io->tell_proc( handle ) % 2) != 0)) {
 
994
                                // align to word for version 2
 
995
                                opcode = Read8( io, handle );
 
996
                        }
 
997
                        if (version == 2) {
 
998
                                opcode = Read16( io, handle );
 
999
                        }
 
1000
                        
 
1001
                        if (opcode == 0xFF || opcode == 0xFFFF) {
 
1002
                                done = TRUE;
 
1003
                                throw "PICT contained only vector data!";
 
1004
                        }
 
1005
                        else if (opcode < 0xa2) {                               
 
1006
                                switch (opcode) {
 
1007
                                        case 0x01:
 
1008
                                        {
 
1009
                                                // skip clipping rectangle
 
1010
                                                MacRect clipRect;
 
1011
                                                WORD len = Read16( io, handle );
 
1012
 
 
1013
                                                if (len == 0x000a) { 
 
1014
                                                        /* null rgn */
 
1015
                                                        ReadRect( io, handle, &clipRect );
 
1016
                                                } else {
 
1017
                                                        io->seek_proc(handle, len - 2, SEEK_CUR);
 
1018
                                                }
 
1019
                                                break;
 
1020
                                        }                                               
 
1021
                                        case 0x12:
 
1022
                                        case 0x13:
 
1023
                                        case 0x14:
 
1024
                                        {
 
1025
                                                // skip pattern definition
 
1026
                                                WORD       patType;
 
1027
                                                WORD       rowBytes;
 
1028
                                                MacpixMap  p;
 
1029
                                                WORD       numColors;
 
1030
                                                
 
1031
                                                patType = Read16( io, handle );
 
1032
                                                
 
1033
                                                switch( patType ) {
 
1034
                                                        case 2:
 
1035
                                                                io->seek_proc(handle, 8, SEEK_CUR);
 
1036
                                                                io->seek_proc(handle, 5, SEEK_CUR);
 
1037
                                                                break;
 
1038
                                                        case 1:
 
1039
                                                        {
 
1040
                                                                io->seek_proc(handle, 8, SEEK_CUR);
 
1041
                                                                rowBytes = Read16( io, handle );
 
1042
                                                                ReadRect( io, handle, &p.Bounds );
 
1043
                                                                ReadPixmap( io, handle, &p);
 
1044
                                                                
 
1045
                                                                RGBQUAD ct[256];
 
1046
                                                                ReadColorTable(io, handle, &numColors, ct );
 
1047
                                                                SkipBits( io, handle, &p.Bounds, rowBytes, p.pixelSize );
 
1048
                                                                break;
 
1049
                                                        }
 
1050
                                                        default:
 
1051
                                                                throw "Unknown pattern type.";
 
1052
                                                }
 
1053
                                                
 
1054
                                                break;
 
1055
                                        }
 
1056
                                        case 0x70:
 
1057
                                        case 0x71:
 
1058
                                        case 0x72:
 
1059
                                        case 0x73:
 
1060
                                        case 0x74:
 
1061
                                        case 0x75:
 
1062
                                        case 0x76:
 
1063
                                        case 0x77:
 
1064
                                        {
 
1065
                                                SkipPolyOrRegion( io, handle );
 
1066
                                                break;
 
1067
                                        }
 
1068
                                        case 0x90:
 
1069
                                        case 0x98:
 
1070
                                        {
 
1071
                                                // Bitmap/pixmap data clipped by a rectangle.
 
1072
                                                rowBytes = Read16( io, handle );    // Bytes per row in source when uncompressed.                                               
 
1073
                                                isRegion = FALSE;
 
1074
                                                
 
1075
                                                if ( rowBytes & 0x8000) {
 
1076
                                                        pictType = pixmap;
 
1077
                                                } else {
 
1078
                                                        pictType = bitmap;
 
1079
                                                }
 
1080
                                                done = TRUE;
 
1081
                                                break;
 
1082
                                        }
 
1083
                                        case 0x91:
 
1084
                                        case 0x99:
 
1085
                                        {
 
1086
                                                // Bitmap/pixmap data clipped by a region.
 
1087
                                                rowBytes = Read16( io, handle );    // Bytes per row in source when uncompressed.                                               
 
1088
                                                isRegion = TRUE;
 
1089
                                                
 
1090
                                                if ( rowBytes & 0x8000) {
 
1091
                                                        pictType = pixmap;
 
1092
                                                } else {
 
1093
                                                        pictType = bitmap;                                              
 
1094
                                                }
 
1095
                                                done = TRUE;
 
1096
                                                break;
 
1097
                                        }
 
1098
                                        case 0x9a:
 
1099
                                        {
 
1100
                                                // DirectBitsRect.
 
1101
                                                Read32( io, handle );           // Skip fake len and fake EOF.
 
1102
                                                Read16( io, handle );                   // bogus row bytes.
 
1103
                                                
 
1104
                                                // Read in the PixMap fields.
 
1105
                                                ReadRect( io, handle, &pixMap.Bounds );
 
1106
                                                ReadPixmap( io, handle, &pixMap );
 
1107
                                                
 
1108
                                                // Ignore source & destination rectangle as well as transfer mode.
 
1109
                                                MacRect dummy;
 
1110
                                                ReadRect( io, handle, &dummy );
 
1111
                                                ReadRect( io, handle, &dummy );
 
1112
                                                WORD mode = Read16( io, handle );
 
1113
                                                
 
1114
                                                pictType=op9a;
 
1115
                                                done = TRUE;
 
1116
                                                break;
 
1117
                                        }
 
1118
                                        case 0xa1:
 
1119
                                        {
 
1120
                                                // long comment
 
1121
                                                WORD type;
 
1122
                                                WORD len;
 
1123
                                                
 
1124
                                                type = Read16( io, handle );
 
1125
                                                len = Read16( io, handle);
 
1126
                                                if (len > 0) {
 
1127
                                                        io->seek_proc(handle, len, SEEK_CUR);
 
1128
                                                }
 
1129
                                                break;
 
1130
                                        }
 
1131
                                        default:
 
1132
                                                // No function => skip to next opcode
 
1133
                                                if (optable[opcode].len == WORD_LEN) {
 
1134
                                                        WORD len = Read16( io, handle );
 
1135
                                                        io->seek_proc(handle, len, SEEK_CUR);
 
1136
                                                } else {
 
1137
                                                        io->seek_proc(handle, optable[opcode].len, SEEK_CUR);
 
1138
                                                }
 
1139
                                                break;
 
1140
                                }
 
1141
                        }
 
1142
                        else if (opcode == 0xc00) {
 
1143
                                // version 2 header (26 bytes)
 
1144
                                WORD minorVersion = Read16( io, handle );       // always FFFE (-2) for extended version 2
 
1145
                                Read16( io, handle );                                           // reserved
 
1146
                                hRes = Read32( io, handle );                            // original horizontal resolution in pixels/inch
 
1147
                                vRes = Read32( io, handle );                            // original horizontal resolution in pixels/inch
 
1148
                                MacRect dummy;
 
1149
                                ReadRect( io, handle, &dummy );                         // frame bounds at original resolution
 
1150
                                Read32( io, handle );                                           // reserved
 
1151
                        }
 
1152
                        else if (opcode == 0x8200) {
 
1153
                                // jpeg
 
1154
                                long opLen = Read32( io, handle );
 
1155
                                BOOL found = FALSE;
 
1156
                                int i = 0;
 
1157
                                
 
1158
                                // skip to JPEG header.
 
1159
                                while ( !found && i < opLen ) {
 
1160
//                                      io->seek_proc( handle, 24, SEEK_CUR );
 
1161
//                                      MacRect dummy;
 
1162
//                                      ReadRect( io, handle, &dummy );
 
1163
//                                      io->seek_proc( handle, 122, SEEK_CUR );
 
1164
//                                      found = TRUE;
 
1165
                                        BYTE data[ 2 ];
 
1166
                                        if( io->read_proc( data, 2, 1, handle ) ) {
 
1167
                                                io->seek_proc( handle, -2, SEEK_CUR );
 
1168
                                                
 
1169
                                                if ( data[0] == 0xFF && data[1] == 0xD8 ) {
 
1170
                                                        found = TRUE;
 
1171
                                                } else {
 
1172
                                                        Read8( io, handle );
 
1173
                                                        i++;
 
1174
                                                }
 
1175
                                        }
 
1176
                                }
 
1177
                                
 
1178
                                if ( found ) {
 
1179
                                        // Pass the data to the JPEG decoder.
 
1180
                                        pictType = jpeg;
 
1181
                                } else {
 
1182
                                        throw "PICT file contains unrecognized quicktime data.";
 
1183
                                }
 
1184
                                done = TRUE;
 
1185
                        }
 
1186
                        else if (opcode >= 0xa2 && opcode <= 0xaf) {
 
1187
                                // reserved
 
1188
                                WORD len = Read16( io, handle );
 
1189
                                io->seek_proc(handle, len, SEEK_CUR);
 
1190
                        }
 
1191
                        else if ((opcode >= 0xb0 && opcode <= 0xcf) || (opcode >= 0x8000 && opcode <= 0x80ff)) {
 
1192
                                // just a reserved opcode, no data
 
1193
                        }
 
1194
                        else if ((opcode >= 0xd0 && opcode <= 0xfe) || opcode >= 8100) {
 
1195
                                // reserved
 
1196
                                LONG len = Read32( io, handle );
 
1197
                                io->seek_proc(handle, len, SEEK_CUR);
 
1198
                        }
 
1199
                        else if (opcode >= 0x100 && opcode <= 0x7fff) {
 
1200
                                // reserved
 
1201
                                io->seek_proc(handle, ((opcode >> 7) & 255), SEEK_CUR);                         
 
1202
                        }
 
1203
                        else {
 
1204
                                sprintf( outputMessage, "Can't handle opcode %x.\n", opcode );
 
1205
                                throw outputMessage;
 
1206
                        }               
 
1207
                }
 
1208
                                
 
1209
                switch ( pictType )     {
 
1210
                        case op9a:
 
1211
                        {
 
1212
                                bounds = pixMap.Bounds;
 
1213
                                int width = bounds.right - bounds.left;
 
1214
                                int height = bounds.bottom - bounds.top;
 
1215
                                
 
1216
                                if ( pixMap.pixelSize > 8 ) {
 
1217
                                        dib = FreeImage_Allocate( width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
 
1218
                                } else {
 
1219
                                        dib = FreeImage_Allocate( width, height, 8);
 
1220
                                }
 
1221
                                hRes = pixMap.hRes << 16;
 
1222
                                vRes = pixMap.vRes << 16;                               
 
1223
                                break;
 
1224
                        }       
 
1225
                                
 
1226
                        case jpeg:
 
1227
                        {
 
1228
                                dib = FreeImage_LoadFromHandle( FIF_JPEG, io, handle );                                 
 
1229
                                break;
 
1230
                        }
 
1231
 
 
1232
                        case pixmap:
 
1233
                        {
 
1234
                                // Decode version 2 pixmap
 
1235
                                ReadRect( io, handle, &pixMap.Bounds );
 
1236
                                ReadPixmap( io, handle, &pixMap );
 
1237
                                
 
1238
                                bounds = pixMap.Bounds;
 
1239
                                int width = bounds.right - bounds.left;
 
1240
                                int height = bounds.bottom - bounds.top;
 
1241
 
 
1242
                                if ( pixMap.pixelSize > 8 ) {
 
1243
                                        dib = FreeImage_Allocate( width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
 
1244
                                } else {
 
1245
                                        dib = FreeImage_Allocate( width, height, 8);
 
1246
                                }
 
1247
                                hRes = pixMap.hRes << 16;
 
1248
                                vRes = pixMap.vRes << 16;                               
 
1249
                                break;
 
1250
                        }
 
1251
                                
 
1252
                        case bitmap:
 
1253
                        {
 
1254
                                // Decode version 1 bitmap: 1 bpp.
 
1255
                                MacRect srcRect;
 
1256
                                MacRect dstRect;
 
1257
                                WORD width;        // Width in pixels
 
1258
                                WORD height;       // Height in pixels
 
1259
                                
 
1260
                                ReadRect( io, handle, &bounds );
 
1261
                                ReadRect( io, handle, &srcRect );
 
1262
                                ReadRect( io, handle, &dstRect );
 
1263
                                
 
1264
                                width = bounds.right - bounds.left;
 
1265
                                height = bounds.bottom - bounds.top;
 
1266
                                
 
1267
                                dib = FreeImage_Allocate(width, height, 8);
 
1268
                                break;
 
1269
                        }                       
 
1270
                }               
 
1271
                
 
1272
                if ( dib ) {
 
1273
                        // need to convert resolution figures from fixed point, pixels/inch
 
1274
                        // to floating point, pixels/meter.                     
 
1275
                        float hres_ppm = hRes * ((float)39.4 / (float)65536.0);
 
1276
                        float vres_ppm = vRes * ((float)39.4 / (float)65536.0);         
 
1277
                        
 
1278
                        FreeImage_SetDotsPerMeterX( dib, (LONG)hres_ppm );
 
1279
                        FreeImage_SetDotsPerMeterY( dib, (LONG)vres_ppm );                      
 
1280
                        
 
1281
                        switch( pictType ) {
 
1282
                                case op9a:
 
1283
                                        DecodeOp9a( io, handle, dib, &pixMap );
 
1284
                                        break;
 
1285
                                case jpeg:
 
1286
                                        // Already decoded if the embedded format was valid.
 
1287
                                        break;
 
1288
                                case pixmap:
 
1289
                                        DecodePixmap( io, handle, dib, isRegion, &pixMap, rowBytes );
 
1290
                                        break;
 
1291
                                case bitmap:
 
1292
                                        DecodeBitmap( io, handle, dib, isRegion, &bounds, rowBytes );
 
1293
                                        break;
 
1294
                                default:
 
1295
                                        throw "invalid pict type";
 
1296
                        }                       
 
1297
                }
 
1298
                
 
1299
                return dib;
 
1300
        } 
 
1301
        catch(const char *message) {
 
1302
                FreeImage_Unload( dib );
 
1303
                FreeImage_OutputMessageProc(s_format_id, message);
 
1304
        }
 
1305
 
 
1306
        return NULL;
 
1307
}
 
1308
 
 
1309
// ==========================================================
 
1310
//   Init
 
1311
// ==========================================================
 
1312
 
 
1313
void DLL_CALLCONV
 
1314
InitPICT(Plugin *plugin, int format_id) {
 
1315
        s_format_id = format_id;
 
1316
 
 
1317
        plugin->format_proc = Format;
 
1318
        plugin->description_proc = Description;
 
1319
        plugin->extension_proc = Extension;
 
1320
        plugin->regexpr_proc = NULL;
 
1321
        plugin->open_proc = NULL;
 
1322
        plugin->close_proc = NULL;
 
1323
        plugin->pagecount_proc = NULL;
 
1324
        plugin->pagecapability_proc = NULL;
 
1325
        plugin->load_proc = Load;
 
1326
        plugin->save_proc = NULL;
 
1327
        plugin->validate_proc = Validate;
 
1328
        plugin->mime_proc = MimeType;
 
1329
        plugin->supports_export_bpp_proc = SupportsExportDepth;
 
1330
        plugin->supports_export_type_proc = SupportsExportType;
 
1331
        plugin->supports_icc_profiles_proc = SupportsICCProfiles;
 
1332
}