From df7d434284d5d14030d893400cfa7121a1adb779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Mon, 27 Mar 2023 02:59:24 +0100 Subject: [PATCH] v3.12.2 - (Improvement) CXDLP: Better parse of machine model from PrusaSlicer profile (#351) - (Fix) OSF: Printer freezes at first layer (#657) - (Upgrade) AvaloniaUI from 0.10.18 to 0.10.19 --- CHANGELOG.md | 6 ++ RELEASE_NOTES.md | 14 +--- Scripts/010 Editor/osf.bt | 4 +- .../UVtools.AvaloniaControls.csproj | 2 +- UVtools.Core/Extensions/EmguExtensions.cs | 82 ++++++++++++------ UVtools.Core/FileFormats/CXDLPFile.cs | 2 +- UVtools.Core/FileFormats/FDGFile.cs | 2 +- UVtools.Core/FileFormats/OSFFile.cs | 29 ++++--- UVtools.Core/FileFormats/PHZFile.cs | 2 +- UVtools.Core/Layers/Layer.cs | 84 +++++++++++++++++-- UVtools.Core/Objects/KernelConfiguration.cs | 2 +- UVtools.Core/Operations/OperationInfill.cs | 2 +- UVtools.Core/UVtools.Core.csproj | 2 +- UVtools.WPF/Extensions/BitmapExtension.cs | 6 +- UVtools.WPF/UVtools.WPF.csproj | 16 ++-- documentation/UVtools.Core.xml | 64 +++++++++++--- 16 files changed, 234 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e07e1b1..97dca1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## 27/03/2023 - v3.12.2 + +- (Improvement) CXDLP: Better parse of machine model from PrusaSlicer profile (#351) +- (Fix) OSF: Printer freezes at first layer (#657) +- (Upgrade) AvaloniaUI from 0.10.18 to 0.10.19 + ## 22/03/2023 - v3.12.1 - **File formats:** diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 70a1bd1..e462509 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,12 +1,4 @@ -- **File formats:** - - (Improvement) Does not set `PerLayerSettings` flag when found different exposure times on transition layers, this fix the issue where users can't edit settings on printer menu when having transition layers (#507) - - (Fix) CTB for UniFormation GKtwo: Unable to show nor print files (#673) - - (Fix) CBDDLP corruption when downgrade version (#675) -- **PCB exposure:** - - (Add) EagleCAD XLN drill format (#676) - - (Add) Allow to re-order gerbers up and down on the grid - - (Change) Drill files does not require G05 to do the holes (#676) - - (Fix) Infinite loop on refresh preview when selecting drl files - - (Fix) Unable to individual invert drl files -- (Upgrade) .NET from 6.0.14 to 6.0.15 +- (Improvement) CXDLP: Better parse of machine model from PrusaSlicer profile (#351) +- (Fix) OSF: Printer freezes at first layer (#657) +- (Upgrade) AvaloniaUI from 0.10.18 to 0.10.19 diff --git a/Scripts/010 Editor/osf.bt b/Scripts/010 Editor/osf.bt index e423987..ea1f22a 100644 --- a/Scripts/010 Editor/osf.bt +++ b/Scripts/010 Editor/osf.bt @@ -123,13 +123,13 @@ struct HEADER { struct LAYER_DEF { ushort Mark ; // (OD OA begins, indicating that the model + support is included; the beginning of 0D 0B, indicating that the layer only has support data) - uint NumberOfPixels ; + uint NumberOfLines ; ushort StartY ; local long currentPos = FTell(); local long rleSize = 0; - if (NumberOfPixels > 0) + if (NumberOfLines > 0) { local byte buffer; local byte slen; diff --git a/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj b/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj index d7f6add..defe1eb 100644 --- a/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj +++ b/UVtools.AvaloniaControls/UVtools.AvaloniaControls.csproj @@ -38,7 +38,7 @@ - + diff --git a/UVtools.Core/Extensions/EmguExtensions.cs b/UVtools.Core/Extensions/EmguExtensions.cs index f58d822..74ae127 100644 --- a/UVtools.Core/Extensions/EmguExtensions.cs +++ b/UVtools.Core/Extensions/EmguExtensions.cs @@ -193,21 +193,6 @@ public static class EmguExtensions public static unsafe byte* GetBytePointer(this Mat mat) => (byte*)mat.DataPointer.ToPointer(); - /// - /// Gets the whole data span to manipulate or read pixels - /// - /// - /// - public static unsafe Span GetDataByteSpan(this Mat mat) - => new(mat.DataPointer.ToPointer(), mat.GetLength()); - - /// - /// Gets the whole data span to manipulate or read pixels - /// - /// - public static Span GetDataByteSpan(this Mat mat, int length, int offset = 0) - => GetDataSpan(mat, length, offset); - /// /// Gets the whole data span to manipulate or read pixels, use this when possibly using ROI /// @@ -225,6 +210,19 @@ public static class EmguExtensions /// public static Span2D GetDataByteSpan2D(this Mat mat) => mat.GetDataSpan2D(); + /// + /// Gets the whole data span to manipulate or read pixels + /// + /// + /// + public static Span GetDataByteSpan(this Mat mat) => mat.GetDataSpan(); + + /// + /// Gets the whole data span to manipulate or read pixels + /// + /// + public static Span GetDataByteSpan(this Mat mat, int length, int offset = 0) => GetDataSpan(mat, length, offset); + /// /// Gets the data span to manipulate or read pixels given a length and offset @@ -234,8 +232,21 @@ public static class EmguExtensions /// /// /// - public static unsafe Span GetDataSpan(this Mat mat, int length = 0, int offset = 0) - => new(IntPtr.Add(mat.DataPointer, offset).ToPointer(), length <= 0 ? mat.GetLength() : length); + public static unsafe Span GetDataSpan(this Mat mat, int length = 0, int offset = 0) + { + if (length <= 0) + { + if (mat.IsSubmatrix) + { + length = mat.Step * (mat.Height - 1) + mat.GetRealStep(); + } + else + { + length = mat.GetLength(); + } + } + return new(IntPtr.Add(mat.DataPointer, offset).ToPointer(), length); + } /// /// Gets a single pixel span to manipulate or read pixels @@ -267,8 +278,22 @@ public static class EmguExtensions /// /// /// - public static unsafe Span GetRowSpan(this Mat mat, int y, int length = 0, int offset = 0) - => new(IntPtr.Add(mat.DataPointer, y * mat.GetRealStep() + offset).ToPointer(), length <= 0 ? mat.GetRealStep() : length); + public static unsafe Span GetRowSpan(this Mat mat, int y, int length = 0, int offset = 0) + { + var originalStep = mat.Step; + if(length <= 0) length = mat.GetRealStep(); + return new(IntPtr.Add(mat.DataPointer, y * originalStep + offset).ToPointer(), length); + } + + /// + /// Gets a row span to manipulate or read pixels + /// + /// + /// + /// + /// + /// + public static Span GetRowByteSpan(this Mat mat, int y, int length = 0, int offset = 0) => mat.GetRowSpan(y, length, offset); /// /// Gets a col span to manipulate or read pixels @@ -340,7 +365,7 @@ public static class EmguExtensions #region Get/Set methods /// - /// .Step return the original Mat step, if ROI step still from original matrix which lead to errors. + /// Step return the original Mat step, if ROI step still from original matrix which lead to errors. /// Use this to get the real step size /// /// @@ -441,8 +466,7 @@ public static class EmguExtensions /// /// /// - public static void SetByte(this Mat mat, int pixel, byte[] value) => - Marshal.Copy(value, 0, mat.DataPointer + pixel, value.Length); + public static void SetByte(this Mat mat, int pixel, byte[] value) => Marshal.Copy(value, 0, mat.DataPointer + pixel, value.Length); /// /// Sets a byte pixel at a position @@ -451,8 +475,15 @@ public static class EmguExtensions /// /// /// - public static void SetByte(this Mat mat, int x, int y, byte value) => - SetByte(mat, x, y, new[] { value }); + public static void SetByte(this Mat mat, int x, int y, byte value) => SetByte(mat, x, y, new[] { value }); + + /// + /// Sets a byte pixel at a position + /// + /// + /// + /// + public static void SetByte(this Mat mat, Point pos, byte value) => SetByte(mat, pos.X, pos.Y, new[] { value }); /// /// Sets a byte pixel at a position @@ -461,8 +492,7 @@ public static class EmguExtensions /// /// /// - public static void SetByte(this Mat mat, int x, int y, byte[] value) => - SetByte(mat, y * mat.GetRealStep() + x * mat.NumberOfChannels, value); + public static void SetByte(this Mat mat, int x, int y, byte[] value) => SetByte(mat, y * mat.GetRealStep() + x * mat.NumberOfChannels, value); /// /// Sets bytes diff --git a/UVtools.Core/FileFormats/CXDLPFile.cs b/UVtools.Core/FileFormats/CXDLPFile.cs index eee0d1c..6b27579 100644 --- a/UVtools.Core/FileFormats/CXDLPFile.cs +++ b/UVtools.Core/FileFormats/CXDLPFile.cs @@ -614,7 +614,7 @@ public sealed class CXDLPFile : FileFormat if (!string.IsNullOrWhiteSpace(value) && !value.StartsWith("CL-") && !value.StartsWith("CT-")) { // Parse from machine name, if coming from PrusaSlicer this will help - var match = Regex.Match(value, @"(CL|CT)-\d+"); + var match = Regex.Match(value, @"(CL|CT)-?\d+[a-zA-Z]?"); if (match is {Success: true, Groups.Count: > 1}) { value = match.Value; diff --git a/UVtools.Core/FileFormats/FDGFile.cs b/UVtools.Core/FileFormats/FDGFile.cs index 8ac32f3..dd8204f 100644 --- a/UVtools.Core/FileFormats/FDGFile.cs +++ b/UVtools.Core/FileFormats/FDGFile.cs @@ -565,7 +565,7 @@ public sealed class FDGFile : FileFormat //int pixel = 0; for (int y = 0; y < mat.Height; y++) { - var span = mat.GetRowSpan(y); + var span = mat.GetRowByteSpan(y); for (int x = 0; x < span.Length; x++) { diff --git a/UVtools.Core/FileFormats/OSFFile.cs b/UVtools.Core/FileFormats/OSFFile.cs index 2933a5d..432972c 100644 --- a/UVtools.Core/FileFormats/OSFFile.cs +++ b/UVtools.Core/FileFormats/OSFFile.cs @@ -156,7 +156,7 @@ public sealed class OSFFile : FileFormat /// [FieldOrder(0)] [FieldEndianness(Endianness.Big)] public ushort Mark { get; set; } = 0x0D_0A; - [FieldOrder(1)] [FieldEndianness(Endianness.Big)] public uint NumberOfPixels { get; set; } + [FieldOrder(1)] [FieldEndianness(Endianness.Big)] public uint NumberOfLines { get; set; } [FieldOrder(2)] [FieldEndianness(Endianness.Big)] public ushort StartY { get; set; } [Ignore] public byte[] EncodedRle { get; set; } = Array.Empty(); @@ -164,16 +164,18 @@ public sealed class OSFFile : FileFormat public override string ToString() { - return $"{nameof(Mark)}: {Mark}, {nameof(NumberOfPixels)}: {NumberOfPixels}, {nameof(StartY)}: {StartY}"; + return $"{nameof(Mark)}: {Mark}, {nameof(NumberOfLines)}: {NumberOfLines}, {nameof(StartY)}: {StartY}"; } - internal unsafe void EncodeImage(Mat mat) + internal unsafe void EncodeImage(Mat mat, Layer layer) { List rawData = new(); - byte color = byte.MaxValue >> 1; + byte color = 0; uint stride = 0; var span = mat.GetBytePointer(); var imageLength = mat.GetLength(); + var step = mat.GetRealStep(); + uint lines = 0; void AddRep() { @@ -189,6 +191,7 @@ public sealed class OSFFile : FileFormat break; } + lines++; rawData.Add(color); if (stride <= 1) @@ -227,8 +230,7 @@ public sealed class OSFFile : FileFormat } } - - for (int pixel = StartY * mat.GetRealStep(); pixel < imageLength; pixel++) + for (var pixel = StartY * step; pixel <= layer.LastPixelIndex; pixel++) { var grey = span[pixel]; @@ -244,13 +246,21 @@ public sealed class OSFFile : FileFormat } } + // Left-over + if(color != 0) AddRep(); + stride = (uint) ((imageLength - layer.LastPixelIndex - 1) % step); + color = 0; + AddRep(); + + NumberOfLines = lines; + EncodedRle = rawData.ToArray(); } internal Mat DecodeImage(OSFFile parent) { var mat = parent.CreateMat(); - if (NumberOfPixels == 0) return mat; + if (NumberOfLines == 0) return mat; int pixel = (int)(StartY * parent.ResolutionX); for (var n = 0; n < EncodedRle.Length; n++) @@ -721,10 +731,9 @@ public sealed class OSFFile : FileFormat { layerDef[layerIndex] = new OSFLayerDef { - NumberOfPixels = layer.NonZeroPixelCount, StartY = (ushort)layer.BoundingRectangle.Y, }; - layerDef[layerIndex].EncodeImage(mat); + layerDef[layerIndex].EncodeImage(mat, layer); } progress.LockAndIncrement(); }); @@ -786,7 +795,7 @@ public sealed class OSFFile : FileFormat //Debug.WriteLine($"{layerIndex}: {inputFile.Position}"); layerDef[layerIndex] = Helpers.Deserialize(inputFile); - if (layerDef[layerIndex].NumberOfPixels == 0) continue; + if (layerDef[layerIndex].NumberOfLines == 0) continue; int buffer; int slen; diff --git a/UVtools.Core/FileFormats/PHZFile.cs b/UVtools.Core/FileFormats/PHZFile.cs index d9b5558..6d95975 100644 --- a/UVtools.Core/FileFormats/PHZFile.cs +++ b/UVtools.Core/FileFormats/PHZFile.cs @@ -579,7 +579,7 @@ public sealed class PHZFile : FileFormat //int pixel = 0; for (int y = 0; y < image.Height; y++) { - var span = image.GetRowSpan(y); + var span = image.GetRowByteSpan(y); for (int x = 0; x < span.Length; x++) { diff --git a/UVtools.Core/Layers/Layer.cs b/UVtools.Core/Layers/Layer.cs index 0ce23b2..e6bbc23 100644 --- a/UVtools.Core/Layers/Layer.cs +++ b/UVtools.Core/Layers/Layer.cs @@ -63,6 +63,10 @@ public class Layer : BindableBase, IEquatable, IEquatable private byte[]? _compressedBytes; private uint _nonZeroPixelCount; private Rectangle _boundingRectangle = Rectangle.Empty; + private uint _firstPixelIndex; + private uint _lastPixelIndex; + private Point _firstPixelPosition; + private Point _lastPixelPosition; private bool _isModified; private uint _index; private uint _resolutionX; @@ -220,25 +224,62 @@ public class Layer : BindableBase, IEquatable, IEquatable } } + /// + /// Gets the first pixel index on the + /// + public uint BoundingRectangleFirstPixelIndex => (uint)(BoundingRectangle.Y * ResolutionX + BoundingRectangle.X); + + /// + /// Gets the last pixel index on the + /// + public uint BoundingRectangleLastPixelIndex => (uint)(BoundingRectangle.Bottom * ResolutionX + BoundingRectangle.Right); + + /// + /// Gets the first pixel on the + /// + public Point BoundingRectangleFirstPixelPosition => BoundingRectangle.Location; + + /// + /// Gets the last pixel on the + /// + public Point BoundingRectangleLastPixelPosition => new (BoundingRectangle.Right, BoundingRectangle.Bottom); + /// /// Gets the first pixel index on this layer /// - public uint FirstPixelIndex => (uint)(BoundingRectangle.Y * ResolutionX + BoundingRectangle.X); + public uint FirstPixelIndex + { + get => _firstPixelIndex; + private set => RaiseAndSetIfChanged(ref _firstPixelIndex, value); + } /// /// Gets the last pixel index on this layer /// - public uint LastPixelIndex => (uint)(BoundingRectangle.Bottom * ResolutionX + BoundingRectangle.Right); + public uint LastPixelIndex + { + get => _lastPixelIndex; + private set => RaiseAndSetIfChanged(ref _lastPixelIndex, value); + } /// /// Gets the first pixel on this layer /// - public Point FirstPixelPosition => BoundingRectangle.Location; + public Point FirstPixelPosition + { + get => _firstPixelPosition; + private set => RaiseAndSetIfChanged(ref _firstPixelPosition, value); + } /// /// Gets the last pixel on this layer /// - public Point LastPixelPosition => new (BoundingRectangle.Right, BoundingRectangle.Bottom); + public Point LastPixelPosition + { + get => _lastPixelPosition; + private set => RaiseAndSetIfChanged(ref _lastPixelPosition, value); + } + /// /// Gets if is the first layer @@ -1213,6 +1254,8 @@ public class Layer : BindableBase, IEquatable, IEquatable $"{nameof(Filename)}: {Filename}, " + $"{nameof(NonZeroPixelCount)}: {NonZeroPixelCount}, " + $"{nameof(BoundingRectangle)}: {BoundingRectangle}, " + + $"{nameof(FirstPixelPosition)}: {FirstPixelPosition}, " + + $"{nameof(LastPixelPosition)}: {LastPixelPosition}, " + $"{nameof(IsBottomLayer)}: {IsBottomLayer}, " + $"{nameof(IsNormalLayer)}: {IsNormalLayer}, " + $"{nameof(LayerHeight)}: {LayerHeight}mm, " + @@ -1399,11 +1442,38 @@ public class Layer : BindableBase, IEquatable, IEquatable { var roiMat = mat.Roi(_boundingRectangle); NonZeroPixelCount = (uint)CvInvoke.CountNonZero(roiMat); + + // Compute first and last pixel + var span = roiMat.GetDataByteSpan(); + var yOffset = mat.GetRealStep() * BoundingRectangle.Y; + for (var i = 0; i < span.Length; i++) + { + if (span[i] == 0) continue; + var xOffset = BoundingRectangle.X + i; + FirstPixelIndex = (uint) (yOffset + xOffset); + FirstPixelPosition = new Point(xOffset, BoundingRectangle.Y); + break; + } + for (var i = span.Length - 1; i >= 0; i--) + { + if (span[i] == 0) continue; + LastPixelIndex = (uint) (yOffset + BoundingRectangle.X + i); + LastPixelPosition = new Point(BoundingRectangle.Right - (span.Length - i), BoundingRectangle.Bottom - 1); + break; + } + roiMat.DisposeIfSubMatrix(); } + /* // Test + mat.SetByte((int)FirstPixelIndex, 255); + mat.SetByte(FirstPixelPosition, 255); + mat.SetByte((int)LastPixelIndex, 255); + mat.SetByte(LastPixelPosition, 255); + mat.Save("D:\\test.png"); + */ - if (needDispose) mat!.Dispose(); + if (needDispose) mat.Dispose(); return BoundingRectangle; } @@ -1743,6 +1813,10 @@ public class Layer : BindableBase, IEquatable, IEquatable layer._contours = _contours?.Clone(); layer.BoundingRectangle = _boundingRectangle; layer.NonZeroPixelCount = _nonZeroPixelCount; + layer.FirstPixelIndex = _firstPixelIndex; + layer.FirstPixelPosition = _firstPixelPosition; + layer.LastPixelIndex = _lastPixelIndex; + layer.LastPixelPosition = _lastPixelPosition; } public Layer Clone() diff --git a/UVtools.Core/Objects/KernelConfiguration.cs b/UVtools.Core/Objects/KernelConfiguration.cs index 6c17089..952ca92 100644 --- a/UVtools.Core/Objects/KernelConfiguration.cs +++ b/UVtools.Core/Objects/KernelConfiguration.cs @@ -158,7 +158,7 @@ public sealed class KernelConfiguration : BindableBase, IDisposable string text = string.Empty; for (int y = 0; y < kernel.Height; y++) { - var span = kernel.GetRowSpan(y); + var span = kernel.GetRowByteSpan(y); var line = string.Empty; for (int x = 0; x < span.Length; x++) { diff --git a/UVtools.Core/Operations/OperationInfill.cs b/UVtools.Core/Operations/OperationInfill.cs index e28a9d7..a40136f 100644 --- a/UVtools.Core/Operations/OperationInfill.cs +++ b/UVtools.Core/Operations/OperationInfill.cs @@ -442,7 +442,7 @@ public sealed class OperationInfill : Operation for (int y = 0; y < patternMask.Height; y++) { - var span = patternMask.GetRowSpan(y); + var span = patternMask.GetRowByteSpan(y); var yy = y * scaleY; // y position of pixel for (int x = 0; x < patternMask.Width; x++) { diff --git a/UVtools.Core/UVtools.Core.csproj b/UVtools.Core/UVtools.Core.csproj index 77c2f73..1911bc5 100644 --- a/UVtools.Core/UVtools.Core.csproj +++ b/UVtools.Core/UVtools.Core.csproj @@ -10,7 +10,7 @@ https://github.com/sn4k3/UVtools https://github.com/sn4k3/UVtools MSLA/DLP, file analysis, calibration, repair, conversion and manipulation - 3.12.1 + 3.12.2 Copyright © 2020 PTRTECH UVtools.png AnyCPU;x64 diff --git a/UVtools.WPF/Extensions/BitmapExtension.cs b/UVtools.WPF/Extensions/BitmapExtension.cs index ed63ebe..063938b 100644 --- a/UVtools.WPF/Extensions/BitmapExtension.cs +++ b/UVtools.WPF/Extensions/BitmapExtension.cs @@ -223,7 +223,7 @@ public static class BitmapExtension Parallel.For(0, height, y => { var spanBitmap = lockBuffer.GetPixelRowSpan(y); - var spanMat = mat.GetRowSpan(y); + var spanMat = mat.GetRowByteSpan(y); for (var x = 0; x < width; x++) { var color = spanMat[x]; @@ -237,7 +237,7 @@ public static class BitmapExtension Parallel.For(0, height, y => { var spanBitmap = lockBuffer.GetPixelRowSpan(y); - var spanMat = mat.GetRowSpan(y); + var spanMat = mat.GetRowByteSpan(y); int pixel = 0; for (var x = 0; x < width; x++) { @@ -252,7 +252,7 @@ public static class BitmapExtension Parallel.For(0, height, y => { var spanBitmap = lockBuffer.GetPixelRowSpan(y); - var spanMat = mat.GetRowSpan(y); + var spanMat = mat.GetRowByteSpan(y); int pixel = 0; for (var x = 0; x < width; x++) { diff --git a/UVtools.WPF/UVtools.WPF.csproj b/UVtools.WPF/UVtools.WPF.csproj index 76fac1f..9574e0c 100644 --- a/UVtools.WPF/UVtools.WPF.csproj +++ b/UVtools.WPF/UVtools.WPF.csproj @@ -12,7 +12,7 @@ LICENSE https://github.com/sn4k3/UVtools Git - 3.12.1 + 3.12.2 AnyCPU;x64 UVtools.png README.md @@ -43,14 +43,14 @@ portable - - - - + + + + - - - + + + diff --git a/documentation/UVtools.Core.xml b/documentation/UVtools.Core.xml index 251151b..606544d 100644 --- a/documentation/UVtools.Core.xml +++ b/documentation/UVtools.Core.xml @@ -572,6 +572,18 @@ + + + Gets the whole data span to manipulate or read pixels, use this when possibly using ROI + + + + + + Gets the whole data span to manipulate or read pixels, use this when possibly using ROI + + + Gets the whole data span to manipulate or read pixels @@ -585,18 +597,6 @@ - - - Gets the whole data span to manipulate or read pixels, use this when possibly using ROI - - - - - - Gets the whole data span to manipulate or read pixels, use this when possibly using ROI - - - Gets the data span to manipulate or read pixels given a length and offset @@ -637,6 +637,16 @@ + + + Gets a row span to manipulate or read pixels + + + + + + + Gets a col span to manipulate or read pixels @@ -681,7 +691,7 @@ - .Step return the original Mat step, if ROI step still from original matrix which lead to errors. + Step return the original Mat step, if ROI step still from original matrix which lead to errors. Use this to get the real step size @@ -768,6 +778,14 @@ + + + Sets a byte pixel at a position + + + + + Sets a byte pixel at a position @@ -4944,6 +4962,26 @@ Gets the bounding rectangle for the image area in millimeters + + + Gets the first pixel index on the + + + + + Gets the last pixel index on the + + + + + Gets the first pixel on the + + + + + Gets the last pixel on the + + Gets the first pixel index on this layer