1 module skia.SKImage; 2 3 // TODO: `MakeCrossContextFromEncoded` 4 // TODO: `MakeFromYUVTexturesCopy` and `MakeFromNV12TexturesCopy` 5 // TODO: `FromPicture` with bit depth and color space 6 // TODO: `GetTextureHandle` 7 // TODO: `MakeColorSpace` 8 9 import skia.Definitions; 10 import skia.EnumMappings; 11 import skia.Exceptions; 12 import skia.DelegateProxies; 13 import skia.MathTypes; 14 import skia.GRContext; 15 import skia.GRDefinitions; 16 import skia.GRBackendTexture; 17 import skia.SKObject; 18 import skia.SKImageInfo; 19 import skia.SKStream; 20 import skia.SKPixmap; 21 import skia.SKColorTable; 22 import skia.SKData; 23 import skia.SKBitmap; 24 import skia.SKColorSpace; 25 import skia.SKPicture; 26 import skia.SKPaint; 27 import skia.SKShader; 28 import skia.SKPixelSerializer; 29 import skia.SKImageFilter; 30 import skia.SKMatrix; 31 import skia.SkiaApi; 32 33 class SKImage : SKObject { 34 this(void* x, bool owns) { 35 super(x, owns); 36 } 37 38 // protected override void Dispose(bool disposing) { 39 // return super.Dispose(disposing); 40 // } 41 42 // create brand new image 43 44 // static SKImage Create(SKImageInfo info) { 45 // auto pixels = Marshal.AllocCoTaskMem(info.BytesSize); 46 // SKPixmap pixmap = new SKPixmap(info, pixels); 47 48 // // don't use the managed version as that is just extra overhead which isn't necessary 49 // return GetObject(SkiaApi.sk_image_new_raster(cast(sk_pixmap_t*)pixmap.Handle, 50 // DelegateProxies.SKImageRasterReleaseDelegateProxyForCoTaskMem, null)); 51 52 // } 53 54 // create a new image from a copy of pixel data 55 56 static SKImage FromPixelCopy(SKImageInfo info, SKStream pixels) { 57 return FromPixelCopy(info, pixels, info.RowBytes); 58 } 59 60 static SKImage FromPixelCopy(SKImageInfo info, SKStream pixels, int rowBytes) { 61 if (pixels is null) 62 throw new ArgumentNullException(pixels.stringof); 63 64 SKData data = SKData.Create(pixels); 65 return FromPixels(info, data, rowBytes); 66 } 67 68 // static SKImage FromPixelCopy (SKImageInfo info, Stream pixels) 69 // { 70 // return FromPixelCopy (info, pixels, info.RowBytes); 71 // } 72 73 // static SKImage FromPixelCopy (SKImageInfo info, Stream pixels, int rowBytes) 74 // { 75 // if (pixels is null) 76 // throw new ArgumentNullException (pixels.stringof); 77 78 // SKData data = SKData.Create (pixels); 79 // return FromPixels (info, data, rowBytes); 80 // } 81 82 static SKImage FromPixelCopy(SKImageInfo info, byte[] pixels) { 83 return FromPixelCopy(info, pixels, info.RowBytes); 84 } 85 86 // static SKImage FromPixelCopy(SKImageInfo info, byte[] pixels, int rowBytes) { 87 // if (pixels is null) 88 // throw new ArgumentNullException(pixels.stringof); 89 90 // SKData data = SKData.CreateCopy(pixels); 91 // return FromPixels(info, data, rowBytes); 92 // } 93 94 static SKImage FromPixelCopy(SKImageInfo info, void* pixels) { 95 return FromPixelCopy(info, pixels, info.RowBytes); 96 } 97 98 static SKImage FromPixelCopy(SKImageInfo info, void* pixels, int rowBytes) { 99 if (pixels is null) 100 throw new ArgumentNullException(pixels.stringof); 101 102 auto nInfo = SKImageInfo.FromManaged(info); 103 return GetObject(SkiaApi.sk_image_new_raster_copy(&nInfo, 104 cast(void*) pixels, cast(void*) rowBytes)); 105 } 106 107 static SKImage FromPixelCopy(SKImageInfo info, void* pixels, int rowBytes, SKColorTable ctable) { 108 return FromPixelCopy(info, pixels, rowBytes); 109 } 110 111 static SKImage FromPixelCopy(SKPixmap pixmap) { 112 if (pixmap is null) 113 throw new ArgumentNullException(pixmap.stringof); 114 return GetObject(SkiaApi.sk_image_new_raster_copy_with_pixmap(cast(sk_pixmap_t*)pixmap.Handle)); 115 } 116 117 static SKImage FromPixelCopy(SKImageInfo info, const(byte)[] pixels) { 118 return FromPixelCopy(info, cast(void*)pixels, info.RowBytes); 119 } 120 121 static SKImage FromPixelCopy(SKImageInfo info, byte[] pixels, int rowBytes) { 122 if (pixels is null) 123 throw new ArgumentNullException(pixels.stringof); 124 125 SKData data = SKData.CreateCopy(pixels); 126 return FromPixels(info, data, rowBytes); 127 } 128 129 // create a new image around existing pixel data 130 131 static SKImage FromPixelData(SKImageInfo info, SKData data, int rowBytes) { 132 if (data is null) 133 throw new ArgumentNullException(data.stringof); 134 auto cinfo = SKImageInfo.FromManaged(info); 135 return GetObject(SkiaApi.sk_image_new_raster_data(&cinfo, cast(sk_data_t*)data.Handle, 136 cast(void*) rowBytes)); 137 } 138 139 static SKImage FromPixels(SKImageInfo info, SKData data) { 140 return FromPixels(info, data, info.RowBytes); 141 } 142 143 static SKImage FromPixels(SKImageInfo info, SKData data, int rowBytes) { 144 if (data is null) 145 throw new ArgumentNullException(data.stringof); 146 auto cinfo = SKImageInfo.FromManaged(info); 147 return GetObject(SkiaApi.sk_image_new_raster_data(&cinfo, cast(sk_data_t*)data.Handle, 148 cast(void*) rowBytes)); 149 } 150 151 static SKImage FromPixels(SKImageInfo info, void* pixels) { 152 SKPixmap pixmap = new SKPixmap(info, pixels, info.RowBytes); 153 return FromPixels(pixmap); 154 } 155 156 static SKImage FromPixels(SKImageInfo info, void* pixels, int rowBytes) { 157 158 SKPixmap pixmap = new SKPixmap(info, pixels, rowBytes); 159 return FromPixels(pixmap); 160 } 161 162 static SKImage FromPixels(SKPixmap pixmap) { 163 return FromPixels(pixmap); 164 } 165 166 static SKImage FromPixels(SKPixmap pixmap, SKImageRasterReleaseDelegate releaseProc) { 167 return FromPixels(pixmap, releaseProc); 168 } 169 170 // static SKImage FromPixels (SKPixmap pixmap, SKImageRasterReleaseDelegate releaseProc, object releaseContext) 171 // { 172 // if (pixmap is null) 173 // throw new ArgumentNullException (pixmap.stringof); 174 175 // auto del = releaseProc !is null && releaseContext !is null 176 // ? new SKImageRasterReleaseDelegate ((addr, _) {return releaseProc (addr, releaseContext);}) 177 // : releaseProc; 178 // auto proxy = DelegateProxies.Create (del, DelegateProxies.SKImageRasterReleaseDelegateProxy, _, out var ctx); 179 // return GetObject (SkiaApi.sk_image_new_raster (pixmap.Handle, proxy, cast(void*)ctx)); 180 // } 181 182 // create a new image from encoded data 183 184 static SKImage FromEncodedData(SKData data, SKRectI subset) { 185 if (data is null) 186 throw new ArgumentNullException(data.stringof); 187 188 auto handle = SkiaApi.sk_image_new_from_encoded(cast(sk_data_t*)data.Handle, &subset); 189 return GetObject(handle); 190 } 191 192 static SKImage FromEncodedData(SKData data) { 193 if (data is null) 194 throw new ArgumentNullException(data.stringof); 195 196 auto handle = SkiaApi.sk_image_new_from_encoded(cast(sk_data_t*)data.Handle, null); 197 return GetObject(handle); 198 } 199 200 static SKImage FromEncodedData(byte[] data) { 201 if (data is null) 202 throw new ArgumentNullException(data.stringof); 203 if (data.length == 0) 204 throw new ArgumentException("The data buffer was empty."); 205 206 SKData skdata = SKData.CreateCopy(data); 207 return FromEncodedData(skdata); 208 } 209 210 static SKImage FromEncodedData(SKStream data) { 211 if (data is null) 212 throw new ArgumentNullException(data.stringof); 213 214 SKData skdata = SKData.Create(data); 215 if (skdata is null) 216 return null; 217 return FromEncodedData(skdata); 218 } 219 220 // static SKImage FromEncodedData (Stream data) 221 // { 222 // if (data is null) 223 // throw new ArgumentNullException (data.stringof); 224 225 // SKData skdata = SKData.Create (data); 226 // if (skdata is null) 227 // return null; 228 // return FromEncodedData (skdata); 229 230 // } 231 232 static SKImage FromEncodedData(string filename) { 233 if (filename is null) 234 throw new ArgumentNullException(filename.stringof); 235 236 SKData skdata = SKData.Create(filename); 237 if (skdata is null) 238 return null; 239 return FromEncodedData(skdata); 240 } 241 242 // create a new image from a bitmap 243 244 static SKImage FromBitmap(SKBitmap bitmap) { 245 if (bitmap is null) 246 throw new ArgumentNullException(bitmap.stringof); 247 248 auto image = GetObject(SkiaApi.sk_image_new_from_bitmap(cast(sk_bitmap_t*)bitmap.Handle)); 249 // GC.KeepAlive(bitmap); 250 return image; 251 } 252 253 // create a new image from a GPU texture 254 255 static SKImage FromTexture(GRContext context, GRBackendTextureDesc desc) { 256 return FromTexture(context, desc, SKAlphaType.Premul); 257 } 258 259 static SKImage FromTexture(GRContext context, GRBackendTextureDesc desc, SKAlphaType alpha) { 260 return FromTexture(context, desc, alpha); 261 } 262 263 static SKImage FromTexture(GRContext context, GRBackendTextureDesc desc, 264 SKAlphaType alpha, SKImageTextureReleaseDelegate releaseProc) { 265 return FromTexture(context, desc, alpha, releaseProc); 266 } 267 268 // static SKImage FromTexture (GRContext context, GRBackendTextureDesc desc, SKAlphaType alpha, SKImageTextureReleaseDelegate releaseProc, object releaseContext) 269 // { 270 // if (context is null) 271 // throw new ArgumentNullException (context.stringof); 272 273 // auto texture = new GRBackendTexture (desc); 274 // return FromTexture (context, texture, desc.Origin, desc.Config.ToColorType (), alpha, null, releaseProc, releaseContext); 275 // } 276 277 static SKImage FromTexture(GRContext context, GRGlBackendTextureDesc desc) { 278 return FromTexture(context, desc, SKAlphaType.Premul); 279 } 280 281 static SKImage FromTexture(GRContext context, GRGlBackendTextureDesc desc, SKAlphaType alpha) { 282 return FromTexture(context, desc, alpha); 283 } 284 285 static SKImage FromTexture(GRContext context, GRGlBackendTextureDesc desc, 286 SKAlphaType alpha, SKImageTextureReleaseDelegate releaseProc) { 287 return FromTexture(context, desc, alpha, releaseProc); 288 } 289 290 // static SKImage FromTexture (GRContext context, GRGlBackendTextureDesc desc, SKAlphaType alpha, SKImageTextureReleaseDelegate releaseProc, object releaseContext) 291 // { 292 // auto texture = new GRBackendTexture (desc); 293 // return FromTexture (context, texture, desc.Origin, desc.Config.ToColorType (), alpha, null, releaseProc, releaseContext); 294 // } 295 296 static SKImage FromTexture(GRContext context, GRBackendTexture texture, SKColorType colorType) { 297 return FromTexture(context, texture, GRSurfaceOrigin.BottomLeft, 298 colorType, SKAlphaType.Premul); 299 } 300 301 static SKImage FromTexture(GRContext context, GRBackendTexture texture, 302 GRSurfaceOrigin origin, SKColorType colorType) { 303 return FromTexture(context, texture, origin, colorType, 304 SKAlphaType.Premul); 305 } 306 307 static SKImage FromTexture(GRContext context, GRBackendTexture texture, 308 GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha) { 309 return FromTexture(context, texture, origin, colorType, alpha); 310 } 311 312 static SKImage FromTexture(GRContext context, GRBackendTexture texture, 313 GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha, 314 SKColorSpace colorspace) { 315 return FromTexture(context, texture, origin, colorType, alpha, colorspace); 316 } 317 318 static SKImage FromTexture(GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType, 319 SKAlphaType alpha, SKColorSpace colorspace, SKImageTextureReleaseDelegate releaseProc) { 320 return FromTexture(context, texture, origin, colorType, alpha, 321 colorspace, releaseProc); 322 } 323 324 // static SKImage FromTexture (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha, SKColorSpace colorspace, SKImageTextureReleaseDelegate releaseProc, object releaseContext) 325 // { 326 // if (context is null) 327 // throw new ArgumentNullException (context.stringof); 328 // if (texture is null) 329 // throw new ArgumentNullException (texture.stringof); 330 331 // auto cs = colorspace is null ? null : colorspace.Handle; 332 // auto del = releaseProc !is null && releaseContext !is null 333 // ? new SKImageTextureReleaseDelegate ((_){return releaseProc (releaseContext);}) 334 // : releaseProc; 335 // auto proxy = DelegateProxies.Create (del, DelegateProxies.SKImageTextureReleaseDelegateProxy, _, out var ctx); 336 // return GetObject (SkiaApi.sk_image_new_from_texture (context.Handle, texture.Handle, origin, colorType.ToNative (), alpha, cs, proxy, (void*)ctx)); 337 // } 338 339 static SKImage FromAdoptedTexture(GRContext context, GRBackendTextureDesc desc) { 340 return FromAdoptedTexture(context, desc, SKAlphaType.Premul); 341 } 342 343 static SKImage FromAdoptedTexture(GRContext context, GRBackendTextureDesc desc, 344 SKAlphaType alpha) { 345 GRBackendTexture texture = new GRBackendTexture(desc); 346 return FromAdoptedTexture(context, texture, desc.Origin, 347 desc.Config.ToColorType(), alpha, null); 348 } 349 350 static SKImage FromAdoptedTexture(GRContext context, GRGlBackendTextureDesc desc) { 351 return FromAdoptedTexture(context, desc, SKAlphaType.Premul); 352 } 353 354 static SKImage FromAdoptedTexture(GRContext context, 355 GRGlBackendTextureDesc desc, SKAlphaType alpha) { 356 GRBackendTexture texture = new GRBackendTexture(desc); 357 return FromAdoptedTexture(context, texture, desc.Origin, 358 desc.Config.ToColorType(), alpha, null); 359 } 360 361 static SKImage FromAdoptedTexture(GRContext context, 362 GRBackendTexture texture, SKColorType colorType) { 363 return FromAdoptedTexture(context, texture, GRSurfaceOrigin.BottomLeft, 364 colorType, SKAlphaType.Premul, null); 365 } 366 367 static SKImage FromAdoptedTexture(GRContext context, 368 GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType) { 369 return FromAdoptedTexture(context, texture, origin, colorType, SKAlphaType.Premul, null); 370 } 371 372 static SKImage FromAdoptedTexture(GRContext context, GRBackendTexture texture, 373 GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha) { 374 return FromAdoptedTexture(context, texture, origin, colorType, alpha, null); 375 } 376 377 static SKImage FromAdoptedTexture(GRContext context, GRBackendTexture texture, 378 GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha, 379 SKColorSpace colorspace) { 380 if (context is null) 381 throw new ArgumentNullException(context.stringof); 382 if (texture is null) 383 throw new ArgumentNullException(texture.stringof); 384 385 auto cs = colorspace is null ? null : colorspace.Handle; 386 return GetObject(SkiaApi.sk_image_new_from_adopted_texture(cast(gr_context_t*)context.Handle, 387 cast(gr_backendtexture_t*)texture.Handle, origin, colorType.ToNative(), alpha, cast(sk_colorspace_t*)cs)); 388 } 389 390 // create a new image from a picture 391 392 static SKImage FromPicture(SKPicture picture, SKSizeI dimensions) { 393 return FromPicture(picture, dimensions, null, null); 394 } 395 396 static SKImage FromPicture(SKPicture picture, SKSizeI dimensions, SKMatrix matrix) { 397 return FromPicture(picture, dimensions, &matrix, null); 398 } 399 400 static SKImage FromPicture(SKPicture picture, SKSizeI dimensions, SKPaint paint) { 401 return FromPicture(picture, dimensions, null, paint); 402 } 403 404 static SKImage FromPicture(SKPicture picture, SKSizeI dimensions, SKMatrix matrix, SKPaint paint) { 405 return FromPicture(picture, dimensions, &matrix, paint); 406 } 407 408 private static SKImage FromPicture(SKPicture picture, SKSizeI dimensions, 409 SKMatrix* matrix, SKPaint paint) { 410 if (picture is null) 411 throw new ArgumentNullException(picture.stringof); 412 413 auto p = paint.Handle ? paint.Handle : null; 414 return GetObject(SkiaApi.sk_image_new_from_picture(cast(sk_picture_t*)picture.Handle, &dimensions, matrix, cast(sk_paint_t*)p)); 415 } 416 417 SKData Encode() { 418 return SKData.GetObject(SkiaApi.sk_image_encode(cast(sk_image_t*)Handle)); 419 } 420 421 SKData Encode(SKPixelSerializer serializer) { 422 if (serializer is null) 423 throw new ArgumentNullException(serializer.stringof); 424 425 // try old data 426 auto encoded = EncodedData; 427 if (encoded !is null) { 428 if (serializer.UseEncodedData(encoded.Data, cast(ulong) encoded.Size)) { 429 return encoded; 430 } else { 431 encoded.Dispose(); 432 encoded = null; 433 } 434 } 435 436 // get new data (raster) 437 if (!IsTextureBacked) { 438 auto pixmap = PeekPixels(); 439 return serializer.Encode(pixmap); 440 441 } 442 443 // get new data (texture / gpu) 444 // this involves a copy from gpu to cpu first 445 if (IsTextureBacked) { 446 SKImageInfo info = SKImageInfo(Width, Height, ColorType, AlphaType, ColorSpace); 447 SKBitmap temp = new SKBitmap(info); 448 SKPixmap pixmap = temp.PeekPixels(); 449 if (pixmap !is null && ReadPixels(pixmap, 0, 0)) { 450 return serializer.Encode(pixmap); 451 } 452 453 } 454 455 // some error 456 return null; 457 } 458 459 SKData Encode(SKEncodedImageFormat format, int quality) { 460 return SKData.GetObject(SkiaApi.sk_image_encode_specific(cast(sk_image_t*)Handle, format, quality)); 461 } 462 463 int Width() { 464 return SkiaApi.sk_image_get_width(cast(sk_image_t*)Handle); 465 } 466 467 int Height() { 468 return SkiaApi.sk_image_get_height(cast(sk_image_t*)Handle); 469 } 470 471 uint UniqueId() { 472 return SkiaApi.sk_image_get_unique_id(cast(sk_image_t*)Handle); 473 } 474 475 SKAlphaType AlphaType() { 476 return SkiaApi.sk_image_get_alpha_type(cast(sk_image_t*)Handle); 477 } 478 479 SKColorType ColorType() { 480 // return SkiaApi.sk_image_get_color_type(cast(sk_image_t*)Handle).FromNative(); 481 return SKColorType.Rgba8888; 482 } 483 484 SKColorSpace ColorSpace() { 485 return SKColorSpace.GetObject(SkiaApi.sk_image_get_colorspace(cast(sk_image_t*)Handle)); 486 } 487 488 bool IsAlphaOnly() { 489 return SkiaApi.sk_image_is_alpha_only(cast(sk_image_t*)Handle); 490 } 491 492 SKData EncodedData() { 493 return SKData.GetObject(SkiaApi.sk_image_ref_encoded(cast(sk_image_t*)Handle)); 494 } 495 496 // ToShader 497 498 SKShader ToShader() { 499 return ToShader(SKShaderTileMode.Clamp, SKShaderTileMode.Clamp); 500 } 501 502 SKShader ToShader(SKShaderTileMode tileX, SKShaderTileMode tileY) { 503 return SKShader.GetObject(SkiaApi.sk_image_make_shader(cast(sk_image_t*)Handle, tileX, tileY, null)); 504 } 505 506 SKShader ToShader(SKShaderTileMode tileX, SKShaderTileMode tileY, SKMatrix localMatrix) { 507 return SKShader.GetObject(SkiaApi.sk_image_make_shader(cast(sk_image_t*)Handle, tileX, 508 tileY, &localMatrix)); 509 } 510 511 // PeekPixels 512 513 bool PeekPixels(SKPixmap pixmap) { 514 if (pixmap is null) 515 throw new ArgumentNullException(pixmap.stringof); 516 517 auto result = SkiaApi.sk_image_peek_pixels(cast(sk_image_t*)Handle, cast(sk_pixmap_t*)pixmap.Handle); 518 if (result) 519 pixmap.pixelSource = this; 520 return result; 521 } 522 523 SKPixmap PeekPixels() { 524 auto pixmap = new SKPixmap(); 525 if (!PeekPixels(pixmap)) { 526 pixmap.Dispose(); 527 pixmap = null; 528 } 529 return pixmap; 530 } 531 532 bool IsTextureBacked() { 533 return SkiaApi.sk_image_is_texture_backed(cast(sk_image_t*)Handle); 534 } 535 536 bool IsLazyGenerated() { 537 return SkiaApi.sk_image_is_lazy_generated(cast(sk_image_t*)Handle); 538 } 539 540 bool IsValid(GRContext context) { 541 return SkiaApi.sk_image_is_valid(cast(sk_image_t*)Handle, cast(gr_context_t*)(context.Handle ? context.Handle : null)); 542 } 543 544 // ReadPixels 545 546 bool ReadPixels(SKImageInfo dstInfo, void* dstPixels) { 547 return ReadPixels(dstInfo, dstPixels, dstInfo.RowBytes, 0, 0, SKImageCachingHint.Allow); 548 } 549 550 bool ReadPixels(SKImageInfo dstInfo, void* dstPixels, int dstRowBytes) { 551 return ReadPixels(dstInfo, dstPixels, dstRowBytes, 0, 0, SKImageCachingHint.Allow); 552 } 553 554 bool ReadPixels(SKImageInfo dstInfo, void* dstPixels, int dstRowBytes, int srcX, int srcY) { 555 return ReadPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY, SKImageCachingHint.Allow); 556 } 557 558 bool ReadPixels(SKImageInfo dstInfo, void* dstPixels, int dstRowBytes, 559 int srcX, int srcY, SKImageCachingHint cachingHint) { 560 auto cinfo = SKImageInfo.FromManaged(dstInfo); 561 auto result = SkiaApi.sk_image_read_pixels(cast(sk_image_t*)Handle, &cinfo, 562 cast(void*) dstPixels, cast(void*) dstRowBytes, srcX, srcY, cachingHint); 563 // GC.KeepAlive(this); 564 return result; 565 } 566 567 bool ReadPixels(SKPixmap pixmap) { 568 return ReadPixels(pixmap, 0, 0, SKImageCachingHint.Allow); 569 } 570 571 bool ReadPixels(SKPixmap pixmap, int srcX, int srcY) { 572 return ReadPixels(pixmap, srcX, srcY, SKImageCachingHint.Allow); 573 } 574 575 bool ReadPixels(SKPixmap pixmap, int srcX, int srcY, SKImageCachingHint cachingHint) { 576 if (pixmap is null) 577 throw new ArgumentNullException(pixmap.stringof); 578 579 auto result = SkiaApi.sk_image_read_pixels_into_pixmap(cast(sk_image_t*)Handle, 580 cast(sk_pixmap_t*)pixmap.Handle, srcX, srcY, cachingHint); 581 // GC.KeepAlive(this); 582 return result; 583 } 584 585 // ScalePixels 586 587 bool ScalePixels(SKPixmap dst, SKFilterQuality quality) { 588 return ScalePixels(dst, quality, SKImageCachingHint.Allow); 589 } 590 591 bool ScalePixels(SKPixmap dst, SKFilterQuality quality, SKImageCachingHint cachingHint) { 592 if (dst is null) 593 throw new ArgumentNullException(dst.stringof); 594 return SkiaApi.sk_image_scale_pixels(cast(sk_image_t*)Handle, cast(sk_pixmap_t*)dst.Handle, quality, cachingHint); 595 } 596 597 // Subset 598 599 SKImage Subset(SKRectI subset) { 600 return GetObject(SkiaApi.sk_image_make_subset(cast(sk_image_t*)Handle, &subset)); 601 } 602 603 // ToRasterImage 604 605 SKImage ToRasterImage() { 606 return ToRasterImage(false); 607 } 608 609 SKImage ToRasterImage(bool ensurePixelData) { 610 return ensurePixelData ? GetObject(SkiaApi.sk_image_make_raster_image(cast(sk_image_t*)Handle)) : GetObject( 611 SkiaApi.sk_image_make_non_texture_image(cast(sk_image_t*)Handle)); 612 } 613 614 // ToTextureImage 615 616 SKImage ToTextureImage(GRContext context) { 617 return ToTextureImage(context, false); 618 } 619 620 SKImage ToTextureImage(GRContext context, SKColorSpace colorspace) { 621 return ToTextureImage(context, false); 622 } 623 624 SKImage ToTextureImage(GRContext context, bool mipmapped) { 625 if (context is null) 626 throw new ArgumentNullException(context.stringof); 627 628 return GetObject(SkiaApi.sk_image_make_texture_image(cast(sk_image_t*)Handle, cast(gr_context_t*)context.Handle, mipmapped)); 629 } 630 631 // ApplyImageFilter 632 633 SKImage ApplyImageFilter(SKImageFilter filter, SKRectI subset, 634 SKRectI clipBounds, out SKRectI outSubset, out SKPoint outOffset) { 635 SKPointI outOffsetActual; 636 auto image = ApplyImageFilter(filter, subset, clipBounds, outSubset, outOffsetActual); 637 // outOffset = outOffsetActual; 638 return image; 639 } 640 641 SKImage ApplyImageFilter(SKImageFilter filter, SKRectI subset, 642 SKRectI clipBounds, out SKRectI outSubset, out SKPointI outOffset) { 643 if (filter is null) 644 throw new ArgumentNullException(filter.stringof); 645 646 SKRectI* os = &outSubset; 647 SKPointI* oo = &outOffset; 648 return GetObject(SkiaApi.sk_image_make_with_filter(cast(sk_image_t*)Handle, 649 cast(sk_imagefilter_t*)filter.Handle, &subset, &clipBounds, os, oo)); 650 } 651 652 static SKImage GetObject(void* handle) { 653 return GetOrAddObject!(SKImage)(handle, delegate SKImage (h, o) { return new SKImage (h, o);}); 654 // return GetOrAddObject(handle, (h, o) { return new SKImage(h, o); }); 655 } 656 657 }