BioLib  4.1.1
A GUI-less version of Bio .NET library for editing & annotating various microscopy image formats.
Loading...
Searching...
No Matches
BioLib.ImageUtil Class Reference

Static Public Member Functions

static Image< L8 > Join8Bit (IEnumerable< Tuple< Extent, byte[]> > srcPixelTiles, Extent srcPixelExtent, Extent dstPixelExtent)
 Join by srcPixelTiles and cut by srcPixelExtent then scale to dstPixelExtent (only height an width is useful).
 
static Image< Rgb24 > JoinRGB24 (IEnumerable< Tuple< Extent, byte[]> > srcPixelTiles, Extent srcPixelExtent, Extent dstPixelExtent)
 Join by srcPixelTiles and cut by srcPixelExtent then scale to dstPixelExtent (only height and width is useful).
 
static Image< L16 > Join16 (IEnumerable< Tuple< Extent, byte[]> > srcPixelTiles, Extent srcPixelExtent, Extent dstPixelExtent)
 Join by srcPixelTiles and cut by srcPixelExtent then scale to dstPixelExtent (only height an width is useful).
 
static unsafe NetVips.Image JoinVipsRGB24 (IEnumerable< Tuple< Extent, byte[]> > srcPixelTiles, Extent srcPixelExtent, Extent dstPixelExtent)
 Join by srcPixelTiles and cut by srcPixelExtent then scale to dstPixelExtent (only height an width is useful).
 
static unsafe NetVips.Image JoinVips16 (IEnumerable< Tuple< Extent, byte[]> > srcPixelTiles, Extent srcPixelExtent, Extent dstPixelExtent)
 Join by srcPixelTiles and cut by srcPixelExtent then scale to dstPixelExtent (only height an width is useful).
 
static SixLabors.ImageSharp.Image CreateImageFromBytes (byte[] rgbBytes, int width, int height, AForge.PixelFormat px)
 

Member Function Documentation

◆ CreateImageFromBytes()

static SixLabors.ImageSharp.Image BioLib.ImageUtil.CreateImageFromBytes ( byte[] rgbBytes,
int width,
int height,
AForge.PixelFormat px )
static
562 {
563 if (px == AForge.PixelFormat.Format24bppRgb)
564 {
565 if (rgbBytes.Length != width * height * 3)
566 {
567 throw new ArgumentException("Byte array size does not match the dimensions of the image");
568 }
569
570 // Create a new image of the specified size
571 Image<Rgb24> image = new Image<Rgb24>(width, height);
572
573 // Index for the byte array
574 int byteIndex = 0;
575
576 // Iterate over the image pixels
577 for (int y = 0; y < height; y++)
578 {
579 for (int x = 0; x < width; x++)
580 {
581 // Create a color from the next three bytes
582 Rgb24 color = new Rgb24(rgbBytes[byteIndex], rgbBytes[byteIndex + 1], rgbBytes[byteIndex + 2]);
583 byteIndex += 3;
584 // Set the pixel
585 image[x, y] = color;
586 }
587 }
588
589 return image;
590 }
591 else
592 if (px == AForge.PixelFormat.Format16bppGrayScale)
593 {
594 if (rgbBytes.Length != width * height * 2)
595 {
596 throw new ArgumentException("Byte array size does not match the dimensions of the image");
597 }
598
599 // Create a new image of the specified size
600 Image<L16> image = new Image<L16>(width, height);
601
602 // Index for the byte array
603 int byteIndex = 0;
604
605 // Iterate over the image pixels
606 for (int y = 0; y < height; y++)
607 {
608 for (int x = 0; x < width; x++)
609 {
610 // Create a color from the next three bytes
611 L16 color = new L16(BitConverter.ToUInt16(rgbBytes, byteIndex));
612 byteIndex += 2;
613 // Set the pixel
614 image[x, y] = color;
615 }
616 }
617
618 return image;
619 }
620 else
621 if (px == AForge.PixelFormat.Format8bppIndexed)
622 {
623 if (rgbBytes.Length != width * height)
624 {
625 throw new ArgumentException("Byte array size does not match the dimensions of the image");
626 }
627
628 // Create a new image of the specified size
629 Image<L8> image = new Image<L8>(width, height);
630
631 // Index for the byte array
632 int byteIndex = 0;
633
634 // Iterate over the image pixels
635 for (int y = 0; y < height; y++)
636 {
637 for (int x = 0; x < width; x++)
638 {
639 // Create a color from the next three bytes
640 L8 color = new L8(rgbBytes[byteIndex]);
641 byteIndex++;
642 // Set the pixel
643 image[x, y] = color;
644 }
645 }
646
647 return image;
648 }
649 else
650 if (px == AForge.PixelFormat.Format32bppArgb)
651 {
652 if (rgbBytes.Length != width * height * 4)
653 {
654 throw new ArgumentException("Byte array size does not match the dimensions of the image");
655 }
656
657 // Create a new image of the specified size
658 Image<Bgra32> image = new Image<Bgra32>(width, height);
659
660 // Index for the byte array
661 int byteIndex = 0;
662
663 // Iterate over the image pixels
664 for (int y = 0; y < height; y++)
665 {
666 for (int x = 0; x < width; x++)
667 {
668 // Create a color from the next three bytes
669 Bgra32 color = new Bgra32(rgbBytes[byteIndex], rgbBytes[byteIndex + 1], rgbBytes[byteIndex + 2], rgbBytes[byteIndex + 3]);
670 byteIndex += 4;
671 // Set the pixel
672 image[x, y] = color;
673 }
674 }
675
676 return image;
677 }
678 return null;
679 }

◆ Join16()

static Image< L16 > BioLib.ImageUtil.Join16 ( IEnumerable< Tuple< Extent, byte[]> > srcPixelTiles,
Extent srcPixelExtent,
Extent dstPixelExtent )
static

Join by srcPixelTiles and cut by srcPixelExtent then scale to dstPixelExtent (only height an width is useful).

Parameters
srcPixelTilestile with tile extent collection
srcPixelExtentcanvas extent
dstPixelExtentjpeg output size
Returns
333 {
334 if (srcPixelTiles == null || srcPixelTiles.Count() == 0)
335 return null;
336
337 static Extent SafeToIntegerExtent(Extent extent)
338 {
339 return extent.ToIntegerExtent();
340 }
341
342 static Extent? SafeIntersect(Extent a, Extent b)
343 {
344 try
345 {
346 return a.Intersect(b);
347 }
348 catch
349 {
350 return null;
351 }
352 }
353
354 srcPixelExtent = SafeToIntegerExtent(srcPixelExtent);
355 dstPixelExtent = SafeToIntegerExtent(dstPixelExtent);
356 int canvasWidth = (int)srcPixelExtent.Width;
357 int canvasHeight = (int)srcPixelExtent.Height;
358 int dstWidth = (int)dstPixelExtent.Width;
359 int dstHeight = (int)dstPixelExtent.Height;
360
361 if (canvasWidth <= 0 || canvasHeight <= 0)
362 return null;
363
364 Image<L16> canvas = new Image<L16>(canvasWidth, canvasHeight);
365 foreach (var tile in srcPixelTiles)
366 {
367 try
368 {
369 if (tile?.Item2 == null || tile.Item2.Length == 0)
370 continue;
371
372 var tileExtent = SafeToIntegerExtent(tile.Item1);
373 if (tileExtent.Width <= 0 || tileExtent.Height <= 0)
374 continue;
375
376 var intersect = SafeIntersect(srcPixelExtent, tileExtent);
377 if (intersect == null || intersect.Value.Width <= 0 || intersect.Value.Height <= 0)
378 continue;
379
380 using Image<L16> tileRawData = (Image<L16>)CreateImageFromBytes(
381 tile.Item2,
382 (int)tileExtent.Width,
383 (int)tileExtent.Height,
384 AForge.PixelFormat.Format16bppGrayScale);
385
386 int tileOffsetPixelX = (int)Math.Max(0, Math.Floor(intersect.Value.MinX - tileExtent.MinX));
387 int tileOffsetPixelY = (int)Math.Max(0, Math.Floor(intersect.Value.MinY - tileExtent.MinY));
388 int canvasOffsetPixelX = (int)Math.Max(0, Math.Floor(intersect.Value.MinX - srcPixelExtent.MinX));
389 int canvasOffsetPixelY = (int)Math.Max(0, Math.Floor(intersect.Value.MinY - srcPixelExtent.MinY));
390
391 int copyWidth = (int)Math.Min(
392 Math.Min(intersect.Value.Width, tileRawData.Width - tileOffsetPixelX),
393 canvas.Width - canvasOffsetPixelX);
394 int copyHeight = (int)Math.Min(
395 Math.Min(intersect.Value.Height, tileRawData.Height - tileOffsetPixelY),
396 canvas.Height - canvasOffsetPixelY);
397
398 if (copyWidth <= 0 || copyHeight <= 0)
399 continue;
400
401 // We copy the tile region to the canvas.
402 for (int y = 0; y < copyHeight; y++)
403 {
404 int canvasY = canvasOffsetPixelY + y;
405 int tileY = tileOffsetPixelY + y;
406 if (canvasY < 0 || canvasY >= canvas.Height ||
407 tileY < 0 || tileY >= tileRawData.Height)
408 break;
409
410 for (int x = 0; x < copyWidth; x++)
411 {
412 int canvasX = canvasOffsetPixelX + x;
413 int tileX = tileOffsetPixelX + x;
414 if (canvasX < 0 || canvasX >= canvas.Width ||
415 tileX < 0 || tileX >= tileRawData.Width)
416 break;
417
418 canvas[canvasX, canvasY] = tileRawData[tileX, tileY];
419 }
420 }
421 }
422 catch (Exception e)
423 {
424 Console.WriteLine(e.ToString());
425 }
426
427 }
428 if (dstWidth != canvasWidth || dstHeight != canvasHeight)
429 {
430 try
431 {
432 canvas.Mutate(x => x.Resize(dstWidth, dstHeight));
433 }
434 catch (Exception e)
435 {
436 Console.WriteLine(e.Message);
437 }
438 }
439 return canvas;
440 }

◆ Join8Bit()

static Image< L8 > BioLib.ImageUtil.Join8Bit ( IEnumerable< Tuple< Extent, byte[]> > srcPixelTiles,
Extent srcPixelExtent,
Extent dstPixelExtent )
static

Join by srcPixelTiles and cut by srcPixelExtent then scale to dstPixelExtent (only height an width is useful).

Parameters
srcPixelTilestile with tile extent collection
srcPixelExtentcanvas extent
dstPixelExtentjpeg output size
Returns
25 {
26 if (srcPixelTiles == null || !srcPixelTiles.Any())
27 return null;
28
29 // Convert extents to integer extents
30 srcPixelExtent = srcPixelExtent.ToIntegerExtent();
31 dstPixelExtent = dstPixelExtent.ToIntegerExtent();
32
33 int canvasWidth = (int)srcPixelExtent.Width;
34 int canvasHeight = (int)srcPixelExtent.Height;
35 int dstWidth = (int)dstPixelExtent.Width;
36 int dstHeight = (int)dstPixelExtent.Height;
37
38 // Create the canvas image
39 var canvas = new Image<L8>(canvasWidth, canvasHeight);
40
41 foreach (var tile in srcPixelTiles)
42 {
43 try
44 {
45 if (tile?.Item2 == null) // Skip null tiles
46 continue;
47
48 var tileExtent = tile.Item1.ToIntegerExtent();
49 var intersect = srcPixelExtent.Intersect(tileExtent);
50
51 // Skip tiles that do not intersect with the source extent
52 if (intersect.Width == 0 || intersect.Height == 0)
53 continue;
54
55 // Create an image from the tile data
56 using Image<L8> tileRawData = (Image<L8>)CreateImageFromBytes(
57 tile.Item2,
58 (int)tileExtent.Width,
59 (int)tileExtent.Height,
60 AForge.PixelFormat.Format8bppIndexed
61 );
62
63 // Compute offsets
64 int tileOffsetX = (int)(intersect.MinX - tileExtent.MinX);
65 int tileOffsetY = (int)(intersect.MinY - tileExtent.MinY);
66 int canvasOffsetX = (int)(intersect.MinX - srcPixelExtent.MinX);
67 int canvasOffsetY = (int)(intersect.MinY - srcPixelExtent.MinY);
68
69 // Copy intersected region from tile to canvas
70 for (int y = 0; y < intersect.Height; y++)
71 {
72 for (int x = 0; x < intersect.Width; x++)
73 {
74 int canvasX = canvasOffsetX + x;
75 int canvasY = canvasOffsetY + y;
76 int tileX = tileOffsetX + x;
77 int tileY = tileOffsetY + y;
78
79 // Use the older approach to manipulate pixel data
80 canvas[canvasX, canvasY] = tileRawData[tileX, tileY];
81 }
82 }
83 }
84 catch (Exception ex)
85 {
86 Console.WriteLine($"Error processing tile: {ex.Message}\n{ex.StackTrace}");
87 }
88 }
89
90 // Resize if necessary
91 if (dstWidth != canvasWidth || dstHeight != canvasHeight)
92 {
93 try
94 {
95 canvas.Mutate(x => x.Resize(dstWidth, dstHeight));
96 }
97 catch (Exception ex)
98 {
99 Console.WriteLine($"Error resizing canvas: {ex.Message}\n{ex.StackTrace}");
100 return null;
101 }
102 }
103
104 return canvas; // Return the canvas image
105 }

◆ JoinRGB24()

static Image< Rgb24 > BioLib.ImageUtil.JoinRGB24 ( IEnumerable< Tuple< Extent, byte[]> > srcPixelTiles,
Extent srcPixelExtent,
Extent dstPixelExtent )
static

Join by srcPixelTiles and cut by srcPixelExtent then scale to dstPixelExtent (only height and width is useful).

Parameters
srcPixelTilestile with tile extent collection
srcPixelExtentcanvas extent
dstPixelExtentjpeg output size
Returns
115 {
116 if (srcPixelTiles == null || !srcPixelTiles.Any())
117 return null;
118
119 try
120 {
121 // Safely convert to integer extents
122 srcPixelExtent = SafeToIntegerExtent(srcPixelExtent);
123 dstPixelExtent = SafeToIntegerExtent(dstPixelExtent);
124
125 int canvasWidth = (int)srcPixelExtent.Width;
126 int canvasHeight = (int)srcPixelExtent.Height;
127 int dstWidth = (int)dstPixelExtent.Width;
128 int dstHeight = (int)dstPixelExtent.Height;
129
130 // Validate dimensions
131 if (canvasWidth <= 0 || canvasHeight <= 0)
132 {
133 Console.WriteLine($"Invalid canvas dimensions: {canvasWidth}x{canvasHeight}");
134 return null;
135 }
136
137 Image<Rgb24> canvas = new Image<Rgb24>(canvasWidth, canvasHeight);
138
139 foreach (var tile in srcPixelTiles)
140 {
141 try
142 {
143 // Skip invalid tiles
144 if (tile?.Item2 == null || tile.Item2.Length == 0)
145 continue;
146
147 // Safely convert tile extent
148 var tileExtent = SafeToIntegerExtent(tile.Item1);
149
150 // Validate tile extent
151 if (tileExtent.Width <= 0 || tileExtent.Height <= 0)
152 continue;
153
154 // Calculate intersection manually to avoid errors
155 var intersect = SafeIntersect(srcPixelExtent, tileExtent);
156
157 // Skip if no intersection
158 if (intersect == null || intersect.Value.Width <= 0 || intersect.Value.Height <= 0)
159 continue;
160
161 // Create image from tile data
162 Image<Rgb24> tileRawData = null;
163 try
164 {
165 tileRawData = (Image<Rgb24>)CreateImageFromBytes(
166 tile.Item2,
167 (int)tileExtent.Width,
168 (int)tileExtent.Height,
169 AForge.PixelFormat.Format24bppRgb
170 );
171 }
172 catch (Exception ex)
173 {
174 Console.WriteLine($"Failed to create image from tile data: {ex.Message}");
175 continue;
176 }
177
178 if (tileRawData == null)
179 continue;
180
181 // Calculate offsets (using Floor instead of Ceiling for better precision)
182 int tileOffsetPixelX = (int)Math.Max(0, intersect.Value.MinX - tileExtent.MinX);
183 int tileOffsetPixelY = (int)Math.Max(0, intersect.Value.MinY - tileExtent.MinY);
184 int canvasOffsetPixelX = (int)Math.Max(0, intersect.Value.MinX - srcPixelExtent.MinX);
185 int canvasOffsetPixelY = (int)Math.Max(0, intersect.Value.MinY - srcPixelExtent.MinY);
186
187 // Calculate safe copy dimensions
188 int copyWidth = (int)Math.Min(
189 Math.Min(intersect.Value.Width, tileRawData.Width - tileOffsetPixelX),
190 canvas.Width - canvasOffsetPixelX
191 );
192
193 int copyHeight = (int)Math.Min(
194 Math.Min(intersect.Value.Height, tileRawData.Height - tileOffsetPixelY),
195 canvas.Height - canvasOffsetPixelY
196 );
197
198 // Validate copy dimensions
199 if (copyWidth <= 0 || copyHeight <= 0)
200 {
201 tileRawData.Dispose();
202 continue;
203 }
204
205 // Copy the tile region to the canvas with bounds checking
206 for (int y = 0; y < copyHeight; y++)
207 {
208 int canvasY = canvasOffsetPixelY + y;
209 int tileY = tileOffsetPixelY + y;
210
211 // Safety check
212 if (canvasY < 0 || canvasY >= canvas.Height ||
213 tileY < 0 || tileY >= tileRawData.Height)
214 break;
215
216 for (int x = 0; x < copyWidth; x++)
217 {
218 int canvasX = canvasOffsetPixelX + x;
219 int tileX = tileOffsetPixelX + x;
220
221 // Safety check
222 if (canvasX < 0 || canvasX >= canvas.Width ||
223 tileX < 0 || tileX >= tileRawData.Width)
224 break;
225
226 canvas[canvasX, canvasY] = tileRawData[tileX, tileY];
227 }
228 }
229
230 tileRawData.Dispose();
231 }
232 catch (Exception e)
233 {
234 Console.WriteLine($"Error processing tile: {e.Message}");
235 }
236 }
237
238 // Resize if needed
239 if (dstWidth > 0 && dstHeight > 0 &&
240 (dstWidth != canvasWidth || dstHeight != canvasHeight))
241 {
242 try
243 {
244 canvas.Mutate(x => x.Resize(dstWidth, dstHeight));
245 }
246 catch (Exception e)
247 {
248 Console.WriteLine($"Error resizing canvas: {e.Message}");
249 }
250 }
251
252 return canvas;
253 }
254 catch (Exception e)
255 {
256 Console.WriteLine($"Fatal error in JoinRGB24: {e.Message}\n{e.StackTrace}");
257 return null;
258 }
259 }

◆ JoinVips16()

static unsafe NetVips.Image BioLib.ImageUtil.JoinVips16 ( IEnumerable< Tuple< Extent, byte[]> > srcPixelTiles,
Extent srcPixelExtent,
Extent dstPixelExtent )
static

Join by srcPixelTiles and cut by srcPixelExtent then scale to dstPixelExtent (only height an width is useful).

Parameters
srcPixelTilestile with tile extent collection
srcPixelExtentcanvas extent
dstPixelExtentjpeg output size
Returns
509 {
510 if (srcPixelTiles == null || !srcPixelTiles.Any())
511 return null;
512
513 srcPixelExtent = srcPixelExtent.ToIntegerExtent();
514 dstPixelExtent = dstPixelExtent.ToIntegerExtent();
515 int canvasWidth = (int)srcPixelExtent.Width;
516 int canvasHeight = (int)srcPixelExtent.Height;
517
518 // Create a base canvas. Adjust as necessary, for example, using a transparent image if needed.
519 Bitmap bf = new Bitmap(canvasWidth, canvasHeight, AForge.PixelFormat.Format16bppGrayScale);
520 NetVips.Image canvas = NetVips.Image.NewFromMemory(bf.Bytes, bf.SizeX, bf.SizeY, 1, Enums.BandFormat.Ushort);
521
522 foreach (var tile in srcPixelTiles)
523 {
524 if (tile.Item2 == null)
525 continue;
526
527 fixed (byte* pTileData = tile.Item2)
528 {
529 var tileExtent = tile.Item1.ToIntegerExtent();
530 NetVips.Image tileImage = NetVips.Image.NewFromMemory((IntPtr)pTileData, (ulong)tile.Item2.Length, (int)tileExtent.Width, (int)tileExtent.Height, 1, Enums.BandFormat.Ushort);
531
532 // Calculate positions and sizes for cropping and inserting
533 var intersect = srcPixelExtent.Intersect(tileExtent);
534 if (intersect.Width == 0 || intersect.Height == 0)
535 continue;
536
537 int tileOffsetPixelX = (int)Math.Ceiling(intersect.MinX - tileExtent.MinX);
538 int tileOffsetPixelY = (int)Math.Ceiling(intersect.MinY - tileExtent.MinY);
539 int canvasOffsetPixelX = (int)Math.Ceiling(intersect.MinX - srcPixelExtent.MinX);
540 int canvasOffsetPixelY = (int)Math.Ceiling(intersect.MinY - srcPixelExtent.MinY);
541
542 using (var croppedTile = tileImage.Crop(tileOffsetPixelX, tileOffsetPixelY, (int)intersect.Width, (int)intersect.Height))
543 {
544 // Instead of inserting directly, we composite over the base canvas
545 canvas = canvas.Composite2(croppedTile, Enums.BlendMode.Over, canvasOffsetPixelX, canvasOffsetPixelY);
546 }
547 }
548 }
549
550 // Resize if the destination extent differs from the source canvas size
551 if ((int)dstPixelExtent.Width != canvasWidth || (int)dstPixelExtent.Height != canvasHeight)
552 {
553 double scaleX = (double)dstPixelExtent.Width / canvasWidth;
554 double scaleY = (double)dstPixelExtent.Height / canvasHeight;
555 canvas = canvas.Resize(scaleX, vscale: scaleY, kernel: Enums.Kernel.Nearest);
556 }
557
558 return canvas;
559 }

◆ JoinVipsRGB24()

static unsafe NetVips.Image BioLib.ImageUtil.JoinVipsRGB24 ( IEnumerable< Tuple< Extent, byte[]> > srcPixelTiles,
Extent srcPixelExtent,
Extent dstPixelExtent )
static

Join by srcPixelTiles and cut by srcPixelExtent then scale to dstPixelExtent (only height an width is useful).

Parameters
srcPixelTilestile with tile extent collection
srcPixelExtentcanvas extent
dstPixelExtentjpeg output size
Returns
450 {
451 if (srcPixelTiles == null || !srcPixelTiles.Any())
452 return null;
453
454 srcPixelExtent = srcPixelExtent.ToIntegerExtent();
455 dstPixelExtent = dstPixelExtent.ToIntegerExtent();
456 int canvasWidth = (int)srcPixelExtent.Width;
457 int canvasHeight = (int)srcPixelExtent.Height;
458
459 // Create a base canvas. Adjust as necessary, for example, using a transparent image if needed.
460 NetVips.Image canvas = NetVips.Image.Black(canvasWidth, canvasHeight, bands: 3);
461
462 foreach (var tile in srcPixelTiles)
463 {
464 if (tile.Item2 == null)
465 continue;
466
467 fixed (byte* pTileData = tile.Item2)
468 {
469 var tileExtent = tile.Item1.ToIntegerExtent();
470 NetVips.Image tileImage = NetVips.Image.NewFromMemory((IntPtr)pTileData, (ulong)tile.Item2.Length, (int)tileExtent.Width, (int)tileExtent.Height, 3, Enums.BandFormat.Uchar);
471
472 // Calculate positions and sizes for cropping and inserting
473 var intersect = srcPixelExtent.Intersect(tileExtent);
474 if (intersect.Width == 0 || intersect.Height == 0)
475 continue;
476
477 int tileOffsetPixelX = (int)Math.Ceiling(intersect.MinX - tileExtent.MinX);
478 int tileOffsetPixelY = (int)Math.Ceiling(intersect.MinY - tileExtent.MinY);
479 int canvasOffsetPixelX = (int)Math.Ceiling(intersect.MinX - srcPixelExtent.MinX);
480 int canvasOffsetPixelY = (int)Math.Ceiling(intersect.MinY - srcPixelExtent.MinY);
481
482 using (var croppedTile = tileImage.Crop(tileOffsetPixelX, tileOffsetPixelY, (int)intersect.Width, (int)intersect.Height))
483 {
484 // Instead of inserting directly, we composite over the base canvas
485 canvas = canvas.Composite2(croppedTile, Enums.BlendMode.Over, canvasOffsetPixelX, canvasOffsetPixelY);
486 }
487 }
488 }
489
490 // Resize if the destination extent differs from the source canvas size
491 if ((int)dstPixelExtent.Width != canvasWidth || (int)dstPixelExtent.Height != canvasHeight)
492 {
493 double scaleX = (double)dstPixelExtent.Width / canvasWidth;
494 double scaleY = (double)dstPixelExtent.Height / canvasHeight;
495 canvas = canvas.Resize(scaleX, vscale: scaleY, kernel: Enums.Kernel.Nearest);
496 }
497
498 return canvas;
499 }

The documentation for this class was generated from the following file: