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/core/SkColor.h"
12#include "include/core/SkICC.h"
13#include "include/core/SkTypes.h"
14#include "include/private/SkColorData.h"
15#include "include/third_party/skcms/skcms.h"
16
17typedef void (*transform_scanline_proc)(char* dst, const char* src, int width, int bpp);
18
19static inline void transform_scanline_memcpy(char* dst, const char* src, int width, int bpp) {
20    memcpy(dst, src, width * bpp);
21}
22
23static inline void transform_scanline_A8_to_GrayAlpha(char* dst, const char* src, int width, int) {
24    for (int i = 0; i < width; i++) {
25        *dst++ = 0;
26        *dst++ = *src++;
27    }
28}
29
30
31static void skcms(char* dst, const char* src, int n,
32                  skcms_PixelFormat srcFmt, skcms_AlphaFormat srcAlpha,
33                  skcms_PixelFormat dstFmt, skcms_AlphaFormat dstAlpha) {
34    SkAssertResult(skcms_Transform(src, srcFmt, srcAlpha, nullptr,
35                                   dst, dstFmt, dstAlpha, nullptr, n));
36}
37
38static inline void transform_scanline_gray(char* dst, const char* src, int width, int) {
39    skcms(dst, src, width,
40          skcms_PixelFormat_G_8,     skcms_AlphaFormat_Unpremul,
41          skcms_PixelFormat_RGB_888, skcms_AlphaFormat_Unpremul);
42}
43
44static inline void transform_scanline_565(char* dst, const char* src, int width, int) {
45    skcms(dst, src, width,
46          skcms_PixelFormat_BGR_565, skcms_AlphaFormat_Unpremul,
47          skcms_PixelFormat_RGB_888, skcms_AlphaFormat_Unpremul);
48}
49
50static inline void transform_scanline_RGBX(char* dst, const char* src, int width, int) {
51    skcms(dst, src, width,
52          skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul,
53          skcms_PixelFormat_RGB_888  , skcms_AlphaFormat_Unpremul);
54}
55
56static inline void transform_scanline_BGRX(char* dst, const char* src, int width, int) {
57    skcms(dst, src, width,
58          skcms_PixelFormat_BGRA_8888, skcms_AlphaFormat_Unpremul,
59          skcms_PixelFormat_RGB_888  , skcms_AlphaFormat_Unpremul);
60}
61
62static inline void transform_scanline_444(char* dst, const char* src, int width, int) {
63    skcms(dst, src, width,
64          skcms_PixelFormat_ABGR_4444, skcms_AlphaFormat_Unpremul,
65          skcms_PixelFormat_RGB_888  , skcms_AlphaFormat_Unpremul);
66}
67
68static inline void transform_scanline_rgbA(char* dst, const char* src, int width, int) {
69    skcms(dst, src, width,
70          skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_PremulAsEncoded,
71          skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
72}
73
74static inline void transform_scanline_bgrA(char* dst, const char* src, int width, int) {
75    skcms(dst, src, width,
76          skcms_PixelFormat_BGRA_8888, skcms_AlphaFormat_PremulAsEncoded,
77          skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
78}
79
80static inline void transform_scanline_to_premul_legacy(char* dst, const char* src, int width, int) {
81    skcms(dst, src, width,
82          skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul,
83          skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_PremulAsEncoded);
84}
85
86static inline void transform_scanline_BGRA(char* dst, const char* src, int width, int) {
87    skcms(dst, src, width,
88          skcms_PixelFormat_BGRA_8888, skcms_AlphaFormat_Unpremul,
89          skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
90}
91
92static inline void transform_scanline_4444(char* dst, const char* src, int width, int) {
93    skcms(dst, src, width,
94          skcms_PixelFormat_ABGR_4444, skcms_AlphaFormat_PremulAsEncoded,
95          skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
96}
97
98static inline void transform_scanline_101010x(char* dst, const char* src, int width, int) {
99    skcms(dst, src, width,
100          skcms_PixelFormat_RGBA_1010102, skcms_AlphaFormat_Unpremul,
101          skcms_PixelFormat_RGB_161616BE, skcms_AlphaFormat_Unpremul);
102}
103
104static inline void transform_scanline_1010102(char* dst, const char* src, int width, int) {
105    skcms(dst, src, width,
106          skcms_PixelFormat_RGBA_1010102,    skcms_AlphaFormat_Unpremul,
107          skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
108}
109
110static inline void transform_scanline_1010102_premul(char* dst, const char* src, int width, int) {
111    skcms(dst, src, width,
112          skcms_PixelFormat_RGBA_1010102,    skcms_AlphaFormat_PremulAsEncoded,
113          skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
114}
115
116static inline void transform_scanline_bgr_101010x(char* dst, const char* src, int width, int) {
117    skcms(dst, src, width,
118          skcms_PixelFormat_BGRA_1010102, skcms_AlphaFormat_Unpremul,
119          skcms_PixelFormat_RGB_161616BE, skcms_AlphaFormat_Unpremul);
120}
121
122static inline void transform_scanline_bgra_1010102(char* dst, const char* src, int width, int) {
123    skcms(dst, src, width,
124          skcms_PixelFormat_BGRA_1010102,    skcms_AlphaFormat_Unpremul,
125          skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
126}
127
128static inline void transform_scanline_bgra_1010102_premul(char* dst, const char* src, int width, int) {
129    skcms(dst, src, width,
130          skcms_PixelFormat_BGRA_1010102,    skcms_AlphaFormat_PremulAsEncoded,
131          skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
132}
133
134static inline void transform_scanline_F16(char* dst, const char* src, int width, int) {
135    skcms(dst, src, width,
136          skcms_PixelFormat_RGBA_hhhh,       skcms_AlphaFormat_Unpremul,
137          skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
138}
139
140static inline void transform_scanline_F16_premul(char* dst, const char* src, int width, int) {
141    skcms(dst, src, width,
142          skcms_PixelFormat_RGBA_hhhh,       skcms_AlphaFormat_PremulAsEncoded,
143          skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
144}
145
146static inline void transform_scanline_F16_to_8888(char* dst, const char* src, int width, int) {
147    skcms(dst, src, width,
148          skcms_PixelFormat_RGBA_hhhh, skcms_AlphaFormat_Unpremul,
149          skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
150}
151
152static inline void transform_scanline_F16_premul_to_8888(char* dst,
153                                                         const char* src,
154                                                         int width,
155                                                         int) {
156    skcms(dst, src, width,
157          skcms_PixelFormat_RGBA_hhhh, skcms_AlphaFormat_PremulAsEncoded,
158          skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_Unpremul);
159}
160
161static inline void transform_scanline_F16_to_premul_8888(char* dst,
162                                                         const char* src,
163                                                         int width,
164                                                         int) {
165    skcms(dst, src, width,
166          skcms_PixelFormat_RGBA_hhhh, skcms_AlphaFormat_Unpremul,
167          skcms_PixelFormat_RGBA_8888, skcms_AlphaFormat_PremulAsEncoded);
168}
169
170static inline void transform_scanline_F32(char* dst, const char* src, int width, int) {
171    skcms(dst, src, width,
172          skcms_PixelFormat_RGBA_ffff,       skcms_AlphaFormat_Unpremul,
173          skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
174}
175
176static inline void transform_scanline_F32_premul(char* dst, const char* src, int width, int) {
177    skcms(dst, src, width,
178          skcms_PixelFormat_RGBA_ffff,       skcms_AlphaFormat_PremulAsEncoded,
179          skcms_PixelFormat_RGBA_16161616BE, skcms_AlphaFormat_Unpremul);
180}
181
182static inline sk_sp<SkData> icc_from_color_space(const SkImageInfo& info) {
183    SkColorSpace* cs = info.colorSpace();
184    if (!cs) {
185        return nullptr;
186    }
187
188    skcms_TransferFunction fn;
189    skcms_Matrix3x3 toXYZD50;
190    cs->transferFn(&fn);
191    if (cs->toXYZD50(&toXYZD50)) {
192        skcms_CICP cicp{};
193        if (cs->GetIccCicp(&cicp)) {
194            return SkWriteICCProfileWithCicp(fn, toXYZD50, cicp);
195        }
196        return SkWriteICCProfile(fn, toXYZD50);
197    }
198    return nullptr;
199}
200
201#endif  // SkImageEncoderFns_DEFINED
202