OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006 Apple Computer, Inc. | 2 * Copyright (C) 2006 Apple Computer, Inc. |
3 * | 3 * |
4 * Portions are Copyright (C) 2001-6 mozilla.org | 4 * Portions are Copyright (C) 2001-6 mozilla.org |
5 * | 5 * |
6 * Other contributors: | 6 * Other contributors: |
7 * Stuart Parmenter <stuart@mozilla.com> | 7 * Stuart Parmenter <stuart@mozilla.com> |
8 * | 8 * |
9 * This library is free software; you can redistribute it and/or | 9 * This library is free software; you can redistribute it and/or |
10 * modify it under the terms of the GNU Lesser General Public | 10 * modify it under the terms of the GNU Lesser General Public |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 unsigned count = readUint32(ifd + 4, isBigEndian); | 198 unsigned count = readUint32(ifd + 4, isBigEndian); |
199 if (tag == orientationTag && type == shortType && count == 1) | 199 if (tag == orientationTag && type == shortType && count == 1) |
200 return ImageOrientation::fromEXIFValue(readUint16(ifd + 8, isBig
Endian)); | 200 return ImageOrientation::fromEXIFValue(readUint16(ifd + 8, isBig
Endian)); |
201 } | 201 } |
202 } | 202 } |
203 | 203 |
204 return ImageOrientation(); | 204 return ImageOrientation(); |
205 } | 205 } |
206 | 206 |
207 #if USE(QCMSLIB) | 207 #if USE(QCMSLIB) |
208 static void readColorProfile(jpeg_decompress_struct* info, ColorProfile& colorPr
ofile) | 208 static void readColorProfile(jpeg_decompress_struct* info, ColorProfile& colorPr
ofile, ColorProfileStatus& status) |
209 { | 209 { |
210 #if USE(ICCJPEG) | 210 #if USE(ICCJPEG) |
211 JOCTET* profile; | 211 JOCTET* profile; |
212 unsigned profileLength; | 212 unsigned profileLength; |
213 | 213 |
214 if (!read_icc_profile(info, &profile, &profileLength)) | 214 if (!read_icc_profile(info, &profile, &profileLength)) { |
| 215 status = ColorProfileNone; |
215 return; | 216 return; |
| 217 } |
216 | 218 |
217 // Only accept RGB color profiles from input class devices. | 219 // Only accept RGB color profiles from input class devices. |
218 bool ignoreProfile = false; | 220 ASSERT(status == ColorProfileSuccess); |
219 char* profileData = reinterpret_cast_ptr<char*>(profile); | 221 char* profileData = reinterpret_cast_ptr<char*>(profile); |
220 if (profileLength < ImageDecoder::iccColorProfileHeaderLength) | 222 if (profileLength < ImageDecoder::iccColorProfileHeaderLength) |
221 ignoreProfile = true; | 223 status = ColorProfileIsCorrupted; |
| 224 else if (ImageDecoder::isICCv4(profileData, profileLength)) |
| 225 status = ColorProfileIsV4; |
222 else if (!ImageDecoder::rgbColorProfile(profileData, profileLength)) | 226 else if (!ImageDecoder::rgbColorProfile(profileData, profileLength)) |
223 ignoreProfile = true; | 227 status = ColorProfileIsNotRGB; |
224 else if (!ImageDecoder::inputDeviceColorProfile(profileData, profileLength)) | 228 else if (!ImageDecoder::inputDeviceColorProfile(profileData, profileLength)) |
225 ignoreProfile = true; | 229 status = ColorProfileIsNotAnInputProfile; |
226 | 230 |
227 ASSERT(colorProfile.isEmpty()); | 231 ASSERT(colorProfile.isEmpty()); |
228 if (!ignoreProfile) | 232 if (status == ColorProfileSuccess) |
229 colorProfile.append(profileData, profileLength); | 233 colorProfile.append(profileData, profileLength); |
230 free(profile); | 234 free(profile); |
231 #endif | 235 #endif |
232 } | 236 } |
233 #endif | 237 #endif |
234 | 238 |
235 static IntSize computeYUVSize(const jpeg_decompress_struct* info, int component,
ImageDecoder::SizeType sizeType) | 239 static IntSize computeYUVSize(const jpeg_decompress_struct* info, int component,
ImageDecoder::SizeType sizeType) |
236 { | 240 { |
237 if (sizeType == ImageDecoder::SizeForMemoryAllocation) { | 241 if (sizeType == ImageDecoder::SizeForMemoryAllocation) { |
238 return IntSize(info->cur_comp_info[component]->width_in_blocks * DCTSIZE
, info->cur_comp_info[component]->height_in_blocks * DCTSIZE); | 242 return IntSize(info->cur_comp_info[component]->width_in_blocks * DCTSIZE
, info->cur_comp_info[component]->height_in_blocks * DCTSIZE); |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 overrideColorSpace = JCS_UNKNOWN; | 473 overrideColorSpace = JCS_UNKNOWN; |
470 jpeg_calc_output_dimensions(&m_info); | 474 jpeg_calc_output_dimensions(&m_info); |
471 m_decoder->setDecodedSize(m_info.output_width, m_info.output_height)
; | 475 m_decoder->setDecodedSize(m_info.output_width, m_info.output_height)
; |
472 | 476 |
473 m_decoder->setOrientation(readImageOrientation(info())); | 477 m_decoder->setOrientation(readImageOrientation(info())); |
474 | 478 |
475 #if USE(QCMSLIB) | 479 #if USE(QCMSLIB) |
476 // Allow color management of the decoded RGBA pixels if possible. | 480 // Allow color management of the decoded RGBA pixels if possible. |
477 if (!m_decoder->ignoresGammaAndColorProfile()) { | 481 if (!m_decoder->ignoresGammaAndColorProfile()) { |
478 ColorProfile colorProfile; | 482 ColorProfile colorProfile; |
479 readColorProfile(info(), colorProfile); | 483 ColorProfileStatus status = ColorProfileSuccess; |
480 createColorTransform(colorProfile, colorSpaceHasAlpha(m_info.out
_color_space)); | 484 readColorProfile(info(), colorProfile, status); |
| 485 createColorTransform(colorProfile, colorSpaceHasAlpha(m_info.out
_color_space), status); |
| 486 Platform::current()->histogramEnumeration("ColorManagement.JPEGC
olorProfileStatus", status, ColorProfileStatus::ValueCount); |
481 if (m_transform) { | 487 if (m_transform) { |
482 overrideColorSpace = JCS_UNKNOWN; | 488 overrideColorSpace = JCS_UNKNOWN; |
483 #if defined(TURBO_JPEG_RGB_SWIZZLE) | 489 #if defined(TURBO_JPEG_RGB_SWIZZLE) |
484 // Input RGBA data to qcms. Note: restored to BGRA on output
. | 490 // Input RGBA data to qcms. Note: restored to BGRA on output
. |
485 if (m_info.out_color_space == JCS_EXT_BGRA) | 491 if (m_info.out_color_space == JCS_EXT_BGRA) |
486 m_info.out_color_space = JCS_EXT_RGBA; | 492 m_info.out_color_space = JCS_EXT_RGBA; |
487 #endif | 493 #endif |
488 } | 494 } |
489 m_decoder->setHasColorProfile(!!m_transform); | 495 m_decoder->setHasColorProfile(!!m_transform); |
490 } | 496 } |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 #if USE(QCMSLIB) | 634 #if USE(QCMSLIB) |
629 qcms_transform* colorTransform() const { return m_transform; } | 635 qcms_transform* colorTransform() const { return m_transform; } |
630 | 636 |
631 void clearColorTransform() | 637 void clearColorTransform() |
632 { | 638 { |
633 if (m_transform) | 639 if (m_transform) |
634 qcms_transform_release(m_transform); | 640 qcms_transform_release(m_transform); |
635 m_transform = 0; | 641 m_transform = 0; |
636 } | 642 } |
637 | 643 |
638 void createColorTransform(const ColorProfile& colorProfile, bool hasAlpha) | 644 void createColorTransform(const ColorProfile& colorProfile, bool hasAlpha, C
olorProfileStatus& status) |
639 { | 645 { |
640 clearColorTransform(); | 646 clearColorTransform(); |
641 | 647 |
642 if (colorProfile.isEmpty()) | 648 if (colorProfile.isEmpty()) |
| 649 return; // status should already have a !success code if this is the
case |
| 650 qcms_profile* inputProfile = qcms_profile_from_memory(colorProfile.data(
), colorProfile.size()); |
| 651 if (!inputProfile) { |
| 652 status = ColorProfileFailedDecode; |
643 return; | 653 return; |
| 654 } |
644 qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile(); | 655 qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile(); |
645 if (!deviceProfile) | 656 if (!deviceProfile) |
646 return; | 657 return; |
647 qcms_profile* inputProfile = qcms_profile_from_memory(colorProfile.data(
), colorProfile.size()); | |
648 if (!inputProfile) | |
649 return; | |
650 // We currently only support color profiles for RGB profiled images. | 658 // We currently only support color profiles for RGB profiled images. |
651 ASSERT(rgbData == qcms_profile_get_color_space(inputProfile)); | 659 ASSERT(rgbData == qcms_profile_get_color_space(inputProfile)); |
652 qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_
8; | 660 qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_
8; |
653 // FIXME: Don't force perceptual intent if the image profile contains an
intent. | 661 // FIXME: Don't force perceptual intent if the image profile contains an
intent. |
654 m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProf
ile, dataFormat, QCMS_INTENT_PERCEPTUAL); | 662 m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProf
ile, dataFormat, QCMS_INTENT_PERCEPTUAL); |
655 qcms_profile_release(inputProfile); | 663 qcms_profile_release(inputProfile); |
656 } | 664 } |
657 #endif | 665 #endif |
658 | 666 |
659 private: | 667 private: |
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1060 // has failed. | 1068 // has failed. |
1061 if (!m_reader->decode(onlySize) && isAllDataReceived()) | 1069 if (!m_reader->decode(onlySize) && isAllDataReceived()) |
1062 setFailed(); | 1070 setFailed(); |
1063 | 1071 |
1064 // If decoding is done or failed, we don't need the JPEGImageReader anymore. | 1072 // If decoding is done or failed, we don't need the JPEGImageReader anymore. |
1065 if (isComplete(this, onlySize) || failed()) | 1073 if (isComplete(this, onlySize) || failed()) |
1066 m_reader.clear(); | 1074 m_reader.clear(); |
1067 } | 1075 } |
1068 | 1076 |
1069 } | 1077 } |
OLD | NEW |