1/* 2 * Copyright 2015 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 "SkCodecPriv.h" 9#include "SkColorPriv.h" 10#include "SkMaskSwizzler.h" 11 12static void swizzle_mask16_to_n32_opaque( 13 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 14 uint32_t startX, uint32_t sampleX) { 15 16 // Use the masks to decode to the destination 17 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; 18 SkPMColor* dstPtr = (SkPMColor*) dstRow; 19 for (int i = 0; i < width; i++) { 20 uint16_t p = srcPtr[0]; 21 uint8_t red = masks->getRed(p); 22 uint8_t green = masks->getGreen(p); 23 uint8_t blue = masks->getBlue(p); 24 dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); 25 srcPtr += sampleX; 26 } 27} 28 29static void swizzle_mask16_to_n32_unpremul( 30 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 31 uint32_t startX, uint32_t sampleX) { 32 33 // Use the masks to decode to the destination 34 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; 35 SkPMColor* dstPtr = (SkPMColor*) dstRow; 36 for (int i = 0; i < width; i++) { 37 uint16_t p = srcPtr[0]; 38 uint8_t red = masks->getRed(p); 39 uint8_t green = masks->getGreen(p); 40 uint8_t blue = masks->getBlue(p); 41 uint8_t alpha = masks->getAlpha(p); 42 dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue); 43 srcPtr += sampleX; 44 } 45} 46 47static void swizzle_mask16_to_n32_premul( 48 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 49 uint32_t startX, uint32_t sampleX) { 50 51 // Use the masks to decode to the destination 52 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; 53 SkPMColor* dstPtr = (SkPMColor*) dstRow; 54 for (int i = 0; i < width; i++) { 55 uint16_t p = srcPtr[0]; 56 uint8_t red = masks->getRed(p); 57 uint8_t green = masks->getGreen(p); 58 uint8_t blue = masks->getBlue(p); 59 uint8_t alpha = masks->getAlpha(p); 60 dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue); 61 srcPtr += sampleX; 62 } 63} 64 65// TODO (msarett): We have promoted a two byte per pixel image to 8888, only to 66// convert it back to 565. Instead, we should swizzle to 565 directly. 67static void swizzle_mask16_to_565( 68 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 69 uint32_t startX, uint32_t sampleX) { 70 71 // Use the masks to decode to the destination 72 uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; 73 uint16_t* dstPtr = (uint16_t*) dstRow; 74 for (int i = 0; i < width; i++) { 75 uint16_t p = srcPtr[0]; 76 uint8_t red = masks->getRed(p); 77 uint8_t green = masks->getGreen(p); 78 uint8_t blue = masks->getBlue(p); 79 dstPtr[i] = SkPack888ToRGB16(red, green, blue); 80 srcPtr += sampleX; 81 } 82} 83 84static void swizzle_mask24_to_n32_opaque( 85 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 86 uint32_t startX, uint32_t sampleX) { 87 88 // Use the masks to decode to the destination 89 srcRow += 3 * startX; 90 SkPMColor* dstPtr = (SkPMColor*) dstRow; 91 for (int i = 0; i < width; i++) { 92 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; 93 uint8_t red = masks->getRed(p); 94 uint8_t green = masks->getGreen(p); 95 uint8_t blue = masks->getBlue(p); 96 dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); 97 srcRow += 3 * sampleX; 98 } 99} 100 101static void swizzle_mask24_to_n32_unpremul( 102 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 103 uint32_t startX, uint32_t sampleX) { 104 105 // Use the masks to decode to the destination 106 srcRow += 3 * startX; 107 SkPMColor* dstPtr = (SkPMColor*) dstRow; 108 for (int i = 0; i < width; i++) { 109 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; 110 uint8_t red = masks->getRed(p); 111 uint8_t green = masks->getGreen(p); 112 uint8_t blue = masks->getBlue(p); 113 uint8_t alpha = masks->getAlpha(p); 114 dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue); 115 srcRow += 3 * sampleX; 116 } 117} 118 119static void swizzle_mask24_to_n32_premul( 120 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 121 uint32_t startX, uint32_t sampleX) { 122 123 // Use the masks to decode to the destination 124 srcRow += 3 * startX; 125 SkPMColor* dstPtr = (SkPMColor*) dstRow; 126 for (int i = 0; i < width; i++) { 127 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; 128 uint8_t red = masks->getRed(p); 129 uint8_t green = masks->getGreen(p); 130 uint8_t blue = masks->getBlue(p); 131 uint8_t alpha = masks->getAlpha(p); 132 dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue); 133 srcRow += 3 * sampleX; 134 } 135} 136 137static void swizzle_mask24_to_565( 138 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 139 uint32_t startX, uint32_t sampleX) { 140 141 // Use the masks to decode to the destination 142 srcRow += 3 * startX; 143 uint16_t* dstPtr = (uint16_t*) dstRow; 144 for (int i = 0; i < width; i++) { 145 uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; 146 uint8_t red = masks->getRed(p); 147 uint8_t green = masks->getGreen(p); 148 uint8_t blue = masks->getBlue(p); 149 dstPtr[i] = SkPack888ToRGB16(red, green, blue); 150 srcRow += 3 * sampleX; 151 } 152} 153 154static void swizzle_mask32_to_n32_opaque( 155 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 156 uint32_t startX, uint32_t sampleX) { 157 158 // Use the masks to decode to the destination 159 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; 160 SkPMColor* dstPtr = (SkPMColor*) dstRow; 161 for (int i = 0; i < width; i++) { 162 uint32_t p = srcPtr[0]; 163 uint8_t red = masks->getRed(p); 164 uint8_t green = masks->getGreen(p); 165 uint8_t blue = masks->getBlue(p); 166 dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); 167 srcPtr += sampleX; 168 } 169} 170 171static void swizzle_mask32_to_n32_unpremul( 172 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 173 uint32_t startX, uint32_t sampleX) { 174 175 // Use the masks to decode to the destination 176 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; 177 SkPMColor* dstPtr = (SkPMColor*) dstRow; 178 for (int i = 0; i < width; i++) { 179 uint32_t p = srcPtr[0]; 180 uint8_t red = masks->getRed(p); 181 uint8_t green = masks->getGreen(p); 182 uint8_t blue = masks->getBlue(p); 183 uint8_t alpha = masks->getAlpha(p); 184 dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue); 185 srcPtr += sampleX; 186 } 187} 188 189static void swizzle_mask32_to_n32_premul( 190 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 191 uint32_t startX, uint32_t sampleX) { 192 193 // Use the masks to decode to the destination 194 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; 195 SkPMColor* dstPtr = (SkPMColor*) dstRow; 196 for (int i = 0; i < width; i++) { 197 uint32_t p = srcPtr[0]; 198 uint8_t red = masks->getRed(p); 199 uint8_t green = masks->getGreen(p); 200 uint8_t blue = masks->getBlue(p); 201 uint8_t alpha = masks->getAlpha(p); 202 dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue); 203 srcPtr += sampleX; 204 } 205} 206 207static void swizzle_mask32_to_565( 208 void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, 209 uint32_t startX, uint32_t sampleX) { 210 // Use the masks to decode to the destination 211 uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; 212 uint16_t* dstPtr = (uint16_t*) dstRow; 213 for (int i = 0; i < width; i++) { 214 uint32_t p = srcPtr[0]; 215 uint8_t red = masks->getRed(p); 216 uint8_t green = masks->getGreen(p); 217 uint8_t blue = masks->getBlue(p); 218 dstPtr[i] = SkPack888ToRGB16(red, green, blue); 219 srcPtr += sampleX; 220 } 221} 222 223/* 224 * 225 * Create a new mask swizzler 226 * 227 */ 228SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(const SkImageInfo& dstInfo, 229 const SkImageInfo& srcInfo, SkMasks* masks, uint32_t bitsPerPixel, 230 const SkCodec::Options& options) { 231 232 // Choose the appropriate row procedure 233 RowProc proc = nullptr; 234 switch (bitsPerPixel) { 235 case 16: 236 switch (dstInfo.colorType()) { 237 case kN32_SkColorType: 238 if (kOpaque_SkAlphaType == srcInfo.alphaType()) { 239 proc = &swizzle_mask16_to_n32_opaque; 240 } else { 241 switch (dstInfo.alphaType()) { 242 case kUnpremul_SkAlphaType: 243 proc = &swizzle_mask16_to_n32_unpremul; 244 break; 245 case kPremul_SkAlphaType: 246 proc = &swizzle_mask16_to_n32_premul; 247 break; 248 default: 249 break; 250 } 251 } 252 break; 253 case kRGB_565_SkColorType: 254 proc = &swizzle_mask16_to_565; 255 break; 256 default: 257 break; 258 } 259 break; 260 case 24: 261 switch (dstInfo.colorType()) { 262 case kN32_SkColorType: 263 if (kOpaque_SkAlphaType == srcInfo.alphaType()) { 264 proc = &swizzle_mask24_to_n32_opaque; 265 } else { 266 switch (dstInfo.alphaType()) { 267 case kUnpremul_SkAlphaType: 268 proc = &swizzle_mask24_to_n32_unpremul; 269 break; 270 case kPremul_SkAlphaType: 271 proc = &swizzle_mask24_to_n32_premul; 272 break; 273 default: 274 break; 275 } 276 } 277 break; 278 case kRGB_565_SkColorType: 279 proc = &swizzle_mask24_to_565; 280 break; 281 default: 282 break; 283 } 284 break; 285 case 32: 286 switch (dstInfo.colorType()) { 287 case kN32_SkColorType: 288 if (kOpaque_SkAlphaType == srcInfo.alphaType()) { 289 proc = &swizzle_mask32_to_n32_opaque; 290 } else { 291 switch (dstInfo.alphaType()) { 292 case kUnpremul_SkAlphaType: 293 proc = &swizzle_mask32_to_n32_unpremul; 294 break; 295 case kPremul_SkAlphaType: 296 proc = &swizzle_mask32_to_n32_premul; 297 break; 298 default: 299 break; 300 } 301 } 302 break; 303 case kRGB_565_SkColorType: 304 proc = &swizzle_mask32_to_565; 305 break; 306 default: 307 break; 308 } 309 break; 310 default: 311 SkASSERT(false); 312 return nullptr; 313 } 314 315 int srcOffset = 0; 316 int srcWidth = dstInfo.width(); 317 if (options.fSubset) { 318 srcOffset = options.fSubset->left(); 319 srcWidth = options.fSubset->width(); 320 } 321 322 return new SkMaskSwizzler(masks, proc, srcOffset, srcWidth); 323} 324 325/* 326 * 327 * Constructor for mask swizzler 328 * 329 */ 330SkMaskSwizzler::SkMaskSwizzler(SkMasks* masks, RowProc proc, int srcOffset, int subsetWidth) 331 : fMasks(masks) 332 , fRowProc(proc) 333 , fSubsetWidth(subsetWidth) 334 , fDstWidth(subsetWidth) 335 , fSampleX(1) 336 , fSrcOffset(srcOffset) 337 , fX0(srcOffset) 338{} 339 340int SkMaskSwizzler::onSetSampleX(int sampleX) { 341 // FIXME: Share this function with SkSwizzler? 342 SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be 343 // way to report failure? 344 fSampleX = sampleX; 345 fX0 = get_start_coord(sampleX) + fSrcOffset; 346 fDstWidth = get_scaled_dimension(fSubsetWidth, sampleX); 347 348 // check that fX0 is valid 349 SkASSERT(fX0 >= 0); 350 return fDstWidth; 351} 352 353/* 354 * 355 * Swizzle the specified row 356 * 357 */ 358void SkMaskSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) { 359 SkASSERT(nullptr != dst && nullptr != src); 360 fRowProc(dst, src, fDstWidth, fMasks, fX0, fSampleX); 361} 362