image.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. /*
  2. * Copyright 2011 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/core/SkBitmap.h"
  9. #include "include/core/SkCanvas.h"
  10. #include "include/core/SkColor.h"
  11. #include "include/core/SkColorPriv.h"
  12. #include "include/core/SkColorSpace.h"
  13. #include "include/core/SkData.h"
  14. #include "include/core/SkEncodedImageFormat.h"
  15. #include "include/core/SkFilterQuality.h"
  16. #include "include/core/SkFont.h"
  17. #include "include/core/SkImage.h"
  18. #include "include/core/SkImageEncoder.h"
  19. #include "include/core/SkImageInfo.h"
  20. #include "include/core/SkPaint.h"
  21. #include "include/core/SkPicture.h"
  22. #include "include/core/SkPictureRecorder.h"
  23. #include "include/core/SkPixmap.h"
  24. #include "include/core/SkRect.h"
  25. #include "include/core/SkRefCnt.h"
  26. #include "include/core/SkScalar.h"
  27. #include "include/core/SkSize.h"
  28. #include "include/core/SkString.h"
  29. #include "include/core/SkSurface.h"
  30. #include "include/core/SkTypeface.h"
  31. #include "include/core/SkTypes.h"
  32. #include "include/private/SkMalloc.h"
  33. #include "src/core/SkAutoPixmapStorage.h"
  34. #include "src/core/SkReadBuffer.h"
  35. #include "src/core/SkWriteBuffer.h"
  36. #include "tools/ToolUtils.h"
  37. #include <functional>
  38. #include <utility>
  39. class GrContext;
  40. class GrRenderTargetContext;
  41. static void drawContents(SkSurface* surface, SkColor fillC) {
  42. SkSize size = SkSize::Make(SkIntToScalar(surface->width()),
  43. SkIntToScalar(surface->height()));
  44. SkCanvas* canvas = surface->getCanvas();
  45. SkScalar stroke = size.fWidth / 10;
  46. SkScalar radius = (size.fWidth - stroke) / 2;
  47. SkPaint paint;
  48. paint.setAntiAlias(true);
  49. paint.setColor(fillC);
  50. canvas->drawCircle(size.fWidth/2, size.fHeight/2, radius, paint);
  51. paint.setStyle(SkPaint::kStroke_Style);
  52. paint.setStrokeWidth(stroke);
  53. paint.setColor(SK_ColorBLACK);
  54. canvas->drawCircle(size.fWidth/2, size.fHeight/2, radius, paint);
  55. }
  56. static void test_surface(SkCanvas* canvas, SkSurface* surf, bool usePaint) {
  57. drawContents(surf, SK_ColorRED);
  58. sk_sp<SkImage> imgR = surf->makeImageSnapshot();
  59. if (true) {
  60. sk_sp<SkImage> imgR2 = surf->makeImageSnapshot();
  61. SkASSERT(imgR == imgR2);
  62. }
  63. drawContents(surf, SK_ColorGREEN);
  64. sk_sp<SkImage> imgG = surf->makeImageSnapshot();
  65. // since we've drawn after we snapped imgR, imgG will be a different obj
  66. SkASSERT(imgR != imgG);
  67. drawContents(surf, SK_ColorBLUE);
  68. SkPaint paint;
  69. // paint.setFilterBitmap(true);
  70. // paint.setAlpha(0x80);
  71. canvas->drawImage(imgR, 0, 0, usePaint ? &paint : nullptr);
  72. canvas->drawImage(imgG, 0, 80, usePaint ? &paint : nullptr);
  73. surf->draw(canvas, 0, 160, usePaint ? &paint : nullptr);
  74. SkRect src1, src2, src3;
  75. src1.iset(0, 0, surf->width(), surf->height());
  76. src2.iset(-surf->width() / 2, -surf->height() / 2,
  77. surf->width(), surf->height());
  78. src3.iset(0, 0, surf->width() / 2, surf->height() / 2);
  79. SkRect dst1, dst2, dst3, dst4;
  80. dst1.set(0, 240, 65, 305);
  81. dst2.set(0, 320, 65, 385);
  82. dst3.set(0, 400, 65, 465);
  83. dst4.set(0, 480, 65, 545);
  84. canvas->drawImageRect(imgR, src1, dst1, usePaint ? &paint : nullptr);
  85. canvas->drawImageRect(imgG, src2, dst2, usePaint ? &paint : nullptr);
  86. canvas->drawImageRect(imgR, src3, dst3, usePaint ? &paint : nullptr);
  87. canvas->drawImageRect(imgG, dst4, usePaint ? &paint : nullptr);
  88. }
  89. class ImageGM : public skiagm::GM {
  90. void* fBuffer;
  91. size_t fBufferSize;
  92. SkSize fSize;
  93. enum {
  94. W = 64,
  95. H = 64,
  96. RB = W * 4 + 8,
  97. };
  98. public:
  99. ImageGM() {
  100. fBufferSize = RB * H;
  101. fBuffer = sk_malloc_throw(fBufferSize);
  102. fSize.set(SkIntToScalar(W), SkIntToScalar(H));
  103. }
  104. ~ImageGM() override {
  105. sk_free(fBuffer);
  106. }
  107. protected:
  108. SkString onShortName() override {
  109. return SkString("image-surface");
  110. }
  111. SkISize onISize() override {
  112. return SkISize::Make(960, 1200);
  113. }
  114. void onDraw(SkCanvas* canvas) override {
  115. canvas->scale(2, 2);
  116. SkFont font(ToolUtils::create_portable_typeface(), 8);
  117. canvas->drawString("Original Img", 10, 60, font, SkPaint());
  118. canvas->drawString("Modified Img", 10, 140, font, SkPaint());
  119. canvas->drawString("Cur Surface", 10, 220, font, SkPaint());
  120. canvas->drawString("Full Crop", 10, 300, font, SkPaint());
  121. canvas->drawString("Over-crop", 10, 380, font, SkPaint());
  122. canvas->drawString("Upper-left", 10, 460, font, SkPaint());
  123. canvas->drawString("No Crop", 10, 540, font, SkPaint());
  124. canvas->drawString("Pre-Alloc Img", 80, 10, font, SkPaint());
  125. canvas->drawString("New Alloc Img", 160, 10, font, SkPaint());
  126. canvas->drawString( "GPU", 265, 10, font, SkPaint());
  127. canvas->translate(80, 20);
  128. // since we draw into this directly, we need to start fresh
  129. sk_bzero(fBuffer, fBufferSize);
  130. SkImageInfo info = SkImageInfo::MakeN32Premul(W, H);
  131. sk_sp<SkSurface> surf0(SkSurface::MakeRasterDirect(info, fBuffer, RB));
  132. sk_sp<SkSurface> surf1(SkSurface::MakeRaster(info));
  133. sk_sp<SkSurface> surf2(SkSurface::MakeRenderTarget(canvas->getGrContext(),
  134. SkBudgeted::kNo, info));
  135. test_surface(canvas, surf0.get(), true);
  136. canvas->translate(80, 0);
  137. test_surface(canvas, surf1.get(), true);
  138. if (surf2) {
  139. canvas->translate(80, 0);
  140. test_surface(canvas, surf2.get(), true);
  141. }
  142. }
  143. private:
  144. typedef skiagm::GM INHERITED;
  145. };
  146. DEF_GM( return new ImageGM; )
  147. ///////////////////////////////////////////////////////////////////////////////////////////////////
  148. static void draw_pixmap(SkCanvas* canvas, const SkPixmap& pmap) {
  149. SkBitmap bitmap;
  150. bitmap.installPixels(pmap);
  151. canvas->drawBitmap(bitmap, 0, 0, nullptr);
  152. }
  153. static void show_scaled_pixels(SkCanvas* canvas, SkImage* image) {
  154. SkAutoCanvasRestore acr(canvas, true);
  155. canvas->drawImage(image, 0, 0, nullptr);
  156. canvas->translate(110, 10);
  157. const SkImageInfo info = SkImageInfo::MakeN32Premul(40, 40);
  158. SkAutoPixmapStorage storage;
  159. storage.alloc(info);
  160. const SkImage::CachingHint chints[] = {
  161. SkImage::kAllow_CachingHint, SkImage::kDisallow_CachingHint,
  162. };
  163. const SkFilterQuality qualities[] = {
  164. kNone_SkFilterQuality, kLow_SkFilterQuality, kMedium_SkFilterQuality, kHigh_SkFilterQuality,
  165. };
  166. for (auto ch : chints) {
  167. canvas->save();
  168. for (auto q : qualities) {
  169. if (image->scalePixels(storage, q, ch)) {
  170. draw_pixmap(canvas, storage);
  171. }
  172. canvas->translate(70, 0);
  173. }
  174. canvas->restore();
  175. canvas->translate(0, 45);
  176. }
  177. }
  178. static void draw_contents(SkCanvas* canvas) {
  179. SkPaint paint;
  180. paint.setStyle(SkPaint::kStroke_Style);
  181. paint.setStrokeWidth(20);
  182. canvas->drawCircle(50, 50, 35, paint);
  183. }
  184. static sk_sp<SkImage> make_raster(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
  185. auto surface(SkSurface::MakeRaster(info));
  186. draw(surface->getCanvas());
  187. return surface->makeImageSnapshot();
  188. }
  189. static sk_sp<SkImage> make_picture(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
  190. SkPictureRecorder recorder;
  191. draw(recorder.beginRecording(SkRect::MakeIWH(info.width(), info.height())));
  192. return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
  193. info.dimensions(), nullptr, nullptr, SkImage::BitDepth::kU8,
  194. SkColorSpace::MakeSRGB());
  195. }
  196. static sk_sp<SkImage> make_codec(const SkImageInfo& info, GrContext*, void (*draw)(SkCanvas*)) {
  197. sk_sp<SkImage> image(make_raster(info, nullptr, draw));
  198. return SkImage::MakeFromEncoded(image->encodeToData());
  199. }
  200. static sk_sp<SkImage> make_gpu(const SkImageInfo& info, GrContext* ctx, void (*draw)(SkCanvas*)) {
  201. if (!ctx) { return nullptr; }
  202. auto surface(SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info));
  203. if (!surface) { return nullptr; }
  204. draw(surface->getCanvas());
  205. return surface->makeImageSnapshot();
  206. }
  207. typedef sk_sp<SkImage> (*ImageMakerProc)(const SkImageInfo&, GrContext*, void (*)(SkCanvas*));
  208. class ScalePixelsGM : public skiagm::GM {
  209. public:
  210. ScalePixelsGM() {}
  211. protected:
  212. SkString onShortName() override {
  213. return SkString("scale-pixels");
  214. }
  215. SkISize onISize() override {
  216. return SkISize::Make(960, 1200);
  217. }
  218. void onDraw(SkCanvas* canvas) override {
  219. const SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
  220. const ImageMakerProc procs[] = {
  221. make_codec, make_raster, make_picture, make_codec, make_gpu,
  222. };
  223. for (auto& proc : procs) {
  224. sk_sp<SkImage> image(proc(info, canvas->getGrContext(), draw_contents));
  225. if (image) {
  226. show_scaled_pixels(canvas, image.get());
  227. }
  228. canvas->translate(0, 120);
  229. }
  230. }
  231. private:
  232. typedef skiagm::GM INHERITED;
  233. };
  234. DEF_GM( return new ScalePixelsGM; )
  235. ///////////////////////////////////////////////////////////////////////////////////////////////////
  236. DEF_SIMPLE_GPU_GM(new_texture_image, context, rtc, canvas, 280, 60) {
  237. auto render_image = [](SkCanvas* canvas) {
  238. canvas->clear(SK_ColorBLUE);
  239. SkPaint paint;
  240. paint.setColor(SK_ColorRED);
  241. canvas->drawRect(SkRect::MakeXYWH(10.f,10.f,10.f,10.f), paint);
  242. paint.setColor(SK_ColorGREEN);
  243. canvas->drawRect(SkRect::MakeXYWH(30.f,10.f,10.f,10.f), paint);
  244. paint.setColor(SK_ColorYELLOW);
  245. canvas->drawRect(SkRect::MakeXYWH(10.f,30.f,10.f,10.f), paint);
  246. paint.setColor(SK_ColorCYAN);
  247. canvas->drawRect(SkRect::MakeXYWH(30.f,30.f,10.f,10.f), paint);
  248. };
  249. static constexpr int kSize = 50;
  250. SkBitmap bmp;
  251. bmp.allocPixels(SkImageInfo::MakeS32(kSize, kSize, kPremul_SkAlphaType));
  252. SkCanvas bmpCanvas(bmp);
  253. render_image(&bmpCanvas);
  254. std::function<sk_sp<SkImage>()> imageFactories[] = {
  255. // Create sw raster image.
  256. [bmp] {
  257. return SkImage::MakeFromBitmap(bmp);
  258. },
  259. // Create encoded image.
  260. [bmp] {
  261. auto src = SkEncodeBitmap(bmp, SkEncodedImageFormat::kPNG, 100);
  262. return SkImage::MakeFromEncoded(std::move(src));
  263. },
  264. // Create YUV encoded image.
  265. [bmp] {
  266. auto src = SkEncodeBitmap(bmp, SkEncodedImageFormat::kJPEG, 100);
  267. return SkImage::MakeFromEncoded(std::move(src));
  268. },
  269. // Create a picture image.
  270. [render_image] {
  271. SkPictureRecorder recorder;
  272. SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kSize), SkIntToScalar(kSize));
  273. render_image(canvas);
  274. sk_sp<SkColorSpace> srgbColorSpace = SkColorSpace::MakeSRGB();
  275. return SkImage::MakeFromPicture(recorder.finishRecordingAsPicture(),
  276. SkISize::Make(kSize, kSize), nullptr, nullptr,
  277. SkImage::BitDepth::kU8, srgbColorSpace);
  278. },
  279. // Create a texture image
  280. [context, render_image]() -> sk_sp<SkImage> {
  281. auto surface(SkSurface::MakeRenderTarget(context, SkBudgeted::kYes,
  282. SkImageInfo::MakeS32(kSize, kSize,
  283. kPremul_SkAlphaType)));
  284. if (!surface) {
  285. return nullptr;
  286. }
  287. render_image(surface->getCanvas());
  288. return surface->makeImageSnapshot();
  289. }
  290. };
  291. constexpr SkScalar kPad = 5.f;
  292. canvas->translate(kPad, kPad);
  293. for (auto factory : imageFactories) {
  294. auto image(factory());
  295. if (image) {
  296. sk_sp<SkImage> texImage(image->makeTextureImage(context,
  297. canvas->imageInfo().colorSpace()));
  298. if (texImage) {
  299. canvas->drawImage(texImage, 0, 0);
  300. }
  301. }
  302. canvas->translate(kSize + kPad, 0);
  303. }
  304. }
  305. static void draw_pixmap(SkCanvas* canvas, const SkPixmap& pm, SkScalar x, SkScalar y) {
  306. canvas->drawImage(SkImage::MakeRasterCopy(pm), x, y, nullptr);
  307. }
  308. static void slam_ff(const SkPixmap& pm) {
  309. for (int y = 0; y < pm.height(); ++y) {
  310. for (int x = 0; x < pm.width(); ++x) {
  311. *pm.writable_addr32(x, y) = *pm.addr32(x, y) | SkPackARGB32(0xFF, 0, 0, 0);
  312. }
  313. }
  314. }
  315. DEF_SIMPLE_GM(scalepixels_unpremul, canvas, 1080, 280) {
  316. SkImageInfo info = SkImageInfo::MakeN32(16, 16, kUnpremul_SkAlphaType);
  317. SkAutoPixmapStorage pm;
  318. pm.alloc(info);
  319. for (int y = 0; y < 16; ++y) {
  320. for (int x = 0; x < 16; ++x) {
  321. *pm.writable_addr32(x, y) = SkPackARGB32NoCheck(0, (y << 4) | y, (x << 4) | x, 0xFF);
  322. }
  323. }
  324. SkAutoPixmapStorage pm2;
  325. pm2.alloc(SkImageInfo::MakeN32(256, 256, kUnpremul_SkAlphaType));
  326. const SkFilterQuality qualities[] = {
  327. kNone_SkFilterQuality, kLow_SkFilterQuality, kMedium_SkFilterQuality, kHigh_SkFilterQuality
  328. };
  329. for (auto fq : qualities) {
  330. pm.scalePixels(pm2, fq);
  331. slam_ff(pm2);
  332. draw_pixmap(canvas, pm2, 10, 10);
  333. canvas->translate(pm2.width() + 10.0f, 0);
  334. }
  335. }
  336. ///////////////////////////////////////////////////////////////////////////////////////////////////
  337. static sk_sp<SkImage> make_lazy_image(SkSurface* surf) {
  338. surf->getCanvas()->drawCircle(100, 100, 100, SkPaint());
  339. sk_sp<SkData> data = surf->makeImageSnapshot()->encodeToData();
  340. if (!data) {
  341. return nullptr;
  342. }
  343. return SkImage::MakeFromEncoded(std::move(data));
  344. }
  345. static sk_sp<SkImage> serial_deserial(SkImage* img) {
  346. SkBinaryWriteBuffer writer;
  347. writer.writeImage(img);
  348. size_t length = writer.bytesWritten();
  349. auto data = SkData::MakeUninitialized(length);
  350. writer.writeToMemory(data->writable_data());
  351. SkReadBuffer reader(data->data(), length);
  352. return reader.readImage();
  353. }
  354. DEF_SIMPLE_GM_CAN_FAIL(image_subset, canvas, errorMsg, 440, 220) {
  355. SkImageInfo info = SkImageInfo::MakeN32Premul(200, 200, nullptr);
  356. auto surf = ToolUtils::makeSurface(canvas, info, nullptr);
  357. auto img = make_lazy_image(surf.get());
  358. if (!img) {
  359. *errorMsg = "Failed to make lazy image.";
  360. return skiagm::DrawResult::kFail;
  361. }
  362. canvas->drawImage(img, 10, 10, nullptr);
  363. auto sub = img->makeSubset({100, 100, 200, 200});
  364. canvas->drawImage(sub, 220, 10);
  365. sub = serial_deserial(sub.get());
  366. canvas->drawImage(sub, 220+110, 10);
  367. return skiagm::DrawResult::kOk;
  368. }