Subversion Repositories Scribus

Rev

Rev 7362 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5977 jghali 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
5937 jghali 7
#include <qfile.h>
5947 jghali 8
#include <qfileinfo.h>
5977 jghali 9
#include <qobject.h>
5937 jghali 10
#include <setjmp.h>
11
#include "scconfig.h"
12
#include "scimgdataloader_jpeg.h"
13
#include "exif.h"
14
 
6566 fschmid 15
#include CMS_INC
5937 jghali 16
 
17
typedef struct my_error_mgr
18
{
19
        struct jpeg_error_mgr pub;            /* "public" fields */
20
        jmp_buf setjmp_buffer;  /* for return to caller */
21
} *my_error_ptr;
22
 
23
static void my_error_exit (j_common_ptr cinfo)
24
{
25
        my_error_ptr myerr = (my_error_ptr) cinfo->err;
26
        (*cinfo->err->output_message) (cinfo);
27
        longjmp (myerr->setjmp_buffer, 1);
28
}
29
 
30
#define ICC_MARKER  (JPEG_APP0 + 2)     /* JPEG marker code for ICC */
31
#define PHOTOSHOP_MARKER  (JPEG_APP0 + 13)      /* JPEG marker code for PHOTOSHOP */
32
#define ICC_OVERHEAD_LEN  14            /* size of non-profile data in APP2 */
33
#define MAX_BYTES_IN_MARKER  65533      /* maximum data len of a JPEG marker */
34
#define MAX_DATA_BYTES_IN_MARKER  (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN)
35
 
36
 
37
ScImgDataLoader_JPEG::ScImgDataLoader_JPEG(void)
38
{
39
        initSupportedFormatList();
40
}
41
 
42
void ScImgDataLoader_JPEG::initSupportedFormatList(void)
43
{
44
        m_supportedFormats.clear();
45
        m_supportedFormats.append( "jpg" );
46
        m_supportedFormats.append( "jpeg" );
47
}
48
 
49
void ScImgDataLoader_JPEG::loadEmbeddedProfile(const QString& fn)
50
{
51
        m_embeddedProfile.resize(0);
52
        m_profileComponents = 0;
53
        if (!QFile::exists(fn))
54
                return;
55
        struct jpeg_decompress_struct cinfo;
56
        struct my_error_mgr         jerr;
57
        FILE     *infile;
58
        cinfo.err = jpeg_std_error (&jerr.pub);
59
        jerr.pub.error_exit = my_error_exit;
60
        infile = NULL;
61
        if (setjmp (jerr.setjmp_buffer))
62
        {
63
                jpeg_destroy_decompress (&cinfo);
64
                if (infile)
65
                        fclose (infile);
66
                return;
67
        }
68
        jpeg_create_decompress (&cinfo);
69
        if ((infile = fopen (fn.local8Bit(), "rb")) == NULL)
70
                return;
71
        jpeg_stdio_src(&cinfo, infile);
72
        jpeg_save_markers(&cinfo, ICC_MARKER, 0xFFFF);
73
        jpeg_read_header(&cinfo, true);
6158 jghali 74
        //jpeg_start_decompress(&cinfo);
5937 jghali 75
        unsigned int EmbedLen = 0;
76
        unsigned char* EmbedBuffer;
77
        if (read_jpeg_marker(ICC_MARKER,&cinfo, &EmbedBuffer, &EmbedLen))
78
        {
79
                cmsHPROFILE prof = cmsOpenProfileFromMem(EmbedBuffer, EmbedLen);
80
                if (prof)
81
                {
82
                        if (static_cast<int>(cmsGetColorSpace(prof)) == icSigRgbData)
83
                                m_profileComponents = 3;
84
                        if (static_cast<int>(cmsGetColorSpace(prof)) == icSigCmykData)
85
                                m_profileComponents = 4;
86
                        m_embeddedProfile.duplicate((const char*) EmbedBuffer, EmbedLen);
87
                }
88
                cmsCloseProfile(prof);
89
                free(EmbedBuffer);
90
        }
6158 jghali 91
        //(void) jpeg_finish_decompress(&cinfo);
5937 jghali 92
        fclose (infile);
93
        jpeg_destroy_decompress (&cinfo);
94
}
95
 
96
void ScImgDataLoader_JPEG::preloadAlphaChannel(const QString& fn, int res)
97
{
98
        // No support for aplha in jpeg pictures
99
        initialize();
100
}
101
 
102
bool ScImgDataLoader_JPEG::loadPicture(const QString& fn, int res, bool thumbnail)
103
{
104
        bool isCMYK = false;
7041 fschmid 105
        bool fromPS = false;
5937 jghali 106
        float xres = 72.0, yres = 72.0;
107
        if (!QFile::exists(fn))
108
                return false;
109
        ExifData ExifInf;
110
        struct jpeg_decompress_struct cinfo;
111
        struct my_error_mgr         jerr;
112
        FILE     *infile;
113
        cinfo.err = jpeg_std_error (&jerr.pub);
114
        jerr.pub.error_exit = my_error_exit;
115
        infile = NULL;
116
 
117
        initialize();
118
        m_imageInfoRecord.type = 0;
119
        m_imageInfoRecord.exifInfo.thumbnail = QImage();
120
        if (setjmp (jerr.setjmp_buffer))
121
        {
122
                jpeg_destroy_decompress (&cinfo);
123
                if (infile)
124
                        fclose (infile);
125
                return false;
126
        }
127
        jpeg_create_decompress (&cinfo);
128
        if ((infile = fopen (fn.local8Bit(), "rb")) == NULL)
129
                return false;
130
        jpeg_stdio_src(&cinfo, infile);
131
        jpeg_save_markers(&cinfo, ICC_MARKER, 0xFFFF);
132
        jpeg_save_markers(&cinfo, PHOTOSHOP_MARKER, 0xFFFF);
133
        jpeg_read_header(&cinfo, true);
134
        jpeg_start_decompress(&cinfo);
135
        bool exi = ExifInf.scan(fn);
136
        if ((exi) && (ExifInf.exifDataValid))
137
        {
6716 fschmid 138
                if (cinfo.output_components == 4)
139
                        m_imageInfoRecord.colorspace = 1;
140
                else if (cinfo.output_components == 3)
141
                        m_imageInfoRecord.colorspace = 0;
142
                else if (cinfo.output_components == 1)
143
                        m_imageInfoRecord.colorspace = 2;
5937 jghali 144
                if ((!ExifInf.isNullThumbnail()) && thumbnail)
6716 fschmid 145
                {
5937 jghali 146
                        m_image = ExifInf.getThumbnail();
6716 fschmid 147
                        m_imageInfoRecord.exifInfo.thumbnail = ExifInf.getThumbnail();
148
                        if (cinfo.output_components == 4)
149
                        {
7175 fschmid 150
                                QRgb *s;
151
                                unsigned char cc, cm, cy, ck;
6716 fschmid 152
                                for( int yit=0; yit < m_image.height(); ++yit )
153
                                {
7175 fschmid 154
                                        s = (QRgb*)(m_image.scanLine( yit ));
6716 fschmid 155
                                        for(int xit=0; xit < m_image.width(); ++xit )
156
                                        {
7175 fschmid 157
                                                cc = 255 - qRed(*s);
158
                                                cm = 255 - qGreen(*s);
159
                                                cy = 255 - qBlue(*s);
160
                                                ck = QMIN(QMIN(cc, cm), cy);
6716 fschmid 161
                                                *s = qRgba(cc-ck,cm-ck,cy-ck,ck);
7040 fschmid 162
                                                s++;
6716 fschmid 163
                                        }
164
                                }
165
                        }
166
                }
167
                else
168
                        m_imageInfoRecord.exifInfo.thumbnail = QImage();
5937 jghali 169
                m_imageInfoRecord.exifInfo.cameraName = ExifInf.getCameraModel();
170
                m_imageInfoRecord.exifInfo.cameraVendor = ExifInf.getCameraMake();
171
                m_imageInfoRecord.exifInfo.comment = ExifInf.getComment();
172
                m_imageInfoRecord.exifInfo.width = ExifInf.getWidth();
173
                m_imageInfoRecord.exifInfo.height = ExifInf.getHeight();
174
                m_imageInfoRecord.exifInfo.userComment = ExifInf.getUserComment();
175
                m_imageInfoRecord.exifInfo.dateTime = ExifInf.getDateTime();
7362 fschmid 176
                m_imageInfoRecord.exifInfo.ApertureFNumber = ExifInf.getApertureFNumber();
177
                m_imageInfoRecord.exifInfo.ExposureTime = ExifInf.getExposureTime();
178
                m_imageInfoRecord.exifInfo.ISOequivalent = ExifInf.getISOequivalent();
5937 jghali 179
                m_imageInfoRecord.exifDataValid = true;
180
                if (cinfo.density_unit == 0)
181
                {
182
                        xres = 72;
183
                        yres = 72;
184
                }
185
                else if ( cinfo.density_unit == 1 )
186
                {
187
                        xres = cinfo.X_density;
188
                        yres = cinfo.Y_density;
189
                }
190
                else if ( cinfo.density_unit == 2 )
191
                {
192
                        xres = cinfo.X_density * 2.54;
193
                        yres = cinfo.Y_density * 2.54;
194
                }
6650 fschmid 195
                if( xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0 )
5947 jghali 196
                {
197
                        xres = yres = 72.0;
198
                        QFileInfo qfi(fn);
6650 fschmid 199
                        m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName());
5977 jghali 200
                        m_msgType = warningMsg;
5947 jghali 201
                }
5937 jghali 202
                m_imageInfoRecord.xres = qRound(xres);
203
                m_imageInfoRecord.yres = qRound(yres);
204
                m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo);
205
                if ((!ExifInf.isNullThumbnail()) && thumbnail)
206
                {
207
                        jpeg_destroy_decompress(&cinfo);
208
                        fclose(infile);
209
                        return true;
210
                }
211
        }
212
        else
213
                m_imageInfoRecord.exifDataValid = false;
6716 fschmid 214
        m_imageInfoRecord.exifInfo.thumbnail = QImage();
5937 jghali 215
        unsigned int EmbedLen = 0;
216
        unsigned char* EmbedBuffer;
217
        if (read_jpeg_marker(ICC_MARKER,&cinfo, &EmbedBuffer, &EmbedLen))
218
        {
219
                const char *Descriptor;
220
                cmsHPROFILE prof = cmsOpenProfileFromMem(EmbedBuffer, EmbedLen);
221
                Descriptor = cmsTakeProductDesc(prof);
222
                m_embeddedProfile.duplicate((const char*) EmbedBuffer, EmbedLen);
223
                m_imageInfoRecord.profileName = QString(Descriptor);
224
                m_imageInfoRecord.isEmbedded = true;
225
                free(EmbedBuffer);
226
        }
227
        else
228
        {
229
                m_imageInfoRecord.isEmbedded = false;
230
                m_imageInfoRecord.profileName = "";
231
        }
232
        unsigned int PhotoshopLen = 0;
233
        unsigned char * PhotoshopBuffer;
234
        if (cinfo.density_unit == 0)
235
        {
236
                xres = 72;
237
                yres = 72;
238
                m_image.setDotsPerMeterX(2834);
239
                m_image.setDotsPerMeterY(2834);
240
        }
241
        else if ( cinfo.density_unit == 1 )
242
        {
243
                xres = cinfo.X_density;
244
                yres = cinfo.Y_density;
245
                m_image.setDotsPerMeterX( int(100. * cinfo.X_density / 2.54) );
246
                m_image.setDotsPerMeterY( int(100. * cinfo.Y_density / 2.54) );
247
        }
248
        else if ( cinfo.density_unit == 2 )
249
        {
250
                xres = cinfo.X_density * 2.54;
251
                yres = cinfo.Y_density * 2.54;
252
                m_image.setDotsPerMeterX( int(100. * cinfo.X_density) );
253
                m_image.setDotsPerMeterY( int(100. * cinfo.Y_density) );
254
        }
6650 fschmid 255
        if( xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0 )
5947 jghali 256
        {
257
                xres = yres = 72.0;
6650 fschmid 258
                m_image.setDotsPerMeterX(2834);
259
                m_image.setDotsPerMeterY(2834);
5947 jghali 260
                QFileInfo qfi(fn);
6650 fschmid 261
                m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName());
5977 jghali 262
                m_msgType = warningMsg;
5947 jghali 263
        }
5937 jghali 264
        m_imageInfoRecord.xres = qRound(xres);
265
        m_imageInfoRecord.yres = qRound(yres);
266
        if (cinfo.output_components == 4)
267
        {
268
                isCMYK = true;
269
                m_imageInfoRecord.colorspace = 1;
270
        }
271
        else if (cinfo.output_components == 3)
272
                m_imageInfoRecord.colorspace = 0;
273
        else if (cinfo.output_components == 1)
274
                m_imageInfoRecord.colorspace = 2;
275
        m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo);
276
 
277
        if (read_jpeg_marker(PHOTOSHOP_MARKER,&cinfo, &PhotoshopBuffer, &PhotoshopLen) )
278
        {
279
                if (PhotoshopLen != 0)
280
                {
281
                        bool savEx = m_imageInfoRecord.exifDataValid;
282
                        QByteArray arrayPhot(PhotoshopLen);
283
                        arrayPhot.setRawData((const char*)PhotoshopBuffer,PhotoshopLen);
284
                        QDataStream strPhot(arrayPhot,IO_ReadOnly);
285
                        strPhot.setByteOrder( QDataStream::BigEndian );
286
                        PSDHeader fakeHeader;
287
                        fakeHeader.width = cinfo.output_width;
288
                        fakeHeader.height = cinfo.output_height;
289
                        if (cinfo.output_components == 4)
290
                                m_imageInfoRecord.colorspace = 1;
291
                        else if (cinfo.output_components == 3)
292
                                m_imageInfoRecord.colorspace = 0;
293
                        else if (cinfo.output_components == 1)
294
                                m_imageInfoRecord.colorspace = 2;
295
                        m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo);
296
                        parseRessourceData(strPhot, fakeHeader, PhotoshopLen);
297
                        // Photoshop resolution is more accurate than jpeg header resolution
298
                        xres = m_imageInfoRecord.xres;
299
                        yres = m_imageInfoRecord.yres;
300
                        m_image.setDotsPerMeterX( int(100. * m_imageInfoRecord.xres / 2.54) );
301
                        m_image.setDotsPerMeterY( int(100. * m_imageInfoRecord.yres / 2.54) );
6650 fschmid 302
                        if( xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0 )
303
                        {
304
                                xres = yres = 72.0;
7980 fschmid 305
                                m_imageInfoRecord.xres = qRound(xres);
306
                                m_imageInfoRecord.yres = qRound(yres);
6650 fschmid 307
                                m_image.setDotsPerMeterX(2834);
308
                                m_image.setDotsPerMeterY(2834);
309
                                QFileInfo qfi(fn);
310
                                m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName());
311
                                m_msgType = warningMsg;
312
                        }
7040 fschmid 313
                        if (m_imageInfoRecord.exifDataValid && thumbnail)
314
                        {
315
                                m_image.create(m_imageInfoRecord.exifInfo.width, m_imageInfoRecord.exifInfo.height, 32 );
316
                                m_imageInfoRecord.exifInfo.width = cinfo.output_width;
317
                                m_imageInfoRecord.exifInfo.height = cinfo.output_height;
318
                                if (cinfo.output_components == 4)
319
                                {
7041 fschmid 320
                                        m_image.setAlphaBuffer(false);
7175 fschmid 321
                                        QRgb *d;
322
                                        QRgb *s;
323
                                        unsigned char cc, cm, cy, ck;
7040 fschmid 324
                                        for( int yit=0; yit < m_image.height(); ++yit )
325
                                        {
7175 fschmid 326
                                                d = (QRgb*)(m_image.scanLine( yit ));
327
                                                s = (QRgb*)(m_imageInfoRecord.exifInfo.thumbnail.scanLine( yit ));
7040 fschmid 328
                                                for(int xit=0; xit < m_image.width(); ++xit )
329
                                                {
7175 fschmid 330
                                                        cc = 255 - qRed(*s);
331
                                                        cm = 255 - qGreen(*s);
332
                                                        cy = 255 - qBlue(*s);
333
                                                        ck = QMIN(QMIN(cc, cm), cy);
7040 fschmid 334
                                                        *d = qRgba(cc-ck,cm-ck,cy-ck,ck);
335
                                                        s++;
336
                                                        d++;
337
                                                }
338
                                        }
339
                                }
7041 fschmid 340
                                else
341
                                        m_image = m_imageInfoRecord.exifInfo.thumbnail.copy();
7040 fschmid 342
                        }
5937 jghali 343
                        m_imageInfoRecord.valid = (m_imageInfoRecord.PDSpathData.size())>0?true:false; // The only interest is vectormask
344
                        arrayPhot.resetRawData((const char*)PhotoshopBuffer,PhotoshopLen);
345
                        free( PhotoshopBuffer );
7040 fschmid 346
                        if (m_imageInfoRecord.exifDataValid && thumbnail)
347
                        {
348
                                jpeg_destroy_decompress(&cinfo);
349
                                fclose(infile);
350
                                return true;
351
                        }
6716 fschmid 352
                        m_imageInfoRecord.exifInfo.thumbnail = QImage();
5937 jghali 353
                        m_imageInfoRecord.exifDataValid = savEx;
7041 fschmid 354
                        fromPS = true;
5937 jghali 355
                }
356
        }
357
        if ( cinfo.output_components == 3 || cinfo.output_components == 4)
358
                m_image.create( cinfo.output_width, cinfo.output_height, 32 );
359
        else if ( cinfo.output_components == 1 )
360
        {
361
                m_image.create( cinfo.output_width, cinfo.output_height, 8, 256 );
362
                for (int i=0; i<256; i++)
363
                        m_image.setColor(i, qRgb(i,i,i));
364
        }
365
        if (!m_image.isNull())
366
        {
367
                uchar** lines = m_image.jumpTable();
368
                while (cinfo.output_scanline < cinfo.output_height)
369
                        (void) jpeg_read_scanlines(&cinfo, lines + cinfo.output_scanline, cinfo.output_height);
370
                if ( cinfo.output_components == 3 )
371
                {
7175 fschmid 372
                        uchar *in;
373
                        QRgb *out;
5937 jghali 374
                        for (uint j=0; j<cinfo.output_height; j++)
375
                        {
7175 fschmid 376
                                in = m_image.scanLine(j) + cinfo.output_width * 3;
377
                                out = (QRgb*) m_image.scanLine(j);
5937 jghali 378
                                for (uint i=cinfo.output_width; i--; )
379
                                {
380
                                        in -= 3;
381
                                        out[i] = qRgb(in[0], in[1], in[2]);
382
                                }
383
                        }
384
                }
385
                if ( cinfo.output_components == 4 )
386
                {
7041 fschmid 387
                        int method = 0;
388
                        if (cinfo.jpeg_color_space == JCS_YCCK)
389
                                method = 1;
390
                        else if (fromPS)
391
                        {
392
                                if ((cinfo.jpeg_color_space == JCS_CMYK) && (cinfo.saw_Adobe_marker) && (cinfo.Adobe_transform == 0))
393
                                        method = 2;
394
                        }
395
                        else if ((cinfo.jpeg_color_space == JCS_CMYK) && (cinfo.saw_Adobe_marker))
396
                                method = 1;
7175 fschmid 397
                        QRgb *ptr;
398
                        unsigned char c, m, y ,k;
399
                        unsigned char *p;
5937 jghali 400
                        for (int i = 0; i < m_image.height(); i++)
401
                        {
7175 fschmid 402
                                ptr = (QRgb*)  m_image.scanLine(i);
7041 fschmid 403
                                if (method == 1)
5937 jghali 404
                                {
405
                                        for (int j = 0; j <  m_image.width(); j++)
406
                                        {
7175 fschmid 407
                                                p = (unsigned char *) ptr;
5937 jghali 408
                                                c = p[0];
409
                                                m = p[1];
410
                                                y =  p[2];
411
                                                k =  p[3];
412
                                                *ptr = qRgba(255 - c, 255 - m, 255 - y, 255 - k);
413
                                                ptr++;
414
                                        }
415
                                }
7041 fschmid 416
                                else if (method == 2)
417
                                {
418
                                        for (int j = 0; j <  m_image.width(); j++)
419
                                        {
7175 fschmid 420
                                                p = (unsigned char *) ptr;
7041 fschmid 421
                                                c = p[0];
422
                                                m = p[1];
423
                                                y =  p[2];
424
                                                k =  p[3];
425
                                                *ptr = qRgba(255 - c, 255 - m, 255 - y, k);
426
                                                ptr++;
427
                                        }
428
                                }
5937 jghali 429
                                else
430
                                {
431
                                        for (int j = 0; j <  m_image.width(); j++)
432
                                        {
7175 fschmid 433
                                                p = (unsigned char *) ptr;
5937 jghali 434
                                                c = p[0];
435
                                                m = p[1];
436
                                                y =  p[2];
437
                                                k =  p[3];
438
                                                *ptr = qRgba(y, m, c, k);
439
                                                ptr++;
440
                                        }
441
                                }
442
                        }
443
                        isCMYK = true;
444
                }
445
                else
446
                        isCMYK = false;
447
                if ( cinfo.output_components == 1 )
448
                {
449
                        QImage tmpImg = m_image.convertDepth(32);
7175 fschmid 450
                        m_image.create( cinfo.output_width, cinfo.output_height, 32 );
451
                        QRgb *s;
452
                        QRgb *d;
5937 jghali 453
                        for( int yi=0; yi < tmpImg.height(); ++yi )
454
                        {
7175 fschmid 455
                                s = (QRgb*)(tmpImg.scanLine( yi ));
456
                                d = (QRgb*)(m_image.scanLine( yi ));
5937 jghali 457
                                for(int xi=0; xi < tmpImg.width(); ++xi )
458
                                {
459
                                        (*d) = (*s);
460
                                        s++;
461
                                        d++;
462
                                }
463
                        }
464
                }
465
                m_image.setAlphaBuffer(true);
466
        }
467
        (void) jpeg_finish_decompress(&cinfo);
468
        fclose (infile);
469
        jpeg_destroy_decompress (&cinfo);
470
        m_imageInfoRecord.layerInfo.clear();
471
        m_imageInfoRecord.BBoxX = 0;
472
        m_imageInfoRecord.BBoxH = m_image.height();
473
        return (!m_image.isNull());
474
}
475
 
476
bool ScImgDataLoader_JPEG::marker_is_icc (jpeg_saved_marker_ptr marker)
477
{
478
        return
479
            marker->marker == ICC_MARKER &&
480
            marker->data_length >= ICC_OVERHEAD_LEN &&
481
            /* verify the identifying string */
482
            GETJOCTET(marker->data[0]) == 0x49 &&
483
            GETJOCTET(marker->data[1]) == 0x43 &&
484
            GETJOCTET(marker->data[2]) == 0x43 &&
485
            GETJOCTET(marker->data[3]) == 0x5F &&
486
            GETJOCTET(marker->data[4]) == 0x50 &&
487
            GETJOCTET(marker->data[5]) == 0x52 &&
488
            GETJOCTET(marker->data[6]) == 0x4F &&
489
            GETJOCTET(marker->data[7]) == 0x46 &&
490
            GETJOCTET(marker->data[8]) == 0x49 &&
491
            GETJOCTET(marker->data[9]) == 0x4C &&
492
            GETJOCTET(marker->data[10]) == 0x45 &&
493
            GETJOCTET(marker->data[11]) == 0x0;
494
}
495
 
496
bool ScImgDataLoader_JPEG::marker_is_photoshop (jpeg_saved_marker_ptr marker)
497
{
498
        return
499
            marker->marker == PHOTOSHOP_MARKER &&
500
            marker->data_length >= ICC_OVERHEAD_LEN &&
501
            /* verify the identifying string */
502
            GETJOCTET(marker->data[0]) == 0x50 &&
503
            GETJOCTET(marker->data[1]) == 0x68 &&
504
            GETJOCTET(marker->data[2]) == 0x6F &&
505
            GETJOCTET(marker->data[3]) == 0x74 &&
506
            GETJOCTET(marker->data[4]) == 0x6F &&
507
            GETJOCTET(marker->data[5]) == 0x73 &&
508
            GETJOCTET(marker->data[6]) == 0x68 &&
509
            GETJOCTET(marker->data[7]) == 0x6F &&
510
            GETJOCTET(marker->data[8]) == 0x70 &&
511
            GETJOCTET(marker->data[9]) == 0x20 &&
512
            GETJOCTET(marker->data[10]) == 0x33 &&
513
            GETJOCTET(marker->data[11]) == 0x2E &&
514
            GETJOCTET(marker->data[12]) == 0x30 &&
515
            GETJOCTET(marker->data[13]) == 0x0;
516
}
517
 
518
/* Small modification of original read_icc_profile method from jpegicc of lcms project
519
 * to enable read of Photoshop marker
520
 */
521
bool ScImgDataLoader_JPEG::read_jpeg_marker (UINT8 requestmarker, j_decompress_ptr cinfo, JOCTET **icc_data_ptr, unsigned int *icc_data_len)
522
{
523
        jpeg_saved_marker_ptr marker;
524
        int num_markers = 0;
525
        int seq_no;
526
        JOCTET *icc_data;
527
        unsigned int total_length;
528
#define MAX_SEQ_NO  255         /* sufficient since marker numbers are bytes */
529
        char marker_present[MAX_SEQ_NO+1];        /* 1 if marker found */
530
        unsigned int data_length[MAX_SEQ_NO+1]; /* size of profile data in marker */
531
        unsigned int data_offset[MAX_SEQ_NO+1]; /* offset for data in marker */
532
 
533
        *icc_data_ptr = NULL;           /* avoid confusion if false return */
534
        *icc_data_len = 0;
535
 
536
        /* This first pass over the saved markers discovers whether there are
537
         * any ICC markers and verifies the consistency of the marker numbering.
538
         */
539
 
540
        for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++)
541
                marker_present[seq_no] = 0;
542
        seq_no = 0;
543
        for (marker = cinfo->marker_list; marker != NULL; marker = marker->next)
544
        {
545
                if (requestmarker == ICC_MARKER && marker_is_icc(marker))
546
                {
547
                        if (num_markers == 0)
548
                                num_markers = GETJOCTET(marker->data[13]);
549
                        else if (num_markers != GETJOCTET(marker->data[13]))
550
                                return false;           /* inconsistent num_markers fields */
551
                        seq_no = GETJOCTET(marker->data[12]);
552
                        if (seq_no <= 0 || seq_no > num_markers)
553
                                return false;           /* bogus sequence number */
554
                        if (marker_present[seq_no])
555
                                return false;           /* duplicate sequence numbers */
556
                        marker_present[seq_no] = 1;
557
                        data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
558
                }
559
                else if(requestmarker == PHOTOSHOP_MARKER && marker_is_photoshop(marker))
560
                {
561
                        num_markers = ++seq_no;
562
                        marker_present[seq_no] = 1;
563
                        data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
564
                }
565
        }
566
 
567
        if (num_markers == 0)
568
                return false;
569
 
570
        /* Check for missing markers, count total space needed,
571
         * compute offset of each marker's part of the data.
572
         */
573
 
574
        total_length = 0;
575
        for (seq_no = 1; seq_no <= num_markers; seq_no++)
576
        {
577
                if (marker_present[seq_no] == 0)
578
                        return false;           /* missing sequence number */
579
                data_offset[seq_no] = total_length;
580
                total_length += data_length[seq_no];
581
        }
582
 
583
        if (total_length <= 0)
584
                return false;           /* found only empty markers? */
585
 
586
        /* Allocate space for assembled data */
587
        icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET));
588
        if (icc_data == NULL)
589
                return false;           /* oops, out of memory */
590
        seq_no=0;
591
        /* and fill it in */
592
        for (marker = cinfo->marker_list; marker != NULL; marker = marker->next)
593
        {
594
                if ( (requestmarker == ICC_MARKER && marker_is_icc(marker)) ||
595
                        (requestmarker == PHOTOSHOP_MARKER && marker_is_photoshop(marker)) || (requestmarker == 0xE1))
596
                {
597
                        JOCTET FAR *src_ptr;
598
                        JOCTET *dst_ptr;
599
                        unsigned int length;
600
                        if(requestmarker == ICC_MARKER)
601
                                seq_no = GETJOCTET(marker->data[12]);
602
                        else if(requestmarker == PHOTOSHOP_MARKER)
603
                                seq_no++;
604
                        dst_ptr = icc_data + data_offset[seq_no];
605
                        src_ptr = marker->data + ICC_OVERHEAD_LEN;
606
                        length = data_length[seq_no];
607
                        while (length--)
608
                        {
609
                                *dst_ptr++ = *src_ptr++;
610
                        }
611
                }
612
        }
613
 
614
        *icc_data_ptr = icc_data;
615
        *icc_data_len = total_length;
616
 
617
        return true;
6650 fschmid 618
}