Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkImageEncoder.h" | 8 #include "SkImageEncoder.h" |
| 9 #include "SkColor.h" | 9 #include "SkColor.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 longjmp(png_jmpbuf(png_ptr), 1); | 51 longjmp(png_jmpbuf(png_ptr), 1); |
| 52 } | 52 } |
| 53 | 53 |
| 54 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { | 54 static void sk_write_fn(png_structp png_ptr, png_bytep data, png_size_t len) { |
| 55 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); | 55 SkWStream* sk_stream = (SkWStream*)png_get_io_ptr(png_ptr); |
| 56 if (!sk_stream->write(data, len)) { | 56 if (!sk_stream->write(data, len)) { |
| 57 png_error(png_ptr, "sk_write_fn Error!"); | 57 png_error(png_ptr, "sk_write_fn Error!"); |
| 58 } | 58 } |
| 59 } | 59 } |
| 60 | 60 |
| 61 static transform_scanline_proc choose_proc(SkColorType ct, bool hasAlpha) { | 61 static transform_scanline_proc choose_proc(SkColorType ct, SkAlphaType alphaType ) { |
| 62 // we don't care about search on alpha if we're kIndex8, since only the | |
| 63 // colortable packing cares about that distinction, not the pixels | |
| 64 if (kIndex_8_SkColorType == ct) { | |
| 65 hasAlpha = false; // we store false in the table entries for kIndex8 | |
| 66 } | |
| 67 | |
| 68 static const struct { | 62 static const struct { |
| 69 SkColorType fColorType; | 63 SkColorType fColorType; |
| 70 bool fHasAlpha; | 64 SkAlphaType fAlphaType; |
| 71 transform_scanline_proc fProc; | 65 transform_scanline_proc fProc; |
| 72 } gMap[] = { | 66 } gMap[] = { |
| 73 { kRGB_565_SkColorType, false, transform_scanline_565 }, | 67 { kRGB_565_SkColorType, kOpaque_SkAlphaType, transform_scanline_565 }, |
| 74 { kN32_SkColorType, false, transform_scanline_888 }, | 68 { kRGBA_8888_SkColorType, kOpaque_SkAlphaType, transform_scanline_RGB1 }, |
| 75 { kN32_SkColorType, true, transform_scanline_8888 }, | 69 { kBGRA_8888_SkColorType, kOpaque_SkAlphaType, transform_scanline_BGR1 }, |
| 76 { kARGB_4444_SkColorType, false, transform_scanline_444 }, | 70 { kRGBA_8888_SkColorType, kPremul_SkAlphaType, transform_scanline_rgbA }, |
| 77 { kARGB_4444_SkColorType, true, transform_scanline_4444 }, | 71 { kBGRA_8888_SkColorType, kPremul_SkAlphaType, transform_scanline_bgrA }, |
| 78 { kIndex_8_SkColorType, false, transform_scanline_memcpy }, | 72 { kRGBA_8888_SkColorType, kUnpremul_SkAlphaType, transform_scanline_memc py }, |
| 79 { kGray_8_SkColorType, false, transform_scanline_memcpy }, | 73 { kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, transform_scanline_BGRA }, |
| 74 { kARGB_4444_SkColorType, kOpaque_SkAlphaType, transform_scanline_444 }, | |
| 75 { kARGB_4444_SkColorType, kPremul_SkAlphaType, transform_scanline_4444 }, | |
| 76 { kIndex_8_SkColorType, kOpaque_SkAlphaType, transform_scanline_memc py }, | |
| 77 { kIndex_8_SkColorType, kPremul_SkAlphaType, transform_scanline_memc py }, | |
| 78 { kIndex_8_SkColorType, kUnpremul_SkAlphaType, transform_scanline_memc py }, | |
| 79 { kGray_8_SkColorType, kOpaque_SkAlphaType, transform_scanline_memc py }, | |
| 80 }; | 80 }; |
| 81 | 81 |
| 82 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { | 82 for (int i = SK_ARRAY_COUNT(gMap) - 1; i >= 0; --i) { |
|
scroggo
2016/09/12 17:16:49
nit: Can you update this to a for each loop?
msarett
2016/09/12 19:39:19
Done.
| |
| 83 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { | 83 if (gMap[i].fColorType == ct && gMap[i].fAlphaType == alphaType) { |
| 84 return gMap[i].fProc; | 84 return gMap[i].fProc; |
| 85 } | 85 } |
| 86 } | 86 } |
| 87 sk_throw(); | 87 sk_throw(); |
| 88 return nullptr; | 88 return nullptr; |
| 89 } | 89 } |
| 90 | 90 |
| 91 // return the minimum legal bitdepth (by png standards) for this many colortable | 91 // return the minimum legal bitdepth (by png standards) for this many colortable |
| 92 // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16, | 92 // entries. SkBitmap always stores in 8bits per pixel, but for colorcount <= 16, |
| 93 // we can use fewer bits per in png | 93 // we can use fewer bits per in png |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 105 | 105 |
| 106 /* Pack palette[] with the corresponding colors, and if hasAlpha is true, also | 106 /* Pack palette[] with the corresponding colors, and if hasAlpha is true, also |
| 107 pack trans[] and return the number of trans[] entries written. If hasAlpha | 107 pack trans[] and return the number of trans[] entries written. If hasAlpha |
| 108 is false, the return value will always be 0. | 108 is false, the return value will always be 0. |
| 109 | 109 |
| 110 Note: this routine takes care of unpremultiplying the RGB values when we | 110 Note: this routine takes care of unpremultiplying the RGB values when we |
| 111 have alpha in the colortable, since png doesn't support premul colors | 111 have alpha in the colortable, since png doesn't support premul colors |
| 112 */ | 112 */ |
| 113 static inline int pack_palette(SkColorTable* ctable, | 113 static inline int pack_palette(SkColorTable* ctable, |
| 114 png_color* SK_RESTRICT palette, | 114 png_color* SK_RESTRICT palette, |
| 115 png_byte* SK_RESTRICT trans, bool hasAlpha) { | 115 png_byte* SK_RESTRICT trans, SkAlphaType alphaTyp e) { |
|
scroggo
2016/09/12 17:16:50
I'm confused. Didn't you change this method differ
msarett
2016/09/12 19:39:19
Sorry I've sent my code reviews backwards. That C
| |
| 116 const SkPMColor* SK_RESTRICT colors = ctable ? ctable->readColors() : nullpt r; | 116 const SkPMColor* SK_RESTRICT colors = ctable ? ctable->readColors() : nullpt r; |
| 117 const int ctCount = ctable->count(); | 117 const int ctCount = ctable->count(); |
| 118 int i, num_trans = 0; | 118 int i, num_trans = 0; |
| 119 | 119 |
| 120 if (hasAlpha) { | 120 if (kOpaque_SkAlphaType != alphaType) { |
| 121 /* first see if we have some number of fully opaque at the end of the | 121 /* first see if we have some number of fully opaque at the end of the |
| 122 ctable. PNG allows num_trans < num_palette, but all of the trans | 122 ctable. PNG allows num_trans < num_palette, but all of the trans |
| 123 entries must come first in the palette. If I was smarter, I'd | 123 entries must come first in the palette. If I was smarter, I'd |
| 124 reorder the indices and ctable so that all non-opaque colors came | 124 reorder the indices and ctable so that all non-opaque colors came |
| 125 first in the palette. But, since that would slow down the encode, | 125 first in the palette. But, since that would slow down the encode, |
| 126 I'm leaving the indices and ctable order as is, and just looking | 126 I'm leaving the indices and ctable order as is, and just looking |
| 127 at the tail of the ctable for opaqueness. | 127 at the tail of the ctable for opaqueness. |
| 128 */ | 128 */ |
| 129 num_trans = ctCount; | 129 num_trans = ctCount; |
| 130 for (i = ctCount - 1; i >= 0; --i) { | 130 for (i = ctCount - 1; i >= 0; --i) { |
| 131 if (SkGetPackedA32(colors[i]) != 0xFF) { | 131 if (SkGetPackedA32(colors[i]) != 0xFF) { |
| 132 break; | 132 break; |
| 133 } | 133 } |
| 134 num_trans -= 1; | 134 num_trans -= 1; |
| 135 } | 135 } |
| 136 | 136 |
| 137 const SkUnPreMultiply::Scale* SK_RESTRICT table = | 137 if (kPremul_SkAlphaType == alphaType) { |
| 138 SkUnPreMultiply::GetScaleTable(); | 138 const SkUnPreMultiply::Scale* SK_RESTRICT table = SkUnPreMultiply::G etScaleTable(); |
| 139 for (i = 0; i < num_trans; i++) { | |
| 140 const SkPMColor c = *colors++; | |
| 141 const unsigned a = SkGetPackedA32(c); | |
| 142 const SkUnPreMultiply::Scale s = table[a]; | |
| 143 trans[i] = a; | |
| 144 palette[i].red = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c )); | |
| 145 palette[i].green = SkUnPreMultiply::ApplyScale(s,SkGetPackedG32( c)); | |
| 146 palette[i].blue = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32( c)); | |
| 147 } | |
| 148 } else { | |
| 149 for (i = 0; i < num_trans; i++) { | |
| 150 const SkPMColor c = *colors++; | |
| 151 trans[i] = SkGetPackedA32(c); | |
| 152 palette[i].red = SkGetPackedR32(c); | |
| 153 palette[i].green = SkGetPackedG32(c); | |
| 154 palette[i].blue = SkGetPackedB32(c); | |
| 155 } | |
| 156 } | |
| 139 | 157 |
| 140 for (i = 0; i < num_trans; i++) { | |
| 141 const SkPMColor c = *colors++; | |
| 142 const unsigned a = SkGetPackedA32(c); | |
| 143 const SkUnPreMultiply::Scale s = table[a]; | |
| 144 trans[i] = a; | |
| 145 palette[i].red = SkUnPreMultiply::ApplyScale(s, SkGetPackedR32(c)); | |
| 146 palette[i].green = SkUnPreMultiply::ApplyScale(s,SkGetPackedG32(c)); | |
| 147 palette[i].blue = SkUnPreMultiply::ApplyScale(s, SkGetPackedB32(c)); | |
| 148 } | |
| 149 // now fall out of this if-block to use common code for the trailing | 158 // now fall out of this if-block to use common code for the trailing |
| 150 // opaque entries | 159 // opaque entries |
| 151 } | 160 } |
| 152 | 161 |
| 153 // these (remaining) entries are opaque | 162 // these (remaining) entries are opaque |
| 154 for (i = num_trans; i < ctCount; i++) { | 163 for (i = num_trans; i < ctCount; i++) { |
| 155 SkPMColor c = *colors++; | 164 SkPMColor c = *colors++; |
| 156 palette[i].red = SkGetPackedR32(c); | 165 palette[i].red = SkGetPackedR32(c); |
| 157 palette[i].green = SkGetPackedG32(c); | 166 palette[i].green = SkGetPackedG32(c); |
| 158 palette[i].blue = SkGetPackedB32(c); | 167 palette[i].blue = SkGetPackedB32(c); |
| 159 } | 168 } |
| 160 return num_trans; | 169 return num_trans; |
| 161 } | 170 } |
| 162 | 171 |
| 163 class SkPNGImageEncoder : public SkImageEncoder { | 172 class SkPNGImageEncoder : public SkImageEncoder { |
| 164 protected: | 173 protected: |
| 165 bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override; | 174 bool onEncode(SkWStream* stream, const SkBitmap& bm, int quality) override; |
| 166 private: | 175 private: |
| 167 bool doEncode(SkWStream* stream, const SkBitmap& bm, | 176 bool doEncode(SkWStream* stream, const SkBitmap& bm, |
| 168 const bool& hasAlpha, int colorType, | 177 SkAlphaType alphaType, int colorType, |
| 169 int bitDepth, SkColorType ct, | 178 int bitDepth, SkColorType ct, |
| 170 png_color_8& sig_bit); | 179 png_color_8& sig_bit); |
| 171 | 180 |
| 172 typedef SkImageEncoder INHERITED; | 181 typedef SkImageEncoder INHERITED; |
| 173 }; | 182 }; |
| 174 | 183 |
| 175 bool SkPNGImageEncoder::onEncode(SkWStream* stream, | 184 bool SkPNGImageEncoder::onEncode(SkWStream* stream, |
| 176 const SkBitmap& originalBitmap, | 185 const SkBitmap& originalBitmap, |
| 177 int /*quality*/) { | 186 int /*quality*/) { |
| 178 SkBitmap copy; | 187 SkBitmap copy; |
| 179 const SkBitmap* bitmap = &originalBitmap; | 188 const SkBitmap* bitmap = &originalBitmap; |
| 180 switch (originalBitmap.colorType()) { | 189 switch (originalBitmap.colorType()) { |
| 181 case kIndex_8_SkColorType: | 190 case kIndex_8_SkColorType: |
| 182 case kGray_8_SkColorType: | 191 case kGray_8_SkColorType: |
| 183 case kN32_SkColorType: | 192 case kRGBA_8888_SkColorType: |
| 193 case kBGRA_8888_SkColorType: | |
| 184 case kARGB_4444_SkColorType: | 194 case kARGB_4444_SkColorType: |
| 185 case kRGB_565_SkColorType: | 195 case kRGB_565_SkColorType: |
| 186 break; | 196 break; |
| 187 default: | 197 default: |
| 188 // TODO(scroggo): support 8888-but-not-N32 natively. | |
| 189 // TODO(scroggo): support Alpha_8 as Grayscale(black)+Alpha | 198 // TODO(scroggo): support Alpha_8 as Grayscale(black)+Alpha |
| 190 if (originalBitmap.copyTo(©, kN32_SkColorType)) { | 199 if (originalBitmap.copyTo(©, kN32_SkColorType)) { |
| 191 bitmap = © | 200 bitmap = © |
| 192 } | 201 } |
| 193 } | 202 } |
| 194 SkColorType ct = bitmap->colorType(); | 203 SkColorType ct = bitmap->colorType(); |
| 195 | 204 |
| 196 const bool hasAlpha = !bitmap->isOpaque(); | 205 SkAlphaType alphaType = bitmap->alphaType(); |
|
scroggo
2016/09/12 17:16:50
nit: could be const?
msarett
2016/09/12 19:39:19
Done.
| |
| 206 switch (alphaType) { | |
| 207 case kUnpremul_SkAlphaType: | |
| 208 if (kARGB_4444_SkColorType == ct) { | |
| 209 return false; | |
| 210 } | |
| 211 | |
| 212 break; | |
| 213 case kOpaque_SkAlphaType: | |
| 214 case kPremul_SkAlphaType: | |
| 215 break; | |
| 216 default: | |
| 217 return false; | |
| 218 } | |
| 219 | |
| 220 const bool isOpaque = (kOpaque_SkAlphaType == alphaType); | |
| 197 int bitDepth = 8; // default for color | 221 int bitDepth = 8; // default for color |
| 198 png_color_8 sig_bit; | 222 png_color_8 sig_bit; |
| 199 sk_bzero(&sig_bit, sizeof(png_color_8)); | 223 sk_bzero(&sig_bit, sizeof(png_color_8)); |
| 200 | 224 |
| 201 int colorType; | 225 int colorType; |
| 202 switch (ct) { | 226 switch (ct) { |
| 203 case kIndex_8_SkColorType: | 227 case kIndex_8_SkColorType: |
| 204 sig_bit.red = 8; | 228 sig_bit.red = 8; |
| 205 sig_bit.green = 8; | 229 sig_bit.green = 8; |
| 206 sig_bit.blue = 8; | 230 sig_bit.blue = 8; |
| 207 sig_bit.alpha = 8; | 231 sig_bit.alpha = 8; |
| 208 colorType = PNG_COLOR_TYPE_PALETTE; | 232 colorType = PNG_COLOR_TYPE_PALETTE; |
| 209 break; | 233 break; |
| 210 case kGray_8_SkColorType: | 234 case kGray_8_SkColorType: |
| 211 sig_bit.gray = 8; | 235 sig_bit.gray = 8; |
| 212 colorType = PNG_COLOR_TYPE_GRAY; | 236 colorType = PNG_COLOR_TYPE_GRAY; |
| 213 SkASSERT(!hasAlpha); | 237 SkASSERT(isOpaque); |
| 214 break; | 238 break; |
| 215 case kN32_SkColorType: | 239 case kRGBA_8888_SkColorType: |
| 240 case kBGRA_8888_SkColorType: | |
| 216 sig_bit.red = 8; | 241 sig_bit.red = 8; |
| 217 sig_bit.green = 8; | 242 sig_bit.green = 8; |
| 218 sig_bit.blue = 8; | 243 sig_bit.blue = 8; |
| 219 sig_bit.alpha = 8; | 244 sig_bit.alpha = 8; |
| 220 colorType = hasAlpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB ; | 245 colorType = isOpaque ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA ; |
| 221 break; | 246 break; |
| 222 case kARGB_4444_SkColorType: | 247 case kARGB_4444_SkColorType: |
| 223 sig_bit.red = 4; | 248 sig_bit.red = 4; |
| 224 sig_bit.green = 4; | 249 sig_bit.green = 4; |
| 225 sig_bit.blue = 4; | 250 sig_bit.blue = 4; |
| 226 sig_bit.alpha = 4; | 251 sig_bit.alpha = 4; |
| 227 colorType = hasAlpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB ; | 252 colorType = isOpaque ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGB_ALPHA ; |
| 228 break; | 253 break; |
| 229 case kRGB_565_SkColorType: | 254 case kRGB_565_SkColorType: |
| 230 sig_bit.red = 5; | 255 sig_bit.red = 5; |
| 231 sig_bit.green = 6; | 256 sig_bit.green = 6; |
| 232 sig_bit.blue = 5; | 257 sig_bit.blue = 5; |
| 233 colorType = PNG_COLOR_TYPE_RGB; | 258 colorType = PNG_COLOR_TYPE_RGB; |
| 234 SkASSERT(!hasAlpha); | 259 SkASSERT(isOpaque); |
| 235 break; | 260 break; |
| 236 default: | 261 default: |
| 237 return false; | 262 return false; |
| 238 } | 263 } |
| 239 | 264 |
| 240 SkAutoLockPixels alp(*bitmap); | 265 SkAutoLockPixels alp(*bitmap); |
| 241 // readyToDraw checks for pixels (and colortable if that is required) | 266 // readyToDraw checks for pixels (and colortable if that is required) |
| 242 if (!bitmap->readyToDraw()) { | 267 if (!bitmap->readyToDraw()) { |
| 243 return false; | 268 return false; |
| 244 } | 269 } |
| 245 | 270 |
| 246 // we must do this after we have locked the pixels | 271 // we must do this after we have locked the pixels |
| 247 SkColorTable* ctable = bitmap->getColorTable(); | 272 SkColorTable* ctable = bitmap->getColorTable(); |
| 248 if (ctable) { | 273 if (ctable) { |
| 249 if (ctable->count() == 0) { | 274 if (ctable->count() == 0) { |
| 250 return false; | 275 return false; |
| 251 } | 276 } |
| 252 // check if we can store in fewer than 8 bits | 277 // check if we can store in fewer than 8 bits |
| 253 bitDepth = computeBitDepth(ctable->count()); | 278 bitDepth = computeBitDepth(ctable->count()); |
| 254 } | 279 } |
| 255 | 280 |
| 256 return doEncode(stream, *bitmap, hasAlpha, colorType, bitDepth, ct, sig_bit) ; | 281 return doEncode(stream, *bitmap, alphaType, colorType, bitDepth, ct, sig_bit ); |
| 257 } | 282 } |
| 258 | 283 |
| 259 bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, | 284 bool SkPNGImageEncoder::doEncode(SkWStream* stream, const SkBitmap& bitmap, |
| 260 const bool& hasAlpha, int colorType, | 285 SkAlphaType alphaType, int colorType, |
| 261 int bitDepth, SkColorType ct, | 286 int bitDepth, SkColorType ct, |
| 262 png_color_8& sig_bit) { | 287 png_color_8& sig_bit) { |
| 263 | 288 |
| 264 png_structp png_ptr; | 289 png_structp png_ptr; |
| 265 png_infop info_ptr; | 290 png_infop info_ptr; |
| 266 | 291 |
| 267 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, sk_error_f n, | 292 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, sk_error_f n, |
| 268 nullptr); | 293 nullptr); |
| 269 if (nullptr == png_ptr) { | 294 if (nullptr == png_ptr) { |
| 270 return false; | 295 return false; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 298 png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(), | 323 png_set_IHDR(png_ptr, info_ptr, bitmap.width(), bitmap.height(), |
| 299 bitDepth, colorType, | 324 bitDepth, colorType, |
| 300 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, | 325 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, |
| 301 PNG_FILTER_TYPE_BASE); | 326 PNG_FILTER_TYPE_BASE); |
| 302 | 327 |
| 303 // set our colortable/trans arrays if needed | 328 // set our colortable/trans arrays if needed |
| 304 png_color paletteColors[256]; | 329 png_color paletteColors[256]; |
| 305 png_byte trans[256]; | 330 png_byte trans[256]; |
| 306 if (kIndex_8_SkColorType == ct) { | 331 if (kIndex_8_SkColorType == ct) { |
| 307 SkColorTable* ct = bitmap.getColorTable(); | 332 SkColorTable* ct = bitmap.getColorTable(); |
| 308 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); | 333 int numTrans = pack_palette(ct, paletteColors, trans, alphaType); |
| 309 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); | 334 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); |
| 310 if (numTrans > 0) { | 335 if (numTrans > 0) { |
| 311 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); | 336 png_set_tRNS(png_ptr, info_ptr, trans, numTrans, nullptr); |
| 312 } | 337 } |
| 313 } | 338 } |
| 314 | 339 |
| 315 png_set_sBIT(png_ptr, info_ptr, &sig_bit); | 340 png_set_sBIT(png_ptr, info_ptr, &sig_bit); |
| 316 png_write_info(png_ptr, info_ptr); | 341 png_write_info(png_ptr, info_ptr); |
| 317 | 342 |
| 318 const char* srcImage = (const char*)bitmap.getPixels(); | 343 const uint8_t* srcImage = (const uint8_t*)bitmap.getPixels(); |
| 319 SkAutoSTMalloc<1024, char> rowStorage(bitmap.width() << 2); | 344 SkAutoSTMalloc<1024, uint8_t> rowStorage(bitmap.width() << 2); |
| 320 char* storage = rowStorage.get(); | 345 uint8_t* storage = rowStorage.get(); |
| 321 transform_scanline_proc proc = choose_proc(ct, hasAlpha); | 346 transform_scanline_proc proc = choose_proc(ct, alphaType); |
| 322 | 347 |
| 323 for (int y = 0; y < bitmap.height(); y++) { | 348 for (int y = 0; y < bitmap.height(); y++) { |
| 324 png_bytep row_ptr = (png_bytep)storage; | 349 png_bytep row_ptr = (png_bytep)storage; |
| 325 proc(srcImage, bitmap.width(), storage); | 350 proc(storage, srcImage, bitmap.width(), SkColorTypeBytesPerPixel(ct)); |
| 326 png_write_rows(png_ptr, &row_ptr, 1); | 351 png_write_rows(png_ptr, &row_ptr, 1); |
| 327 srcImage += bitmap.rowBytes(); | 352 srcImage += bitmap.rowBytes(); |
| 328 } | 353 } |
| 329 | 354 |
| 330 png_write_end(png_ptr, info_ptr); | 355 png_write_end(png_ptr, info_ptr); |
| 331 | 356 |
| 332 /* clean up after the write, and free any memory allocated */ | 357 /* clean up after the write, and free any memory allocated */ |
| 333 png_destroy_write_struct(&png_ptr, &info_ptr); | 358 png_destroy_write_struct(&png_ptr, &info_ptr); |
| 334 return true; | 359 return true; |
| 335 } | 360 } |
| 336 | 361 |
| 337 /////////////////////////////////////////////////////////////////////////////// | 362 /////////////////////////////////////////////////////////////////////////////// |
| 338 DEFINE_ENCODER_CREATOR(PNGImageEncoder); | 363 DEFINE_ENCODER_CREATOR(PNGImageEncoder); |
| 339 /////////////////////////////////////////////////////////////////////////////// | 364 /////////////////////////////////////////////////////////////////////////////// |
| 340 | 365 |
| 341 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { | 366 SkImageEncoder* sk_libpng_efactory(SkImageEncoder::Type t) { |
| 342 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; | 367 return (SkImageEncoder::kPNG_Type == t) ? new SkPNGImageEncoder : nullptr; |
| 343 } | 368 } |
| 344 | 369 |
| 345 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); | 370 static SkImageEncoder_EncodeReg gEReg(sk_libpng_efactory); |
| OLD | NEW |