• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 Google Inc.
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 #include "include/private/SkColorData.h"
9 #include "include/private/SkHalf.h"
10 #include "include/private/SkImageInfoPriv.h"
11 #include "src/core/SkColorSpacePriv.h"
12 #include "src/core/SkColorSpaceXformSteps.h"
13 #include "src/core/SkConvertPixels.h"
14 #include "src/core/SkOpts.h"
15 #include "src/core/SkRasterPipeline.h"
16 
rect_memcpy(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRB,const SkImageInfo & srcInfo,const void * srcPixels,size_t srcRB,const SkColorSpaceXformSteps & steps)17 static bool rect_memcpy(const SkImageInfo& dstInfo,       void* dstPixels, size_t dstRB,
18                         const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
19                         const SkColorSpaceXformSteps& steps) {
20     // We can copy the pixels when no color type, alpha type, or color space changes.
21     if (dstInfo.colorType() != srcInfo.colorType()) {
22         return false;
23     }
24     if (dstInfo.colorType() != kAlpha_8_SkColorType
25             && steps.flags.mask() != 0b00000) {
26         return false;
27     }
28 
29     SkRectMemcpy(dstPixels, dstRB,
30                  srcPixels, srcRB, dstInfo.minRowBytes(), dstInfo.height());
31     return true;
32 }
33 
swizzle_or_premul(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRB,const SkImageInfo & srcInfo,const void * srcPixels,size_t srcRB,const SkColorSpaceXformSteps & steps)34 static bool swizzle_or_premul(const SkImageInfo& dstInfo,       void* dstPixels, size_t dstRB,
35                               const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
36                               const SkColorSpaceXformSteps& steps) {
37     auto is_8888 = [](SkColorType ct) {
38         return ct == kRGBA_8888_SkColorType || ct == kBGRA_8888_SkColorType;
39     };
40     if (!is_8888(dstInfo.colorType()) ||
41         !is_8888(srcInfo.colorType()) ||
42         steps.flags.linearize         ||
43         steps.flags.gamut_transform   ||
44         steps.flags.unpremul          ||
45         steps.flags.encode) {
46         return false;
47     }
48 
49     const bool swapRB = dstInfo.colorType() != srcInfo.colorType();
50 
51     void (*fn)(uint32_t*, const uint32_t*, int) = nullptr;
52 
53     if (steps.flags.premul) {
54         fn = swapRB ? SkOpts::RGBA_to_bgrA
55                     : SkOpts::RGBA_to_rgbA;
56     } else {
57         // If we're not swizzling, we ought to have used rect_memcpy().
58         SkASSERT(swapRB);
59         fn = SkOpts::RGBA_to_BGRA;
60     }
61 
62     for (int y = 0; y < dstInfo.height(); y++) {
63         fn((uint32_t*)dstPixels, (const uint32_t*)srcPixels, dstInfo.width());
64         dstPixels = SkTAddOffset<void>(dstPixels, dstRB);
65         srcPixels = SkTAddOffset<const void>(srcPixels, srcRB);
66     }
67     return true;
68 }
69 
convert_to_alpha8(const SkImageInfo & dstInfo,void * vdst,size_t dstRB,const SkImageInfo & srcInfo,const void * src,size_t srcRB,const SkColorSpaceXformSteps &)70 static bool convert_to_alpha8(const SkImageInfo& dstInfo,       void* vdst, size_t dstRB,
71                               const SkImageInfo& srcInfo, const void*  src, size_t srcRB,
72                               const SkColorSpaceXformSteps&) {
73     if (dstInfo.colorType() != kAlpha_8_SkColorType) {
74         return false;
75     }
76     auto dst = (uint8_t*)vdst;
77 
78     switch (srcInfo.colorType()) {
79         case kUnknown_SkColorType:
80         case kAlpha_8_SkColorType: {
81             // Unknown should never happen.
82             // Alpha8 should have been handled by rect_memcpy().
83             SkASSERT(false);
84             return false;
85         }
86 
87         case kA16_unorm_SkColorType: {
88             auto src16 = (const uint16_t*) src;
89             for (int y = 0; y < srcInfo.height(); y++) {
90                 for (int x = 0; x < srcInfo.width(); x++) {
91                     dst[x] = src16[x] >> 8;
92                 }
93                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
94                 src16 = SkTAddOffset<const uint16_t>(src16, srcRB);
95             }
96             return true;
97         }
98 
99         case kGray_8_SkColorType:
100         case kRGB_565_SkColorType:
101         case kR8G8_unorm_SkColorType:
102         case kR16G16_unorm_SkColorType:
103         case kR16G16_float_SkColorType:
104         case kRGB_888x_SkColorType:
105         case kRGB_101010x_SkColorType:
106         case kBGR_101010x_SkColorType: {
107             for (int y = 0; y < srcInfo.height(); ++y) {
108                memset(dst, 0xFF, srcInfo.width());
109                dst = SkTAddOffset<uint8_t>(dst, dstRB);
110             }
111             return true;
112         }
113 
114         case kARGB_4444_SkColorType: {
115             auto src16 = (const uint16_t*) src;
116             for (int y = 0; y < srcInfo.height(); y++) {
117                 for (int x = 0; x < srcInfo.width(); x++) {
118                     dst[x] = SkPacked4444ToA32(src16[x]);
119                 }
120                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
121                 src16 = SkTAddOffset<const uint16_t>(src16, srcRB);
122             }
123             return true;
124         }
125 
126         case kBGRA_8888_SkColorType:
127         case kRGBA_8888_SkColorType:
128         case kSRGBA_8888_SkColorType: {
129             auto src32 = (const uint32_t*) src;
130             for (int y = 0; y < srcInfo.height(); y++) {
131                 for (int x = 0; x < srcInfo.width(); x++) {
132                     dst[x] = src32[x] >> 24;
133                 }
134                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
135                 src32 = SkTAddOffset<const uint32_t>(src32, srcRB);
136             }
137             return true;
138         }
139 
140         case kRGBA_1010102_SkColorType:
141         case kBGRA_1010102_SkColorType: {
142             auto src32 = (const uint32_t*) src;
143             for (int y = 0; y < srcInfo.height(); y++) {
144                 for (int x = 0; x < srcInfo.width(); x++) {
145                     dst[x] = (src32[x] >> 30) * 0x55;
146                 }
147                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
148                 src32 = SkTAddOffset<const uint32_t>(src32, srcRB);
149             }
150             return true;
151         }
152 
153         case kRGBA_F16Norm_SkColorType:
154         case kRGBA_F16_SkColorType: {
155             auto src64 = (const uint64_t*) src;
156             for (int y = 0; y < srcInfo.height(); y++) {
157                 for (int x = 0; x < srcInfo.width(); x++) {
158                     dst[x] = (uint8_t) (255.0f * SkHalfToFloat(src64[x] >> 48));
159                 }
160                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
161                 src64 = SkTAddOffset<const uint64_t>(src64, srcRB);
162             }
163             return true;
164         }
165 
166         case kRGBA_F32_SkColorType: {
167             auto rgba = (const float*)src;
168             for (int y = 0; y < srcInfo.height(); y++) {
169                 for (int x = 0; x < srcInfo.width(); x++) {
170                     dst[x] = (uint8_t)(255.0f * rgba[4*x+3]);
171                 }
172                 dst  = SkTAddOffset<uint8_t>(dst, dstRB);
173                 rgba = SkTAddOffset<const float>(rgba, srcRB);
174             }
175             return true;
176         }
177 
178         case kA16_float_SkColorType: {
179             auto srcF16 = (const uint16_t*) src;
180             for (int y = 0; y < srcInfo.height(); y++) {
181                 for (int x = 0; x < srcInfo.width(); x++) {
182                     dst[x] = (uint8_t) (255.0f * SkHalfToFloat(srcF16[x]));
183                 }
184                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
185                 srcF16 = SkTAddOffset<const uint16_t>(srcF16, srcRB);
186             }
187             return true;
188         }
189 
190         case kR16G16B16A16_unorm_SkColorType: {
191             auto src64 = (const uint64_t*) src;
192             for (int y = 0; y < srcInfo.height(); y++) {
193                 for (int x = 0; x < srcInfo.width(); x++) {
194                     dst[x] = (src64[x] >> 48) >> 8;
195                 }
196                 dst = SkTAddOffset<uint8_t>(dst, dstRB);
197                 src64 = SkTAddOffset<const uint64_t>(src64, srcRB);
198             }
199             return true;
200         }
201     }
202     return false;
203 }
204 
205 // Default: Use the pipeline.
convert_with_pipeline(const SkImageInfo & dstInfo,void * dstRow,int dstStride,const SkImageInfo & srcInfo,const void * srcRow,int srcStride,const SkColorSpaceXformSteps & steps)206 static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, int dstStride,
207                                   const SkImageInfo& srcInfo, const void* srcRow, int srcStride,
208                                   const SkColorSpaceXformSteps& steps) {
209     SkRasterPipeline_MemoryCtx src = { (void*)srcRow, srcStride },
210                                dst = { (void*)dstRow, dstStride };
211 
212     SkRasterPipeline_<256> pipeline;
213     pipeline.append_load(srcInfo.colorType(), &src);
214     steps.apply(&pipeline);
215 
216     pipeline.append_gamut_clamp_if_normalized(dstInfo);
217 
218     pipeline.append_store(dstInfo.colorType(), &dst);
219     pipeline.run(0,0, srcInfo.width(), srcInfo.height());
220 }
221 
SkConvertPixels(const SkImageInfo & dstInfo,void * dstPixels,size_t dstRB,const SkImageInfo & srcInfo,const void * srcPixels,size_t srcRB)222 bool SkConvertPixels(const SkImageInfo& dstInfo,       void* dstPixels, size_t dstRB,
223                      const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB) {
224     SkASSERT(dstInfo.dimensions() == srcInfo.dimensions());
225     SkASSERT(SkImageInfoValidConversion(dstInfo, srcInfo));
226 
227     int srcStride = (int)(srcRB / srcInfo.bytesPerPixel());
228     int dstStride = (int)(dstRB / dstInfo.bytesPerPixel());
229     if ((size_t)srcStride * srcInfo.bytesPerPixel() != srcRB ||
230         (size_t)dstStride * dstInfo.bytesPerPixel() != dstRB) {
231         return false;
232     }
233 
234     SkColorSpaceXformSteps steps{srcInfo.colorSpace(), srcInfo.alphaType(),
235                                  dstInfo.colorSpace(), dstInfo.alphaType()};
236 
237     for (auto fn : {rect_memcpy, swizzle_or_premul, convert_to_alpha8}) {
238         if (fn(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, steps)) {
239             return true;
240         }
241     }
242     convert_with_pipeline(dstInfo, dstPixels, dstStride, srcInfo, srcPixels, srcStride, steps);
243     return true;
244 }
245