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_RGBX
}, |
75 { kN32_SkColorType, true, transform_scanline_8888 }, | 69 { kBGRA_8888_SkColorType, kOpaque_SkAlphaType, transform_scanline_BGRX
}, |
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 (auto entry : gMap) { |
83 if (gMap[i].fColorType == ct && gMap[i].fHasAlpha == hasAlpha) { | 83 if (entry.fColorType == ct && entry.fAlphaType == alphaType) { |
84 return gMap[i].fProc; | 84 return entry.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 |
94 static int computeBitDepth(int colorCount) { | 94 static int computeBitDepth(int colorCount) { |
(...skipping 10 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) { |
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 const SkAlphaType alphaType = bitmap->alphaType(); |
| 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 26 matching lines...) Expand all Loading... |
297 | 322 |
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* colorTable = bitmap.getColorTable(); |
308 int numTrans = pack_palette(ct, paletteColors, trans, hasAlpha); | 333 int numTrans = pack_palette(colorTable, paletteColors, trans, alphaType)
; |
309 png_set_PLTE(png_ptr, info_ptr, paletteColors, ct->count()); | 334 png_set_PLTE(png_ptr, info_ptr, paletteColors, colorTable->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 char* srcImage = (const char*)bitmap.getPixels(); |
319 SkAutoSTMalloc<1024, char> rowStorage(bitmap.width() << 2); | 344 SkAutoSTMalloc<1024, char> rowStorage(bitmap.width() << 2); |
320 char* storage = rowStorage.get(); | 345 char* 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 |