| 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 21 matching lines...) Expand all  Loading... | 
| 32  * deletingthe provisions above and replace them with the notice and | 32  * deletingthe provisions above and replace them with the notice and | 
| 33  * other provisions required by the MPL or the GPL, as the case may be. | 33  * other provisions required by the MPL or the GPL, as the case may be. | 
| 34  * If you do not delete the provisions above, a recipient may use your | 34  * If you do not delete the provisions above, a recipient may use your | 
| 35  * version of this file under any of the LGPL, the MPL or the GPL. | 35  * version of this file under any of the LGPL, the MPL or the GPL. | 
| 36  */ | 36  */ | 
| 37 | 37 | 
| 38 #include "config.h" | 38 #include "config.h" | 
| 39 #include "platform/image-decoders/jpeg/JPEGImageDecoder.h" | 39 #include "platform/image-decoders/jpeg/JPEGImageDecoder.h" | 
| 40 | 40 | 
| 41 #include "platform/PlatformInstrumentation.h" | 41 #include "platform/PlatformInstrumentation.h" | 
|  | 42 #include "platform/graphics/GraphicsScreen.h" | 
| 42 | 43 | 
| 43 extern "C" { | 44 extern "C" { | 
| 44 #include <stdio.h> // jpeglib.h needs stdio FILE. | 45 #include <stdio.h> // jpeglib.h needs stdio FILE. | 
| 45 #include "jpeglib.h" | 46 #include "jpeglib.h" | 
| 46 #if USE(ICCJPEG) | 47 #if USE(ICCJPEG) | 
| 47 #include "iccjpeg.h" | 48 #include "iccjpeg.h" | 
| 48 #endif | 49 #endif | 
| 49 #if USE(QCMSLIB) | 50 #if USE(QCMSLIB) | 
| 50 #include "qcms.h" | 51 #include "qcms.h" | 
| 51 #endif | 52 #endif | 
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 470             jpeg_calc_output_dimensions(&m_info); | 471             jpeg_calc_output_dimensions(&m_info); | 
| 471             m_decoder->setDecodedSize(m_info.output_width, m_info.output_height)
      ; | 472             m_decoder->setDecodedSize(m_info.output_width, m_info.output_height)
      ; | 
| 472 | 473 | 
| 473             m_decoder->setOrientation(readImageOrientation(info())); | 474             m_decoder->setOrientation(readImageOrientation(info())); | 
| 474 | 475 | 
| 475 #if USE(QCMSLIB) | 476 #if USE(QCMSLIB) | 
| 476             // Allow color management of the decoded RGBA pixels if possible. | 477             // Allow color management of the decoded RGBA pixels if possible. | 
| 477             if (!m_decoder->ignoresGammaAndColorProfile()) { | 478             if (!m_decoder->ignoresGammaAndColorProfile()) { | 
| 478                 ColorProfile colorProfile; | 479                 ColorProfile colorProfile; | 
| 479                 readColorProfile(info(), colorProfile); | 480                 readColorProfile(info(), colorProfile); | 
| 480                 createColorTransform(colorProfile, colorSpaceHasAlpha(m_info.out
      _color_space)); | 481                 bool imageHasAlpha = colorSpaceHasAlpha(m_info.out_color_space); | 
| 481                 if (m_transform) { | 482                 RefPtr<ColorSpaceProfile> imageColorProfile = createColorTransfo
      rm(colorProfile, imageHasAlpha); | 
|  | 483                 m_decoder->setHasColorProfile(!!imageColorProfile.get()); | 
|  | 484                 if (m_decoder->hasColorProfile()) { | 
|  | 485                     // FIXME: allow YUV decoding of color profiled images. | 
| 482                     overrideColorSpace = JCS_UNKNOWN; | 486                     overrideColorSpace = JCS_UNKNOWN; | 
| 483 #if defined(TURBO_JPEG_RGB_SWIZZLE) | 487 #if defined(TURBO_JPEG_RGB_SWIZZLE) | 
| 484                     // Input RGBA data to qcms. Note: restored to BGRA on output
      . | 488                     // Input RGBA data to qcms. Note: restored to BGRA on output
      . | 
| 485                     if (m_info.out_color_space == JCS_EXT_BGRA) | 489                     if (m_transform && m_info.out_color_space == JCS_EXT_BGRA) | 
| 486                         m_info.out_color_space = JCS_EXT_RGBA; | 490                         m_info.out_color_space = JCS_EXT_RGBA; | 
| 487 #endif | 491 #endif | 
|  | 492                     if (imageColorProfilesEnabled()) { | 
|  | 493                         RELEASE_ASSERT(imageColorProfile->profile()); | 
|  | 494                         m_decoder->setColorProfile(imageColorProfile); | 
|  | 495                     } | 
| 488                 } | 496                 } | 
| 489                 m_decoder->setHasColorProfile(!!m_transform); |  | 
| 490             } | 497             } | 
| 491 #endif | 498 #endif | 
| 492             if (overrideColorSpace == JCS_YCbCr) { | 499             if (overrideColorSpace == JCS_YCbCr) { | 
| 493                 m_info.out_color_space = JCS_YCbCr; | 500                 m_info.out_color_space = JCS_YCbCr; | 
| 494                 m_info.raw_data_out = TRUE; | 501                 m_info.raw_data_out = TRUE; | 
| 495                 m_uvSize = computeYUVSize(&m_info, 1, ImageDecoder::SizeForMemor
      yAllocation); // U size and V size have to be the same if we got here | 502                 m_uvSize = computeYUVSize(&m_info, 1, ImageDecoder::SizeForMemor
      yAllocation); // U size and V size have to be the same if we got here | 
| 496             } | 503             } | 
| 497 | 504 | 
| 498             // Don't allocate a giant and superfluous memory buffer when the | 505             // Don't allocate a giant and superfluous memory buffer when the | 
| 499             // image is a sequential JPEG. | 506             // image is a sequential JPEG. | 
| 500             m_info.buffered_image = jpeg_has_multiple_scans(&m_info); | 507             m_info.buffered_image = jpeg_has_multiple_scans(&m_info); | 
| 501             if (m_info.buffered_image) { | 508             if (m_info.buffered_image) { | 
| 502                 m_err.pub.emit_message = emit_message; | 509                 m_err.pub.emit_message = emit_message; | 
| 503                 m_err.num_corrupt_warnings = 0; | 510                 m_err.num_corrupt_warnings = 0; | 
| 504             } | 511             } | 
| 505 | 512 | 
|  | 513             fprintf(stderr, "JPEG decoder %p headerAvailable %dx%d %s\n", m_deco
      der, m_info.image_width, m_info.image_height, onlySize ? "size-only-decode" : ""
      ); | 
|  | 514 | 
| 506             if (onlySize) { | 515             if (onlySize) { | 
| 507                 // This exits the function while there is still potentially | 516                 // This exits the function while there is still potentially | 
| 508                 // data in the buffer. Before this function is called again, | 517                 // data in the buffer. Before this function is called again, | 
| 509                 // the SharedBuffer may be collapsed (by a call to | 518                 // the SharedBuffer may be collapsed (by a call to | 
| 510                 // mergeSegmentsIntoBuffer), invalidating the "buffer" (which | 519                 // mergeSegmentsIntoBuffer), invalidating the "buffer" (which | 
| 511                 // in reality is a pointer into the SharedBuffer's data). | 520                 // in reality is a pointer into the SharedBuffer's data). | 
| 512                 // Defensively empty the buffer, but first find the latest | 521                 // Defensively empty the buffer, but first find the latest | 
| 513                 // restart position and signal to restart, so the next call to | 522                 // restart position and signal to restart, so the next call to | 
| 514                 // fillBuffer will resume from the correct point. | 523                 // fillBuffer will resume from the correct point. | 
| 515                 m_needsRestart = true; | 524                 m_needsRestart = true; | 
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 628 #if USE(QCMSLIB) | 637 #if USE(QCMSLIB) | 
| 629     qcms_transform* colorTransform() const { return m_transform; } | 638     qcms_transform* colorTransform() const { return m_transform; } | 
| 630 | 639 | 
| 631     void clearColorTransform() | 640     void clearColorTransform() | 
| 632     { | 641     { | 
| 633         if (m_transform) | 642         if (m_transform) | 
| 634             qcms_transform_release(m_transform); | 643             qcms_transform_release(m_transform); | 
| 635         m_transform = 0; | 644         m_transform = 0; | 
| 636     } | 645     } | 
| 637 | 646 | 
| 638     void createColorTransform(const ColorProfile& colorProfile, bool hasAlpha) | 647     PassRefPtr<ColorSpaceProfile> createColorTransform(const ColorProfile& color
      Profile, bool hasAlpha) | 
| 639     { | 648     { | 
| 640         clearColorTransform(); | 649         clearColorTransform(); | 
| 641 | 650 | 
|  | 651         fprintf(stderr, "JPEG decoder %p createColorTransform ", m_decoder); | 
|  | 652 | 
|  | 653         if (m_decoder->deviceProfile()) | 
|  | 654             fprintf(stderr, ": device %p\n", m_decoder->deviceProfile().get()); | 
|  | 655         else | 
|  | 656             fprintf(stderr, ": %p\n", nullptr); | 
|  | 657         fprintf(stderr, "image color profiles enabled: %d\n", imageColorProfiles
      Enabled()); | 
|  | 658         fflush(stderr); | 
|  | 659 | 
| 642         if (colorProfile.isEmpty()) | 660         if (colorProfile.isEmpty()) | 
| 643             return; | 661             return nullptr; | 
|  | 662 | 
| 644         qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile(); | 663         qcms_profile* deviceProfile = ImageDecoder::qcmsOutputDeviceProfile(); | 
|  | 664         if (m_decoder->deviceProfile()) | 
|  | 665             deviceProfile = m_decoder->deviceProfile()->profile(); | 
| 645         if (!deviceProfile) | 666         if (!deviceProfile) | 
| 646             return; | 667             return nullptr; | 
|  | 668 | 
| 647         qcms_profile* inputProfile = qcms_profile_from_memory(colorProfile.data(
      ), colorProfile.size()); | 669         qcms_profile* inputProfile = qcms_profile_from_memory(colorProfile.data(
      ), colorProfile.size()); | 
| 648         if (!inputProfile) | 670         if (!inputProfile) | 
| 649             return; | 671             return nullptr; | 
|  | 672 | 
|  | 673         fprintf(stderr, " from source profile [%s]", qcms_profile_get_descriptio
      n(inputProfile)); | 
|  | 674         fprintf(stderr, " to [%s]\n", qcms_profile_get_description(deviceProfile
      )); | 
|  | 675         fflush(stderr); | 
|  | 676 | 
|  | 677         // There is no need to create a color transform if the color profiles ma
      tch. | 
|  | 678         if (imageColorProfilesEnabled() && qcms_profile_match(inputProfile, devi
      ceProfile)) | 
|  | 679             return ColorSpaceProfile::create(inputProfile); | 
|  | 680 | 
| 650         // We currently only support color profiles for RGB profiled images. | 681         // We currently only support color profiles for RGB profiled images. | 
| 651         ASSERT(rgbData == qcms_profile_get_color_space(inputProfile)); | 682         ASSERT(rgbData == qcms_profile_get_color_space(inputProfile)); | 
| 652         qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_
      8; | 683         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. | 684         // 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); | 685         m_transform = qcms_transform_create(inputProfile, dataFormat, deviceProf
      ile, dataFormat, QCMS_INTENT_PERCEPTUAL); | 
|  | 686         if (m_transform) | 
|  | 687             return ColorSpaceProfile::create(inputProfile); | 
|  | 688 | 
| 655         qcms_profile_release(inputProfile); | 689         qcms_profile_release(inputProfile); | 
|  | 690         return nullptr; | 
| 656     } | 691     } | 
| 657 #endif | 692 #endif | 
| 658 | 693 | 
| 659 private: | 694 private: | 
| 660     JSAMPARRAY allocateSampleArray() | 695     JSAMPARRAY allocateSampleArray() | 
| 661     { | 696     { | 
| 662         // Some output color spaces don't need the sample array: don't allocate 
      in that case. | 697         // Some output color spaces don't need the sample array: don't allocate 
      in that case. | 
| 663 #if defined(TURBO_JPEG_RGB_SWIZZLE) | 698 #if defined(TURBO_JPEG_RGB_SWIZZLE) | 
| 664         if (turboSwizzled(m_info.out_color_space)) | 699         if (turboSwizzled(m_info.out_color_space)) | 
| 665             return nullptr; | 700             return nullptr; | 
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 756 | 791 | 
| 757 void term_source(j_decompress_ptr jd) | 792 void term_source(j_decompress_ptr jd) | 
| 758 { | 793 { | 
| 759     reinterpret_cast_ptr<decoder_source_mgr*>(jd->src)->reader->decoder()->compl
      ete(); | 794     reinterpret_cast_ptr<decoder_source_mgr*>(jd->src)->reader->decoder()->compl
      ete(); | 
| 760 } | 795 } | 
| 761 | 796 | 
| 762 JPEGImageDecoder::JPEGImageDecoder(AlphaOption alphaOption, GammaAndColorProfile
      Option colorOptions, size_t maxDecodedBytes) | 797 JPEGImageDecoder::JPEGImageDecoder(AlphaOption alphaOption, GammaAndColorProfile
      Option colorOptions, size_t maxDecodedBytes) | 
| 763     : ImageDecoder(alphaOption, colorOptions, maxDecodedBytes) | 798     : ImageDecoder(alphaOption, colorOptions, maxDecodedBytes) | 
| 764     , m_hasColorProfile(false) | 799     , m_hasColorProfile(false) | 
| 765 { | 800 { | 
|  | 801     fprintf(stderr, "JPEG decoder %p created %s\n", this, !isMainThread() ? "imp
      l-side-thread" : ""); | 
| 766 } | 802 } | 
| 767 | 803 | 
| 768 JPEGImageDecoder::~JPEGImageDecoder() | 804 JPEGImageDecoder::~JPEGImageDecoder() | 
| 769 { | 805 { | 
| 770 } | 806 } | 
| 771 | 807 | 
| 772 bool JPEGImageDecoder::setSize(unsigned width, unsigned height) | 808 bool JPEGImageDecoder::setSize(unsigned width, unsigned height) | 
| 773 { | 809 { | 
| 774     if (!ImageDecoder::setSize(width, height)) | 810     if (!ImageDecoder::setSize(width, height)) | 
| 775         return false; | 811         return false; | 
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1001         buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); | 1037         buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); | 
| 1002     } | 1038     } | 
| 1003 | 1039 | 
| 1004 #if defined(TURBO_JPEG_RGB_SWIZZLE) | 1040 #if defined(TURBO_JPEG_RGB_SWIZZLE) | 
| 1005     if (turboSwizzled(info->out_color_space)) { | 1041     if (turboSwizzled(info->out_color_space)) { | 
| 1006         while (info->output_scanline < info->output_height) { | 1042         while (info->output_scanline < info->output_height) { | 
| 1007             unsigned char* row = reinterpret_cast_ptr<unsigned char*>(buffer.get
      Addr(0, info->output_scanline)); | 1043             unsigned char* row = reinterpret_cast_ptr<unsigned char*>(buffer.get
      Addr(0, info->output_scanline)); | 
| 1008             if (jpeg_read_scanlines(info, &row, 1) != 1) | 1044             if (jpeg_read_scanlines(info, &row, 1) != 1) | 
| 1009                 return false; | 1045                 return false; | 
| 1010 #if USE(QCMSLIB) | 1046 #if USE(QCMSLIB) | 
| 1011             if (qcms_transform* transform = m_reader->colorTransform()) | 1047             if (qcms_transform* transform = m_reader->colorTransform()) { | 
|  | 1048                 if (info->output_scanline <= 3 || info->output_scanline >= info-
      >output_height) | 
|  | 1049                     fprintf(stderr, "JPEG decoder %p %dx%d color transform row %
      d\n", this, size().width(), size().height(), info->output_scanline - 1); | 
| 1012                 qcms_transform_data_type(transform, row, row, info->output_width
      , rgbOutputColorSpace() == JCS_EXT_BGRA ? QCMS_OUTPUT_BGRX : QCMS_OUTPUT_RGBX); | 1050                 qcms_transform_data_type(transform, row, row, info->output_width
      , rgbOutputColorSpace() == JCS_EXT_BGRA ? QCMS_OUTPUT_BGRX : QCMS_OUTPUT_RGBX); | 
|  | 1051             } | 
| 1013 #endif | 1052 #endif | 
|  | 1053             if (info->output_scanline <= 3) | 
|  | 1054                 fprintf(stderr, "JPEG decoder %p %dx%d row %d\n", this, size().w
      idth(), size().height(), info->output_scanline - 1); | 
|  | 1055 | 
|  | 1056             if (info->output_scanline >= info->output_height) { | 
|  | 1057                 fprintf(stderr, "JPEG decoder %p %dx%d row %d\n", this, size().w
      idth(), size().height(), info->output_scanline - 1); | 
|  | 1058                 fflush(stderr); | 
|  | 1059             } | 
| 1014         } | 1060         } | 
|  | 1061 | 
| 1015         buffer.setPixelsChanged(true); | 1062         buffer.setPixelsChanged(true); | 
| 1016         return true; | 1063         return true; | 
| 1017     } | 1064     } | 
| 1018 #endif | 1065 #endif | 
| 1019 | 1066 | 
| 1020     switch (info->out_color_space) { | 1067     switch (info->out_color_space) { | 
| 1021     case JCS_RGB: | 1068     case JCS_RGB: | 
| 1022         return outputRows<JCS_RGB>(m_reader.get(), buffer); | 1069         return outputRows<JCS_RGB>(m_reader.get(), buffer); | 
| 1023     case JCS_CMYK: | 1070     case JCS_CMYK: | 
| 1024         return outputRows<JCS_CMYK>(m_reader.get(), buffer); | 1071         return outputRows<JCS_CMYK>(m_reader.get(), buffer); | 
| 1025     default: | 1072     default: | 
| 1026         ASSERT_NOT_REACHED(); | 1073         ASSERT_NOT_REACHED(); | 
| 1027     } | 1074     } | 
| 1028 | 1075 | 
| 1029     return setFailed(); | 1076     return setFailed(); | 
| 1030 } | 1077 } | 
| 1031 | 1078 | 
| 1032 void JPEGImageDecoder::complete() | 1079 void JPEGImageDecoder::complete() | 
| 1033 { | 1080 { | 
|  | 1081     fflush(stderr); | 
|  | 1082 | 
| 1034     if (m_frameBufferCache.isEmpty()) | 1083     if (m_frameBufferCache.isEmpty()) | 
| 1035         return; | 1084         return; | 
| 1036 | 1085 | 
| 1037     m_frameBufferCache[0].setHasAlpha(false); | 1086     m_frameBufferCache[0].setHasAlpha(false); | 
| 1038     m_frameBufferCache[0].setStatus(ImageFrame::FrameComplete); | 1087     m_frameBufferCache[0].setStatus(ImageFrame::FrameComplete); | 
| 1039 } | 1088 } | 
| 1040 | 1089 | 
| 1041 inline bool isComplete(const JPEGImageDecoder* decoder, bool onlySize) | 1090 inline bool isComplete(const JPEGImageDecoder* decoder, bool onlySize) | 
| 1042 { | 1091 { | 
| 1043     if (decoder->hasImagePlanes() && !onlySize) | 1092     if (decoder->hasImagePlanes() && !onlySize) | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 1060     // has failed. | 1109     // has failed. | 
| 1061     if (!m_reader->decode(onlySize) && isAllDataReceived()) | 1110     if (!m_reader->decode(onlySize) && isAllDataReceived()) | 
| 1062         setFailed(); | 1111         setFailed(); | 
| 1063 | 1112 | 
| 1064     // If decoding is done or failed, we don't need the JPEGImageReader anymore. | 1113     // If decoding is done or failed, we don't need the JPEGImageReader anymore. | 
| 1065     if (isComplete(this, onlySize) || failed()) | 1114     if (isComplete(this, onlySize) || failed()) | 
| 1066         m_reader.clear(); | 1115         m_reader.clear(); | 
| 1067 } | 1116 } | 
| 1068 | 1117 | 
| 1069 } | 1118 } | 
| OLD | NEW | 
|---|