SkConvertPixels.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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. #include "include/private/SkColorData.h"
  8. #include "include/private/SkHalf.h"
  9. #include "include/private/SkImageInfoPriv.h"
  10. #include "src/core/SkColorSpacePriv.h"
  11. #include "src/core/SkColorSpaceXformSteps.h"
  12. #include "src/core/SkConvertPixels.h"
  13. #include "src/core/SkOpts.h"
  14. #include "src/core/SkRasterPipeline.h"
  15. static bool rect_memcpy(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
  16. const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
  17. const SkColorSpaceXformSteps& steps) {
  18. // We can copy the pixels when no color type, alpha type, or color space changes.
  19. if (dstInfo.colorType() != srcInfo.colorType()) {
  20. return false;
  21. }
  22. if (dstInfo.colorType() != kAlpha_8_SkColorType
  23. && steps.flags.mask() != 0b00000) {
  24. return false;
  25. }
  26. SkRectMemcpy(dstPixels, dstRB,
  27. srcPixels, srcRB, dstInfo.minRowBytes(), dstInfo.height());
  28. return true;
  29. }
  30. static bool swizzle_or_premul(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
  31. const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
  32. const SkColorSpaceXformSteps& steps) {
  33. auto is_8888 = [](SkColorType ct) {
  34. return ct == kRGBA_8888_SkColorType || ct == kBGRA_8888_SkColorType;
  35. };
  36. if (!is_8888(dstInfo.colorType()) ||
  37. !is_8888(srcInfo.colorType()) ||
  38. steps.flags.linearize ||
  39. steps.flags.gamut_transform ||
  40. steps.flags.unpremul ||
  41. steps.flags.encode) {
  42. return false;
  43. }
  44. const bool swapRB = dstInfo.colorType() != srcInfo.colorType();
  45. void (*fn)(uint32_t*, const uint32_t*, int) = nullptr;
  46. if (steps.flags.premul) {
  47. fn = swapRB ? SkOpts::RGBA_to_bgrA
  48. : SkOpts::RGBA_to_rgbA;
  49. } else {
  50. // If we're not swizzling, we ought to have used rect_memcpy().
  51. SkASSERT(swapRB);
  52. fn = SkOpts::RGBA_to_BGRA;
  53. }
  54. for (int y = 0; y < dstInfo.height(); y++) {
  55. fn((uint32_t*)dstPixels, (const uint32_t*)srcPixels, dstInfo.width());
  56. dstPixels = SkTAddOffset<void>(dstPixels, dstRB);
  57. srcPixels = SkTAddOffset<const void>(srcPixels, srcRB);
  58. }
  59. return true;
  60. }
  61. static bool convert_to_alpha8(const SkImageInfo& dstInfo, void* vdst, size_t dstRB,
  62. const SkImageInfo& srcInfo, const void* src, size_t srcRB,
  63. const SkColorSpaceXformSteps&) {
  64. if (dstInfo.colorType() != kAlpha_8_SkColorType) {
  65. return false;
  66. }
  67. auto dst = (uint8_t*)vdst;
  68. switch (srcInfo.colorType()) {
  69. case kUnknown_SkColorType:
  70. case kAlpha_8_SkColorType: {
  71. // Unknown should never happen.
  72. // Alpha8 should have been handled by rect_memcpy().
  73. SkASSERT(false);
  74. return false;
  75. }
  76. case kGray_8_SkColorType:
  77. case kRGB_565_SkColorType:
  78. case kRGB_888x_SkColorType:
  79. case kRGB_101010x_SkColorType: {
  80. for (int y = 0; y < srcInfo.height(); ++y) {
  81. memset(dst, 0xFF, srcInfo.width());
  82. dst = SkTAddOffset<uint8_t>(dst, dstRB);
  83. }
  84. return true;
  85. }
  86. case kARGB_4444_SkColorType: {
  87. auto src16 = (const uint16_t*) src;
  88. for (int y = 0; y < srcInfo.height(); y++) {
  89. for (int x = 0; x < srcInfo.width(); x++) {
  90. dst[x] = SkPacked4444ToA32(src16[x]);
  91. }
  92. dst = SkTAddOffset<uint8_t>(dst, dstRB);
  93. src16 = SkTAddOffset<const uint16_t>(src16, srcRB);
  94. }
  95. return true;
  96. }
  97. case kBGRA_8888_SkColorType:
  98. case kRGBA_8888_SkColorType: {
  99. auto src32 = (const uint32_t*) src;
  100. for (int y = 0; y < srcInfo.height(); y++) {
  101. for (int x = 0; x < srcInfo.width(); x++) {
  102. dst[x] = src32[x] >> 24;
  103. }
  104. dst = SkTAddOffset<uint8_t>(dst, dstRB);
  105. src32 = SkTAddOffset<const uint32_t>(src32, srcRB);
  106. }
  107. return true;
  108. }
  109. case kRGBA_1010102_SkColorType: {
  110. auto src32 = (const uint32_t*) src;
  111. for (int y = 0; y < srcInfo.height(); y++) {
  112. for (int x = 0; x < srcInfo.width(); x++) {
  113. dst[x] = (src32[x] >> 30) * 0x55;
  114. }
  115. dst = SkTAddOffset<uint8_t>(dst, dstRB);
  116. src32 = SkTAddOffset<const uint32_t>(src32, srcRB);
  117. }
  118. return true;
  119. }
  120. case kRGBA_F16Norm_SkColorType:
  121. case kRGBA_F16_SkColorType: {
  122. auto src64 = (const uint64_t*) src;
  123. for (int y = 0; y < srcInfo.height(); y++) {
  124. for (int x = 0; x < srcInfo.width(); x++) {
  125. dst[x] = (uint8_t) (255.0f * SkHalfToFloat(src64[x] >> 48));
  126. }
  127. dst = SkTAddOffset<uint8_t>(dst, dstRB);
  128. src64 = SkTAddOffset<const uint64_t>(src64, srcRB);
  129. }
  130. return true;
  131. }
  132. case kRGBA_F32_SkColorType: {
  133. auto rgba = (const float*)src;
  134. for (int y = 0; y < srcInfo.height(); y++) {
  135. for (int x = 0; x < srcInfo.width(); x++) {
  136. dst[x] = (uint8_t)(255.0f * rgba[4*x+3]);
  137. }
  138. dst = SkTAddOffset<uint8_t>(dst, dstRB);
  139. rgba = SkTAddOffset<const float>(rgba, srcRB);
  140. }
  141. return true;
  142. }
  143. }
  144. return false;
  145. }
  146. // Default: Use the pipeline.
  147. static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB,
  148. const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB,
  149. const SkColorSpaceXformSteps& steps) {
  150. SkRasterPipeline_MemoryCtx src = { (void*)srcRow, (int)(srcRB / srcInfo.bytesPerPixel()) },
  151. dst = { (void*)dstRow, (int)(dstRB / dstInfo.bytesPerPixel()) };
  152. SkRasterPipeline_<256> pipeline;
  153. pipeline.append_load(srcInfo.colorType(), &src);
  154. steps.apply(&pipeline, srcInfo.colorType());
  155. pipeline.append_gamut_clamp_if_normalized(dstInfo);
  156. pipeline.append_store(dstInfo.colorType(), &dst);
  157. pipeline.run(0,0, srcInfo.width(), srcInfo.height());
  158. }
  159. void SkConvertPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
  160. const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB) {
  161. SkASSERT(dstInfo.dimensions() == srcInfo.dimensions());
  162. SkASSERT(SkImageInfoValidConversion(dstInfo, srcInfo));
  163. SkColorSpaceXformSteps steps{srcInfo.colorSpace(), srcInfo.alphaType(),
  164. dstInfo.colorSpace(), dstInfo.alphaType()};
  165. for (auto fn : {rect_memcpy, swizzle_or_premul, convert_to_alpha8}) {
  166. if (fn(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, steps)) {
  167. return;
  168. }
  169. }
  170. convert_with_pipeline(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, steps);
  171. }