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 "SkBitmap.h" 9 #include "SkCanvas.h" 10 #include "SkConfig8888.h" 11 #include "SkColorPriv.h" 12 #include "SkDither.h" 13 #include "SkMathPriv.h" 14 #include "SkUnPreMultiply.h" 15 16 enum AlphaVerb { 17 kNothing_AlphaVerb, 18 kPremul_AlphaVerb, 19 kUnpremul_AlphaVerb, 20 }; 21 22 template <bool doSwapRB, AlphaVerb doAlpha> uint32_t convert32(uint32_t c) { 23 if (doSwapRB) { 24 c = SkSwizzle_RB(c); 25 } 26 27 // Lucky for us, in both RGBA and BGRA, the alpha component is always in the same place, so 28 // we can perform premul or unpremul the same way without knowing the swizzles for RGB. 29 switch (doAlpha) { 30 case kNothing_AlphaVerb: 31 // no change 32 break; 33 case kPremul_AlphaVerb: 34 c = SkPreMultiplyARGB(SkGetPackedA32(c), SkGetPackedR32(c), 35 SkGetPackedG32(c), SkGetPackedB32(c)); 36 break; 37 case kUnpremul_AlphaVerb: 38 c = SkUnPreMultiply::UnPreMultiplyPreservingByteOrder(c); 39 break; 40 } 41 return c; 42 } 43 44 template <bool doSwapRB, AlphaVerb doAlpha> 45 void convert32_row(uint32_t* dst, const uint32_t* src, int count) { 46 // This has to be correct if src == dst (but not partial overlap) 47 for (int i = 0; i < count; ++i) { 48 dst[i] = convert32<doSwapRB, doAlpha>(src[i]); 49 } 50 } 51 52 static bool is_32bit_colortype(SkColorType ct) { 53 return kRGBA_8888_SkColorType == ct || kBGRA_8888_SkColorType == ct; 54 } 55 56 static AlphaVerb compute_AlphaVerb(SkAlphaType src, SkAlphaType dst) { 57 SkASSERT(kUnknown_SkAlphaType != src); 58 SkASSERT(kUnknown_SkAlphaType != dst); 59 60 if (kOpaque_SkAlphaType == src || kOpaque_SkAlphaType == dst || src == dst) { 61 return kNothing_AlphaVerb; 62 } 63 if (kPremul_SkAlphaType == dst) { 64 SkASSERT(kUnpremul_SkAlphaType == src); 65 return kPremul_AlphaVerb; 66 } else { 67 SkASSERT(kPremul_SkAlphaType == src); 68 SkASSERT(kUnpremul_SkAlphaType == dst); 69 return kUnpremul_AlphaVerb; 70 } 71 } 72 73 static void memcpy32_row(uint32_t* dst, const uint32_t* src, int count) { 74 memcpy(dst, src, count * 4); 75 } 76 77 bool SkSrcPixelInfo::convertPixelsTo(SkDstPixelInfo* dst, int width, int height) const { 78 if (width <= 0 || height <= 0) { 79 return false; 80 } 81 82 if (!is_32bit_colortype(fColorType) || !is_32bit_colortype(dst->fColorType)) { 83 return false; 84 } 85 86 void (*proc)(uint32_t* dst, const uint32_t* src, int count); 87 AlphaVerb doAlpha = compute_AlphaVerb(fAlphaType, dst->fAlphaType); 88 bool doSwapRB = fColorType != dst->fColorType; 89 90 switch (doAlpha) { 91 case kNothing_AlphaVerb: 92 if (doSwapRB) { 93 proc = convert32_row<true, kNothing_AlphaVerb>; 94 } else { 95 if (fPixels == dst->fPixels) { 96 return true; 97 } 98 proc = memcpy32_row; 99 } 100 break; 101 case kPremul_AlphaVerb: 102 if (doSwapRB) { 103 proc = convert32_row<true, kPremul_AlphaVerb>; 104 } else { 105 proc = convert32_row<false, kPremul_AlphaVerb>; 106 } 107 break; 108 case kUnpremul_AlphaVerb: 109 if (doSwapRB) { 110 proc = convert32_row<true, kUnpremul_AlphaVerb>; 111 } else { 112 proc = convert32_row<false, kUnpremul_AlphaVerb>; 113 } 114 break; 115 } 116 117 uint32_t* dstP = static_cast<uint32_t*>(dst->fPixels); 118 const uint32_t* srcP = static_cast<const uint32_t*>(fPixels); 119 size_t srcInc = fRowBytes >> 2; 120 size_t dstInc = dst->fRowBytes >> 2; 121 for (int y = 0; y < height; ++y) { 122 proc(dstP, srcP, width); 123 dstP += dstInc; 124 srcP += srcInc; 125 } 126 return true; 127 } 128 129 static void copy_g8_to_32(void* dst, size_t dstRB, const void* src, size_t srcRB, int w, int h) { 130 uint32_t* dst32 = (uint32_t*)dst; 131 const uint8_t* src8 = (const uint8_t*)src; 132 133 for (int y = 0; y < h; ++y) { 134 for (int x = 0; x < w; ++x) { 135 dst32[x] = SkPackARGB32(0xFF, src8[x], src8[x], src8[x]); 136 } 137 dst32 = (uint32_t*)((char*)dst32 + dstRB); 138 src8 += srcRB; 139 } 140 } 141 142 static void copy_32_to_g8(void* dst, size_t dstRB, const void* src, size_t srcRB, 143 const SkImageInfo& srcInfo) { 144 uint8_t* dst8 = (uint8_t*)dst; 145 const uint32_t* src32 = (const uint32_t*)src; 146 147 const int w = srcInfo.width(); 148 const int h = srcInfo.height(); 149 const bool isBGRA = (kBGRA_8888_SkColorType == srcInfo.colorType()); 150 151 for (int y = 0; y < h; ++y) { 152 if (isBGRA) { 153 // BGRA 154 for (int x = 0; x < w; ++x) { 155 uint32_t s = src32[x]; 156 dst8[x] = SkComputeLuminance((s >> 16) & 0xFF, (s >> 8) & 0xFF, s & 0xFF); 157 } 158 } else { 159 // RGBA 160 for (int x = 0; x < w; ++x) { 161 uint32_t s = src32[x]; 162 dst8[x] = SkComputeLuminance(s & 0xFF, (s >> 8) & 0xFF, (s >> 16) & 0xFF); 163 } 164 } 165 src32 = (const uint32_t*)((const char*)src32 + srcRB); 166 dst8 += dstRB; 167 } 168 } 169 170 bool SkPixelInfo::CopyPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, 171 const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB, 172 SkColorTable* ctable) { 173 if (srcInfo.dimensions() != dstInfo.dimensions()) { 174 return false; 175 } 176 177 const int width = srcInfo.width(); 178 const int height = srcInfo.height(); 179 180 // Do the easiest one first : both configs are equal 181 if ((srcInfo == dstInfo) && !ctable) { 182 size_t bytes = width * srcInfo.bytesPerPixel(); 183 for (int y = 0; y < height; ++y) { 184 memcpy(dstPixels, srcPixels, bytes); 185 srcPixels = (const char*)srcPixels + srcRB; 186 dstPixels = (char*)dstPixels + dstRB; 187 } 188 return true; 189 } 190 191 // Handle fancy alpha swizzling if both are ARGB32 192 if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel()) { 193 SkDstPixelInfo dstPI; 194 dstPI.fColorType = dstInfo.colorType(); 195 dstPI.fAlphaType = dstInfo.alphaType(); 196 dstPI.fPixels = dstPixels; 197 dstPI.fRowBytes = dstRB; 198 199 SkSrcPixelInfo srcPI; 200 srcPI.fColorType = srcInfo.colorType(); 201 srcPI.fAlphaType = srcInfo.alphaType(); 202 srcPI.fPixels = srcPixels; 203 srcPI.fRowBytes = srcRB; 204 205 return srcPI.convertPixelsTo(&dstPI, width, height); 206 } 207 208 // If they agree on colorType and the alphaTypes are compatible, then we just memcpy. 209 // Note: we've already taken care of 32bit colortypes above. 210 if (srcInfo.colorType() == dstInfo.colorType()) { 211 switch (srcInfo.colorType()) { 212 case kRGB_565_SkColorType: 213 case kAlpha_8_SkColorType: 214 case kGray_8_SkColorType: 215 break; 216 case kIndex_8_SkColorType: 217 case kARGB_4444_SkColorType: 218 if (srcInfo.alphaType() != dstInfo.alphaType()) { 219 return false; 220 } 221 break; 222 default: 223 return false; 224 } 225 SkRectMemcpy(dstPixels, dstRB, srcPixels, srcRB, width * srcInfo.bytesPerPixel(), height); 226 return true; 227 } 228 229 /* 230 * Begin section where we try to change colorTypes along the way. Not all combinations 231 * are supported. 232 */ 233 234 if (kGray_8_SkColorType == srcInfo.colorType() && 4 == dstInfo.bytesPerPixel()) { 235 copy_g8_to_32(dstPixels, dstRB, srcPixels, srcRB, width, height); 236 return true; 237 } 238 if (kGray_8_SkColorType == dstInfo.colorType() && 4 == srcInfo.bytesPerPixel()) { 239 copy_32_to_g8(dstPixels, dstRB, srcPixels, srcRB, srcInfo); 240 return true; 241 } 242 243 // Can no longer draw directly into 4444, but we can manually whack it for a few combinations 244 if (kARGB_4444_SkColorType == dstInfo.colorType() && 245 (kN32_SkColorType == srcInfo.colorType() || kIndex_8_SkColorType == srcInfo.colorType())) { 246 if (srcInfo.alphaType() == kUnpremul_SkAlphaType) { 247 // Our method for converting to 4444 assumes premultiplied. 248 return false; 249 } 250 251 const SkPMColor* table = nullptr; 252 if (kIndex_8_SkColorType == srcInfo.colorType()) { 253 if (nullptr == ctable) { 254 return false; 255 } 256 table = ctable->readColors(); 257 } 258 259 for (int y = 0; y < height; ++y) { 260 DITHER_4444_SCAN(y); 261 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*)dstPixels; 262 if (table) { 263 const uint8_t* SK_RESTRICT srcRow = (const uint8_t*)srcPixels; 264 for (int x = 0; x < width; ++x) { 265 dstRow[x] = SkDitherARGB32To4444(table[srcRow[x]], DITHER_VALUE(x)); 266 } 267 } else { 268 const SkPMColor* SK_RESTRICT srcRow = (const SkPMColor*)srcPixels; 269 for (int x = 0; x < width; ++x) { 270 dstRow[x] = SkDitherARGB32To4444(srcRow[x], DITHER_VALUE(x)); 271 } 272 } 273 dstPixels = (char*)dstPixels + dstRB; 274 srcPixels = (const char*)srcPixels + srcRB; 275 } 276 return true; 277 } 278 279 if (dstInfo.alphaType() == kUnpremul_SkAlphaType) { 280 // We do not support drawing to unpremultiplied bitmaps. 281 return false; 282 } 283 284 // Final fall-back, draw with a canvas 285 // 286 // Always clear the dest in case one of the blitters accesses it 287 // TODO: switch the allocation of tmpDst to call sk_calloc_throw 288 { 289 SkBitmap bm; 290 if (!bm.installPixels(srcInfo, const_cast<void*>(srcPixels), srcRB, ctable, nullptr, nullptr)) { 291 return false; 292 } 293 SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterDirect(dstInfo, dstPixels, dstRB)); 294 if (nullptr == canvas.get()) { 295 return false; 296 } 297 298 SkPaint paint; 299 paint.setDither(true); 300 301 canvas->clear(0); 302 canvas->drawBitmap(bm, 0, 0, &paint); 303 return true; 304 } 305 } 306 307