blob: a02e98ab07326584cc0ab75924f94628d6212d33 [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 */
7
8/**
9 * Functions to transform scanlines between packed-pixel formats.
10 */
11
12#include "SkBitmap.h"
13#include "SkColor.h"
14#include "SkColorPriv.h"
15#include "SkPreConfig.h"
16#include "SkUnPreMultiply.h"
17
18/**
19 * Function template for transforming scanlines.
20 * Transform 'width' pixels from 'src' buffer into 'dst' buffer,
21 * repacking color channel data as appropriate for the given transformation.
msarettf17b71f2016-09-12 14:30:03 -070022 * 'bpp' is bytes per pixel in the 'src' buffer.
epoger@google.com4ce738b2012-11-16 18:44:18 +000023 */
msarettf17b71f2016-09-12 14:30:03 -070024typedef void (*transform_scanline_proc)(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
25 int width, int bpp);
epoger@google.com4ce738b2012-11-16 18:44:18 +000026
27/**
28 * Identity transformation: just copy bytes from src to dst.
29 */
msarettf17b71f2016-09-12 14:30:03 -070030static void transform_scanline_memcpy(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
31 int width, int bpp) {
32 memcpy(dst, src, width * bpp);
epoger@google.com4ce738b2012-11-16 18:44:18 +000033}
34
35/**
36 * Transform from kRGB_565_Config to 3-bytes-per-pixel RGB.
37 * Alpha channel data is not present in kRGB_565_Config format, so there is no
38 * alpha channel data to preserve.
39 */
msarettf17b71f2016-09-12 14:30:03 -070040static void transform_scanline_565(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
41 int width, int) {
42 const uint16_t* srcP = (const uint16_t*)src;
epoger@google.com4ce738b2012-11-16 18:44:18 +000043 for (int i = 0; i < width; i++) {
44 unsigned c = *srcP++;
45 *dst++ = SkPacked16ToR32(c);
46 *dst++ = SkPacked16ToG32(c);
47 *dst++ = SkPacked16ToB32(c);
48 }
49}
50
51/**
msarettf17b71f2016-09-12 14:30:03 -070052 * Transform from kRGBA_8888_SkColorType to 3-bytes-per-pixel RGB.
53 * Alpha channel data is abandoned.
epoger@google.com4ce738b2012-11-16 18:44:18 +000054 */
msarettf17b71f2016-09-12 14:30:03 -070055static void transform_scanline_RGBX(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
56 int width, int) {
57 const uint32_t* srcP = (const SkPMColor*)src;
epoger@google.com4ce738b2012-11-16 18:44:18 +000058 for (int i = 0; i < width; i++) {
msarettf17b71f2016-09-12 14:30:03 -070059 uint32_t c = *srcP++;
60 *dst++ = (c >> 0) & 0xFF;
61 *dst++ = (c >> 8) & 0xFF;
62 *dst++ = (c >> 16) & 0xFF;
63 }
64}
65
66/**
67 * Transform from kBGRA_8888_SkColorType to 3-bytes-per-pixel RGB.
68 * Alpha channel data is abandoned.
69 */
70static void transform_scanline_BGRX(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
71 int width, int) {
72 const uint32_t* srcP = (const SkPMColor*)src;
73 for (int i = 0; i < width; i++) {
74 uint32_t c = *srcP++;
75 *dst++ = (c >> 16) & 0xFF;
76 *dst++ = (c >> 8) & 0xFF;
77 *dst++ = (c >> 0) & 0xFF;
epoger@google.com4ce738b2012-11-16 18:44:18 +000078 }
79}
80
81/**
82 * Transform from kARGB_4444_Config to 3-bytes-per-pixel RGB.
83 * Alpha channel data, if any, is abandoned.
84 */
msarettf17b71f2016-09-12 14:30:03 -070085static void transform_scanline_444(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
86 int width, int) {
87 const SkPMColor16* srcP = (const SkPMColor16*)src;
epoger@google.com4ce738b2012-11-16 18:44:18 +000088 for (int i = 0; i < width; i++) {
89 SkPMColor16 c = *srcP++;
90 *dst++ = SkPacked4444ToR32(c);
91 *dst++ = SkPacked4444ToG32(c);
92 *dst++ = SkPacked4444ToB32(c);
93 }
94}
95
msarettf17b71f2016-09-12 14:30:03 -070096template <bool kIsRGBA>
97static inline void transform_scanline_unpremultiply(char* SK_RESTRICT dst,
98 const char* SK_RESTRICT src, int width, int) {
99 const uint32_t* srcP = (const SkPMColor*)src;
100 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
epoger@google.com4ce738b2012-11-16 18:44:18 +0000101
102 for (int i = 0; i < width; i++) {
msarettf17b71f2016-09-12 14:30:03 -0700103 uint32_t c = *srcP++;
104 unsigned r, g, b, a;
105 if (kIsRGBA) {
106 r = (c >> 0) & 0xFF;
107 g = (c >> 8) & 0xFF;
108 b = (c >> 16) & 0xFF;
109 a = (c >> 24) & 0xFF;
110 } else {
111 r = (c >> 16) & 0xFF;
112 g = (c >> 8) & 0xFF;
113 b = (c >> 0) & 0xFF;
114 a = (c >> 24) & 0xFF;
115 }
epoger@google.com4ce738b2012-11-16 18:44:18 +0000116
117 if (0 != a && 255 != a) {
118 SkUnPreMultiply::Scale scale = table[a];
119 r = SkUnPreMultiply::ApplyScale(scale, r);
120 g = SkUnPreMultiply::ApplyScale(scale, g);
121 b = SkUnPreMultiply::ApplyScale(scale, b);
122 }
123 *dst++ = r;
124 *dst++ = g;
125 *dst++ = b;
126 *dst++ = a;
127 }
128}
129
130/**
msarettf17b71f2016-09-12 14:30:03 -0700131 * Transform from kPremul, kRGBA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA.
132 */
133static void transform_scanline_rgbA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
134 int width, int bpp) {
135 transform_scanline_unpremultiply<true>(dst, src, width, bpp);
136}
137
138/**
139 * Transform from kPremul, kBGRA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA.
140 */
141static void transform_scanline_bgrA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
142 int width, int bpp) {
143 transform_scanline_unpremultiply<false>(dst, src, width, bpp);
144}
145
146/**
147 * Transform from kUnpremul, kBGRA_8888_SkColorType to 4-bytes-per-pixel unpremultiplied RGBA.
148 */
149static void transform_scanline_BGRA(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
150 int width, int) {
151 const uint32_t* srcP = (const SkPMColor*)src;
152 for (int i = 0; i < width; i++) {
153 uint32_t c = *srcP++;
154 *dst++ = (c >> 16) & 0xFF;
155 *dst++ = (c >> 8) & 0xFF;
156 *dst++ = (c >> 0) & 0xFF;
157 *dst++ = (c >> 24) & 0xFF;
158 }
159}
160
161/**
epoger@google.com4ce738b2012-11-16 18:44:18 +0000162 * Transform from kARGB_8888_Config to 4-bytes-per-pixel RGBA,
163 * with scaling of RGB based on alpha channel.
164 */
msarettf17b71f2016-09-12 14:30:03 -0700165static void transform_scanline_4444(char* SK_RESTRICT dst, const char* SK_RESTRICT src,
166 int width, int) {
167 const SkPMColor16* srcP = (const SkPMColor16*)src;
168 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
epoger@google.com4ce738b2012-11-16 18:44:18 +0000169
170 for (int i = 0; i < width; i++) {
171 SkPMColor16 c = *srcP++;
172 unsigned a = SkPacked4444ToA32(c);
173 unsigned r = SkPacked4444ToR32(c);
174 unsigned g = SkPacked4444ToG32(c);
175 unsigned b = SkPacked4444ToB32(c);
176
177 if (0 != a && 255 != a) {
178 SkUnPreMultiply::Scale scale = table[a];
179 r = SkUnPreMultiply::ApplyScale(scale, r);
180 g = SkUnPreMultiply::ApplyScale(scale, g);
181 b = SkUnPreMultiply::ApplyScale(scale, b);
182 }
183 *dst++ = r;
184 *dst++ = g;
185 *dst++ = b;
186 *dst++ = a;
187 }
188}