Modified: trunk/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp (136188 => 136189)
--- trunk/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp 2012-11-30 01:13:33 UTC (rev 136188)
+++ trunk/Source/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp 2012-11-30 01:15:15 UTC (rev 136189)
@@ -646,6 +646,78 @@
return ImageDecoder::setFailed();
}
+template <int colorSpace>
+void setPixel(ImageFrame& buffer, ImageFrame::PixelData* currentAddress, JSAMPARRAY samples, int column)
+{
+ JSAMPLE* jsample = *samples + column * (static_cast<J_COLOR_SPACE>(colorSpace) == JCS_RGB ? 3 : 4);
+
+ switch (static_cast<J_COLOR_SPACE>(colorSpace)) {
+#if defined(TURBO_JPEG_RGB_SWIZZLE)
+ case JCS_EXT_BGRA:
+ buffer.setRGBA(currentAddress, jsample[2], jsample[1], jsample[1], 0xFF);
+ break;
+ case JCS_EXT_RGBA: // Fallback to JSC_RGB case here.
+#endif
+ case JCS_RGB:
+ buffer.setRGBA(currentAddress, jsample[0], jsample[1], jsample[2], 0xFF);
+ break;
+ case JCS_CMYK:
+ // Source is 'Inverted CMYK', output is RGB.
+ // See: http://www.easyrgb.com/math.php?MATH=M12#text12
+ // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb
+ // From CMYK to CMY:
+ // X = X * (1 - K ) + K [for X = C, M, or Y]
+ // Thus, from Inverted CMYK to CMY is:
+ // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK
+ // From CMY (0..1) to RGB (0..1):
+ // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar]
+ unsigned k = jsample[3];
+ buffer.setRGBA(currentAddress, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF);
+ break;
+ }
+}
+
+template <int colorSpace, bool isScaled>
+bool JPEGImageDecoder::outputScanlines(ImageFrame& buffer)
+{
+ JSAMPARRAY samples = m_reader->samples();
+ jpeg_decompress_struct* info = m_reader->info();
+
+ int width = isScaled ? m_scaledColumns.size() : info->output_width;
+
+ while (info->output_scanline < info->output_height) {
+ // jpeg_read_scanlines will increase the scanline counter, so we
+ // save the scanline before calling it.
+ int sourceY = info->output_scanline;
+ /* Request one scanline. Returns 0 or 1 scanlines. */
+ if (jpeg_read_scanlines(info, samples, 1) != 1)
+ return false;
+
+ int destY = scaledY(sourceY);
+ if (destY < 0)
+ continue;
+
+#if USE(QCMSLIB)
+ if (m_reader->colorTransform() && colorSpace == JCS_RGB)
+ qcms_transform_data(m_reader->colorTransform(), *samples, *samples, info->output_width);
+#endif
+
+ ImageFrame::PixelData* currentAddress = buffer.getAddr(0, destY);
+
+ for (int x = 0; x < width; ++x) {
+ setPixel<colorSpace>(buffer, currentAddress, samples, isScaled ? m_scaledColumns[x] : x);
+ ++currentAddress;
+ }
+ }
+ return true;
+}
+
+template <int colorSpace>
+bool JPEGImageDecoder::outputScanlines(ImageFrame& buffer)
+{
+ return m_scaled ? outputScanlines<colorSpace, true>(buffer) : outputScanlines<colorSpace, false>(buffer);
+}
+
bool JPEGImageDecoder::outputScanlines()
{
if (m_frameBufferCache.isEmpty())
@@ -684,54 +756,26 @@
}
#endif
- JSAMPARRAY samples = m_reader->samples();
-
- while (info->output_scanline < info->output_height) {
- // jpeg_read_scanlines will increase the scanline counter, so we
- // save the scanline before calling it.
- int sourceY = info->output_scanline;
- /* Request one scanline. Returns 0 or 1 scanlines. */
- if (jpeg_read_scanlines(info, samples, 1) != 1)
- return false;
-
- int destY = scaledY(sourceY);
- if (destY < 0)
- continue;
-#if USE(QCMSLIB)
- if (m_reader->colorTransform() && info->out_color_space == JCS_RGB)
- qcms_transform_data(m_reader->colorTransform(), *samples, *samples, info->output_width);
-#endif
- int width = m_scaled ? m_scaledColumns.size() : info->output_width;
- for (int x = 0; x < width; ++x) {
- JSAMPLE* jsample = *samples + (m_scaled ? m_scaledColumns[x] : x) * ((info->out_color_space == JCS_RGB) ? 3 : 4);
- if (info->out_color_space == JCS_RGB)
- buffer.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF);
+ switch (info->out_color_space) {
+ // The code inside outputScanlines<int, bool> will be executed
+ // for each pixel, so we want to avoid any extra comparisons there.
+ // That is why we use template and template specializations here so
+ // the proper code will be generated at compile time.
+ case JCS_RGB:
+ return outputScanlines<JCS_RGB>(buffer);
#if defined(TURBO_JPEG_RGB_SWIZZLE)
- else if (info->out_color_space == JCS_EXT_RGBA)
- buffer.setRGBA(x, destY, jsample[0], jsample[1], jsample[2], 0xFF);
- else if (info->out_color_space == JCS_EXT_BGRA)
- buffer.setRGBA(x, destY, jsample[2], jsample[1], jsample[0], 0xFF);
+ case JCS_EXT_RGBA:
+ return outputScanlines<JCS_EXT_RGBA>(buffer);
+ case JCS_EXT_BGRA:
+ return outputScanlines<JCS_EXT_BGRA>(buffer);
#endif
- else if (info->out_color_space == JCS_CMYK) {
- // Source is 'Inverted CMYK', output is RGB.
- // See: http://www.easyrgb.com/math.php?MATH=M12#text12
- // Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb
- // From CMYK to CMY:
- // X = X * (1 - K ) + K [for X = C, M, or Y]
- // Thus, from Inverted CMYK to CMY is:
- // X = (1-iX) * (1 - (1-iK)) + (1-iK) => 1 - iX*iK
- // From CMY (0..1) to RGB (0..1):
- // R = 1 - C => 1 - (1 - iC*iK) => iC*iK [G and B similar]
- unsigned k = jsample[3];
- buffer.setRGBA(x, destY, jsample[0] * k / 255, jsample[1] * k / 255, jsample[2] * k / 255, 0xFF);
- } else {
- ASSERT_NOT_REACHED();
- return setFailed();
- }
- }
+ case JCS_CMYK:
+ return outputScanlines<JCS_CMYK>(buffer);
+ default:
+ ASSERT_NOT_REACHED();
}
- return true;
+ return setFailed();
}
void JPEGImageDecoder::jpegComplete()