SkConfig8888.h revision 5194e1507dbf77fb6a6feb731c6e19571faee452
1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkCanvas.h" 11#include "SkColorPriv.h" 12 13namespace { 14 15/** 16 Copies all pixels from a bitmap to a dst ptr with a given rowBytes and 17 Config8888. The bitmap must have kARGB_8888_Config. 18 */ 19inline void SkCopyBitmapToConfig8888(uint32_t* dstPixels, 20 size_t dstRowBytes, 21 SkCanvas::Config8888 dstConfig8888, 22 const SkBitmap& srcBmp); 23 24/** 25 * Copies all pixels in a bitmap to a dst ptr with row bytes. The src bitmap 26 * is assumed to have pixels and be kARGB_8888_Config. No conversion is applied 27 */ 28inline void SkCopyARGB8888BitmapTo(uint32_t* dstPixels, 29 size_t dstRowBytes, 30 const SkBitmap& srcBmp); 31 32/** 33 Copies over all pixels in a bitmap from a src ptr with a given rowBytes and 34 Config8888. The bitmap must have pixels and be kARGB_8888_Config. 35 */ 36inline void SkCopyConfig8888ToBitmap(const SkBitmap& dstBmp, 37 const uint32_t* srcPixels, 38 size_t srcRowBytes, 39 SkCanvas::Config8888 srcConfig8888); 40 41} 42 43/////////////////////////////////////////////////////////////////////////////// 44// Implementation 45 46namespace { 47 48template <int A_IDX, int R_IDX, int G_IDX, int B_IDX> 49inline uint32_t pack_config8888(uint32_t a, uint32_t r, 50 uint32_t g, uint32_t b) { 51#ifdef SK_CPU_LENDIAN 52 return (a << (A_IDX * 8)) | (r << (R_IDX * 8)) | 53 (g << (G_IDX * 8)) | (b << (B_IDX * 8)); 54#else 55 return (a << ((3-A_IDX) * 8)) | (r << ((3-R_IDX) * 8)) | 56 (g << ((3-G_IDX) * 8)) | (b << ((3-B_IDX) * 8)); 57#endif 58} 59 60template <int A_IDX, int R_IDX, int G_IDX, int B_IDX> 61inline void unpack_config8888(uint32_t color, 62 uint32_t* a, uint32_t* r, 63 uint32_t* g, uint32_t* b) { 64#ifdef SK_CPU_LENDIAN 65 *a = (color >> (A_IDX * 8)) & 0xff; 66 *r = (color >> (R_IDX * 8)) & 0xff; 67 *g = (color >> (G_IDX * 8)) & 0xff; 68 *b = (color >> (B_IDX * 8)) & 0xff; 69#else 70 *a = (color >> ((3 - A_IDX) * 8)) & 0xff; 71 *r = (color >> ((3 - R_IDX) * 8)) & 0xff; 72 *g = (color >> ((3 - G_IDX) * 8)) & 0xff; 73 *b = (color >> ((3 - B_IDX) * 8)) & 0xff; 74#endif 75} 76 77template <bool UNPM, int A_IDX, int R_IDX, int G_IDX, int B_IDX> 78inline void bitmap_copy_to_config8888(uint32_t* dstPixels, 79 size_t dstRowBytes, 80 const SkBitmap& srcBmp) { 81 SkASSERT(SkBitmap::kARGB_8888_Config == srcBmp.config()); 82 SkAutoLockPixels alp(srcBmp); 83 int w = srcBmp.width(); 84 int h = srcBmp.height(); 85 size_t srcRowBytes = srcBmp.rowBytes(); 86 87 intptr_t src = reinterpret_cast<intptr_t>(srcBmp.getPixels()); 88 intptr_t dst = reinterpret_cast<intptr_t>(dstPixels); 89 90 for (int y = 0; y < h; ++y) { 91 const SkPMColor* srcRow = reinterpret_cast<SkPMColor*>(src); 92 uint32_t* dstRow = reinterpret_cast<uint32_t*>(dst); 93 for (int x = 0; x < w; ++x) { 94 SkPMColor pmcolor = srcRow[x]; 95 if (UNPM) { 96 U8CPU a, r, g, b; 97 a = SkGetPackedA32(pmcolor); 98 if (a) { 99 // We're doing the explicit divide to match WebKit layout 100 // test expectations. We can modify and rebaseline if there 101 // it can be shown that there is a more performant way to 102 // unpremul. 103 r = SkGetPackedR32(pmcolor) * 0xff / a; 104 g = SkGetPackedG32(pmcolor) * 0xff / a; 105 b = SkGetPackedB32(pmcolor) * 0xff / a; 106 dstRow[x] = pack_config8888<A_IDX, R_IDX, 107 G_IDX, B_IDX>(a, r, g, b); 108 } else { 109 dstRow[x] = 0; 110 } 111 } else { 112 dstRow[x] = pack_config8888<A_IDX, R_IDX, 113 G_IDX, B_IDX>( 114 SkGetPackedA32(pmcolor), 115 SkGetPackedR32(pmcolor), 116 SkGetPackedG32(pmcolor), 117 SkGetPackedB32(pmcolor)); 118 } 119 } 120 dst += dstRowBytes; 121 src += srcRowBytes; 122 } 123} 124 125template <bool PM, int A_IDX, int R_IDX, int G_IDX, int B_IDX> 126inline void config8888_copy_to_bitmap(const SkBitmap& dstBmp, 127 const uint32_t* srcPixels, 128 size_t srcRowBytes) { 129 SkASSERT(SkBitmap::kARGB_8888_Config == dstBmp.config()); 130 SkAutoLockPixels alp(dstBmp); 131 int w = dstBmp.width(); 132 int h = dstBmp.height(); 133 size_t dstRowBytes = dstBmp.rowBytes(); 134 135 intptr_t src = reinterpret_cast<intptr_t>(srcPixels); 136 intptr_t dst = reinterpret_cast<intptr_t>(dstBmp.getPixels()); 137 138 for (int y = 0; y < h; ++y) { 139 const uint32_t* srcRow = reinterpret_cast<uint32_t*>(src); 140 SkPMColor* dstRow = reinterpret_cast<SkPMColor*>(dst); 141 for (int x = 0; x < w; ++x) { 142 uint32_t c8888 = srcRow[x]; 143 uint32_t a, r, g, b; 144 unpack_config8888<A_IDX, R_IDX, G_IDX, B_IDX>(c8888, &a, &r, 145 &g, &b); 146 if (PM) { 147 // This matches WebKit's conversion which we are replacing. 148 // We can consider alternative rounding rules for performance. 149 r = SkMulDiv255Ceiling(r, a); 150 g = SkMulDiv255Ceiling(g, a); 151 b = SkMulDiv255Ceiling(b, a); 152 } 153 // NoCheck: https://bugs.webkit.org/show_bug.cgi?id=74025 154 dstRow[x] = SkPackARGB32NoCheck(a, r, g, b); 155 } 156 src += srcRowBytes; 157 dst += dstRowBytes; 158 } 159} 160 161#ifdef SK_CPU_LENDIAN 162 static const int SK_NATIVE_A_IDX = SK_A32_SHIFT / 8; 163 static const int SK_NATIVE_R_IDX = SK_R32_SHIFT / 8; 164 static const int SK_NATIVE_G_IDX = SK_G32_SHIFT / 8; 165 static const int SK_NATIVE_B_IDX = SK_B32_SHIFT / 8; 166#else 167 static const int SK_NATIVE_A_IDX = 3 - (SK_A32_SHIFT / 8); 168 static const int SK_NATIVE_R_IDX = 3 - (SK_R32_SHIFT / 8); 169 static const int SK_NATIVE_G_IDX = 3 - (SK_G32_SHIFT / 8); 170 static const int SK_NATIVE_B_IDX = 3 - (SK_B32_SHIFT / 8); 171#endif 172 173inline void SkCopyBitmapToConfig8888(uint32_t* dstPixels, 174 size_t dstRowBytes, 175 SkCanvas::Config8888 dstConfig8888, 176 const SkBitmap& srcBmp) { 177 switch (dstConfig8888) { 178 case SkCanvas::kNative_Premul_Config8888: 179 bitmap_copy_to_config8888<false, 180 SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, 181 SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>( 182 dstPixels, 183 dstRowBytes, 184 srcBmp); 185 break; 186 case SkCanvas::kNative_Unpremul_Config8888: 187 bitmap_copy_to_config8888<true, 188 SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, 189 SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>( 190 dstPixels, 191 dstRowBytes, 192 srcBmp); 193 break; 194 case SkCanvas::kBGRA_Premul_Config8888: 195 bitmap_copy_to_config8888<false, 3, 2, 1, 0> ( 196 dstPixels, dstRowBytes, srcBmp); 197 break; 198 case SkCanvas::kBGRA_Unpremul_Config8888: 199 bitmap_copy_to_config8888<true, 3, 2, 1, 0> ( 200 dstPixels, dstRowBytes, srcBmp); 201 break; 202 case SkCanvas::kRGBA_Premul_Config8888: 203 bitmap_copy_to_config8888<false, 3, 0, 1, 2> ( 204 dstPixels, dstRowBytes, srcBmp); 205 break; 206 case SkCanvas::kRGBA_Unpremul_Config8888: 207 bitmap_copy_to_config8888<true, 3, 0, 1, 2> ( 208 dstPixels, dstRowBytes, srcBmp); 209 break; 210 default: 211 SkASSERT(false && "unexpected Config8888"); 212 break; 213 } 214} 215 216inline void SkCopyConfig8888ToBitmap(const SkBitmap& dstBmp, 217 const uint32_t* srcPixels, 218 size_t srcRowBytes, 219 SkCanvas::Config8888 srcConfig8888) { 220 switch (srcConfig8888) { 221 case SkCanvas::kNative_Premul_Config8888: 222 config8888_copy_to_bitmap<false, 223 SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, 224 SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>( 225 dstBmp, 226 srcPixels, 227 srcRowBytes); 228 break; 229 case SkCanvas::kNative_Unpremul_Config8888: 230 config8888_copy_to_bitmap<true, 231 SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, 232 SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>( 233 dstBmp, 234 srcPixels, 235 srcRowBytes); 236 break; 237 case SkCanvas::kBGRA_Premul_Config8888: 238 config8888_copy_to_bitmap<false, 3, 2, 1, 0> ( 239 dstBmp, srcPixels, srcRowBytes); 240 break; 241 case SkCanvas::kBGRA_Unpremul_Config8888: 242 config8888_copy_to_bitmap<true, 3, 2, 1, 0> ( 243 dstBmp, srcPixels, srcRowBytes); 244 break; 245 case SkCanvas::kRGBA_Premul_Config8888: 246 config8888_copy_to_bitmap<false, 3, 0, 1, 2> ( 247 dstBmp, srcPixels, srcRowBytes); 248 break; 249 case SkCanvas::kRGBA_Unpremul_Config8888: 250 config8888_copy_to_bitmap<true, 3, 0, 1, 2> ( 251 dstBmp, srcPixels, srcRowBytes); 252 break; 253 default: 254 SkASSERT(false && "unexpected Config8888"); 255 break; 256 } 257} 258 259inline void SkCopyARGB8888BitmapTo(uint32_t* dstPixels, 260 size_t dstRowBytes, 261 const SkBitmap& srcBmp) { 262 SkASSERT(SkBitmap::kARGB_8888_Config == srcBmp.config()); 263 264 SkAutoLockPixels alp(srcBmp); 265 266 int w = srcBmp.width(); 267 int h = srcBmp.height(); 268 size_t srcRowBytes = srcBmp.rowBytes(); 269 270 size_t tightRowBytes = w * 4; 271 272 char* src = reinterpret_cast<char*>(srcBmp.getPixels()); 273 char* dst = reinterpret_cast<char*>(dstPixels); 274 275 if (tightRowBytes == srcRowBytes && 276 tightRowBytes == dstRowBytes) { 277 memcpy(dst, src, tightRowBytes * h); 278 } else { 279 for (int y = 0; y < h; ++y) { 280 memcpy(dst, src, tightRowBytes); 281 dst += dstRowBytes; 282 src += srcRowBytes; 283 } 284 } 285} 286 287} 288