Index: src/ports/SkImageEncoder_WIC.cpp |
diff --git a/src/ports/SkImageEncoder_WIC.cpp b/src/ports/SkImageEncoder_WIC.cpp |
index 5523ea2e11e267e13ad049e48752043a5bf5c9e8..9be95727cad2b0cd16d82da44ae46def4cbc6092 100644 |
--- a/src/ports/SkImageEncoder_WIC.cpp |
+++ b/src/ports/SkImageEncoder_WIC.cpp |
@@ -83,35 +83,49 @@ bool SkImageEncoder_WIC::onEncode(SkWStream* stream |
return false; |
} |
- //Convert to 8888 if needed. |
- const SkBitmap* bitmap; |
- SkBitmap bitmapCopy; |
- if (kN32_SkColorType == bitmapOrig.colorType() && bitmapOrig.isOpaque()) { |
- bitmap = &bitmapOrig; |
- } else { |
- if (!bitmapOrig.copyTo(&bitmapCopy, kN32_SkColorType)) { |
- return false; |
- } |
- bitmap = &bitmapCopy; |
+ // First convert to BGRA if necessary. |
+ SkBitmap bitmap; |
+ if (!bitmapOrig.copyTo(&bitmap, kBGRA_8888_SkColorType)) { |
+ return false; |
} |
- // We cannot use PBGRA so we need to unpremultiply ourselves |
- if (!bitmap->isOpaque()) { |
- SkAutoLockPixels alp(*bitmap); |
- |
- uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap->getPixels()); |
- for (int y = 0; y < bitmap->height(); ++y) { |
- for (int x = 0; x < bitmap->width(); ++x) { |
- uint8_t* bytes = pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel(); |
- |
+ // WIC expects unpremultiplied pixels. Unpremultiply if necessary. |
+ if (kPremul_SkAlphaType == bitmap.alphaType()) { |
+ uint8_t* pixels = reinterpret_cast<uint8_t*>(bitmap.getPixels()); |
+ for (int y = 0; y < bitmap.height(); ++y) { |
+ for (int x = 0; x < bitmap.width(); ++x) { |
+ uint8_t* bytes = pixels + y * bitmap.rowBytes() + x * bitmap.bytesPerPixel(); |
SkPMColor* src = reinterpret_cast<SkPMColor*>(bytes); |
SkColor* dst = reinterpret_cast<SkColor*>(bytes); |
- |
*dst = SkUnPreMultiply::PMColorToColor(*src); |
} |
} |
} |
+ // Finally, if we are performing a jpeg encode, we must convert to BGR. |
+ void* pixels = bitmap.getPixels(); |
+ size_t rowBytes = bitmap.rowBytes(); |
+ SkAutoMalloc pixelStorage; |
+ WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA; |
+ if (kJPEG_Type == fType) { |
+ formatDesired = GUID_WICPixelFormat24bppBGR; |
+ rowBytes = SkAlign4(bitmap.width() * 3); |
+ pixelStorage.reset(rowBytes * bitmap.height()); |
+ for (int y = 0; y < bitmap.height(); y++) { |
+ uint8_t* dstRow = SkTAddOffset<uint8_t>(pixelStorage.get(), y * rowBytes); |
+ for (int x = 0; x < bitmap.width(); x++) { |
+ uint32_t bgra = *bitmap.getAddr32(x, y); |
+ dstRow[0] = (uint8_t) (bgra >> 0); |
+ dstRow[1] = (uint8_t) (bgra >> 8); |
+ dstRow[2] = (uint8_t) (bgra >> 16); |
+ dstRow += 3; |
+ } |
+ } |
+ |
+ pixels = pixelStorage.get(); |
+ } |
+ |
+ |
//Initialize COM. |
SkAutoCoInitialize scopedCo; |
if (!scopedCo.succeeded()) { |
@@ -176,15 +190,14 @@ bool SkImageEncoder_WIC::onEncode(SkWStream* stream |
} |
//Set the size of the frame. |
- const UINT width = bitmap->width(); |
- const UINT height = bitmap->height(); |
+ const UINT width = bitmap.width(); |
+ const UINT height = bitmap.height(); |
if (SUCCEEDED(hr)) { |
hr = piBitmapFrameEncode->SetSize(width, height); |
} |
//Set the pixel format of the frame. If native encoded format cannot match BGRA, |
//it will choose the closest pixel format that it supports. |
- const WICPixelFormatGUID formatDesired = GUID_WICPixelFormat32bppBGRA; |
WICPixelFormatGUID formatGUID = formatDesired; |
if (SUCCEEDED(hr)) { |
hr = piBitmapFrameEncode->SetPixelFormat(&formatGUID); |
@@ -196,13 +209,10 @@ bool SkImageEncoder_WIC::onEncode(SkWStream* stream |
//Write the pixels into the frame. |
if (SUCCEEDED(hr)) { |
- SkAutoLockPixels alp(*bitmap); |
- const UINT stride = (UINT) bitmap->rowBytes(); |
- hr = piBitmapFrameEncode->WritePixels( |
- height |
- , stride |
- , stride * height |
- , reinterpret_cast<BYTE*>(bitmap->getPixels())); |
+ hr = piBitmapFrameEncode->WritePixels(height, |
+ (UINT) rowBytes, |
+ (UINT) rowBytes * height, |
+ reinterpret_cast<BYTE*>(pixels)); |
} |
if (SUCCEEDED(hr)) { |
@@ -223,6 +233,7 @@ static SkImageEncoder* sk_imageencoder_wic_factory(SkImageEncoder::Type t) { |
case SkImageEncoder::kBMP_Type: |
case SkImageEncoder::kICO_Type: |
case SkImageEncoder::kPNG_Type: |
+ case SkImageEncoder::kJPEG_Type: |
break; |
default: |
return nullptr; |