134{
135 struct jpeg_decompress_struct cinfo;
136 struct jpeg_error_mgr jerr;
137
138 cinfo.err = jpeg_std_error(&jerr);
139 jerr.error_exit = jpegErrorExit;
140
141 try {
142 jpeg_create_decompress(&cinfo);
143
145
146 jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF);
147
148 for (int m = 0; m < 16; m++)
149 jpeg_save_markers(&cinfo, JPEG_APP0 + m, 0xFFFF);
150
151
152
153
154 jpeg_read_header(&cinfo, (boolean)true);
155
156
157 jpeg_start_decompress(&cinfo);
158
159
160 QString modelId = getColorSpaceModelForColorType(cinfo.out_color_space);
161 if (modelId.isEmpty()) {
162 dbgFile <<
"unsupported colorspace :" << cinfo.out_color_space;
163 jpeg_destroy_decompress(&cinfo);
165 }
166
167 uchar* profile_data = 0;
168 uint profile_len = 0;
170 QByteArray profile_rawdata;
172 profile_rawdata.resize(profile_len);
173 memcpy(profile_rawdata.data(), profile_data, profile_len);
174 cmsHPROFILE hProfile = cmsOpenProfileFromMem(profile_data, profile_len);
175
176 if (hProfile != (cmsHPROFILE) 0) {
178 Q_CHECK_PTR(profile);
179 dbgFile <<
"profile name:" << profile->
name() <<
" product information:" << profile->
info();
181 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";
182 }
183 }
184
185 free(profile_data);
186 }
187
188 const QString colorSpaceId =
190
191
193 warnFile <<
"The profile " << profile->
name() <<
" is not compatible with the color space model " << modelId;
194 profile = 0;
195 }
196
197
200 dbgFile <<
"image has embedded profile:" << profile ->
name() <<
"";
202 } else
204
205 if (cs == 0) {
206 dbgFile <<
"unknown colorspace";
207 jpeg_destroy_decompress(&cinfo);
209 }
210
211
212
216 }
217
218
219 if (transform && !transform->
isValid()) {
220 delete transform;
221 transform = 0;
222 }
223
224
226 m_d->image =
new KisImage(
m_d->doc->createUndoStore(), cinfo.image_width, cinfo.image_height, cs,
"built image");
227 Q_CHECK_PTR(
m_d->image);
228 }
229
230
231 double xres = 72, yres = 72;
232 if (cinfo.density_unit == 1) {
233 xres = cinfo.X_density;
234 yres = cinfo.Y_density;
235 } else if (cinfo.density_unit == 2) {
236 xres = cinfo.X_density * 2.54;
237 yres = cinfo.Y_density * 2.54;
238 }
239 if (xres < 72) {
240 xres = 72;
241 }
242 if (yres < 72) {
243 yres = 72;
244 }
246
247
249
250
251 JSAMPROW row_pointer = new JSAMPLE[cinfo.image_width*cinfo.num_components];
252
253 for (; cinfo.output_scanline < cinfo.image_height;) {
255 jpeg_read_scanlines(&cinfo, &row_pointer, 1);
256 quint8 *
src = row_pointer;
257 switch (cinfo.out_color_space) {
258 case JCS_GRAYSCALE:
259 do {
260 quint8 *
d = it->rawData();
262 if (transform) transform->
transform(d, d, 1);
264
265 } while (it->nextPixel());
266 break;
267 case JCS_RGB:
268 do {
269 quint8 *
d = it->rawData();
273 if (transform) transform->
transform(d, d, 1);
275
276 } while (it->nextPixel());
277 break;
278 case JCS_CMYK:
279 do {
280 quint8 *
d = it->rawData();
285 if (transform) transform->
transform(d, d, 1);
287
288 } while (it->nextPixel());
289 break;
290 default:
292 }
293 }
294
296
297
298
299 dbgFile <<
"Looking for exif information";
300
301 for (jpeg_saved_marker_ptr marker = cinfo.marker_list; marker != 0; marker = marker->next) {
302 dbgFile <<
"Marker is" << marker->marker;
303 if (marker->marker != (JOCTET)(JPEG_APP0 + 1)
304 || marker->data_length < 14) {
305 continue;
306 }
307
308 if (GETJOCTET(marker->data[0]) != (JOCTET) 0x45 ||
309 GETJOCTET(marker->data[1]) != (JOCTET) 0x78 ||
310 GETJOCTET(marker->data[2]) != (JOCTET) 0x69 ||
311 GETJOCTET(marker->data[3]) != (JOCTET) 0x66 ||
312 GETJOCTET(marker->data[4]) != (JOCTET) 0x00 ||
313 GETJOCTET(marker->data[5]) != (JOCTET) 0x00)
314 continue;
315
316 dbgFile <<
"Found exif information of length :" << marker->data_length;
318 Q_ASSERT(exifIO);
319 QByteArray byteArray((const char*)marker->data + 6, marker->data_length - 6);
320 QBuffer buf(&byteArray);
322
327 case 2:
329 break;
330 case 3:
332 break;
333 case 4:
335 break;
336 case 5:
339 break;
340 case 6:
342 break;
343 case 7:
346 break;
347 case 8:
349 break;
350 default:
351 break;
352 }
353 }
355 }
356 break;
357 }
358
359 dbgFile <<
"Looking for IPTC information";
360
361 for (jpeg_saved_marker_ptr marker = cinfo.marker_list; marker != 0; marker = marker->next) {
362 dbgFile <<
"Marker is" << marker->marker;
363 if (marker->marker != (JOCTET)(JPEG_APP0 + 13) || marker->data_length < 14) {
364 continue;
365 }
367 for (int i = 0; i < 14; i++) {
369 }
370 dbgFile <<
"No photoshop marker";
371 continue;
372 }
373
374 dbgFile <<
"Found Photoshop information of length :" << marker->data_length;
376 Q_ASSERT(iptcIO);
377 const Exiv2::byte *record = 0;
378 uint32_t sizeIptc = 0;
379 uint32_t sizeHdr = 0;
380
381 if (!Exiv2::Photoshop::locateIptcIrb((Exiv2::byte*)(marker->data + 14),
382#if EXIV2_TEST_VERSION(0,28,0)
383 marker->data_length - 14, &record, sizeHdr, sizeIptc)) {
384#else
385 marker->data_length - 14, &record, &sizeHdr, &sizeIptc)) {
386#endif
387 if (sizeIptc) {
388
389 QByteArray byteArray((const char*)(record + sizeHdr), sizeIptc);
390 QBuffer buf(&byteArray);
392 } else {
393 dbgFile <<
"IPTC Not found in Photoshop marker";
394 }
395 }
396 break;
397 }
398
399 dbgFile <<
"Looking for XMP information";
400
401 for (jpeg_saved_marker_ptr marker = cinfo.marker_list; marker != 0; marker = marker->next) {
402 dbgFile <<
"Marker is" << marker->marker;
403 if (marker->marker != (JOCTET)(JPEG_APP0 + 1) || marker->data_length < 31) {
404 continue;
405 }
406 if (memcmp(marker->data,
xmpMarker, 29) != 0) {
408 continue;
409 }
410 dbgFile <<
"Found XMP Marker of length " << marker->data_length;
411 QByteArray byteArray((const char*)marker->data + 29, marker->data_length - 29);
413 Q_ASSERT(xmpIO);
415 break;
416 }
417
418
420
421
425 if (xres != 0 && yres != 0) {
427 }
428 }
429
430
431 jpeg_finish_decompress(&cinfo);
432 jpeg_destroy_decompress(&cinfo);
433 delete [] row_pointer;
435 }
436 catch( std::runtime_error &) {
437 jpeg_destroy_decompress(&cinfo);
439 }
440}
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
constexpr qreal POINT_TO_INCH(qreal px)
KisGroupLayerSP rootLayer() const
void rotateImage(double radians)
start asynchronous operation on rotating the image
const KisMetaData::Value & value() const
KisHLineIteratorSP createHLineIteratorNG(qint32 x, qint32 y, qint32 w)
virtual KoColorConversionTransformation * createColorConverter(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) const
boolean read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr, unsigned int *icc_data_len)
const char photoshopMarker[]
KisSharedPtr< KisPaintLayer > KisPaintLayerSP
KisSharedPtr< KisNode > KisNodeSP
@ FormatColorSpaceUnsupported
const char * name(StandardAction id)
void setSource(j_decompress_ptr cinfo, QIODevice *inputDevice)
KisMetaData::Store * metaData()
virtual bool isSuitableForOutput() const =0
QString colorSpaceId(const QString &colorModelId, const QString &colorDepthId) const
const KoColorProfile * createColorProfile(const QString &colorModelId, const QString &colorDepthId, const QByteArray &rawData)