1 /*
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 */
7
8 #ifndef SkImageEncoderFns_DEFINED
9 #define SkImageEncoderFns_DEFINED
10
11 #include "include/codec/SkEncodedOrigin.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkData.h"
14 #include "include/core/SkImageInfo.h"
15 #include "include/core/SkRefCnt.h"
16 #include "include/core/SkTypes.h"
17 #include "include/encode/SkICC.h"
18 #include "include/private/SkExif.h"
19 #include "modules/skcms/skcms.h"
20
21 #include <cstring>
22 #include <optional>
23
24 typedef void (*transform_scanline_proc)(char* dst, const char* src, int width, int bpp);
25
transform_scanline_memcpy(char * dst,const char * src,int width,int bpp)26 static inline void transform_scanline_memcpy(char* dst, const char* src, int width, int bpp) {
27 memcpy(dst, src, width * bpp);
28 }
29
transform_scanline_A8_to_GrayAlpha(char * dst,const char * src,int width,int)30 static inline void transform_scanline_A8_to_GrayAlpha(char* dst, const char* src, int width, int) {
31 for (int i = 0; i < width; i++) {
32 *dst++ = 0;
33 *dst++ = *src++;
34 }
35 }
36
37
skcms(char * dst,const char * src,int n,skcms_PixelFormat srcFmt,skcms_AlphaFormat srcAlpha,skcms_PixelFormat dstFmt,skcms_AlphaFormat dstAlpha)38 static void skcms(char* dst, const char* src, int n,
39 skcms_PixelFormat srcFmt, skcms_AlphaFormat srcAlpha,
40 skcms_PixelFormat dstFmt, skcms_AlphaFormat dstAlpha) {
41 SkAssertResult(skcms_Transform(src, srcFmt, srcAlpha, nullptr,
42 dst, dstFmt, dstAlpha, nullptr, n));
43 }
44
transform_scanline_gray(char * dst,const char * src,int width,int)45 static inline void transform_scanline_gray(char* dst, const char* src, int width, int) {
46 skcms(dst, src, width,
47 skcms_PixelFormat_G_8, skcms_AlphaFormat_Unpremul,
48 skcms_PixelFormat_RGB_888, skcms_AlphaFormat_Unpremul);
49 }
50
transform_scanline_565(char * dst,const char * src,int width,int)51 static inline void transform_scanline_565(char* dst, const char* src, int width, int) {
52 skcms(dst, src, width,
53 skcms_PixelFormat_BGR_565, skcms_AlphaFormat_Unpremul,
54 skcms_PixelFormat_RGB_888, skcms_AlphaFormat_Unpremul);
55 }
56
transform_scanline_RGBX(char * dst,const char * src,int width,int)57 static inline void transform_scanline_RGBX(char* dst, const char* src, int width, int) {
58 skcms(dst, src, width,
59 skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul,
60 skcms_PixelFormat_RGB_888 , skcms_AlphaFormat_Unpremul);
61 }
62
transform_scanline_BGRX(char * dst,const char * src,int width,int)63 static inline void transform_scanline_BGRX(char* dst, const char* src, int width, int) {
64 skcms(dst, src, width,
65 skcms_PixelFormat_BGRA_8888, skcms_AlphaFormat_Unpremul,
66 skcms_PixelFormat_RGB_888 , skcms_AlphaFormat_Unpremul);
67 }
68
transform_scanline_444(char * dst,const char * src,int width,int)69 static inline void transform_scanline_444(char* dst, const char* src, int width, int) {
70 skcms(dst, src, width,
71 skcms_PixelFormat_ABGR_4444, skcms_AlphaFormat_Unpremul,
72 skcms_PixelFormat_RGB_888 , skcms_AlphaFormat_Unpremul);
73 }
74
transform_scanline_rgbA(char * dst,const char * src,int width,int)75 static inline void transform_scanline_rgbA(char* dst, const char* src, int width, int) {
76 skcms(dst, src, width,
77 skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_PremulAsEncoded,
78 skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
79 }
80
transform_scanline_bgrA(char * dst,const char * src,int width,int)81 static inline void transform_scanline_bgrA(char* dst, const char* src, int width, int) {
82 skcms(dst, src, width,
83 skcms_PixelFormat_BGRA_8888, skcms_AlphaFormat_PremulAsEncoded,
84 skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
85 }
86
transform_scanline_to_premul_legacy(char * dst,const char * src,int width,int)87 static inline void transform_scanline_to_premul_legacy(char* dst, const char* src, int width, int) {
88 skcms(dst, src, width,
89 skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul,
90 skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_PremulAsEncoded);
91 }
92
transform_scanline_BGRA(char * dst,const char * src,int width,int)93 static inline void transform_scanline_BGRA(char* dst, const char* src, int width, int) {
94 skcms(dst, src, width,
95 skcms_PixelFormat_BGRA_8888, skcms_AlphaFormat_Unpremul,
96 skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
97 }
98
transform_scanline_4444(char * dst,const char * src,int width,int)99 static inline void transform_scanline_4444(char* dst, const char* src, int width, int) {
100 skcms(dst, src, width,
101 skcms_PixelFormat_ABGR_4444, skcms_AlphaFormat_PremulAsEncoded,
102 skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
103 }
104
transform_scanline_101010x(char * dst,const char * src,int width,int)105 static inline void transform_scanline_101010x(char* dst, const char* src, int width, int) {
106 skcms(dst, src, width,
107 skcms_PixelFormat_RGBA_1010102, skcms_AlphaFormat_Unpremul,
108 skcms_PixelFormat_RGB_161616BE, skcms_AlphaFormat_Unpremul);
109 }
110
transform_scanline_1010102(char * dst,const char * src,int width,int)111 static inline void transform_scanline_1010102(char* dst, const char* src, int width, int) {
112 skcms(dst, src, width,
113 skcms_PixelFormat_RGBA_1010102, skcms_AlphaFormat_Unpremul,
114 skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
115 }
116
transform_scanline_1010102_premul(char * dst,const char * src,int width,int)117 static inline void transform_scanline_1010102_premul(char* dst, const char* src, int width, int) {
118 skcms(dst, src, width,
119 skcms_PixelFormat_RGBA_1010102, skcms_AlphaFormat_PremulAsEncoded,
120 skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
121 }
122
transform_scanline_bgr_101010x(char * dst,const char * src,int width,int)123 static inline void transform_scanline_bgr_101010x(char* dst, const char* src, int width, int) {
124 skcms(dst, src, width,
125 skcms_PixelFormat_BGRA_1010102, skcms_AlphaFormat_Unpremul,
126 skcms_PixelFormat_RGB_161616BE, skcms_AlphaFormat_Unpremul);
127 }
128
transform_scanline_bgra_1010102(char * dst,const char * src,int width,int)129 static inline void transform_scanline_bgra_1010102(char* dst, const char* src, int width, int) {
130 skcms(dst, src, width,
131 skcms_PixelFormat_BGRA_1010102, skcms_AlphaFormat_Unpremul,
132 skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
133 }
134
transform_scanline_bgr_101010x_xr(char * dst,const char * src,int width,int)135 static inline void transform_scanline_bgr_101010x_xr(char* dst, const char* src, int width, int) {
136 skcms(dst, src, width,
137 skcms_PixelFormat_BGR_101010x_XR, skcms_AlphaFormat_Unpremul,
138 skcms_PixelFormat_RGB_161616BE, skcms_AlphaFormat_Unpremul);
139 }
140
transform_scanline_bgra_10101010_xr(char * dst,const char * src,int width,int)141 static inline void transform_scanline_bgra_10101010_xr(char* dst, const char* src, int width, int) {
142 skcms(dst, src, width,
143 skcms_PixelFormat_BGRA_10101010_XR, skcms_AlphaFormat_Unpremul,
144 skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
145 }
146
transform_scanline_bgra_1010102_premul(char * dst,const char * src,int width,int)147 static inline void transform_scanline_bgra_1010102_premul(char* dst, const char* src, int width, int) {
148 skcms(dst, src, width,
149 skcms_PixelFormat_BGRA_1010102, skcms_AlphaFormat_PremulAsEncoded,
150 skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
151 }
152
transform_scanline_bgra_10101010_xr_premul(char * dst,const char * src,int width,int)153 static inline void transform_scanline_bgra_10101010_xr_premul(char* dst, const char* src, int width, int) {
154 skcms(dst, src, width,
155 skcms_PixelFormat_BGRA_10101010_XR, skcms_AlphaFormat_PremulAsEncoded,
156 skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
157 }
158
transform_scanline_F16(char * dst,const char * src,int width,int)159 static inline void transform_scanline_F16(char* dst, const char* src, int width, int) {
160 skcms(dst, src, width,
161 skcms_PixelFormat_RGBA_hhhh, skcms_AlphaFormat_Unpremul,
162 skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
163 }
164
transform_scanline_F16F16F16x(char * dst,const char * src,int width,int)165 static inline void transform_scanline_F16F16F16x(char* dst, const char* src, int width, int) {
166 skcms(dst, src, width,
167 skcms_PixelFormat_RGBA_hhhh, skcms_AlphaFormat_Unpremul,
168 skcms_PixelFormat_RGB_161616BE, skcms_AlphaFormat_Unpremul);
169 }
170
transform_scanline_F16_premul(char * dst,const char * src,int width,int)171 static inline void transform_scanline_F16_premul(char* dst, const char* src, int width, int) {
172 skcms(dst, src, width,
173 skcms_PixelFormat_RGBA_hhhh, skcms_AlphaFormat_PremulAsEncoded,
174 skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
175 }
176
transform_scanline_F16_to_8888(char * dst,const char * src,int width,int)177 static inline void transform_scanline_F16_to_8888(char* dst, const char* src, int width, int) {
178 skcms(dst, src, width,
179 skcms_PixelFormat_RGBA_hhhh, skcms_AlphaFormat_Unpremul,
180 skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
181 }
182
transform_scanline_F16_premul_to_8888(char * dst,const char * src,int width,int)183 static inline void transform_scanline_F16_premul_to_8888(char* dst,
184 const char* src,
185 int width,
186 int) {
187 skcms(dst, src, width,
188 skcms_PixelFormat_RGBA_hhhh, skcms_AlphaFormat_PremulAsEncoded,
189 skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
190 }
191
transform_scanline_F16_to_premul_8888(char * dst,const char * src,int width,int)192 static inline void transform_scanline_F16_to_premul_8888(char* dst,
193 const char* src,
194 int width,
195 int) {
196 skcms(dst, src, width,
197 skcms_PixelFormat_RGBA_hhhh, skcms_AlphaFormat_Unpremul,
198 skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_PremulAsEncoded);
199 }
200
transform_scanline_F32(char * dst,const char * src,int width,int)201 static inline void transform_scanline_F32(char* dst, const char* src, int width, int) {
202 skcms(dst, src, width,
203 skcms_PixelFormat_RGBA_ffff, skcms_AlphaFormat_Unpremul,
204 skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
205 }
206
transform_scanline_F32_premul(char * dst,const char * src,int width,int)207 static inline void transform_scanline_F32_premul(char* dst, const char* src, int width, int) {
208 skcms(dst, src, width,
209 skcms_PixelFormat_RGBA_ffff, skcms_AlphaFormat_PremulAsEncoded,
210 skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
211 }
212
icc_from_color_space(const SkColorSpace * cs,const skcms_ICCProfile * profile,const char * profile_description)213 static inline sk_sp<SkData> icc_from_color_space(const SkColorSpace* cs,
214 const skcms_ICCProfile* profile,
215 const char* profile_description) {
216 // TODO(ccameron): Remove this check.
217 if (!cs) {
218 return nullptr;
219 }
220
221 if (profile) {
222 return SkWriteICCProfile(profile, profile_description);
223 }
224
225 skcms_Matrix3x3 toXYZD50;
226 if (cs->toXYZD50(&toXYZD50)) {
227 skcms_TransferFunction fn;
228 cs->transferFn(&fn);
229 return SkWriteICCProfile(fn, toXYZD50);
230 }
231 return nullptr;
232 }
233
icc_from_color_space(const SkImageInfo & info,const skcms_ICCProfile * profile,const char * profile_description)234 static inline sk_sp<SkData> icc_from_color_space(const SkImageInfo& info,
235 const skcms_ICCProfile* profile,
236 const char* profile_description) {
237 return icc_from_color_space(info.colorSpace(), profile, profile_description);
238 }
239
exif_from_origin(const SkEncodedOrigin origin)240 static inline sk_sp<SkData> exif_from_origin(const SkEncodedOrigin origin) {
241 SkExif::Metadata metadata;
242 metadata.fOrigin = origin;
243 return SkExif::WriteExif(metadata);
244 }
245
246 #endif // SkImageEncoderFns_DEFINED
247