blob: 6bf0081b266976bc04d825ac83a2a03d74f626f9 [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
166template <bool kIsRGBA>
Matt Sarett1da27ef2017-01-19 17:14:07 -0500167static inline void transform_scanline_unpremultiply_sRGB(void* dst, const void* src, int width) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400168 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
169 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400170 SkRasterPipeline_<256> p;
Mike Kleinc2d20762017-06-27 19:53:21 -0400171 if (kIsRGBA) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400172 p.append(SkRasterPipeline::load_8888, &src_ctx);
Mike Kleinc2d20762017-06-27 19:53:21 -0400173 } else {
Mike Klein45c16fa2017-07-18 18:15:13 -0400174 p.append(SkRasterPipeline::load_bgra, &src_ctx);
Matt Sarett84014f02017-01-10 11:28:54 -0500175 }
176
Mike Kleinf1f11622017-12-18 14:07:31 -0500177 p.append(SkRasterPipeline::from_srgb);
Matt Sarett84014f02017-01-10 11:28:54 -0500178 p.append(SkRasterPipeline::unpremul);
179 p.append(SkRasterPipeline::to_srgb);
Mike Klein45c16fa2017-07-18 18:15:13 -0400180 p.append(SkRasterPipeline::store_8888, &dst_ctx);
181 p.run(0,0, width,1);
Matt Sarett84014f02017-01-10 11:28:54 -0500182}
183
184/**
Matt Sarett2e61b182017-05-09 12:46:50 -0400185 * Premultiply RGBA to rgbA.
186 */
187static inline void transform_scanline_to_premul_legacy(char* SK_RESTRICT dst,
188 const char* SK_RESTRICT src,
189 int width, int, const SkPMColor*) {
190 SkOpts::RGBA_to_rgbA((uint32_t*)dst, (const uint32_t*)src, width);
191}
192
193/**
194 * Premultiply RGBA to rgbA linearly.
195 */
196static inline void transform_scanline_to_premul_linear(char* SK_RESTRICT dst,
197 const char* SK_RESTRICT src,
198 int width, int, const SkPMColor*) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400199 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
200 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400201 SkRasterPipeline_<256> p;
Mike Klein45c16fa2017-07-18 18:15:13 -0400202 p.append(SkRasterPipeline::load_8888, &src_ctx);
Mike Kleinf1f11622017-12-18 14:07:31 -0500203 p.append(SkRasterPipeline::from_srgb);
Matt Sarett2e61b182017-05-09 12:46:50 -0400204 p.append(SkRasterPipeline::premul);
205 p.append(SkRasterPipeline::to_srgb);
Mike Klein45c16fa2017-07-18 18:15:13 -0400206 p.append(SkRasterPipeline::store_8888, &dst_ctx);
207 p.run(0,0, width,1);
Matt Sarett2e61b182017-05-09 12:46:50 -0400208}
209
210/**
msarettf17b71f2016-09-12 14:30:03 -0700211 * Transform from kPremul, kRGBA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA.
212 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500213static inline void transform_scanline_srgbA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
214 int width, int, const SkPMColor*) {
Matt Sarett1da27ef2017-01-19 17:14:07 -0500215 transform_scanline_unpremultiply_sRGB<true>(dst, src, width);
msarettf17b71f2016-09-12 14:30:03 -0700216}
217
218/**
219 * Transform from kPremul, kBGRA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA.
220 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500221static inline void transform_scanline_sbgrA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
222 int width, int, const SkPMColor*) {
Matt Sarett1da27ef2017-01-19 17:14:07 -0500223 transform_scanline_unpremultiply_sRGB<false>(dst, src, width);
msarettf17b71f2016-09-12 14:30:03 -0700224}
225
226/**
227 * Transform from kUnpremul, kBGRA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA.
228 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500229static inline void transform_scanline_BGRA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
230 int width, int, const SkPMColor*) {
msarettf17b71f2016-09-12 14:30:03 -0700231 const uint32_t* srcP = (const SkPMColor*)src;
232 for (int i = 0; i < width; i++) {
233 uint32_t c = *srcP++;
234 *dst++ = (c >> 16) & 0xFF;
235 *dst++ = (c >> 8) & 0xFF;
236 *dst++ = (c >> 0) & 0xFF;
237 *dst++ = (c >> 24) & 0xFF;
238 }
239}
240
241/**
epoger@google.com4ce738b2012-11-16 18:44:18 +0000242 * Transform from kARGB_8888_Config to 4-bytes-per-pixel RGBA,
243 * with scaling of RGB based on alpha channel.
244 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500245static inline void transform_scanline_4444(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
246 int width, int, const SkPMColor*) {
msarettf17b71f2016-09-12 14:30:03 -0700247 const SkPMColor16* srcP = (const SkPMColor16*)src;
248 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
epoger@google.com4ce738b2012-11-16 18:44:18 +0000249
250 for (int i = 0; i < width; i++) {
251 SkPMColor16 c = *srcP++;
252 unsigned a = SkPacked4444ToA32(c);
253 unsigned r = SkPacked4444ToR32(c);
254 unsigned g = SkPacked4444ToG32(c);
255 unsigned b = SkPacked4444ToB32(c);
256
257 if (0 != a && 255 != a) {
258 SkUnPreMultiply::Scale scale = table[a];
259 r = SkUnPreMultiply::ApplyScale(scale, r);
260 g = SkUnPreMultiply::ApplyScale(scale, g);
261 b = SkUnPreMultiply::ApplyScale(scale, b);
262 }
263 *dst++ = r;
264 *dst++ = g;
265 *dst++ = b;
266 *dst++ = a;
267 }
268}
Matt Sarett1da27ef2017-01-19 17:14:07 -0500269
Mike Kleinac568a92018-01-25 09:09:32 -0500270// 888x is opaque RGB in four bytes, with 8 junk bits. We convert that to 3 byte RGB.
271static inline void transform_scanline_888x(char* dst, const char* src,
272 int width, int, const SkPMColor*) {
273 while (width --> 0) {
274 dst[0] = src[0];
275 dst[1] = src[1];
276 dst[2] = src[2];
277 dst += 3;
278 src += 4;
279 }
280}
281
282// 101010x is opaque RGB in four bytes, with 2 bits junk. We convert to 6 byte RGB (big endian).
283static inline void transform_scanline_101010x(char* dst, const char* src,
284 int width, int, const SkPMColor*) {
285 auto d = ( uint16_t*)dst;
286 auto s = (const uint32_t*)src;
287 while (width --> 0) {
288 uint32_t r = (*s >> 0) & 1023,
289 g = (*s >> 10) & 1023,
290 b = (*s >> 20) & 1023;
291
292 // Scale 10-bit unorms to 16-bit by replicating the most significant bits.
293 r = (r << 6) | (r >> 4);
294 g = (g << 6) | (g >> 4);
295 b = (b << 6) | (b >> 4);
296
297 // Store big-endian.
298 d[0] = (r >> 8) | (r << 8);
299 d[1] = (g >> 8) | (g << 8);
300 d[2] = (b >> 8) | (b << 8);
301
302 d += 3; // 3 channels
303 s += 1; // 1 whole pixel
304 }
305}
306
307static inline void transform_scanline_1010102(char* dst, const char* src,
308 int width, int, const SkPMColor*) {
309 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
310 dst_ctx = { (void*)dst, 0 };
311 SkRasterPipeline_<256> p;
312 p.append(SkRasterPipeline::load_1010102, &src_ctx);
313 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
314 p.run(0,0, width,1);
315}
316
317static inline void transform_scanline_1010102_premul(char* dst, const char* src,
318 int width, int, const SkPMColor*) {
319 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
320 dst_ctx = { (void*)dst, 0 };
321 SkRasterPipeline_<256> p;
322 p.append(SkRasterPipeline::load_1010102, &src_ctx);
323 p.append(SkRasterPipeline::unpremul);
324 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
325 p.run(0,0, width,1);
326}
327
Matt Sarett1da27ef2017-01-19 17:14:07 -0500328/**
Matt Sarett55213562017-01-23 19:37:37 -0500329 * Transform from kRGBA_F16 to 8-bytes-per-pixel RGBA.
Matt Sarett1da27ef2017-01-19 17:14:07 -0500330 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500331static inline void transform_scanline_F16(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
332 int width, int, const SkPMColor*) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400333 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
334 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400335 SkRasterPipeline_<256> p;
Mike Klein45c16fa2017-07-18 18:15:13 -0400336 p.append(SkRasterPipeline::load_f16, &src_ctx);
Mike Kleince988012017-07-21 13:11:37 -0400337 p.append(SkRasterPipeline::clamp_0); // F16 values may be out of [0,1] range, so clamp.
338 p.append(SkRasterPipeline::clamp_1);
Matt Sarett1950e0a2017-06-12 16:17:30 -0400339 p.append(SkRasterPipeline::to_srgb);
Mike Klein45c16fa2017-07-18 18:15:13 -0400340 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
341 p.run(0,0, width,1);
Matt Sarett1da27ef2017-01-19 17:14:07 -0500342}
343
344/**
Matt Sarett55213562017-01-23 19:37:37 -0500345 * Transform from kPremul, kRGBA_F16 to 8-bytes-per-pixel RGBA.
Matt Sarett1da27ef2017-01-19 17:14:07 -0500346 */
Matt Sarett62bb2802017-01-23 12:28:02 -0500347static inline void transform_scanline_F16_premul(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
348 int width, int, const SkPMColor*) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400349 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
350 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400351 SkRasterPipeline_<256> p;
Mike Klein45c16fa2017-07-18 18:15:13 -0400352 p.append(SkRasterPipeline::load_f16, &src_ctx);
Matt Sarett1da27ef2017-01-19 17:14:07 -0500353 p.append(SkRasterPipeline::unpremul);
Mike Kleince988012017-07-21 13:11:37 -0400354 p.append(SkRasterPipeline::clamp_0); // F16 values may be out of [0,1] range, so clamp.
355 p.append(SkRasterPipeline::clamp_1);
Matt Sarett1950e0a2017-06-12 16:17:30 -0400356 p.append(SkRasterPipeline::to_srgb);
Mike Klein45c16fa2017-07-18 18:15:13 -0400357 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
358 p.run(0,0, width,1);
Matt Sarett1da27ef2017-01-19 17:14:07 -0500359}
Matt Sarett55213562017-01-23 19:37:37 -0500360
361/**
362 * Transform from kRGBA_F16 to 4-bytes-per-pixel RGBA.
363 */
364static inline void transform_scanline_F16_to_8888(char* SK_RESTRICT dst,
365 const char* SK_RESTRICT src, int width, int,
366 const SkPMColor*) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400367 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
368 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400369 SkRasterPipeline_<256> p;
Mike Klein45c16fa2017-07-18 18:15:13 -0400370 p.append(SkRasterPipeline::load_f16, &src_ctx);
Mike Kleince988012017-07-21 13:11:37 -0400371 p.append(SkRasterPipeline::clamp_0); // F16 values may be out of [0,1] range, so clamp.
372 p.append(SkRasterPipeline::clamp_1);
Matt Sarett55213562017-01-23 19:37:37 -0500373 p.append(SkRasterPipeline::to_srgb);
Mike Klein45c16fa2017-07-18 18:15:13 -0400374 p.append(SkRasterPipeline::store_8888, &dst_ctx);
375 p.run(0,0, width,1);
Matt Sarett55213562017-01-23 19:37:37 -0500376}
377
378/**
379 * Transform from kPremul, kRGBA_F16 to 4-bytes-per-pixel RGBA.
380 */
381static inline void transform_scanline_F16_premul_to_8888(char* SK_RESTRICT dst,
382 const char* SK_RESTRICT src, int width,
383 int, const SkPMColor*) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400384 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
385 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400386 SkRasterPipeline_<256> p;
Mike Klein45c16fa2017-07-18 18:15:13 -0400387 p.append(SkRasterPipeline::load_f16, &src_ctx);
Matt Sarett55213562017-01-23 19:37:37 -0500388 p.append(SkRasterPipeline::unpremul);
Mike Kleince988012017-07-21 13:11:37 -0400389 p.append(SkRasterPipeline::clamp_0); // F16 values may be out of [0,1] range, so clamp.
390 p.append(SkRasterPipeline::clamp_1);
Matt Sarett55213562017-01-23 19:37:37 -0500391 p.append(SkRasterPipeline::to_srgb);
Mike Klein45c16fa2017-07-18 18:15:13 -0400392 p.append(SkRasterPipeline::store_8888, &dst_ctx);
393 p.run(0,0, width,1);
Matt Sarett55213562017-01-23 19:37:37 -0500394}
Matt Sarett5df93de2017-03-22 21:52:47 +0000395
Matt Sarett2e61b182017-05-09 12:46:50 -0400396/**
397 * Transform from kUnpremul, kRGBA_F16 to premultiplied rgbA 8888.
398 */
399static inline void transform_scanline_F16_to_premul_8888(char* SK_RESTRICT dst,
400 const char* SK_RESTRICT src, int width, int, const SkPMColor*) {
Mike Klein45c16fa2017-07-18 18:15:13 -0400401 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
402 dst_ctx = { (void*)dst, 0 };
Mike Kleinb24704d2017-05-24 07:53:00 -0400403 SkRasterPipeline_<256> p;
Mike Klein45c16fa2017-07-18 18:15:13 -0400404 p.append(SkRasterPipeline::load_f16, &src_ctx);
Mike Kleince988012017-07-21 13:11:37 -0400405 p.append(SkRasterPipeline::clamp_0); // F16 values may be out of [0,1] range, so clamp.
406 p.append(SkRasterPipeline::clamp_1);
Matt Sarett2e61b182017-05-09 12:46:50 -0400407 p.append(SkRasterPipeline::premul);
408 p.append(SkRasterPipeline::to_srgb);
Mike Klein45c16fa2017-07-18 18:15:13 -0400409 p.append(SkRasterPipeline::store_8888, &dst_ctx);
410 p.run(0,0, width,1);
Matt Sarett2e61b182017-05-09 12:46:50 -0400411}
412
Mike Klein37854712018-06-26 11:43:06 -0400413/**
414 * Transform from kRGBA_F32 to 8-bytes-per-pixel RGBA.
415 */
416static inline void transform_scanline_F32(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
417 int width, int, const SkPMColor*) {
418 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
419 dst_ctx = { (void*)dst, 0 };
420 SkRasterPipeline_<256> p;
421 p.append(SkRasterPipeline::load_f32, &src_ctx);
422 p.append(SkRasterPipeline::clamp_0); // F32 values may be out of [0,1] range, so clamp.
423 p.append(SkRasterPipeline::clamp_1);
424 p.append(SkRasterPipeline::to_srgb);
425 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
426 p.run(0,0, width,1);
427}
428
429/**
430 * Transform from kPremul, kRGBA_F32 to 8-bytes-per-pixel RGBA.
431 */
432static inline void transform_scanline_F32_premul(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
433 int width, int, const SkPMColor*) {
434 SkJumper_MemoryCtx src_ctx = { (void*)src, 0 },
435 dst_ctx = { (void*)dst, 0 };
436 SkRasterPipeline_<256> p;
437 p.append(SkRasterPipeline::load_f32, &src_ctx);
438 p.append(SkRasterPipeline::unpremul);
439 p.append(SkRasterPipeline::clamp_0); // F32 values may be out of [0,1] range, so clamp.
440 p.append(SkRasterPipeline::clamp_1);
441 p.append(SkRasterPipeline::to_srgb);
442 p.append(SkRasterPipeline::store_u16_be, &dst_ctx);
443 p.run(0,0, width,1);
444}
445
Matt Sarett1950e0a2017-06-12 16:17:30 -0400446static inline sk_sp<SkData> icc_from_color_space(const SkImageInfo& info) {
447 SkColorSpace* cs = info.colorSpace();
448 if (!cs) {
449 return nullptr;
450 }
451
452 sk_sp<SkColorSpace> owned;
Mike Klein37854712018-06-26 11:43:06 -0400453 if (kRGBA_F16_SkColorType == info.colorType() ||
454 kRGBA_F32_SkColorType == info.colorType()) {
Brian Osman36703d92017-12-12 14:09:31 -0500455 owned = cs->makeSRGBGamma();
Matt Sarett1950e0a2017-06-12 16:17:30 -0400456 cs = owned.get();
457 }
458
Matt Sarett5df93de2017-03-22 21:52:47 +0000459 SkColorSpaceTransferFn fn;
460 SkMatrix44 toXYZD50(SkMatrix44::kUninitialized_Constructor);
Matt Sarett1950e0a2017-06-12 16:17:30 -0400461 if (cs->isNumericalTransferFn(&fn) && cs->toXYZD50(&toXYZD50)) {
Matt Sarett5df93de2017-03-22 21:52:47 +0000462 return SkICC::WriteToICC(fn, toXYZD50);
463 }
Matt Sarett5df93de2017-03-22 21:52:47 +0000464 return nullptr;
465}
466
467#endif // SkImageEncoderFns_DEFINED