readpixels.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * Copyright 2016 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 "gm/gm.h"
  8. #include "include/codec/SkCodec.h"
  9. #include "include/core/SkBitmap.h"
  10. #include "include/core/SkCanvas.h"
  11. #include "include/core/SkColorSpace.h"
  12. #include "include/core/SkData.h"
  13. #include "include/core/SkImage.h"
  14. #include "include/core/SkImageInfo.h"
  15. #include "include/core/SkPaint.h"
  16. #include "include/core/SkPicture.h"
  17. #include "include/core/SkPictureRecorder.h"
  18. #include "include/core/SkRect.h"
  19. #include "include/core/SkRefCnt.h"
  20. #include "include/core/SkSize.h"
  21. #include "include/core/SkStream.h"
  22. #include "include/core/SkString.h"
  23. #include "include/core/SkTypes.h"
  24. #include "include/third_party/skcms/skcms.h"
  25. #include "tools/Resources.h"
  26. #include <string.h>
  27. #include <memory>
  28. #include <utility>
  29. class GrContext;
  30. static const int kWidth = 64;
  31. static const int kHeight = 64;
  32. static sk_sp<SkImage> make_raster_image(SkColorType colorType) {
  33. std::unique_ptr<SkStream> stream(GetResourceAsStream("images/google_chrome.ico"));
  34. std::unique_ptr<SkCodec> codec = SkCodec::MakeFromStream(std::move(stream));
  35. if (!codec) {
  36. return nullptr;
  37. }
  38. SkBitmap bitmap;
  39. SkImageInfo info = codec->getInfo().makeWH(kWidth, kHeight)
  40. .makeColorType(colorType)
  41. .makeAlphaType(kPremul_SkAlphaType);
  42. bitmap.allocPixels(info);
  43. codec->getPixels(info, bitmap.getPixels(), bitmap.rowBytes());
  44. bitmap.setImmutable();
  45. return SkImage::MakeFromBitmap(bitmap);
  46. }
  47. static sk_sp<SkImage> make_codec_image() {
  48. sk_sp<SkData> encoded = GetResourceAsData("images/randPixels.png");
  49. return SkImage::MakeFromEncoded(encoded);
  50. }
  51. static void draw_contents(SkCanvas* canvas) {
  52. SkPaint paint;
  53. paint.setStyle(SkPaint::kStroke_Style);
  54. paint.setStrokeWidth(20);
  55. paint.setColor(0xFF800000);
  56. canvas->drawCircle(40, 40, 35, paint);
  57. paint.setColor(0xFF008000);
  58. canvas->drawCircle(50, 50, 35, paint);
  59. paint.setColor(0xFF000080);
  60. canvas->drawCircle(60, 60, 35, paint);
  61. }
  62. static sk_sp<SkImage> make_picture_image() {
  63. SkPictureRecorder recorder;
  64. draw_contents(recorder.beginRecording(SkRect::MakeIWH(kWidth, kHeight)));
  65. return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
  66. SkISize::Make(kWidth, kHeight), nullptr, nullptr,
  67. SkImage::BitDepth::kU8,
  68. SkColorSpace::MakeSRGB());
  69. }
  70. static sk_sp<SkColorSpace> make_parametric_transfer_fn(const SkColorSpacePrimaries& primaries) {
  71. skcms_Matrix3x3 toXYZD50;
  72. SkAssertResult(primaries.toXYZD50(&toXYZD50));
  73. skcms_TransferFunction fn = { 1.8f, 1.f, 0.f, 0.f, 0.f, 0.f, 0.f };
  74. return SkColorSpace::MakeRGB(fn, toXYZD50);
  75. }
  76. static sk_sp<SkColorSpace> make_wide_gamut() {
  77. // ProPhoto
  78. SkColorSpacePrimaries primaries;
  79. primaries.fRX = 0.7347f;
  80. primaries.fRY = 0.2653f;
  81. primaries.fGX = 0.1596f;
  82. primaries.fGY = 0.8404f;
  83. primaries.fBX = 0.0366f;
  84. primaries.fBY = 0.0001f;
  85. primaries.fWX = 0.34567f;
  86. primaries.fWY = 0.35850f;
  87. return make_parametric_transfer_fn(primaries);
  88. }
  89. static sk_sp<SkColorSpace> make_small_gamut() {
  90. SkColorSpacePrimaries primaries;
  91. primaries.fRX = 0.50f;
  92. primaries.fRY = 0.33f;
  93. primaries.fGX = 0.30f;
  94. primaries.fGY = 0.50f;
  95. primaries.fBX = 0.25f;
  96. primaries.fBY = 0.16f;
  97. primaries.fWX = 0.3127f;
  98. primaries.fWY = 0.3290f;
  99. return make_parametric_transfer_fn(primaries);
  100. }
  101. static void draw_image(SkCanvas* canvas, SkImage* image, SkColorType dstColorType,
  102. SkAlphaType dstAlphaType, sk_sp<SkColorSpace> dstColorSpace,
  103. SkImage::CachingHint hint) {
  104. size_t rowBytes = image->width() * SkColorTypeBytesPerPixel(dstColorType);
  105. sk_sp<SkData> data = SkData::MakeUninitialized(rowBytes * image->height());
  106. SkImageInfo dstInfo = SkImageInfo::Make(image->width(), image->height(), dstColorType,
  107. dstAlphaType, dstColorSpace);
  108. if (!image->readPixels(dstInfo, data->writable_data(), rowBytes, 0, 0, hint)) {
  109. memset(data->writable_data(), 0, rowBytes * image->height());
  110. }
  111. // Now that we have called readPixels(), dump the raw pixels into an srgb image.
  112. sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
  113. sk_sp<SkImage> raw = SkImage::MakeRasterData(dstInfo.makeColorSpace(srgb), data, rowBytes);
  114. canvas->drawImage(raw.get(), 0.0f, 0.0f, nullptr);
  115. }
  116. class ReadPixelsGM : public skiagm::GM {
  117. public:
  118. ReadPixelsGM() {}
  119. protected:
  120. SkString onShortName() override {
  121. return SkString("readpixels");
  122. }
  123. SkISize onISize() override {
  124. return SkISize::Make(6 * kWidth, 9 * kHeight);
  125. }
  126. void onDraw(SkCanvas* canvas) override {
  127. const SkAlphaType alphaTypes[] = {
  128. kUnpremul_SkAlphaType,
  129. kPremul_SkAlphaType,
  130. };
  131. const SkColorType colorTypes[] = {
  132. kRGBA_8888_SkColorType,
  133. kBGRA_8888_SkColorType,
  134. kRGBA_F16_SkColorType,
  135. };
  136. const sk_sp<SkColorSpace> colorSpaces[] = {
  137. make_wide_gamut(),
  138. SkColorSpace::MakeSRGB(),
  139. make_small_gamut(),
  140. };
  141. for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
  142. for (SkColorType srcColorType : colorTypes) {
  143. canvas->save();
  144. sk_sp<SkImage> image = make_raster_image(srcColorType);
  145. if (!image) {
  146. continue;
  147. }
  148. if (GrContext* context = canvas->getGrContext()) {
  149. image = image->makeTextureImage(context, canvas->imageInfo().colorSpace());
  150. }
  151. if (image) {
  152. for (SkColorType dstColorType : colorTypes) {
  153. for (SkAlphaType dstAlphaType : alphaTypes) {
  154. draw_image(canvas, image.get(), dstColorType, dstAlphaType,
  155. dstColorSpace, SkImage::kAllow_CachingHint);
  156. canvas->translate((float)kWidth, 0.0f);
  157. }
  158. }
  159. }
  160. canvas->restore();
  161. canvas->translate(0.0f, (float) kHeight);
  162. }
  163. }
  164. }
  165. private:
  166. typedef skiagm::GM INHERITED;
  167. };
  168. DEF_GM( return new ReadPixelsGM; )
  169. class ReadPixelsCodecGM : public skiagm::GM {
  170. public:
  171. ReadPixelsCodecGM() {}
  172. protected:
  173. SkString onShortName() override {
  174. return SkString("readpixelscodec");
  175. }
  176. SkISize onISize() override {
  177. return SkISize::Make(3 * (kEncodedWidth + 1), 12 * (kEncodedHeight + 1));
  178. }
  179. DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
  180. if (!canvas->imageInfo().colorSpace()) {
  181. *errorMsg = "This gm is only interesting in color correct modes.";
  182. return DrawResult::kSkip;
  183. }
  184. const SkAlphaType alphaTypes[] = {
  185. kUnpremul_SkAlphaType,
  186. kPremul_SkAlphaType,
  187. };
  188. const SkColorType colorTypes[] = {
  189. kRGBA_8888_SkColorType,
  190. kBGRA_8888_SkColorType,
  191. kRGBA_F16_SkColorType,
  192. };
  193. const sk_sp<SkColorSpace> colorSpaces[] = {
  194. make_wide_gamut(),
  195. SkColorSpace::MakeSRGB(),
  196. make_small_gamut(),
  197. };
  198. const SkImage::CachingHint hints[] = {
  199. SkImage::kAllow_CachingHint,
  200. SkImage::kDisallow_CachingHint,
  201. };
  202. sk_sp<SkImage> image = make_codec_image();
  203. for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
  204. canvas->save();
  205. for (SkColorType dstColorType : colorTypes) {
  206. for (SkAlphaType dstAlphaType : alphaTypes) {
  207. for (SkImage::CachingHint hint : hints) {
  208. draw_image(canvas, image.get(), dstColorType, dstAlphaType, dstColorSpace,
  209. hint);
  210. canvas->translate(0.0f, (float) kEncodedHeight + 1);
  211. }
  212. }
  213. }
  214. canvas->restore();
  215. canvas->translate((float) kEncodedWidth + 1, 0.0f);
  216. }
  217. return DrawResult::kOk;
  218. }
  219. private:
  220. static const int kEncodedWidth = 8;
  221. static const int kEncodedHeight = 8;
  222. typedef skiagm::GM INHERITED;
  223. };
  224. DEF_GM( return new ReadPixelsCodecGM; )
  225. class ReadPixelsPictureGM : public skiagm::GM {
  226. public:
  227. ReadPixelsPictureGM() {}
  228. protected:
  229. SkString onShortName() override {
  230. return SkString("readpixelspicture");
  231. }
  232. SkISize onISize() override {
  233. return SkISize::Make(3 * kWidth, 12 * kHeight);
  234. }
  235. DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
  236. if (!canvas->imageInfo().colorSpace()) {
  237. *errorMsg = "This gm is only interesting in color correct modes.";
  238. return DrawResult::kSkip;
  239. }
  240. const sk_sp<SkImage> images[] = {
  241. make_picture_image(),
  242. };
  243. const SkAlphaType alphaTypes[] = {
  244. kUnpremul_SkAlphaType,
  245. kPremul_SkAlphaType,
  246. };
  247. const SkColorType colorTypes[] = {
  248. kRGBA_8888_SkColorType,
  249. kBGRA_8888_SkColorType,
  250. kRGBA_F16_SkColorType,
  251. };
  252. const sk_sp<SkColorSpace> colorSpaces[] = {
  253. make_wide_gamut(),
  254. SkColorSpace::MakeSRGB(),
  255. make_small_gamut(),
  256. };
  257. const SkImage::CachingHint hints[] = {
  258. SkImage::kAllow_CachingHint,
  259. SkImage::kDisallow_CachingHint,
  260. };
  261. for (sk_sp<SkImage> image : images) {
  262. for (sk_sp<SkColorSpace> dstColorSpace : colorSpaces) {
  263. canvas->save();
  264. for (SkColorType dstColorType : colorTypes) {
  265. for (SkAlphaType dstAlphaType : alphaTypes) {
  266. for (SkImage::CachingHint hint : hints) {
  267. draw_image(canvas, image.get(), dstColorType, dstAlphaType,
  268. dstColorSpace, hint);
  269. canvas->translate(0.0f, (float) kHeight);
  270. }
  271. }
  272. }
  273. canvas->restore();
  274. canvas->translate((float) kWidth, 0.0f);
  275. }
  276. }
  277. return DrawResult::kOk;
  278. }
  279. private:
  280. typedef skiagm::GM INHERITED;
  281. };
  282. DEF_GM( return new ReadPixelsPictureGM; )