SkImage.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538
  1. /*
  2. * Copyright 2012 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/core/SkBitmap.h"
  8. #include "include/core/SkCanvas.h"
  9. #include "include/core/SkData.h"
  10. #include "include/core/SkImageEncoder.h"
  11. #include "include/core/SkImageFilter.h"
  12. #include "include/core/SkImageGenerator.h"
  13. #include "include/core/SkPicture.h"
  14. #include "include/core/SkString.h"
  15. #include "include/core/SkSurface.h"
  16. #include "src/core/SkBitmapCache.h"
  17. #include "src/core/SkCachedData.h"
  18. #include "src/core/SkColorSpacePriv.h"
  19. #include "src/core/SkImageFilterCache.h"
  20. #include "src/core/SkImagePriv.h"
  21. #include "src/core/SkNextID.h"
  22. #include "src/core/SkSpecialImage.h"
  23. #include "src/image/SkImage_Base.h"
  24. #include "src/image/SkReadPixelsRec.h"
  25. #include "src/shaders/SkImageShader.h"
  26. #if SK_SUPPORT_GPU
  27. #include "include/gpu/GrContext.h"
  28. #include "include/gpu/GrTexture.h"
  29. #include "src/image/SkImage_Gpu.h"
  30. #endif
  31. #include "include/gpu/GrBackendSurface.h"
  32. SkImage::SkImage(const SkImageInfo& info, uint32_t uniqueID)
  33. : fInfo(info)
  34. , fUniqueID(kNeedNewImageUniqueID == uniqueID ? SkNextID::ImageID() : uniqueID) {
  35. SkASSERT(info.width() > 0);
  36. SkASSERT(info.height() > 0);
  37. }
  38. bool SkImage::peekPixels(SkPixmap* pm) const {
  39. SkPixmap tmp;
  40. if (!pm) {
  41. pm = &tmp;
  42. }
  43. return as_IB(this)->onPeekPixels(pm);
  44. }
  45. bool SkImage::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX,
  46. int srcY, CachingHint chint) const {
  47. return as_IB(this)->onReadPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY, chint);
  48. }
  49. bool SkImage::scalePixels(const SkPixmap& dst, SkFilterQuality quality, CachingHint chint) const {
  50. if (this->width() == dst.width() && this->height() == dst.height()) {
  51. return this->readPixels(dst, 0, 0, chint);
  52. }
  53. // Idea: If/when SkImageGenerator supports a native-scaling API (where the generator itself
  54. // can scale more efficiently) we should take advantage of it here.
  55. //
  56. SkBitmap bm;
  57. if (as_IB(this)->getROPixels(&bm, chint)) {
  58. SkPixmap pmap;
  59. // Note: By calling the pixmap scaler, we never cache the final result, so the chint
  60. // is (currently) only being applied to the getROPixels. If we get a request to
  61. // also attempt to cache the final (scaled) result, we would add that logic here.
  62. //
  63. return bm.peekPixels(&pmap) && pmap.scalePixels(dst, quality);
  64. }
  65. return false;
  66. }
  67. ///////////////////////////////////////////////////////////////////////////////////////////////////
  68. SkColorType SkImage::colorType() const { return fInfo.colorType(); }
  69. SkAlphaType SkImage::alphaType() const { return fInfo.alphaType(); }
  70. SkColorSpace* SkImage::colorSpace() const { return fInfo.colorSpace(); }
  71. sk_sp<SkColorSpace> SkImage::refColorSpace() const { return fInfo.refColorSpace(); }
  72. sk_sp<SkShader> SkImage::makeShader(SkTileMode tmx, SkTileMode tmy,
  73. const SkMatrix* localMatrix) const {
  74. return SkImageShader::Make(sk_ref_sp(const_cast<SkImage*>(this)), tmx, tmy, localMatrix);
  75. }
  76. sk_sp<SkData> SkImage::encodeToData(SkEncodedImageFormat type, int quality) const {
  77. SkBitmap bm;
  78. if (as_IB(this)->getROPixels(&bm)) {
  79. return SkEncodeBitmap(bm, type, quality);
  80. }
  81. return nullptr;
  82. }
  83. sk_sp<SkData> SkImage::encodeToData() const {
  84. if (auto encoded = this->refEncodedData()) {
  85. return encoded;
  86. }
  87. return this->encodeToData(SkEncodedImageFormat::kPNG, 100);
  88. }
  89. sk_sp<SkData> SkImage::refEncodedData() const {
  90. return sk_sp<SkData>(as_IB(this)->onRefEncoded());
  91. }
  92. sk_sp<SkImage> SkImage::MakeFromEncoded(sk_sp<SkData> encoded, const SkIRect* subset) {
  93. if (nullptr == encoded || 0 == encoded->size()) {
  94. return nullptr;
  95. }
  96. return SkImage::MakeFromGenerator(SkImageGenerator::MakeFromEncoded(std::move(encoded)),
  97. subset);
  98. }
  99. ///////////////////////////////////////////////////////////////////////////////////////////////////
  100. sk_sp<SkImage> SkImage::makeSubset(const SkIRect& subset) const {
  101. if (subset.isEmpty()) {
  102. return nullptr;
  103. }
  104. const SkIRect bounds = SkIRect::MakeWH(this->width(), this->height());
  105. if (!bounds.contains(subset)) {
  106. return nullptr;
  107. }
  108. // optimization : return self if the subset == our bounds
  109. if (bounds == subset) {
  110. return sk_ref_sp(const_cast<SkImage*>(this));
  111. }
  112. // CONTEXT TODO: propagate the context parameter to the top-level API
  113. #if SK_SUPPORT_GPU
  114. return as_IB(this)->onMakeSubset(as_IB(this)->context(), subset);
  115. #else
  116. return as_IB(this)->onMakeSubset(nullptr, subset);
  117. #endif
  118. }
  119. #if SK_SUPPORT_GPU
  120. GrTexture* SkImage::getTexture() const {
  121. return as_IB(this)->onGetTexture();
  122. }
  123. bool SkImage::isTextureBacked() const { return as_IB(this)->onIsTextureBacked(); }
  124. GrBackendTexture SkImage::getBackendTexture(bool flushPendingGrContextIO,
  125. GrSurfaceOrigin* origin) const {
  126. return as_IB(this)->onGetBackendTexture(flushPendingGrContextIO, origin);
  127. }
  128. bool SkImage::isValid(GrContext* context) const {
  129. if (context && context->abandoned()) {
  130. return false;
  131. }
  132. return as_IB(this)->onIsValid(context);
  133. }
  134. GrSemaphoresSubmitted SkImage::flush(GrContext* context, const GrFlushInfo& flushInfo) {
  135. return as_IB(this)->onFlush(context, flushInfo);
  136. }
  137. void SkImage::flush(GrContext* context) { as_IB(this)->onFlush(context, {}); }
  138. #else
  139. GrTexture* SkImage::getTexture() const { return nullptr; }
  140. bool SkImage::isTextureBacked() const { return false; }
  141. GrBackendTexture SkImage::getBackendTexture(bool flushPendingGrContextIO,
  142. GrSurfaceOrigin* origin) const {
  143. return GrBackendTexture(); // invalid
  144. }
  145. bool SkImage::isValid(GrContext* context) const {
  146. if (context) {
  147. return false;
  148. }
  149. return as_IB(this)->onIsValid(context);
  150. }
  151. GrSemaphoresSubmitted SkImage::flush(GrContext*, const GrFlushInfo&) {
  152. return GrSemaphoresSubmitted::kNo;
  153. }
  154. void SkImage::flush(GrContext*) {}
  155. #endif
  156. ///////////////////////////////////////////////////////////////////////////////
  157. SkImage_Base::SkImage_Base(const SkImageInfo& info, uint32_t uniqueID)
  158. : INHERITED(info, uniqueID), fAddedToRasterCache(false) {}
  159. SkImage_Base::~SkImage_Base() {
  160. if (fAddedToRasterCache.load()) {
  161. SkNotifyBitmapGenIDIsStale(this->uniqueID());
  162. }
  163. }
  164. GrBackendTexture SkImage_Base::onGetBackendTexture(bool flushPendingGrContextIO,
  165. GrSurfaceOrigin* origin) const {
  166. return GrBackendTexture(); // invalid
  167. }
  168. bool SkImage::readPixels(const SkPixmap& pmap, int srcX, int srcY, CachingHint chint) const {
  169. return this->readPixels(pmap.info(), pmap.writable_addr(), pmap.rowBytes(), srcX, srcY, chint);
  170. }
  171. ///////////////////////////////////////////////////////////////////////////////////////////////////
  172. sk_sp<SkImage> SkImage::MakeFromBitmap(const SkBitmap& bm) {
  173. if (!bm.pixelRef()) {
  174. return nullptr;
  175. }
  176. return SkMakeImageFromRasterBitmap(bm, kIfMutable_SkCopyPixelsMode);
  177. }
  178. bool SkImage::asLegacyBitmap(SkBitmap* bitmap, LegacyBitmapMode ) const {
  179. return as_IB(this)->onAsLegacyBitmap(bitmap);
  180. }
  181. sk_sp<SkCachedData> SkImage_Base::getPlanes(SkYUVASizeInfo*, SkYUVAIndex[4],
  182. SkYUVColorSpace*, const void*[4]) {
  183. return nullptr;
  184. }
  185. bool SkImage_Base::onAsLegacyBitmap(SkBitmap* bitmap) const {
  186. // As the base-class, all we can do is make a copy (regardless of mode).
  187. // Subclasses that want to be more optimal should override.
  188. SkImageInfo info = fInfo.makeColorType(kN32_SkColorType).makeColorSpace(nullptr);
  189. if (!bitmap->tryAllocPixels(info)) {
  190. return false;
  191. }
  192. if (!this->readPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(), 0, 0)) {
  193. bitmap->reset();
  194. return false;
  195. }
  196. bitmap->setImmutable();
  197. return true;
  198. }
  199. sk_sp<SkImage> SkImage::MakeFromPicture(sk_sp<SkPicture> picture, const SkISize& dimensions,
  200. const SkMatrix* matrix, const SkPaint* paint,
  201. BitDepth bitDepth, sk_sp<SkColorSpace> colorSpace) {
  202. return MakeFromGenerator(SkImageGenerator::MakeFromPicture(dimensions, std::move(picture),
  203. matrix, paint, bitDepth,
  204. std::move(colorSpace)));
  205. }
  206. sk_sp<SkImage> SkImage::makeWithFilter(const SkImageFilter* filter, const SkIRect& subset,
  207. const SkIRect& clipBounds, SkIRect* outSubset,
  208. SkIPoint* offset) const {
  209. GrContext* context = as_IB(this)->context();
  210. return this->makeWithFilter(context, filter, subset, clipBounds, outSubset, offset);
  211. }
  212. sk_sp<SkImage> SkImage::makeWithFilter(GrContext* grContext,
  213. const SkImageFilter* filter, const SkIRect& subset,
  214. const SkIRect& clipBounds, SkIRect* outSubset,
  215. SkIPoint* offset) const {
  216. if (!filter || !outSubset || !offset || !this->bounds().contains(subset)) {
  217. return nullptr;
  218. }
  219. sk_sp<SkSpecialImage> srcSpecialImage =
  220. #if SK_SUPPORT_GPU
  221. SkSpecialImage::MakeFromImage(grContext, subset, sk_ref_sp(const_cast<SkImage*>(this)));
  222. #else
  223. SkSpecialImage::MakeFromImage(nullptr, subset, sk_ref_sp(const_cast<SkImage*>(this)));
  224. #endif
  225. if (!srcSpecialImage) {
  226. return nullptr;
  227. }
  228. sk_sp<SkImageFilterCache> cache(
  229. SkImageFilterCache::Create(SkImageFilterCache::kDefaultTransientSize));
  230. SkImageFilter::OutputProperties outputProperties(fInfo.colorType(), fInfo.colorSpace());
  231. // The filters operate in the local space of the src image, where (0,0) corresponds to the
  232. // subset's top left corner. But the clip bounds and any crop rects on the filters are in the
  233. // original coordinate system, so configure the CTM to correct crop rects and explicitly adjust
  234. // the clip bounds (since it is assumed to already be in image space).
  235. SkImageFilter::Context context(SkMatrix::MakeTrans(-subset.x(), -subset.y()),
  236. clipBounds.makeOffset(-subset.x(), -subset.y()),
  237. cache.get(), outputProperties);
  238. sk_sp<SkSpecialImage> result = filter->filterImage(srcSpecialImage.get(), context, offset);
  239. if (!result) {
  240. return nullptr;
  241. }
  242. // The output image and offset are relative to the subset rectangle, so the offset needs to
  243. // be shifted to put it in the correct spot with respect to the original coordinate system
  244. offset->fX += subset.x();
  245. offset->fY += subset.y();
  246. // Final clip against the exact clipBounds (the clip provided in the context gets adjusted
  247. // to account for pixel-moving filters so doesn't always exactly match when finished). The
  248. // clipBounds are translated into the clippedDstRect coordinate space, including the
  249. // result->subset() ensures that the result's image pixel origin does not affect results.
  250. SkIRect dstRect = result->subset();
  251. SkIRect clippedDstRect = dstRect;
  252. if (!clippedDstRect.intersect(clipBounds.makeOffset(result->subset().x() - offset->x(),
  253. result->subset().y() - offset->y()))) {
  254. return nullptr;
  255. }
  256. // Adjust the geometric offset if the top-left corner moved as well
  257. offset->fX += (clippedDstRect.x() - dstRect.x());
  258. offset->fY += (clippedDstRect.y() - dstRect.y());
  259. *outSubset = clippedDstRect;
  260. return result->asImage();
  261. }
  262. bool SkImage::isLazyGenerated() const {
  263. return as_IB(this)->onIsLazyGenerated();
  264. }
  265. bool SkImage::isAlphaOnly() const { return SkColorTypeIsAlphaOnly(fInfo.colorType()); }
  266. sk_sp<SkImage> SkImage::makeColorSpace(sk_sp<SkColorSpace> target) const {
  267. if (!target) {
  268. return nullptr;
  269. }
  270. // No need to create a new image if:
  271. // (1) The color spaces are equal.
  272. // (2) The color type is kAlpha8.
  273. SkColorSpace* colorSpace = this->colorSpace();
  274. if (!colorSpace) {
  275. colorSpace = sk_srgb_singleton();
  276. }
  277. if (SkColorSpace::Equals(colorSpace, target.get()) || this->isAlphaOnly()) {
  278. return sk_ref_sp(const_cast<SkImage*>(this));
  279. }
  280. // CONTEXT TODO: propagate the context parameter to the top-level API
  281. #if SK_SUPPORT_GPU
  282. return as_IB(this)->onMakeColorTypeAndColorSpace(as_IB(this)->context(),
  283. #else
  284. return as_IB(this)->onMakeColorTypeAndColorSpace(nullptr,
  285. #endif
  286. this->colorType(), std::move(target));
  287. }
  288. sk_sp<SkImage> SkImage::makeColorTypeAndColorSpace(SkColorType targetColorType,
  289. sk_sp<SkColorSpace> targetColorSpace) const {
  290. if (kUnknown_SkColorType == targetColorType || !targetColorSpace) {
  291. return nullptr;
  292. }
  293. SkColorType colorType = this->colorType();
  294. SkColorSpace* colorSpace = this->colorSpace();
  295. if (!colorSpace) {
  296. colorSpace = sk_srgb_singleton();
  297. }
  298. if (colorType == targetColorType &&
  299. (SkColorSpace::Equals(colorSpace, targetColorSpace.get()) || this->isAlphaOnly())) {
  300. return sk_ref_sp(const_cast<SkImage*>(this));
  301. }
  302. // CONTEXT TODO: propagate the context parameter to the top-level API
  303. #if SK_SUPPORT_GPU
  304. return as_IB(this)->onMakeColorTypeAndColorSpace(as_IB(this)->context(),
  305. #else
  306. return as_IB(this)->onMakeColorTypeAndColorSpace(nullptr,
  307. #endif
  308. targetColorType, std::move(targetColorSpace));
  309. }
  310. sk_sp<SkImage> SkImage::makeNonTextureImage() const {
  311. if (!this->isTextureBacked()) {
  312. return sk_ref_sp(const_cast<SkImage*>(this));
  313. }
  314. return this->makeRasterImage();
  315. }
  316. sk_sp<SkImage> SkImage::makeRasterImage() const {
  317. SkPixmap pm;
  318. if (this->peekPixels(&pm)) {
  319. return sk_ref_sp(const_cast<SkImage*>(this));
  320. }
  321. const size_t rowBytes = fInfo.minRowBytes();
  322. size_t size = fInfo.computeByteSize(rowBytes);
  323. if (SkImageInfo::ByteSizeOverflowed(size)) {
  324. return nullptr;
  325. }
  326. sk_sp<SkData> data = SkData::MakeUninitialized(size);
  327. pm = {fInfo.makeColorSpace(nullptr), data->writable_data(), fInfo.minRowBytes()};
  328. if (!this->readPixels(pm, 0, 0)) {
  329. return nullptr;
  330. }
  331. return SkImage::MakeRasterData(fInfo, std::move(data), rowBytes);
  332. }
  333. //////////////////////////////////////////////////////////////////////////////////////
  334. #if !SK_SUPPORT_GPU
  335. sk_sp<SkImage> SkImage::MakeFromTexture(GrContext* ctx,
  336. const GrBackendTexture& tex, GrSurfaceOrigin origin,
  337. SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs,
  338. TextureReleaseProc releaseP, ReleaseContext releaseC) {
  339. return nullptr;
  340. }
  341. bool SkImage::MakeBackendTextureFromSkImage(GrContext*,
  342. sk_sp<SkImage>,
  343. GrBackendTexture*,
  344. BackendTextureReleaseProc*) {
  345. return false;
  346. }
  347. sk_sp<SkImage> SkImage::MakeFromAdoptedTexture(GrContext* ctx,
  348. const GrBackendTexture& tex, GrSurfaceOrigin origin,
  349. SkColorType ct, SkAlphaType at,
  350. sk_sp<SkColorSpace> cs) {
  351. return nullptr;
  352. }
  353. sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopy(GrContext* context,
  354. SkYUVColorSpace yuvColorSpace,
  355. const GrBackendTexture yuvaTextures[],
  356. const SkYUVAIndex yuvaIndices[4],
  357. SkISize imageSize,
  358. GrSurfaceOrigin imageOrigin,
  359. sk_sp<SkColorSpace> imageColorSpace) {
  360. return nullptr;
  361. }
  362. sk_sp<SkImage> SkImage::MakeFromYUVATexturesCopyWithExternalBackend(
  363. GrContext* context,
  364. SkYUVColorSpace yuvColorSpace,
  365. const GrBackendTexture yuvaTextures[],
  366. const SkYUVAIndex yuvaIndices[4],
  367. SkISize imageSize,
  368. GrSurfaceOrigin imageOrigin,
  369. const GrBackendTexture& backendTexture,
  370. sk_sp<SkColorSpace> imageColorSpace) {
  371. return nullptr;
  372. }
  373. sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace space,
  374. const GrBackendTexture[3],
  375. GrSurfaceOrigin origin,
  376. sk_sp<SkColorSpace> imageColorSpace) {
  377. return nullptr;
  378. }
  379. sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopyWithExternalBackend(
  380. GrContext* context, SkYUVColorSpace yuvColorSpace, const GrBackendTexture yuvTextures[3],
  381. GrSurfaceOrigin surfaceOrigin, const GrBackendTexture& backendTexture,
  382. sk_sp<SkColorSpace> colorSpace) {
  383. return nullptr;
  384. }
  385. sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace space,
  386. const GrBackendTexture[2],
  387. GrSurfaceOrigin origin,
  388. sk_sp<SkColorSpace> imageColorSpace) {
  389. return nullptr;
  390. }
  391. sk_sp<SkImage> SkImage::makeTextureImage(GrContext*, SkColorSpace* dstColorSpace,
  392. GrMipMapped mipMapped) const {
  393. return nullptr;
  394. }
  395. sk_sp<SkImage> MakeFromNV12TexturesCopyWithExternalBackend(GrContext* context,
  396. SkYUVColorSpace yuvColorSpace,
  397. const GrBackendTexture nv12Textures[2],
  398. GrSurfaceOrigin surfaceOrigin,
  399. const GrBackendTexture& backendTexture,
  400. sk_sp<SkColorSpace> colorSpace) {
  401. return nullptr;
  402. }
  403. #endif
  404. ///////////////////////////////////////////////////////////////////////////////////////////////////
  405. bool SkImage_pinAsTexture(const SkImage* image, GrContext* ctx) {
  406. SkASSERT(image);
  407. SkASSERT(ctx);
  408. return as_IB(image)->onPinAsTexture(ctx);
  409. }
  410. void SkImage_unpinAsTexture(const SkImage* image, GrContext* ctx) {
  411. SkASSERT(image);
  412. SkASSERT(ctx);
  413. as_IB(image)->onUnpinAsTexture(ctx);
  414. }
  415. SkIRect SkImage_getSubset(const SkImage* image) {
  416. SkASSERT(image);
  417. return as_IB(image)->onGetSubset();
  418. }
  419. ///////////////////////////////////////////////////////////////////////////////////////////////////
  420. sk_sp<SkImage> SkImageMakeRasterCopyAndAssignColorSpace(const SkImage* src,
  421. SkColorSpace* colorSpace) {
  422. // Read the pixels out of the source image, with no conversion
  423. const SkImageInfo& info = src->imageInfo();
  424. if (kUnknown_SkColorType == info.colorType()) {
  425. SkDEBUGFAIL("Unexpected color type");
  426. return nullptr;
  427. }
  428. size_t rowBytes = info.minRowBytes();
  429. size_t size = info.computeByteSize(rowBytes);
  430. if (SkImageInfo::ByteSizeOverflowed(size)) {
  431. return nullptr;
  432. }
  433. auto data = SkData::MakeUninitialized(size);
  434. if (!data) {
  435. return nullptr;
  436. }
  437. SkPixmap pm(info, data->writable_data(), rowBytes);
  438. if (!src->readPixels(pm, 0, 0, SkImage::kDisallow_CachingHint)) {
  439. return nullptr;
  440. }
  441. // Wrap them in a new image with a different color space
  442. return SkImage::MakeRasterData(info.makeColorSpace(sk_ref_sp(colorSpace)), data, rowBytes);
  443. }