~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to krita/plugins/formats/jpeg/kis_jpeg_converter.cc

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-21 15:36:35 UTC
  • mfrom: (1.4.1 upstream) (60.2.11 maverick)
  • Revision ID: james.westby@ubuntu.com-20100921153635-6tejqkiro2u21ydi
Tags: 1:2.2.2-0ubuntu3
Add kubuntu_03_fix-crash-on-closing-sqlite-connection-2.2.2.diff and
kubuntu_04_support-large-memo-values-for-msaccess-2.2.2.diff as
recommended by upstream http://kexi-
project.org/wiki/wikiview/index.php@Kexi2.2_Patches.html#sqlite_stab
ility

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
 
27
27
#include <stdio.h>
28
28
#include <stdint.h>
 
29
#include <lcms.h>
29
30
 
30
31
extern "C" {
31
32
#include <iccjpeg.h>
47
48
#include <KoDocumentInfo.h>
48
49
#include <KoColorSpace.h>
49
50
#include <KoColorSpaceRegistry.h>
 
51
#include <KoColorProfile.h>
50
52
 
51
53
#include <kis_doc2.h>
52
54
#include <kis_image.h>
53
55
#include <kis_iterators_pixel.h>
54
56
#include <kis_paint_layer.h>
 
57
#include <kis_transaction.h>
55
58
#include <kis_group_layer.h>
56
59
#include <kis_meta_data_entry.h>
57
60
#include <kis_meta_data_value.h>
62
65
#include <kis_jpeg_source.h>
63
66
#include <kis_jpeg_destination.h>
64
67
 
65
 
#include <colorprofiles/KoIccColorProfile.h>
 
68
#include <KoColorProfile.h>
 
69
#include <KoColorModelStandardIds.h>
66
70
 
67
71
#define ICC_MARKER  (JPEG_APP0 + 2) /* JPEG marker code for ICC */
68
72
#define ICC_OVERHEAD_LEN  14    /* size of non-profile data in APP2 */
93
97
    return JCS_UNKNOWN;
94
98
}
95
99
 
96
 
QString getColorSpaceForColorType(J_COLOR_SPACE color_type)
 
100
QString getColorSpaceModelForColorType(J_COLOR_SPACE color_type)
97
101
{
98
102
    dbgFile << "color_type =" << color_type;
99
103
    if (color_type == JCS_GRAYSCALE) {
100
 
        return "GRAYA";
 
104
        return GrayAColorModelID.id();
101
105
    } else if (color_type == JCS_RGB) {
102
 
        return "RGBA";
 
106
        return RGBAColorModelID.id();
103
107
    } else if (color_type == JCS_CMYK) {
104
 
        return "CMYK";
 
108
        return CMYKAColorModelID.id();
105
109
    }
106
110
    return "";
107
111
}
131
135
    Q_ASSERT(uri.isLocalFile());
132
136
 
133
137
    // open the file
134
 
    QFile file(QFile::encodeName(uri.toLocalFile()));
 
138
    QFile file(uri.toLocalFile());
135
139
    if (!file.exists()) {
136
140
        return (KisImageBuilder_RESULT_NOT_EXIST);
137
141
    }
138
142
    if (!file.open(QIODevice::ReadOnly)) {
139
143
        return (KisImageBuilder_RESULT_BAD_FETCH);
140
144
    }
141
 
    
 
145
 
142
146
    KisJPEGSource::setSource(&cinfo, &file);
143
147
 
144
148
    jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF);
155
159
    jpeg_start_decompress(&cinfo);
156
160
 
157
161
    // Get the colorspace
158
 
    QString csName = getColorSpaceForColorType(cinfo.out_color_space);
159
 
    if (csName.isEmpty()) {
 
162
    QString modelId = getColorSpaceModelForColorType(cinfo.out_color_space);
 
163
    if (modelId.isEmpty()) {
160
164
        dbgFile << "unsupported colorspace :" << cinfo.out_color_space;
161
165
        jpeg_destroy_decompress(&cinfo);
162
166
        return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE;
163
167
    }
164
168
    uchar* profile_data;
165
169
    uint profile_len;
166
 
    KoColorProfile* profile = 0;
 
170
    const KoColorProfile* profile = 0;
167
171
    QByteArray profile_rawdata;
168
172
    if (read_icc_profile(&cinfo, &profile_data, &profile_len)) {
169
173
        profile_rawdata.resize(profile_len);
171
175
        cmsHPROFILE hProfile = cmsOpenProfileFromMem(profile_data, (DWORD)profile_len);
172
176
 
173
177
        if (hProfile != (cmsHPROFILE) NULL) {
174
 
            profile = new KoIccColorProfile(profile_rawdata);
 
178
            profile = KoColorSpaceRegistry::instance()->createColorProfile(modelId, Integer8BitsColorDepthID.id(), profile_rawdata);
175
179
            Q_CHECK_PTR(profile);
176
 
//             dbgFile <<"profile name:" << profile->productName() <<" profile description:" << profile->productDescription() <<" information sur le produit:" << profile->productInfo();
 
180
            dbgFile <<"profile name:" << profile->name() <<" product information:" << profile->info();
177
181
            if (!profile->isSuitableForOutput()) {
178
182
                dbgFile << "the profile is not suitable for output and therefore cannot be used in krita, we need to convert the image to a standard profile"; // TODO: in ko2 popup a selection menu to inform the user
179
183
            }
180
184
        }
181
185
    }
182
186
 
 
187
    // Check that the profile is used by the color space
 
188
    if (profile && !KoColorSpaceRegistry::instance()->colorSpaceFactory(
 
189
        KoColorSpaceRegistry::instance()->colorSpaceId(
 
190
      modelId, Integer8BitsColorDepthID.id()))->profileIsCompatible(profile)) {
 
191
        warnFile << "The profile " << profile->name() << " is not compatible with the color space model " << modelId;
 
192
        delete profile;
 
193
        profile = 0;
 
194
    }
 
195
 
183
196
    // Retrieve a pointer to the colorspace
184
197
    const KoColorSpace* cs;
185
198
    if (profile && profile->isSuitableForOutput()) {
186
199
        dbgFile << "image has embedded profile:" << profile -> name() << "";
187
 
        cs = KoColorSpaceRegistry::instance()->colorSpace(csName, profile);
 
200
        cs = KoColorSpaceRegistry::instance()->colorSpace(modelId, Integer8BitsColorDepthID.id(), profile);
188
201
    } else
189
 
        cs = KoColorSpaceRegistry::instance()->colorSpace(KoID(csName, ""), "");
 
202
        cs = KoColorSpaceRegistry::instance()->colorSpace(modelId, Integer8BitsColorDepthID.id(), "");
190
203
 
191
204
    if (cs == 0) {
192
205
        dbgFile << "unknown colorspace";
198
211
 
199
212
    KoColorTransformation* transform = 0;
200
213
    if (profile && !profile->isSuitableForOutput()) {
201
 
        transform = KoColorSpaceRegistry::instance()->colorSpace(csName, profile)->createColorConverter(cs);
 
214
        transform = KoColorSpaceRegistry::instance()->colorSpace(modelId, Integer8BitsColorDepthID.id(), profile)->createColorConverter(cs);
202
215
    }
203
216
 
204
217
    // Creating the KisImageWSP
205
 
    if (! m_img) {
206
 
        m_img = new KisImage(m_doc->undoAdapter(),  cinfo.image_width,  cinfo.image_height, cs, "built image");
207
 
        Q_CHECK_PTR(m_img);
 
218
    if (! m_image) {
 
219
        m_image = new KisImage(m_doc->undoAdapter(),  cinfo.image_width,  cinfo.image_height, cs, "built image");
 
220
        Q_CHECK_PTR(m_image);
 
221
        m_image->lock();
208
222
        if (profile && !profile->isSuitableForOutput()) {
209
 
            m_img -> addAnnotation(KisAnnotationSP(new KisAnnotation(profile->name(), "", profile_rawdata)));
 
223
            m_image -> addAnnotation(KisAnnotationSP(new KisAnnotation(profile->name(), "", profile_rawdata)));
210
224
        }
211
225
    }
212
226
 
213
227
    // Set resolution
214
 
    double xres, yres;
215
 
    if (cinfo.density_unit == 0)
216
 
    {
217
 
        xres = 72;
218
 
        yres = 72;
219
 
    }
220
 
    else if ( cinfo.density_unit == 1 )
221
 
    {
 
228
    double xres = 72, yres = 72;
 
229
    if (cinfo.density_unit == 1) {
222
230
        xres = cinfo.X_density;
223
231
        yres = cinfo.Y_density;
224
 
    }
225
 
    else if ( cinfo.density_unit == 2 )
226
 
    {
 
232
    } else if (cinfo.density_unit == 2) {
227
233
        xres = cinfo.X_density * 2.54;
228
234
        yres = cinfo.Y_density * 2.54;
229
235
    }
230
 
    m_img->setResolution(xres / 72, yres / 72);
231
 
    
 
236
    m_image->setResolution(POINT_TO_INCH(xres), POINT_TO_INCH(yres));   // It is the "invert" macro because we convert from pointer-per-inchs to points
 
237
 
232
238
    // Create layer
233
 
    KisPaintLayerSP layer = KisPaintLayerSP(new KisPaintLayer(m_img.data(), m_img -> nextLayerName(), quint8_MAX));
 
239
    KisPaintLayerSP layer = KisPaintLayerSP(new KisPaintLayer(m_image.data(), m_image -> nextLayerName(), quint8_MAX));
 
240
    KisTransaction("", layer->paintDevice());
234
241
 
235
242
    // Read data
236
243
    JSAMPROW row_pointer = new JSAMPLE[cinfo.image_width*cinfo.num_components];
277
284
        }
278
285
    }
279
286
 
280
 
    m_img->addNode(KisNodeSP(layer.data()), m_img->rootLayer().data());
 
287
    m_image->addNode(KisNodeSP(layer.data()), m_image->rootLayer().data());
281
288
    layer->setDirty();
282
289
 
283
290
    // Read exif information
412
419
    if (uri.isEmpty())
413
420
        return KisImageBuilder_RESULT_NO_URI;
414
421
 
415
 
    if (!KIO::NetAccess::exists(uri, false, qApp -> mainWidget())) {
 
422
    if (!KIO::NetAccess::exists(uri, KIO::NetAccess::SourceSide, QApplication::activeWindow())) {
416
423
        return KisImageBuilder_RESULT_NOT_EXIST;
417
424
    }
418
425
 
420
427
    KisImageBuilder_Result result = KisImageBuilder_RESULT_FAILURE;
421
428
    QString tmpFile;
422
429
 
423
 
    if (KIO::NetAccess::download(uri, tmpFile, qApp -> mainWidget())) {
 
430
    if (KIO::NetAccess::download(uri, tmpFile, QApplication::activeWindow())) {
424
431
        KUrl uriTF;
425
432
        uriTF.setPath(tmpFile);
426
433
        result = decode(uriTF);
433
440
 
434
441
KisImageWSP KisJPEGConverter::image()
435
442
{
436
 
    return m_img;
 
443
    return m_image;
437
444
}
438
445
 
439
446
 
442
449
    if (!layer)
443
450
        return KisImageBuilder_RESULT_INVALID_ARG;
444
451
 
445
 
    KisImageWSP img = KisImageWSP(layer -> image());
446
 
    if (!img)
 
452
    KisImageWSP image = KisImageWSP(layer -> image());
 
453
    if (!image)
447
454
        return KisImageBuilder_RESULT_EMPTY;
448
455
 
449
456
    if (uri.isEmpty())
458
465
        return (KisImageBuilder_RESULT_FAILURE);
459
466
    }
460
467
 
461
 
    uint height = img->height();
462
 
    uint width = img->width();
 
468
    uint height = image->height();
 
469
    uint width = image->width();
463
470
    // Initialize structure
464
471
    struct jpeg_compress_struct cinfo;
465
472
    jpeg_create_compress(&cinfo);
469
476
    // Initialize output stream
470
477
    KisJPEGDestination::setDestination(&cinfo, &file);
471
478
 
472
 
    const KoColorSpace * cs = img->colorSpace();
 
479
    const KoColorSpace * cs = image->colorSpace();
473
480
 
474
481
    cinfo.image_width = width;  // image width and height, in pixels
475
482
    cinfo.image_height = height;
538
545
    }
539
546
 
540
547
    // Save resolution
541
 
    cinfo.X_density = img->xRes() * 72;
542
 
    cinfo.Y_density = img->yRes() * 72;
 
548
    cinfo.X_density = INCH_TO_POINT(image->xRes()); // It is the "invert" macro because we convert from pointer-per-inchs to points
 
549
    cinfo.Y_density = INCH_TO_POINT(image->yRes()); // It is the "invert" macro because we convert from pointer-per-inchs to points
543
550
    cinfo.density_unit = 1;
544
551
    cinfo.write_JFIF_header = 1;
545
552