Subversion Repositories Scribus

Rev

Rev 24665 | 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
*/
10223 cbradney 7
#include <QFile>
8
#include <QFileInfo>
9
#include <QObject>
22640 craig 10
#include <csetjmp>
5937 jghali 11
#include "scconfig.h"
14491 jghali 12
#include "colormgmt/sccolormgmtengine.h"
5937 jghali 13
#include "scimgdataloader_jpeg.h"
14170 jghali 14
#include "scribuscore.h"
5937 jghali 15
#include "exif.h"
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
 
22635 craig 37
ScImgDataLoader_JPEG::ScImgDataLoader_JPEG()
5937 jghali 38
{
39
        initSupportedFormatList();
40
}
41
 
22635 craig 42
void ScImgDataLoader_JPEG::initSupportedFormatList()
5937 jghali 43
{
44
        m_supportedFormats.clear();
45
        m_supportedFormats.append( "jpg" );
46
        m_supportedFormats.append( "jpeg" );
47
}
48
 
12141 avox 49
void ScImgDataLoader_JPEG::loadEmbeddedProfile(const QString& fn, int /*page*/)
5937 jghali 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;
22518 craig 60
        infile = nullptr;
5937 jghali 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);
20720 jghali 69
#if defined(Q_OS_WIN32)
22518 craig 70
        if ((infile = _wfopen((const wchar_t*) fn.utf16(), L"rb")) == nullptr)
20720 jghali 71
                return;
72
#else
22518 craig 73
        if ((infile = fopen (fn.toLocal8Bit(), "rb")) == nullptr)
5937 jghali 74
                return;
20720 jghali 75
#endif
5937 jghali 76
        jpeg_stdio_src(&cinfo, infile);
77
        jpeg_save_markers(&cinfo, ICC_MARKER, 0xFFFF);
78
        jpeg_read_header(&cinfo, true);
6158 jghali 79
        //jpeg_start_decompress(&cinfo);
5937 jghali 80
        unsigned int EmbedLen = 0;
22605 craig 81
        unsigned char* EmbedBuffer = nullptr;
20828 jghali 82
        if (read_jpeg_marker(ICC_MARKER, &cinfo, &EmbedBuffer, &EmbedLen))
5937 jghali 83
        {
21679 jghali 84
                bool profileIsValid = false;
24735 jghali 85
                QByteArray profArray((const char*) EmbedBuffer, EmbedLen);
14170 jghali 86
                ScColorProfile prof = ScCore->defaultEngine.openProfileFromMem(profArray);
5937 jghali 87
                if (prof)
88
                {
21679 jghali 89
                        eColorSpaceType colorSpace = prof.colorSpace();
90
                        if (colorSpace == ColorSpace_Rgb)
22123 jghali 91
                                profileIsValid = (cinfo.num_components == 3);
21679 jghali 92
                        if (colorSpace == ColorSpace_Cmyk)
22123 jghali 93
                                profileIsValid = (cinfo.num_components == 4);
21679 jghali 94
                        if (colorSpace == ColorSpace_Gray)
22123 jghali 95
                                profileIsValid = (cinfo.num_components == 1);
21679 jghali 96
                }
97
                if (profileIsValid)
98
                {
14772 jghali 99
                        if (prof.colorSpace() == ColorSpace_Rgb)
5937 jghali 100
                                m_profileComponents = 3;
14772 jghali 101
                        if (prof.colorSpace() == ColorSpace_Cmyk)
5937 jghali 102
                                m_profileComponents = 4;
14772 jghali 103
                        if (prof.colorSpace() == ColorSpace_Gray)
12732 fschmid 104
                                m_profileComponents = 1;
14170 jghali 105
                        m_embeddedProfile = profArray;
5937 jghali 106
                }
107
                free(EmbedBuffer);
108
        }
6158 jghali 109
        //(void) jpeg_finish_decompress(&cinfo);
5937 jghali 110
        fclose (infile);
111
        jpeg_destroy_decompress (&cinfo);
112
}
113
 
12141 avox 114
bool ScImgDataLoader_JPEG::preloadAlphaChannel(const QString& fn, int /*page*/, int res, bool& hasAlpha)
5937 jghali 115
{
24665 jghali 116
        // No support for alpha in jpeg pictures
5937 jghali 117
        initialize();
11468 fschmid 118
        hasAlpha = false;
119
        return true;
5937 jghali 120
}
121
 
12141 avox 122
bool ScImgDataLoader_JPEG::loadPicture(const QString& fn, int /*page*/, int res, bool thumbnail)
5937 jghali 123
{
19730 fschmid 124
//      bool isCMYK = false;
7041 fschmid 125
        bool fromPS = false;
5937 jghali 126
        float xres = 72.0, yres = 72.0;
127
        if (!QFile::exists(fn))
128
                return false;
129
        ExifData ExifInf;
130
        struct jpeg_decompress_struct cinfo;
131
        struct my_error_mgr         jerr;
132
        FILE     *infile;
133
        cinfo.err = jpeg_std_error (&jerr.pub);
134
        jerr.pub.error_exit = my_error_exit;
22518 craig 135
        infile = nullptr;
5937 jghali 136
 
137
        initialize();
11331 jghali 138
        m_imageInfoRecord.type = ImageTypeJPG;
5937 jghali 139
        m_imageInfoRecord.exifInfo.thumbnail = QImage();
140
        if (setjmp (jerr.setjmp_buffer))
141
        {
142
                jpeg_destroy_decompress (&cinfo);
143
                if (infile)
144
                        fclose (infile);
145
                return false;
146
        }
147
        jpeg_create_decompress (&cinfo);
20720 jghali 148
#if defined(Q_OS_WIN32)
22518 craig 149
        if ((infile = _wfopen((const wchar_t*) fn.utf16(), L"rb")) == nullptr)
20720 jghali 150
                return false;
151
#else
22518 craig 152
        if ((infile = fopen (fn.toLocal8Bit(), "rb")) == nullptr)
5937 jghali 153
                return false;
20720 jghali 154
#endif
5937 jghali 155
        jpeg_stdio_src(&cinfo, infile);
156
        jpeg_save_markers(&cinfo, ICC_MARKER, 0xFFFF);
157
        jpeg_save_markers(&cinfo, PHOTOSHOP_MARKER, 0xFFFF);
158
        jpeg_read_header(&cinfo, true);
159
        jpeg_start_decompress(&cinfo);
160
        bool exi = ExifInf.scan(fn);
161
        if ((exi) && (ExifInf.exifDataValid))
162
        {
6716 fschmid 163
                if (cinfo.output_components == 4)
11331 jghali 164
                        m_imageInfoRecord.colorspace = ColorSpaceCMYK;
6716 fschmid 165
                else if (cinfo.output_components == 3)
11331 jghali 166
                        m_imageInfoRecord.colorspace = ColorSpaceRGB;
6716 fschmid 167
                else if (cinfo.output_components == 1)
11331 jghali 168
                        m_imageInfoRecord.colorspace = ColorSpaceGray;
10911 fschmid 169
                if ((!ExifInf.Thumbnail.isNull()) && thumbnail)
6716 fschmid 170
                {
5937 jghali 171
                        m_image = ExifInf.getThumbnail();
6716 fschmid 172
                        m_imageInfoRecord.exifInfo.thumbnail = ExifInf.getThumbnail();
173
                        if (cinfo.output_components == 4)
174
                        {
7175 fschmid 175
                                QRgb *s;
176
                                unsigned char cc, cm, cy, ck;
22535 jghali 177
                                for (int yit=0; yit < m_image.height(); ++yit)
6716 fschmid 178
                                {
7175 fschmid 179
                                        s = (QRgb*)(m_image.scanLine( yit ));
22535 jghali 180
                                        for (int xit=0; xit < m_image.width(); ++xit)
6716 fschmid 181
                                        {
7175 fschmid 182
                                                cc = 255 - qRed(*s);
183
                                                cm = 255 - qGreen(*s);
184
                                                cy = 255 - qBlue(*s);
8562 jghali 185
                                                ck = qMin(qMin(cc, cm), cy);
6716 fschmid 186
                                                *s = qRgba(cc-ck,cm-ck,cy-ck,ck);
7040 fschmid 187
                                                s++;
6716 fschmid 188
                                        }
189
                                }
190
                        }
191
                }
192
                else
193
                        m_imageInfoRecord.exifInfo.thumbnail = QImage();
5937 jghali 194
                m_imageInfoRecord.exifInfo.cameraName = ExifInf.getCameraModel();
195
                m_imageInfoRecord.exifInfo.cameraVendor = ExifInf.getCameraMake();
196
                m_imageInfoRecord.exifInfo.comment = ExifInf.getComment();
197
                m_imageInfoRecord.exifInfo.width = ExifInf.getWidth();
198
                m_imageInfoRecord.exifInfo.height = ExifInf.getHeight();
19938 jghali 199
                m_imageInfoRecord.exifInfo.orientation = ExifInf.getOrientation();
5937 jghali 200
                m_imageInfoRecord.exifInfo.userComment = ExifInf.getUserComment();
201
                m_imageInfoRecord.exifInfo.dateTime = ExifInf.getDateTime();
7362 fschmid 202
                m_imageInfoRecord.exifInfo.ApertureFNumber = ExifInf.getApertureFNumber();
203
                m_imageInfoRecord.exifInfo.ExposureTime = ExifInf.getExposureTime();
204
                m_imageInfoRecord.exifInfo.ISOequivalent = ExifInf.getISOequivalent();
5937 jghali 205
                m_imageInfoRecord.exifDataValid = true;
206
                if (cinfo.density_unit == 0)
207
                {
208
                        xres = 72;
209
                        yres = 72;
210
                }
22535 jghali 211
                else if (cinfo.density_unit == 1)
5937 jghali 212
                {
213
                        xres = cinfo.X_density;
214
                        yres = cinfo.Y_density;
215
                }
22535 jghali 216
                else if (cinfo.density_unit == 2)
5937 jghali 217
                {
218
                        xres = cinfo.X_density * 2.54;
219
                        yres = cinfo.Y_density * 2.54;
220
                }
22535 jghali 221
                if (xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0)
5947 jghali 222
                {
223
                        xres = yres = 72.0;
224
                        QFileInfo qfi(fn);
6650 fschmid 225
                        m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName());
5977 jghali 226
                        m_msgType = warningMsg;
5947 jghali 227
                }
5937 jghali 228
                m_imageInfoRecord.xres = qRound(xres);
229
                m_imageInfoRecord.yres = qRound(yres);
230
                m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo);
10911 fschmid 231
                if ((!ExifInf.Thumbnail.isNull()) && thumbnail)
5937 jghali 232
                {
233
                        jpeg_destroy_decompress(&cinfo);
234
                        fclose(infile);
235
                        return true;
236
                }
237
        }
238
        else
239
                m_imageInfoRecord.exifDataValid = false;
6716 fschmid 240
        m_imageInfoRecord.exifInfo.thumbnail = QImage();
20828 jghali 241
 
5937 jghali 242
        if (cinfo.density_unit == 0)
243
        {
244
                xres = 72;
245
                yres = 72;
246
                m_image.setDotsPerMeterX(2834);
247
                m_image.setDotsPerMeterY(2834);
248
        }
22535 jghali 249
        else if (cinfo.density_unit == 1)
5937 jghali 250
        {
251
                xres = cinfo.X_density;
252
                yres = cinfo.Y_density;
253
                m_image.setDotsPerMeterX( int(100. * cinfo.X_density / 2.54) );
254
                m_image.setDotsPerMeterY( int(100. * cinfo.Y_density / 2.54) );
255
        }
22535 jghali 256
        else if (cinfo.density_unit == 2)
5937 jghali 257
        {
258
                xres = cinfo.X_density * 2.54;
259
                yres = cinfo.Y_density * 2.54;
260
                m_image.setDotsPerMeterX( int(100. * cinfo.X_density) );
261
                m_image.setDotsPerMeterY( int(100. * cinfo.Y_density) );
262
        }
22535 jghali 263
        if (xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0)
5947 jghali 264
        {
265
                xres = yres = 72.0;
6650 fschmid 266
                m_image.setDotsPerMeterX(2834);
267
                m_image.setDotsPerMeterY(2834);
5947 jghali 268
                QFileInfo qfi(fn);
6650 fschmid 269
                m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName());
5977 jghali 270
                m_msgType = warningMsg;
5947 jghali 271
        }
5937 jghali 272
        m_imageInfoRecord.xres = qRound(xres);
273
        m_imageInfoRecord.yres = qRound(yres);
274
        if (cinfo.output_components == 4)
275
        {
19730 fschmid 276
        //      isCMYK = true;
11331 jghali 277
                m_imageInfoRecord.colorspace = ColorSpaceCMYK;
5937 jghali 278
        }
279
        else if (cinfo.output_components == 3)
11331 jghali 280
                m_imageInfoRecord.colorspace = ColorSpaceRGB;
5937 jghali 281
        else if (cinfo.output_components == 1)
11331 jghali 282
                m_imageInfoRecord.colorspace = ColorSpaceGray;
5937 jghali 283
        m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo);
284
 
21679 jghali 285
        unsigned int EmbedLen = 0;
286
        unsigned char* EmbedBuffer;
287
        if (read_jpeg_marker(ICC_MARKER, &cinfo, &EmbedBuffer, &EmbedLen))
288
        {
289
                bool profileIsValid = false;
290
                QByteArray profArray((const char*) EmbedBuffer, EmbedLen);
291
                ScColorProfile prof = ScCore->defaultEngine.openProfileFromMem(profArray);
292
                if (prof)
293
                {
294
                        // #14494: some tools out there produce broken JPEGs with inconsistent
295
                        // profile and image colorspaces. Check consistency, and if profile  
296
                        // and image data are not consistent, discard embedded profile.
297
                        eColorSpaceType colorSpace = prof.colorSpace();
298
                        if (colorSpace == ColorSpace_Rgb)
299
                                profileIsValid = (cinfo.output_components == 3);
300
                        if (colorSpace == ColorSpace_Cmyk)
301
                                profileIsValid = (cinfo.output_components == 4);
302
                        if (colorSpace == ColorSpace_Gray)
303
                                profileIsValid = (cinfo.output_components == 1);
304
                }
305
                if (profileIsValid)
306
                {
307
                        m_embeddedProfile = profArray;
308
                        m_imageInfoRecord.profileName = prof.productDescription();
23537 jghali 309
                        m_imageInfoRecord.embeddedProfileName = m_imageInfoRecord.profileName;
21679 jghali 310
                }
311
                m_imageInfoRecord.isEmbedded = profileIsValid;
312
                free(EmbedBuffer);
313
        }
314
        else
315
        {
316
                m_imageInfoRecord.isEmbedded = false;
23537 jghali 317
                m_imageInfoRecord.profileName.clear();
21679 jghali 318
        }
319
 
20828 jghali 320
        unsigned int PhotoshopLen = 0;
22605 craig 321
        unsigned char * PhotoshopBuffer = nullptr;
20828 jghali 322
        if (read_jpeg_marker(PHOTOSHOP_MARKER, &cinfo, &PhotoshopBuffer, &PhotoshopLen) )
5937 jghali 323
        {
20828 jghali 324
                bool savEx = m_imageInfoRecord.exifDataValid;
325
                QByteArray arrayPhot(PhotoshopLen, ' ');
326
                arrayPhot = QByteArray::fromRawData((const char*)PhotoshopBuffer,PhotoshopLen);
327
                QDataStream strPhot(&arrayPhot,QIODevice::ReadOnly);
328
                strPhot.setByteOrder( QDataStream::BigEndian );
329
                PSDHeader fakeHeader;
330
                fakeHeader.width = cinfo.output_width;
331
                fakeHeader.height = cinfo.output_height;
332
                if (cinfo.output_components == 4)
333
                        m_imageInfoRecord.colorspace = ColorSpaceCMYK;
334
                else if (cinfo.output_components == 3)
335
                        m_imageInfoRecord.colorspace = ColorSpaceRGB;
336
                else if (cinfo.output_components == 1)
337
                        m_imageInfoRecord.colorspace = ColorSpaceGray;
338
                m_imageInfoRecord.progressive = jpeg_has_multiple_scans(&cinfo);
24186 craig 339
                parseResourceData(strPhot, fakeHeader, PhotoshopLen);
20828 jghali 340
                // Photoshop resolution is more accurate than jpeg header resolution
341
                xres = m_imageInfoRecord.xres;
342
                yres = m_imageInfoRecord.yres;
343
                m_image.setDotsPerMeterX( int(100. * m_imageInfoRecord.xres / 2.54) );
344
                m_image.setDotsPerMeterY( int(100. * m_imageInfoRecord.yres / 2.54) );
22535 jghali 345
                if (xres <= 1.0 || yres <= 1.0 || xres > 3000.0 || yres > 3000.0)
5937 jghali 346
                {
20828 jghali 347
                        xres = yres = 72.0;
348
                        m_imageInfoRecord.xres = qRound(xres);
349
                        m_imageInfoRecord.yres = qRound(yres);
350
                        m_image.setDotsPerMeterX(2834);
351
                        m_image.setDotsPerMeterY(2834);
352
                        QFileInfo qfi(fn);
353
                        m_message = QObject::tr("%1 may be corrupted : missing or wrong resolution tags").arg(qfi.fileName());
354
                        m_msgType = warningMsg;
355
                }
356
                if (m_imageInfoRecord.exifDataValid && !m_imageInfoRecord.exifInfo.thumbnail.isNull() && thumbnail)
357
                {
358
                        m_image = QImage(m_imageInfoRecord.exifInfo.width, m_imageInfoRecord.exifInfo.height, QImage::Format_ARGB32 );
359
                        m_imageInfoRecord.exifInfo.width = cinfo.output_width;
360
                        m_imageInfoRecord.exifInfo.height = cinfo.output_height;
5937 jghali 361
                        if (cinfo.output_components == 4)
6650 fschmid 362
                        {
20828 jghali 363
                                QRgb *d;
364
                                QRgb *s;
365
                                unsigned char cc, cm, cy, ck;
22535 jghali 366
                                for (int yit=0; yit < m_image.height(); ++yit)
7040 fschmid 367
                                {
20828 jghali 368
                                        d = (QRgb*)(m_image.scanLine( yit ));
369
                                        s = (QRgb*)(m_imageInfoRecord.exifInfo.thumbnail.scanLine( yit ));
22535 jghali 370
                                        for (int xit=0; xit < m_image.width(); ++xit)
7040 fschmid 371
                                        {
20828 jghali 372
                                                cc = 255 - qRed(*s);
373
                                                cm = 255 - qGreen(*s);
374
                                                cy = 255 - qBlue(*s);
375
                                                ck = qMin(qMin(cc, cm), cy);
376
                                                *d = qRgba(cc-ck,cm-ck,cy-ck,ck);
377
                                                s++;
378
                                                d++;
7040 fschmid 379
                                        }
380
                                }
381
                        }
20828 jghali 382
                        else
383
                                m_image = m_imageInfoRecord.exifInfo.thumbnail.copy();
384
                        m_pixelFormat = Format_BGRA_8;
5937 jghali 385
                }
22605 craig 386
                m_imageInfoRecord.valid = (m_imageInfoRecord.PDSpathData.size())>0; // The only interest is vectormask
20828 jghali 387
                arrayPhot.clear();
388
                free(PhotoshopBuffer );
22605 craig 389
                PhotoshopBuffer = nullptr;
20828 jghali 390
                if (m_imageInfoRecord.exifDataValid && !m_imageInfoRecord.exifInfo.thumbnail.isNull() && thumbnail)
391
                {
392
                        jpeg_destroy_decompress(&cinfo);
393
                        fclose(infile);
394
                        return true;
395
                }
396
                m_imageInfoRecord.exifInfo.thumbnail = QImage();
397
                m_imageInfoRecord.exifDataValid = savEx;
398
                fromPS = true;
5937 jghali 399
        }
22535 jghali 400
        if (cinfo.output_components == 3 || cinfo.output_components == 4)
10561 fschmid 401
                m_image = QImage( cinfo.output_width, cinfo.output_height, QImage::Format_ARGB32 );
22535 jghali 402
        else if (cinfo.output_components == 1)
5937 jghali 403
        {
10561 fschmid 404
                m_image = QImage( cinfo.output_width, cinfo.output_height, QImage::Format_Indexed8 );
18194 fschmid 405
                m_image.setColorCount(256);
23537 jghali 406
                for (int i = 0; i < 256; i++)
407
                        m_image.setColor(i, qRgb(i, i, i));
5937 jghali 408
        }
409
        if (!m_image.isNull())
410
        {
10561 fschmid 411
                uchar* data = m_image.bits();
412
                int bpl = m_image.bytesPerLine();
5937 jghali 413
                while (cinfo.output_scanline < cinfo.output_height)
10561 fschmid 414
                {
415
                        uchar *d = data + cinfo.output_scanline * bpl;
416
                        (void) jpeg_read_scanlines(&cinfo, &d, 1);
417
                }
22535 jghali 418
                if (cinfo.output_components == 3)
5937 jghali 419
                {
7175 fschmid 420
                        uchar *in;
421
                        QRgb *out;
5937 jghali 422
                        for (uint j=0; j<cinfo.output_height; j++)
423
                        {
7175 fschmid 424
                                in = m_image.scanLine(j) + cinfo.output_width * 3;
425
                                out = (QRgb*) m_image.scanLine(j);
5937 jghali 426
                                for (uint i=cinfo.output_width; i--; )
427
                                {
428
                                        in -= 3;
429
                                        out[i] = qRgb(in[0], in[1], in[2]);
430
                                }
431
                        }
15128 jghali 432
                        m_pixelFormat = Format_BGRA_8;
5937 jghali 433
                }
22535 jghali 434
                if (cinfo.output_components == 4)
5937 jghali 435
                {
7041 fschmid 436
                        int method = 0;
21036 jghali 437
                        if ((cinfo.jpeg_color_space == JCS_YCCK) || (cinfo.out_color_space == JCS_CMYK))
7041 fschmid 438
                                method = 1;
439
                        else if (fromPS)
440
                        {
441
                                if ((cinfo.jpeg_color_space == JCS_CMYK) && (cinfo.saw_Adobe_marker) && (cinfo.Adobe_transform == 0))
442
                                        method = 2;
443
                        }
444
                        else if ((cinfo.jpeg_color_space == JCS_CMYK) && (cinfo.saw_Adobe_marker))
445
                                method = 1;
7175 fschmid 446
                        QRgb *ptr;
447
                        unsigned char c, m, y ,k;
448
                        unsigned char *p;
5937 jghali 449
                        for (int i = 0; i < m_image.height(); i++)
450
                        {
7175 fschmid 451
                                ptr = (QRgb*)  m_image.scanLine(i);
7041 fschmid 452
                                if (method == 1)
5937 jghali 453
                                {
454
                                        for (int j = 0; j <  m_image.width(); j++)
455
                                        {
7175 fschmid 456
                                                p = (unsigned char *) ptr;
5937 jghali 457
                                                c = p[0];
458
                                                m = p[1];
459
                                                y =  p[2];
460
                                                k =  p[3];
461
                                                *ptr = qRgba(255 - c, 255 - m, 255 - y, 255 - k);
462
                                                ptr++;
463
                                        }
464
                                }
7041 fschmid 465
                                else if (method == 2)
466
                                {
467
                                        for (int j = 0; j <  m_image.width(); j++)
468
                                        {
7175 fschmid 469
                                                p = (unsigned char *) ptr;
7041 fschmid 470
                                                c = p[0];
471
                                                m = p[1];
472
                                                y =  p[2];
473
                                                k =  p[3];
474
                                                *ptr = qRgba(255 - c, 255 - m, 255 - y, k);
475
                                                ptr++;
476
                                        }
477
                                }
5937 jghali 478
                                else
479
                                {
480
                                        for (int j = 0; j <  m_image.width(); j++)
481
                                        {
7175 fschmid 482
                                                p = (unsigned char *) ptr;
5937 jghali 483
                                                c = p[0];
484
                                                m = p[1];
485
                                                y =  p[2];
486
                                                k =  p[3];
487
                                                *ptr = qRgba(y, m, c, k);
488
                                                ptr++;
489
                                        }
490
                                }
491
                        }
15128 jghali 492
                        m_pixelFormat = Format_YMCK_8;
19730 fschmid 493
                //      isCMYK = true;
5937 jghali 494
                }
19730 fschmid 495
                //else
496
                //      isCMYK = false;
22535 jghali 497
                if (cinfo.output_components == 1)
5937 jghali 498
                {
10561 fschmid 499
                        QImage tmpImg = m_image.convertToFormat(QImage::Format_ARGB32);
500
                        m_image = QImage( cinfo.output_width, cinfo.output_height, QImage::Format_ARGB32 );
7175 fschmid 501
                        QRgb *s;
502
                        QRgb *d;
23537 jghali 503
                        for (int yi = 0; yi < tmpImg.height(); ++yi)
5937 jghali 504
                        {
7175 fschmid 505
                                s = (QRgb*)(tmpImg.scanLine( yi ));
506
                                d = (QRgb*)(m_image.scanLine( yi ));
23537 jghali 507
                                for (int xi = 0; xi < tmpImg.width(); ++xi)
5937 jghali 508
                                {
509
                                        (*d) = (*s);
510
                                        s++;
511
                                        d++;
512
                                }
513
                        }
24467 jghali 514
                        m_pixelFormat = Format_GRAY_8;
5937 jghali 515
                }
516
        }
517
        (void) jpeg_finish_decompress(&cinfo);
518
        fclose (infile);
519
        jpeg_destroy_decompress (&cinfo);
14866 fschmid 520
        if ((exi) && (ExifInf.exifDataValid))
521
        {
522
                int ori = ExifInf.getOrientation();
523
                int oxres, oyres;
524
                if (ori != 1)
525
                {
526
                        QTransform M;
24735 jghali 527
                        QTransform flip(-1, 0, 0, 1, 0, 0);
14866 fschmid 528
                        switch ( ori )
529
                        {  // notice intentional fallthroughs
530
                                case 2:
531
                                        M = flip;
532
                                        break;
533
                                case 4:
534
                                        M = flip;
23749 jghali 535
                                        /* fall through */
14866 fschmid 536
                                case 3:
537
                                        M.rotate (180);
538
                                        break;
539
                                case 5:
540
                                        M = flip;
23749 jghali 541
                                        /* fall through */
14866 fschmid 542
                                case 6:
543
                                        M.rotate(90);
544
                                        oxres = m_imageInfoRecord.xres;
545
                                        oyres = m_imageInfoRecord.yres;
546
                                        m_imageInfoRecord.xres = oyres;
547
                                        m_imageInfoRecord.yres = oxres;
548
                                        break;
549
                                case 7:
550
                                        M = flip;
23749 jghali 551
                                        /* fall through */
14866 fschmid 552
                                case 8:
553
                                        M.rotate(270);
554
                                        oxres = m_imageInfoRecord.xres;
555
                                        oyres = m_imageInfoRecord.yres;
556
                                        m_imageInfoRecord.xres = oyres;
557
                                        m_imageInfoRecord.yres = oxres;
558
                                        break;
23749 jghali 559
                                default:
560
                                        break; // should never happen
14866 fschmid 561
                        }
562
                        m_image = m_image.transformed(M);
563
                }
564
        }
5937 jghali 565
        m_imageInfoRecord.layerInfo.clear();
566
        m_imageInfoRecord.BBoxX = 0;
567
        m_imageInfoRecord.BBoxH = m_image.height();
568
        return (!m_image.isNull());
569
}
570
 
571
bool ScImgDataLoader_JPEG::marker_is_icc (jpeg_saved_marker_ptr marker)
572
{
573
        return
574
            marker->marker == ICC_MARKER &&
575
            marker->data_length >= ICC_OVERHEAD_LEN &&
576
            /* verify the identifying string */
577
            GETJOCTET(marker->data[0]) == 0x49 &&
578
            GETJOCTET(marker->data[1]) == 0x43 &&
579
            GETJOCTET(marker->data[2]) == 0x43 &&
580
            GETJOCTET(marker->data[3]) == 0x5F &&
581
            GETJOCTET(marker->data[4]) == 0x50 &&
582
            GETJOCTET(marker->data[5]) == 0x52 &&
583
            GETJOCTET(marker->data[6]) == 0x4F &&
584
            GETJOCTET(marker->data[7]) == 0x46 &&
585
            GETJOCTET(marker->data[8]) == 0x49 &&
586
            GETJOCTET(marker->data[9]) == 0x4C &&
587
            GETJOCTET(marker->data[10]) == 0x45 &&
588
            GETJOCTET(marker->data[11]) == 0x0;
589
}
590
 
591
bool ScImgDataLoader_JPEG::marker_is_photoshop (jpeg_saved_marker_ptr marker)
592
{
593
        return
594
            marker->marker == PHOTOSHOP_MARKER &&
595
            marker->data_length >= ICC_OVERHEAD_LEN &&
596
            /* verify the identifying string */
597
            GETJOCTET(marker->data[0]) == 0x50 &&
598
            GETJOCTET(marker->data[1]) == 0x68 &&
599
            GETJOCTET(marker->data[2]) == 0x6F &&
600
            GETJOCTET(marker->data[3]) == 0x74 &&
601
            GETJOCTET(marker->data[4]) == 0x6F &&
602
            GETJOCTET(marker->data[5]) == 0x73 &&
603
            GETJOCTET(marker->data[6]) == 0x68 &&
604
            GETJOCTET(marker->data[7]) == 0x6F &&
605
            GETJOCTET(marker->data[8]) == 0x70 &&
606
            GETJOCTET(marker->data[9]) == 0x20 &&
607
            GETJOCTET(marker->data[10]) == 0x33 &&
608
            GETJOCTET(marker->data[11]) == 0x2E &&
609
            GETJOCTET(marker->data[12]) == 0x30 &&
610
            GETJOCTET(marker->data[13]) == 0x0;
611
}
612
 
613
/* Small modification of original read_icc_profile method from jpegicc of lcms project
614
 * to enable read of Photoshop marker
615
 */
616
bool ScImgDataLoader_JPEG::read_jpeg_marker (UINT8 requestmarker, j_decompress_ptr cinfo, JOCTET **icc_data_ptr, unsigned int *icc_data_len)
617
{
618
        jpeg_saved_marker_ptr marker;
619
        int num_markers = 0;
620
        int seq_no;
621
        JOCTET *icc_data;
622
        unsigned int total_length;
623
#define MAX_SEQ_NO  255         /* sufficient since marker numbers are bytes */
624
        char marker_present[MAX_SEQ_NO+1];        /* 1 if marker found */
625
        unsigned int data_length[MAX_SEQ_NO+1]; /* size of profile data in marker */
626
        unsigned int data_offset[MAX_SEQ_NO+1]; /* offset for data in marker */
627
 
22518 craig 628
        *icc_data_ptr = nullptr;                /* avoid confusion if false return */
5937 jghali 629
        *icc_data_len = 0;
630
 
631
        /* This first pass over the saved markers discovers whether there are
632
         * any ICC markers and verifies the consistency of the marker numbering.
633
         */
634
 
635
        for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++)
636
                marker_present[seq_no] = 0;
637
        seq_no = 0;
22518 craig 638
        for (marker = cinfo->marker_list; marker != nullptr; marker = marker->next)
5937 jghali 639
        {
640
                if (requestmarker == ICC_MARKER && marker_is_icc(marker))
641
                {
642
                        if (num_markers == 0)
643
                                num_markers = GETJOCTET(marker->data[13]);
644
                        else if (num_markers != GETJOCTET(marker->data[13]))
645
                                return false;           /* inconsistent num_markers fields */
646
                        seq_no = GETJOCTET(marker->data[12]);
647
                        if (seq_no <= 0 || seq_no > num_markers)
648
                                return false;           /* bogus sequence number */
649
                        if (marker_present[seq_no])
650
                                return false;           /* duplicate sequence numbers */
651
                        marker_present[seq_no] = 1;
652
                        data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
653
                }
22535 jghali 654
                else if (requestmarker == PHOTOSHOP_MARKER && marker_is_photoshop(marker))
5937 jghali 655
                {
656
                        num_markers = ++seq_no;
657
                        marker_present[seq_no] = 1;
658
                        data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
659
                }
660
        }
661
 
662
        if (num_markers == 0)
663
                return false;
664
 
665
        /* Check for missing markers, count total space needed,
666
         * compute offset of each marker's part of the data.
667
         */
668
 
669
        total_length = 0;
670
        for (seq_no = 1; seq_no <= num_markers; seq_no++)
671
        {
672
                if (marker_present[seq_no] == 0)
673
                        return false;           /* missing sequence number */
674
                data_offset[seq_no] = total_length;
675
                total_length += data_length[seq_no];
676
        }
677
 
678
        if (total_length <= 0)
679
                return false;           /* found only empty markers? */
680
 
681
        /* Allocate space for assembled data */
682
        icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET));
22518 craig 683
        if (icc_data == nullptr)
5937 jghali 684
                return false;           /* oops, out of memory */
685
        seq_no=0;
686
        /* and fill it in */
22518 craig 687
        for (marker = cinfo->marker_list; marker != nullptr; marker = marker->next)
5937 jghali 688
        {
689
                if ( (requestmarker == ICC_MARKER && marker_is_icc(marker)) ||
690
                        (requestmarker == PHOTOSHOP_MARKER && marker_is_photoshop(marker)) || (requestmarker == 0xE1))
691
                {
692
                        JOCTET FAR *src_ptr;
693
                        JOCTET *dst_ptr;
694
                        unsigned int length;
22535 jghali 695
                        if (requestmarker == ICC_MARKER)
5937 jghali 696
                                seq_no = GETJOCTET(marker->data[12]);
22535 jghali 697
                        else if (requestmarker == PHOTOSHOP_MARKER)
5937 jghali 698
                                seq_no++;
699
                        dst_ptr = icc_data + data_offset[seq_no];
700
                        src_ptr = marker->data + ICC_OVERHEAD_LEN;
701
                        length = data_length[seq_no];
702
                        while (length--)
703
                        {
704
                                *dst_ptr++ = *src_ptr++;
705
                        }
706
                }
707
        }
708
 
709
        *icc_data_ptr = icc_data;
710
        *icc_data_len = total_length;
711
 
712
        return true;
6650 fschmid 713
}