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 "SkColorSpaceXform_Base.h" 9 #include "SkColorSpaceXformPriv.h" 10 #include "SkColorSpacePriv.h" 11 #include "SkColorTable.h" 12 #include "SkConvertPixels.h" 13 #include "SkHalf.h" 14 #include "SkImageInfoPriv.h" 15 #include "SkOpts.h" 16 #include "SkPM4fPriv.h" 17 #include "SkRasterPipeline.h" 18 #include "SkUnPreMultiply.h" 19 #include "SkUnPreMultiplyPriv.h" 20 #include "../jumper/SkJumper.h" 21 22 // Fast Path 1: The memcpy() case. 23 static inline bool can_memcpy(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) { 24 if (dstInfo.colorType() != srcInfo.colorType()) { 25 return false; 26 } 27 28 if (kAlpha_8_SkColorType == dstInfo.colorType()) { 29 return true; 30 } 31 32 if (dstInfo.alphaType() != srcInfo.alphaType() && 33 kOpaque_SkAlphaType != dstInfo.alphaType() && 34 kOpaque_SkAlphaType != srcInfo.alphaType()) 35 { 36 // We need to premultiply or unpremultiply. 37 return false; 38 } 39 40 return !dstInfo.colorSpace() || 41 SkColorSpace::Equals(dstInfo.colorSpace(), srcInfo.colorSpace()); 42 } 43 44 // Fast Path 2: Simple swizzles and premuls. 45 enum AlphaVerb { 46 kNothing_AlphaVerb, 47 kPremul_AlphaVerb, 48 kUnpremul_AlphaVerb, 49 }; 50 51 template <bool kSwapRB> 52 static void wrap_unpremultiply(uint32_t* dst, const void* src, int count) { 53 SkUnpremultiplyRow<kSwapRB>(dst, (const uint32_t*) src, count); 54 } 55 56 void swizzle_and_multiply(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, 57 const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB) { 58 void (*proc)(uint32_t* dst, const void* src, int count); 59 const bool swapRB = dstInfo.colorType() != srcInfo.colorType(); 60 AlphaVerb alphaVerb = kNothing_AlphaVerb; 61 if (kPremul_SkAlphaType == dstInfo.alphaType() && 62 kUnpremul_SkAlphaType == srcInfo.alphaType()) 63 { 64 alphaVerb = kPremul_AlphaVerb; 65 } else if (kUnpremul_SkAlphaType == dstInfo.alphaType() && 66 kPremul_SkAlphaType == srcInfo.alphaType()) { 67 alphaVerb = kUnpremul_AlphaVerb; 68 } 69 70 switch (alphaVerb) { 71 case kNothing_AlphaVerb: 72 // If we do not need to swap or multiply, we should hit the memcpy case. 73 SkASSERT(swapRB); 74 proc = SkOpts::RGBA_to_BGRA; 75 break; 76 case kPremul_AlphaVerb: 77 proc = swapRB ? SkOpts::RGBA_to_bgrA : SkOpts::RGBA_to_rgbA; 78 break; 79 case kUnpremul_AlphaVerb: 80 proc = swapRB ? wrap_unpremultiply<true> : wrap_unpremultiply<false>; 81 break; 82 } 83 84 for (int y = 0; y < dstInfo.height(); y++) { 85 proc((uint32_t*) dstPixels, srcPixels, dstInfo.width()); 86 dstPixels = SkTAddOffset<void>(dstPixels, dstRB); 87 srcPixels = SkTAddOffset<const void>(srcPixels, srcRB); 88 } 89 } 90 91 // Fast Path 3: Color space xform. 92 static inline bool optimized_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo, 93 SkTransferFunctionBehavior behavior) { 94 // Unpremultiplication is unsupported by SkColorSpaceXform. Note that if |src| is non-linearly 95 // premultiplied, we're always going to have to unpremultiply before doing anything. 96 if (kPremul_SkAlphaType == srcInfo.alphaType() && 97 (kUnpremul_SkAlphaType == dstInfo.alphaType() || 98 SkTransferFunctionBehavior::kIgnore == behavior)) { 99 return false; 100 } 101 102 switch (dstInfo.colorType()) { 103 case kRGBA_8888_SkColorType: 104 case kBGRA_8888_SkColorType: 105 case kRGBA_F16_SkColorType: 106 break; 107 default: 108 return false; 109 } 110 111 switch (srcInfo.colorType()) { 112 case kRGBA_8888_SkColorType: 113 case kBGRA_8888_SkColorType: 114 break; 115 default: 116 return false; 117 } 118 119 return true; 120 } 121 122 static inline void apply_color_xform(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, 123 const SkImageInfo& srcInfo, const void* srcPixels, 124 size_t srcRB, SkTransferFunctionBehavior behavior) { 125 SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType()); 126 SkColorSpaceXform::ColorFormat srcFormat = select_xform_format(srcInfo.colorType()); 127 SkAlphaType xformAlpha; 128 switch (srcInfo.alphaType()) { 129 case kOpaque_SkAlphaType: 130 xformAlpha = kOpaque_SkAlphaType; 131 break; 132 case kPremul_SkAlphaType: 133 SkASSERT(kPremul_SkAlphaType == dstInfo.alphaType()); 134 135 // This signal means: copy the src alpha to the dst, do not premultiply (in this 136 // case because the pixels are already premultiplied). 137 xformAlpha = kUnpremul_SkAlphaType; 138 break; 139 case kUnpremul_SkAlphaType: 140 SkASSERT(kPremul_SkAlphaType == dstInfo.alphaType() || 141 kUnpremul_SkAlphaType == dstInfo.alphaType()); 142 143 xformAlpha = dstInfo.alphaType(); 144 break; 145 default: 146 SkASSERT(false); 147 xformAlpha = kUnpremul_SkAlphaType; 148 break; 149 } 150 151 std::unique_ptr<SkColorSpaceXform> xform = 152 SkColorSpaceXform_Base::New(srcInfo.colorSpace(), dstInfo.colorSpace(), behavior); 153 SkASSERT(xform); 154 155 for (int y = 0; y < dstInfo.height(); y++) { 156 SkAssertResult(xform->apply(dstFormat, dstPixels, srcFormat, srcPixels, dstInfo.width(), 157 xformAlpha)); 158 dstPixels = SkTAddOffset<void>(dstPixels, dstRB); 159 srcPixels = SkTAddOffset<const void>(srcPixels, srcRB); 160 } 161 } 162 163 // Fast Path 4: Alpha 8 dsts. 164 static void convert_to_alpha8(uint8_t* dst, size_t dstRB, const SkImageInfo& srcInfo, 165 const void* src, size_t srcRB, SkColorTable* ctable) { 166 if (srcInfo.isOpaque()) { 167 for (int y = 0; y < srcInfo.height(); ++y) { 168 memset(dst, 0xFF, srcInfo.width()); 169 dst = SkTAddOffset<uint8_t>(dst, dstRB); 170 } 171 return; 172 } 173 174 switch (srcInfo.colorType()) { 175 case kBGRA_8888_SkColorType: 176 case kRGBA_8888_SkColorType: { 177 auto src32 = (const uint32_t*) src; 178 for (int y = 0; y < srcInfo.height(); y++) { 179 for (int x = 0; x < srcInfo.width(); x++) { 180 dst[x] = src32[x] >> 24; 181 } 182 dst = SkTAddOffset<uint8_t>(dst, dstRB); 183 src32 = SkTAddOffset<const uint32_t>(src32, srcRB); 184 } 185 break; 186 } 187 case kARGB_4444_SkColorType: { 188 auto src16 = (const uint16_t*) src; 189 for (int y = 0; y < srcInfo.height(); y++) { 190 for (int x = 0; x < srcInfo.width(); x++) { 191 dst[x] = SkPacked4444ToA32(src16[x]); 192 } 193 dst = SkTAddOffset<uint8_t>(dst, dstRB); 194 src16 = SkTAddOffset<const uint16_t>(src16, srcRB); 195 } 196 break; 197 } 198 case kRGBA_F16_SkColorType: { 199 auto src64 = (const uint64_t*) src; 200 for (int y = 0; y < srcInfo.height(); y++) { 201 for (int x = 0; x < srcInfo.width(); x++) { 202 dst[x] = (uint8_t) (255.0f * SkHalfToFloat(src64[x] >> 48)); 203 } 204 dst = SkTAddOffset<uint8_t>(dst, dstRB); 205 src64 = SkTAddOffset<const uint64_t>(src64, srcRB); 206 } 207 break; 208 } 209 default: 210 SkASSERT(false); 211 break; 212 } 213 } 214 215 // Default: Use the pipeline. 216 static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB, 217 const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB, 218 bool isColorAware, SkTransferFunctionBehavior behavior) { 219 220 SkJumper_MemoryCtx src = { (void*)srcRow, (int)(srcRB / srcInfo.bytesPerPixel()) }, 221 dst = { (void*)dstRow, (int)(dstRB / dstInfo.bytesPerPixel()) }; 222 223 SkRasterPipeline_<256> pipeline; 224 switch (srcInfo.colorType()) { 225 case kRGBA_8888_SkColorType: 226 pipeline.append(SkRasterPipeline::load_8888, &src); 227 break; 228 case kBGRA_8888_SkColorType: 229 pipeline.append(SkRasterPipeline::load_bgra, &src); 230 break; 231 case kRGB_565_SkColorType: 232 pipeline.append(SkRasterPipeline::load_565, &src); 233 break; 234 case kRGBA_F16_SkColorType: 235 pipeline.append(SkRasterPipeline::load_f16, &src); 236 break; 237 case kGray_8_SkColorType: 238 pipeline.append(SkRasterPipeline::load_g8, &src); 239 break; 240 case kARGB_4444_SkColorType: 241 pipeline.append(SkRasterPipeline::load_4444, &src); 242 break; 243 default: 244 SkASSERT(false); 245 break; 246 } 247 248 SkAlphaType premulState = srcInfo.alphaType(); 249 if (kPremul_SkAlphaType == premulState && SkTransferFunctionBehavior::kIgnore == behavior) { 250 pipeline.append(SkRasterPipeline::unpremul); 251 premulState = kUnpremul_SkAlphaType; 252 } 253 254 SkColorSpaceTransferFn srcFn; 255 if (isColorAware && srcInfo.gammaCloseToSRGB()) { 256 pipeline.append(SkRasterPipeline::from_srgb); 257 } else if (isColorAware && !srcInfo.colorSpace()->gammaIsLinear()) { 258 SkAssertResult(srcInfo.colorSpace()->isNumericalTransferFn(&srcFn)); 259 if (is_just_gamma(srcFn)) { 260 pipeline.append(SkRasterPipeline::gamma, &srcFn.fG); 261 } else { 262 pipeline.append(SkRasterPipeline::parametric_r, &srcFn); 263 pipeline.append(SkRasterPipeline::parametric_g, &srcFn); 264 pipeline.append(SkRasterPipeline::parametric_b, &srcFn); 265 } 266 } 267 268 float matrix[12]; 269 if (isColorAware) { 270 append_gamut_transform(&pipeline, matrix, srcInfo.colorSpace(), dstInfo.colorSpace(), 271 premulState); 272 } 273 274 SkAlphaType dat = dstInfo.alphaType(); 275 if (SkTransferFunctionBehavior::kRespect == behavior) { 276 if (kPremul_SkAlphaType == premulState && kUnpremul_SkAlphaType == dat) { 277 pipeline.append(SkRasterPipeline::unpremul); 278 premulState = kUnpremul_SkAlphaType; 279 } else if (kUnpremul_SkAlphaType == premulState && kPremul_SkAlphaType == dat) { 280 pipeline.append(SkRasterPipeline::premul); 281 premulState = kPremul_SkAlphaType; 282 } 283 } 284 285 SkColorSpaceTransferFn dstFn; 286 if (isColorAware && dstInfo.gammaCloseToSRGB()) { 287 pipeline.append(SkRasterPipeline::to_srgb); 288 } else if (isColorAware && !dstInfo.colorSpace()->gammaIsLinear()) { 289 SkAssertResult(dstInfo.colorSpace()->isNumericalTransferFn(&dstFn)); 290 dstFn = dstFn.invert(); 291 if (is_just_gamma(dstFn)) { 292 pipeline.append(SkRasterPipeline::gamma, &dstFn.fG); 293 } else { 294 pipeline.append(SkRasterPipeline::parametric_r, &dstFn); 295 pipeline.append(SkRasterPipeline::parametric_g, &dstFn); 296 pipeline.append(SkRasterPipeline::parametric_b, &dstFn); 297 } 298 } 299 300 if (kUnpremul_SkAlphaType == premulState && kPremul_SkAlphaType == dat && 301 SkTransferFunctionBehavior::kIgnore == behavior) 302 { 303 pipeline.append(SkRasterPipeline::premul); 304 premulState = kPremul_SkAlphaType; 305 } 306 307 // The final premul state must equal the dst alpha type. Note that if we are "converting" 308 // opaque to another alpha type, there's no need to worry about multiplication. 309 SkASSERT(premulState == dat || kOpaque_SkAlphaType == srcInfo.alphaType()); 310 311 // We'll dither if we're decreasing precision below 32-bit. 312 float dither_rate = 0.0f; 313 if (srcInfo.bytesPerPixel() > dstInfo.bytesPerPixel()) { 314 switch (dstInfo.colorType()) { 315 case kRGB_565_SkColorType: dither_rate = 1/63.0f; break; 316 case kARGB_4444_SkColorType: dither_rate = 1/15.0f; break; 317 default: dither_rate = 0.0f; break; 318 } 319 } 320 if (dither_rate > 0) { 321 pipeline.append(SkRasterPipeline::dither, &dither_rate); 322 } 323 324 switch (dstInfo.colorType()) { 325 case kRGBA_8888_SkColorType: 326 pipeline.append(SkRasterPipeline::store_8888, &dst); 327 break; 328 case kBGRA_8888_SkColorType: 329 pipeline.append(SkRasterPipeline::store_bgra, &dst); 330 break; 331 case kRGB_565_SkColorType: 332 pipeline.append(SkRasterPipeline::store_565, &dst); 333 break; 334 case kRGBA_F16_SkColorType: 335 pipeline.append(SkRasterPipeline::store_f16, &dst); 336 break; 337 case kARGB_4444_SkColorType: 338 pipeline.append(SkRasterPipeline::store_4444, &dst); 339 break; 340 default: 341 SkASSERT(false); 342 break; 343 } 344 345 pipeline.run(0,0, srcInfo.width(), srcInfo.height()); 346 } 347 348 void SkConvertPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, 349 const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB, 350 SkColorTable* ctable, SkTransferFunctionBehavior behavior) { 351 SkASSERT(dstInfo.dimensions() == srcInfo.dimensions()); 352 SkASSERT(SkImageInfoValidConversion(dstInfo, srcInfo)); 353 354 // Fast Path 1: The memcpy() case. 355 if (can_memcpy(dstInfo, srcInfo)) { 356 SkRectMemcpy(dstPixels, dstRB, srcPixels, srcRB, dstInfo.minRowBytes(), dstInfo.height()); 357 return; 358 } 359 360 const bool isColorAware = dstInfo.colorSpace(); 361 SkASSERT(srcInfo.colorSpace() || !isColorAware); 362 363 // Fast Path 2: Simple swizzles and premuls. 364 if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel() && !isColorAware) { 365 swizzle_and_multiply(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB); 366 return; 367 } 368 369 // Fast Path 3: Color space xform. 370 if (isColorAware && optimized_color_xform(dstInfo, srcInfo, behavior)) { 371 apply_color_xform(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, behavior); 372 return; 373 } 374 375 // Fast Path 4: Alpha 8 dsts. 376 if (kAlpha_8_SkColorType == dstInfo.colorType()) { 377 convert_to_alpha8((uint8_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable); 378 return; 379 } 380 381 // Default: Use the pipeline. 382 convert_with_pipeline(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, isColorAware, 383 behavior); 384 } 385