blob: 6cde0cb08791a01b2fdbf69829fb586c9e84de71 [file] [log] [blame]
epoger@google.com4ce738b2012-11-16 18:44:18 +00001/*
2 * Copyright 2012 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
Matt Sarett5df93de2017-03-22 21:52:47 +00007
8#ifndef SkImageEncoderFns_DEFINED
9#define SkImageEncoderFns_DEFINED
epoger@google.com4ce738b2012-11-16 18:44:18 +000010
11/**
12 * Functions to transform scanlines between packed-pixel formats.
13 */
14
15#include "SkBitmap.h"
16#include "SkColor.h"
Cary Clarka4083c92017-09-15 11:59:23 -040017#include "SkColorData.h"
Matt Sarett5df93de2017-03-22 21:52:47 +000018#include "SkICC.h"
Matt Sarett2e61b182017-05-09 12:46:50 -040019#include "SkOpts.h"
epoger@google.com4ce738b2012-11-16 18:44:18 +000020#include "SkPreConfig.h"
Matt Sarett84014f02017-01-10 11:28:54 -050021#include "SkRasterPipeline.h"
epoger@google.com4ce738b2012-11-16 18:44:18 +000022#include "SkUnPreMultiply.h"
Matt Sarettc7b29082017-02-09 16:22:39 -050023#include "SkUnPreMultiplyPriv.h"
Mike Klein45c16fa2017-07-18 18:15:13 -040024#include "../jumper/SkJumper.h"
epoger@google.com4ce738b2012-11-16 18:44:18 +000025
26/**
27 * Function template for transforming scanlines.
28 * Transform 'width' pixels from 'src' buffer into 'dst' buffer,
29 * repacking color channel data as appropriate for the given transformation.
msarettf17b71f2016-09-12 14:30:03 -070030 * 'bpp' is bytes per pixel in the 'src' buffer.
epoger@google.com4ce738b2012-11-16 18:44:18 +000031 */
msarettf17b71f2016-09-12 14:30:03 -070032typedef void (*transform_scanline_proc)(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
Matt Sarett62bb2802017-01-23 12:28:02 -050033 int width, int bpp, const SkPMColor* colors);
epoger@google.com4ce738b2012-11-16 18:44:18 +000034
35/**
36 * Identity transformation: just copy bytes from src to dst.
37 */
Matt Sarett62bb2802017-01-23 12:28:02 -050038static inline void transform_scanline_memcpy(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
39 int width, int bpp, const SkPMColor*) {
msarettf17b71f2016-09-12 14:30:03 -070040 memcpy(dst, src, width * bpp);
epoger@google.com4ce738b2012-11-16 18:44:18 +000041}
42
Matt Sarett62bb2802017-01-23 12:28:02 -050043static inline void transform_scanline_index8_opaque(char* SK_RESTRICT dst,
44 const char* SK_RESTRICT src, int width, int,
45 const SkPMColor* colors) {
46 for (int i = 0; i < width; i++) {
47 const uint32_t c = colors[(uint8_t)*src++];
48 dst[0] = SkGetPackedR32(c);
49 dst[1] = SkGetPackedG32(c);
50 dst[2] = SkGetPackedB32(c);
51 dst += 3;
52 }
53}
54
55static inline void transform_scanline_index8_unpremul(char* SK_RESTRICT dst,
56 const char* SK_RESTRICT src, int width, int,
57 const SkPMColor* colors) {
58 uint32_t* SK_RESTRICT dst32 = (uint32_t*) dst;
59 for (int i = 0; i < width; i++) {
60 // This function swizzles R and B on platforms where SkPMColor is BGRA. This is
61 // exactly what we want.
62 dst32[i] = SkSwizzle_RGBA_to_PMColor(colors[(uint8_t)*src++]);
63 }
64}
65
66static inline void transform_scanline_gray(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
67 int width, int, const SkPMColor* colors) {
68 for (int i = 0; i < width; i++) {
69 const uint8_t g = (uint8_t) *src++;
70 dst[0] = g;
71 dst[1] = g;
72 dst[2] = g;
73 dst += 3;
74 }
75}
76
epoger@google.com4ce738b2012-11-16 18:44:18 +000077/**
78 * Transform from kRGB_565_Config to 3-bytes-per-pixel RGB.
79 * Alpha channel data is not present in kRGB_565_Config format, so there is no
80 * alpha channel data to preserve.
81 */
Matt Sarett62bb2802017-01-23 12:28:02 -050082static inline void transform_scanline_565(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
83 int width, int, const SkPMColor*) {
msarettf17b71f2016-09-12 14:30:03 -070084 const uint16_t* srcP = (const uint16_t*)src;
epoger@google.com4ce738b2012-11-16 18:44:18 +000085 for (int i = 0; i < width; i++) {
86 unsigned c = *srcP++;
87 *dst++ = SkPacked16ToR32(c);
88 *dst++ = SkPacked16ToG32(c);
89 *dst++ = SkPacked16ToB32(c);
90 }
91}
92
93/**
Mike Reedd6cb11e2017-11-30 15:33:04 -050094 * Transform from kAlpha_8_Config to 2-bytes-per-pixel GrayAlpha.
95 */
96static inline void transform_scanline_A8_to_GrayAlpha(char* SK_RESTRICT dst,
97 const char* SK_RESTRICT src,
98 int width, int, const SkPMColor*) {
99 for (int i = 0; i < width; i++) {
100 *dst++ = 0; // gray (ignored)
101 *dst++ = *src++; // alpha
102 }
103}
104
105/**
msarettf17b71f2016-09-12 14:30:03 -0700106 * Transform from kRGBA_8888_SkColorType to 3-bytes-per-pixel RGB.
107 * Alpha channel data is abandoned.
epoger@google.com4ce738b2012-11-16 18:44:18 +0000108 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500109static inline void transform_scanline_RGBX(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
110 int width, int, const SkPMColor*) {
msarettf17b71f2016-09-12 14:30:03 -0700111 const uint32_t* srcP = (const SkPMColor*)src;
epoger@google.com4ce738b2012-11-16 18:44:18 +0000112 for (int i = 0; i < width; i++) {
msarettf17b71f2016-09-12 14:30:03 -0700113 uint32_t c = *srcP++;
114 *dst++ = (c >> 0) & 0xFF;
115 *dst++ = (c >> 8) & 0xFF;
116 *dst++ = (c >> 16) & 0xFF;
117 }
118}
119
120/**
121 * Transform from kBGRA_8888_SkColorType to 3-bytes-per-pixel RGB.
122 * Alpha channel data is abandoned.
123 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500124static inline void transform_scanline_BGRX(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
125 int width, int, const SkPMColor*) {
msarettf17b71f2016-09-12 14:30:03 -0700126 const uint32_t* srcP = (const SkPMColor*)src;
127 for (int i = 0; i < width; i++) {
128 uint32_t c = *srcP++;
129 *dst++ = (c >> 16) & 0xFF;
130 *dst++ = (c >> 8) & 0xFF;
131 *dst++ = (c >> 0) & 0xFF;
epoger@google.com4ce738b2012-11-16 18:44:18 +0000132 }
133}
134
135/**
136 * Transform from kARGB_4444_Config to 3-bytes-per-pixel RGB.
137 * Alpha channel data, if any, is abandoned.
138 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500139static inline void transform_scanline_444(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
140 int width, int, const SkPMColor*) {
msarettf17b71f2016-09-12 14:30:03 -0700141 const SkPMColor16* srcP = (const SkPMColor16*)src;
epoger@google.com4ce738b2012-11-16 18:44:18 +0000142 for (int i = 0; i < width; i++) {
143 SkPMColor16 c = *srcP++;
144 *dst++ = SkPacked4444ToR32(c);
145 *dst++ = SkPacked4444ToG32(c);
146 *dst++ = SkPacked4444ToB32(c);
147 }
148}
149
epoger@google.com4ce738b2012-11-16 18:44:18 +0000150/**
Matt Sarett84014f02017-01-10 11:28:54 -0500151 * Transform from legacy kPremul, kRGBA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA.
152 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500153static inline void transform_scanline_rgbA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
154 int width, int, const SkPMColor*) {
Matt Sarettc7b29082017-02-09 16:22:39 -0500155 SkUnpremultiplyRow<false>((uint32_t*) dst, (const uint32_t*) src, width);
Matt Sarett84014f02017-01-10 11:28:54 -0500156}
157
158/**
159 * Transform from legacy kPremul, kBGRA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA.
160 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500161static inline void transform_scanline_bgrA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
162 int width, int, const SkPMColor*) {
Matt Sarettc7b29082017-02-09 16:22:39 -0500163 SkUnpremultiplyRow<true>((uint32_t*) dst, (const uint32_t*) src, width);
Matt Sarett84014f02017-01-10 11:28:54 -0500164}
165
Matt Sarett84014f02017-01-10 11:28:54 -0500166/**
Matt Sarett2e61b182017-05-09 12:46:50 -0400167 * Premultiply RGBA to rgbA.
168 */
169static inline void transform_scanline_to_premul_legacy(char* SK_RESTRICT dst,
170 const char* SK_RESTRICT src,
171 int width, int, const SkPMColor*) {
172 SkOpts::RGBA_to_rgbA((uint32_t*)dst, (const uint32_t*)src, width);
173}
174
175/**
msarettf17b71f2016-09-12 14:30:03 -0700176 * Transform from kUnpremul, kBGRA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA.
177 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500178static inline void transform_scanline_BGRA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
179 int width, int, const SkPMColor*) {
msarettf17b71f2016-09-12 14:30:03 -0700180 const uint32_t* srcP = (const SkPMColor*)src;
181 for (int i = 0; i < width; i++) {
182 uint32_t c = *srcP++;
183 *dst++ = (c >> 16) & 0xFF;
184 *dst++ = (c >> 8) & 0xFF;
185 *dst++ = (c >> 0) & 0xFF;
186 *dst++ = (c >> 24) & 0xFF;
187 }
188}
189
190/**
epoger@google.com4ce738b2012-11-16 18:44:18 +0000191 * Transform from kARGB_8888_Config to 4-bytes-per-pixel RGBA,
192 * with scaling of RGB based on alpha channel.
193 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500194static inline void transform_scanline_4444(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
195 int width, int, const SkPMColor*) {
msarettf17b71f2016-09-12 14:30:03 -0700196 const SkPMColor16* srcP = (const SkPMColor16*)src;
197 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
epoger@google.com4ce738b2012-11-16 18:44:18 +0000198
199 for (int i = 0; i < width; i++) {
200 SkPMColor16 c = *srcP++;
201 unsigned a = SkPacked4444ToA32(c);
202 unsigned r = SkPacked4444ToR32(c);
203 unsigned g = SkPacked4444ToG32(c);
204 unsigned b = SkPacked4444ToB32(c);
205
206 if (0 != a && 255 != a) {
207 SkUnPreMultiply::Scale scale = table[a];
208 r = SkUnPreMultiply::ApplyScale(scale, r);
209 g = SkUnPreMultiply::ApplyScale(scale, g);
210 b = SkUnPreMultiply::ApplyScale(scale, b);
211 }
212 *dst++ = r;
213 *dst++ = g;
214 *dst++ = b;
215 *dst++ = a;
216 }
217}
Matt Sarett1da27ef2017-01-19 17:14:07 -0500218
Mike Kleinac568a92018-01-25 09:09:32 -0500219// 888x is opaque RGB in four bytes, with 8 junk bits. We convert that to 3 byte RGB.
220static inline void transform_scanline_888x(char* dst, const char* src,
221 int width, int, const SkPMColor*) {
222 while (width --> 0) {
223 dst[0] = src[0];
224 dst[1] = src[1];
225 dst[2] = src[2];
226 dst += 3;
227 src += 4;
228 }
229}
230
231// 101010x is opaque RGB in four bytes, with 2 bits junk. We convert to 6 byte RGB (big endian).
232static inline void transform_scanline_101010x(char* dst, const char* src,
233 int width, int, const SkPMColor*) {
234 auto d = ( uint16_t*)dst;
235 auto s = (const uint32_t*)src;
236 while (width --> 0) {
237 uint32_t r = (*s >> 0) & 1023,
238 g = (*s >> 10) & 1023,
239 b = (*s >> 20) & 1023;
240
241 // Scale 10-bit unorms to 16-bit by replicating the most significant bits.
242 r = (r << 6) | (r >> 4);
243 g = (g << 6) | (g >> 4);
244 b = (b << 6) | (b >> 4);
245
246 // Store big-endian.
247 d[0] = (r >> 8) | (r << 8);
248 d[1] = (g >> 8) | (g << 8);
249 d[2] = (b >> 8) | (b << 8);
250
251 d += 3; // 3 channels
252 s += 1; // 1 whole pixel
253 }
254}
255
256static inline void transform_scanline_1010102(char* dst, const char* src,
257 int width, int, const SkPMColor*) {
258 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
259 dst_ctx = { (void*)dst, 0 };
260 SkRasterPipeline_<256> p;
261 p.append(SkRasterPipeline::load_1010102, &src_ctx);
262 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
263 p.run(0,0, width,1);
264}
265
266static inline void transform_scanline_1010102_premul(char* dst, const char* src,
267 int width, int, const SkPMColor*) {
268 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
269 dst_ctx = { (void*)dst, 0 };
270 SkRasterPipeline_<256> p;
271 p.append(SkRasterPipeline::load_1010102, &src_ctx);
272 p.append(SkRasterPipeline::unpremul);
273 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
274 p.run(0,0, width,1);
275}
276
Matt Sarett1da27ef2017-01-19 17:14:07 -0500277/**
Matt Sarett55213562017-01-23 19:37:37 -0500278 * Transform from kRGBA_F16 to 8-bytes-per-pixel RGBA.
Matt Sarett1da27ef2017-01-19 17:14:07 -0500279 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500280static inline void transform_scanline_F16(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
281 int width, int, const SkPMColor*) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400282 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
283 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400284 SkRasterPipeline_<256> p;
Mike Klein45c16fa2017-07-18 18:15:13 -0400285 p.append(SkRasterPipeline::load_f16, &src_ctx);
Mike Kleince988012017-07-21 13:11:37 -0400286 p.append(SkRasterPipeline::clamp_0); // F16 values may be out of [0,1] range, so clamp.
287 p.append(SkRasterPipeline::clamp_1);
Mike Klein45c16fa2017-07-18 18:15:13 -0400288 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
289 p.run(0,0, width,1);
Matt Sarett1da27ef2017-01-19 17:14:07 -0500290}
291
292/**
Matt Sarett55213562017-01-23 19:37:37 -0500293 * Transform from kPremul, kRGBA_F16 to 8-bytes-per-pixel RGBA.
Matt Sarett1da27ef2017-01-19 17:14:07 -0500294 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500295static inline void transform_scanline_F16_premul(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
296 int width, int, const SkPMColor*) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400297 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
298 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400299 SkRasterPipeline_<256> p;
Mike Klein45c16fa2017-07-18 18:15:13 -0400300 p.append(SkRasterPipeline::load_f16, &src_ctx);
Matt Sarett1da27ef2017-01-19 17:14:07 -0500301 p.append(SkRasterPipeline::unpremul);
Mike Kleince988012017-07-21 13:11:37 -0400302 p.append(SkRasterPipeline::clamp_0); // F16 values may be out of [0,1] range, so clamp.
303 p.append(SkRasterPipeline::clamp_1);
Mike Klein45c16fa2017-07-18 18:15:13 -0400304 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
305 p.run(0,0, width,1);
Matt Sarett1da27ef2017-01-19 17:14:07 -0500306}
Matt Sarett55213562017-01-23 19:37:37 -0500307
308/**
309 * Transform from kRGBA_F16 to 4-bytes-per-pixel RGBA.
310 */
311static inline void transform_scanline_F16_to_8888(char* SK_RESTRICT dst,
312 const char* SK_RESTRICT src, int width, int,
313 const SkPMColor*) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400314 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
315 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400316 SkRasterPipeline_<256> p;
Mike Klein45c16fa2017-07-18 18:15:13 -0400317 p.append(SkRasterPipeline::load_f16, &src_ctx);
Mike Kleince988012017-07-21 13:11:37 -0400318 p.append(SkRasterPipeline::clamp_0); // F16 values may be out of [0,1] range, so clamp.
319 p.append(SkRasterPipeline::clamp_1);
Mike Klein45c16fa2017-07-18 18:15:13 -0400320 p.append(SkRasterPipeline::store_8888, &dst_ctx);
321 p.run(0,0, width,1);
Matt Sarett55213562017-01-23 19:37:37 -0500322}
323
324/**
325 * Transform from kPremul, kRGBA_F16 to 4-bytes-per-pixel RGBA.
326 */
327static inline void transform_scanline_F16_premul_to_8888(char* SK_RESTRICT dst,
328 const char* SK_RESTRICT src, int width,
329 int, const SkPMColor*) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400330 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
331 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400332 SkRasterPipeline_<256> p;
Mike Klein45c16fa2017-07-18 18:15:13 -0400333 p.append(SkRasterPipeline::load_f16, &src_ctx);
Matt Sarett55213562017-01-23 19:37:37 -0500334 p.append(SkRasterPipeline::unpremul);
Mike Kleince988012017-07-21 13:11:37 -0400335 p.append(SkRasterPipeline::clamp_0); // F16 values may be out of [0,1] range, so clamp.
336 p.append(SkRasterPipeline::clamp_1);
Mike Klein45c16fa2017-07-18 18:15:13 -0400337 p.append(SkRasterPipeline::store_8888, &dst_ctx);
338 p.run(0,0, width,1);
Matt Sarett55213562017-01-23 19:37:37 -0500339}
Matt Sarett5df93de2017-03-22 21:52:47 +0000340
Matt Sarett2e61b182017-05-09 12:46:50 -0400341/**
342 * Transform from kUnpremul, kRGBA_F16 to premultiplied rgbA 8888.
343 */
344static inline void transform_scanline_F16_to_premul_8888(char* SK_RESTRICT dst,
345 const char* SK_RESTRICT src, int width, int, const SkPMColor*) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400346 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
347 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400348 SkRasterPipeline_<256> p;
Mike Klein45c16fa2017-07-18 18:15:13 -0400349 p.append(SkRasterPipeline::load_f16, &src_ctx);
Mike Kleince988012017-07-21 13:11:37 -0400350 p.append(SkRasterPipeline::clamp_0); // F16 values may be out of [0,1] range, so clamp.
351 p.append(SkRasterPipeline::clamp_1);
Matt Sarett2e61b182017-05-09 12:46:50 -0400352 p.append(SkRasterPipeline::premul);
Mike Klein45c16fa2017-07-18 18:15:13 -0400353 p.append(SkRasterPipeline::store_8888, &dst_ctx);
354 p.run(0,0, width,1);
Matt Sarett2e61b182017-05-09 12:46:50 -0400355}
356
Mike Klein37854712018-06-26 11:43:06 -0400357/**
358 * Transform from kRGBA_F32 to 8-bytes-per-pixel RGBA.
359 */
360static inline void transform_scanline_F32(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
361 int width, int, const SkPMColor*) {
362 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
363 dst_ctx = { (void*)dst, 0 };
364 SkRasterPipeline_<256> p;
365 p.append(SkRasterPipeline::load_f32, &src_ctx);
366 p.append(SkRasterPipeline::clamp_0); // F32 values may be out of [0,1] range, so clamp.
367 p.append(SkRasterPipeline::clamp_1);
Mike Klein37854712018-06-26 11:43:06 -0400368 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
369 p.run(0,0, width,1);
370}
371
372/**
373 * Transform from kPremul, kRGBA_F32 to 8-bytes-per-pixel RGBA.
374 */
375static inline void transform_scanline_F32_premul(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
376 int width, int, const SkPMColor*) {
377 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
378 dst_ctx = { (void*)dst, 0 };
379 SkRasterPipeline_<256> p;
380 p.append(SkRasterPipeline::load_f32, &src_ctx);
381 p.append(SkRasterPipeline::unpremul);
382 p.append(SkRasterPipeline::clamp_0); // F32 values may be out of [0,1] range, so clamp.
383 p.append(SkRasterPipeline::clamp_1);
Mike Klein37854712018-06-26 11:43:06 -0400384 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
385 p.run(0,0, width,1);
386}
387
Matt Sarett1950e0a2017-06-12 16:17:30 -0400388static inline sk_sp<SkData> icc_from_color_space(const SkImageInfo& info) {
389 SkColorSpace* cs = info.colorSpace();
390 if (!cs) {
391 return nullptr;
392 }
393
Matt Sarett5df93de2017-03-22 21:52:47 +0000394 SkColorSpaceTransferFn fn;
Mike Klein4429a4f2018-10-04 09:06:00 -0400395 SkMatrix44 toXYZD50;
Matt Sarett1950e0a2017-06-12 16:17:30 -0400396 if (cs->isNumericalTransferFn(&fn) && cs->toXYZD50(&toXYZD50)) {
Matt Sarett5df93de2017-03-22 21:52:47 +0000397 return SkICC::WriteToICC(fn, toXYZD50);
398 }
Matt Sarett5df93de2017-03-22 21:52:47 +0000399 return nullptr;
400}
401
402#endif // SkImageEncoderFns_DEFINED