mipmap.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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. #include "gm/gm.h"
  8. #include "include/core/SkBitmap.h"
  9. #include "include/core/SkCanvas.h"
  10. #include "include/core/SkColorSpace.h"
  11. #include "include/core/SkFilterQuality.h"
  12. #include "include/core/SkImage.h"
  13. #include "include/core/SkImageInfo.h"
  14. #include "include/core/SkPaint.h"
  15. #include "include/core/SkRect.h"
  16. #include "include/core/SkRefCnt.h"
  17. #include "include/core/SkString.h"
  18. #include "include/core/SkSurface.h"
  19. #include "include/core/SkTypes.h"
  20. static sk_sp<SkImage> make_image() {
  21. const SkImageInfo info = SkImageInfo::MakeN32Premul(319, 52);
  22. auto surface(SkSurface::MakeRaster(info));
  23. SkCanvas* canvas = surface->getCanvas();
  24. canvas->drawColor(0xFFF8F8F8);
  25. SkPaint paint;
  26. paint.setAntiAlias(true);
  27. paint.setStyle(SkPaint::kStroke_Style);
  28. for (int i = 0; i < 20; ++i) {
  29. canvas->drawCircle(-4, 25, 20, paint);
  30. canvas->translate(25, 0);
  31. }
  32. return surface->makeImageSnapshot();
  33. }
  34. DEF_SIMPLE_GM(mipmap, canvas, 400, 200) {
  35. sk_sp<SkImage> img(make_image());//SkImage::NewFromEncoded(data));
  36. SkPaint paint;
  37. const SkRect dst = SkRect::MakeWH(177, 15);
  38. SkString str;
  39. str.printf("scale %g %g", dst.width() / img->width(), dst.height() / img->height());
  40. // canvas->drawString(str, 300, 100, SkFont(nullptr, 30), paint);
  41. canvas->translate(20, 20);
  42. for (int i = 0; i < 4; ++i) {
  43. paint.setFilterQuality(SkFilterQuality(i));
  44. canvas->drawImageRect(img.get(), dst, &paint);
  45. canvas->translate(0, 20);
  46. }
  47. canvas->drawImage(img.get(), 20, 20, nullptr);
  48. }
  49. ///////////////////////////////////////////////////////////////////////////////////////////////////
  50. // create a circle image computed raw, so we can wrap it as a linear or srgb image
  51. static sk_sp<SkImage> make(sk_sp<SkColorSpace> cs) {
  52. const int N = 100;
  53. SkImageInfo info = SkImageInfo::Make(N, N, kN32_SkColorType, kPremul_SkAlphaType, cs);
  54. SkBitmap bm;
  55. bm.allocPixels(info);
  56. for (int y = 0; y < N; ++y) {
  57. for (int x = 0; x < N; ++x) {
  58. *bm.getAddr32(x, y) = (x ^ y) & 1 ? 0xFFFFFFFF : 0xFF000000;
  59. }
  60. }
  61. bm.setImmutable();
  62. return SkImage::MakeFromBitmap(bm);
  63. }
  64. static void show_mips(SkCanvas* canvas, SkImage* img) {
  65. SkPaint paint;
  66. paint.setFilterQuality(kMedium_SkFilterQuality);
  67. // Want to ensure we never draw fractional pixels, so we use an IRect
  68. SkIRect dst = SkIRect::MakeWH(img->width(), img->height());
  69. while (dst.width() > 5) {
  70. canvas->drawImageRect(img, SkRect::Make(dst), &paint);
  71. dst.offset(dst.width() + 10, 0);
  72. dst.fRight = dst.fLeft + dst.width()/2;
  73. dst.fBottom = dst.fTop + dst.height()/2;
  74. }
  75. }
  76. /*
  77. * Ensure that in L32 drawing mode, both images/mips look the same as each other, and
  78. * their mips are darker than the original (since the mips should ignore the gamma in L32).
  79. *
  80. * Ensure that in S32 drawing mode, all images/mips look the same, and look correct (i.e.
  81. * the mip levels match the original in brightness).
  82. */
  83. DEF_SIMPLE_GM(mipmap_srgb, canvas, 260, 230) {
  84. sk_sp<SkImage> limg = make(nullptr);
  85. sk_sp<SkImage> simg = make(SkColorSpace::MakeSRGB());
  86. canvas->translate(10, 10);
  87. show_mips(canvas, limg.get());
  88. canvas->translate(0, limg->height() + 10.0f);
  89. show_mips(canvas, simg.get());
  90. }
  91. ///////////////////////////////////////////////////////////////////////////////////////////////////
  92. // create a gradient image computed raw, so we can wrap it as a linear or srgb image
  93. static sk_sp<SkImage> make_g8_gradient(sk_sp<SkColorSpace> cs) {
  94. const int N = 100;
  95. SkImageInfo info = SkImageInfo::Make(N, N, kGray_8_SkColorType, kOpaque_SkAlphaType, cs);
  96. SkBitmap bm;
  97. bm.allocPixels(info);
  98. for (int y = 0; y < N; ++y) {
  99. for (int x = 0; x < N; ++x) {
  100. *bm.getAddr8(x, y) = static_cast<uint8_t>(255.0f * ((x + y) / (2.0f * (N - 1))));
  101. }
  102. }
  103. bm.setImmutable();
  104. return SkImage::MakeFromBitmap(bm);
  105. }
  106. static void show_mips_only(SkCanvas* canvas, SkImage* img) {
  107. SkPaint paint;
  108. paint.setFilterQuality(kMedium_SkFilterQuality);
  109. // Want to ensure we never draw fractional pixels, so we use an IRect
  110. SkIRect dst = SkIRect::MakeWH(img->width() / 2, img->height() / 2);
  111. while (dst.width() > 5) {
  112. canvas->drawImageRect(img, SkRect::Make(dst), &paint);
  113. dst.offset(dst.width() + 10, 0);
  114. dst.fRight = dst.fLeft + dst.width() / 2;
  115. dst.fBottom = dst.fTop + dst.height() / 2;
  116. }
  117. }
  118. /*
  119. * Ensure that in L32 drawing mode, both images/mips look the same as each other, and
  120. * their mips are darker than the original (since the mips should ignore the gamma in L32).
  121. *
  122. * Ensure that in S32 drawing mode, all images/mips look the same, and look correct (i.e.
  123. * the mip levels match the original in brightness).
  124. */
  125. DEF_SIMPLE_GM(mipmap_gray8_srgb, canvas, 260, 230) {
  126. sk_sp<SkImage> limg = make_g8_gradient(nullptr);
  127. sk_sp<SkImage> simg = make_g8_gradient(SkColorSpace::MakeSRGB());
  128. canvas->translate(10, 10);
  129. show_mips_only(canvas, limg.get());
  130. canvas->translate(0, limg->height() + 10.0f);
  131. show_mips_only(canvas, simg.get());
  132. }