17public class Image : IDisposable, IHasSafeHandle
19 private readonly uint _bufferSize;
20 internal readonly Handle _handle;
21 SafeHandle IHasSafeHandle.Handle => _handle;
24 internal Image(Handle handle)
28 var cImageInfo =
new Backend.Types.peak_icv_image_info();
29 DllHelper.ExecuteAndMapReturnCodes(() =>
30 CInterface.peak_icv_Image_GetInfo(_handle, out cImageInfo,
31 (nuint) Marshal.SizeOf(cImageInfo)));
33 Size =
new Size(cImageInfo.size.width, cImageInfo.size.height);
36 _bufferSize = (uint) cImageInfo.bufferSize;
37 Data = cImageInfo.buffer;
90 CreateFromBuffer(pixelFormat, imageSize, buffer, bufferSize))
142 public Image(
string filePath) : this(CreateFromFile(filePath))
200 public Image(
string filePath,
PixelFormat pixelFormat) : this(CreateFromFile(filePath, pixelFormat))
205 : this(new Handle(other._handle.DangerousGetHandle()))
207 DllHelper.ExecuteAndMapReturnCodes(() =>
208 CInterface.peak_icv_Image_IncreaseUseCount(_handle));
210 _metadata = other._metadata;
257 if (_metadata !=
null)
262 var cCaptureInformation =
new Backend.Types.peak_icv_capture_information();
263 DllHelper.ExecuteAndMapReturnCodes(() =>
264 CInterface.peak_icv_Image_GetCaptureInformation(_handle, out cCaptureInformation,
265 (nuint) Marshal.SizeOf(cCaptureInformation)));
267 _metadata = CaptureInformation.ToMetadata(cCaptureInformation);
269 _metadata.Changed += (_, _) =>
271 Backend.Types.peak_icv_capture_information cCaptureInformation =
272 CaptureInformation.FromMetadata(_metadata,
Size);
273 CInterface.peak_icv_Image_SetCaptureInformation(_handle, cCaptureInformation,
274 (nuint) Marshal.SizeOf(cCaptureInformation));
282 Backend.Types.peak_icv_capture_information cCaptureInformation =
283 CaptureInformation.FromMetadata(value,
Size);
285 DllHelper.ExecuteAndMapReturnCodes(() =>
286 CInterface.peak_icv_Image_SetCaptureInformation(_handle, cCaptureInformation,
287 (nuint) Marshal.SizeOf(cCaptureInformation)));
289 _metadata = value.
Clone();
290 CaptureInformation.MergeWithMetadata(cCaptureInformation, _metadata);
304 var region =
new Region();
305 DllHelper.ExecuteAndMapReturnCodes(() =>
306 CInterface.peak_icv_Image_GetRegion(_handle, ref region._handle));
310 set { DllHelper.ExecuteAndMapReturnCodes(() => CInterface.peak_icv_Image_SetRegion(_handle, value._handle)); }
320 GC.SuppressFinalize(
this);
329 DllHelper.ExecuteAndMapReturnCodes(() => CInterface.peak_icv_Image_ResetRegion(_handle));
341 Buffer.MemoryCopy((
void*)
Data, (
void*) image.Data, (
int) _bufferSize, (
int) _bufferSize);
390 var outputImage =
new Image(pixelFormat,
Size);
391 DllHelper.ExecuteAndMapReturnCodes(() =>
392 CInterface.peak_icv_Image_ConvertPixelFormat(_handle, pixelFormat,
393 outputImage._handle));
422 var outputImage =
new Image(pixelFormat,
Size);
423 DllHelper.ExecuteAndMapReturnCodes(() =>
424 CInterface.peak_icv_Image_ConvertPixelFormatWithFactor(_handle, pixelFormat, factor,
425 outputImage._handle));
452 DllHelper.ExecuteAndMapReturnCodes(() =>
453 CInterface.peak_icv_Image_Subtract(_handle, subtrahend._handle,
454 outputImage._handle));
478 return minuend.
Subtract(subtrahend);
481 private static Handle CreateFromSize(
PixelFormat pixelFormat,
Size imageSize)
483 var imageHandle =
new Handle();
484 DllHelper.ExecuteAndMapReturnCodes(() => CInterface.peak_icv_Image_Create(out imageHandle,
485 pixelFormat,
new Backend.Types.peak_common_size
486 { width = imageSize.Width, height = imageSize.Height }));
491 private static Handle CreateFromBuffer(
PixelFormat pixelFormat,
Size imageSize, IntPtr buffer, nuint bufferSize)
493 var imageHandle =
new Handle();
495 var imageInfo =
new Backend.Types.peak_icv_image_info
497 pixelFormat = pixelFormat,
498 size =
new Backend.Types.peak_common_size { width = imageSize.
Width, height = imageSize.Height },
499 bufferSize = bufferSize,
502 DllHelper.ExecuteAndMapReturnCodes(() =>
503 CInterface.peak_icv_Image_CreateFromImageInfo(out imageHandle, imageInfo,
504 (nuint) Marshal.SizeOf(imageInfo)));
509 private static Handle CreateFromFile(
string filePath)
511 var imageHandle =
new Handle();
512 DllHelper.ExecuteAndMapReturnCodes(() =>
513 CInterface.peak_icv_Image_CreateFromFile(out imageHandle, Utils.ToUtf8(filePath)));
518 private static Handle CreateFromFile(
string filePath,
PixelFormat forcePixelFormat)
520 var imageHandle =
new Handle();
521 DllHelper.ExecuteAndMapReturnCodes(() =>
522 CInterface.peak_icv_Image_CreateFromFileWithPixelFormat(out imageHandle, Utils.ToUtf8(filePath),
528 private static Handle CreateFromImageView(
IImageView imageView)
530 Size imageViewSize = imageView.
Size;
535 if (lineStartOffset == 0 && validBytesPerLine == imageView.
BytesPerLine)
540 Handle handle = CreateFromSize(imageView.
PixelFormat, imageViewSize);
544 DllHelper.ExecuteAndMapReturnCodes(() =>
545 CInterface.peak_icv_Buffer_CutBytes(imageView.
Data, lineStartOffset, imageView.
BytesPerLine,
546 validBytesPerLine, imageViewSize.
Height, handle));
557 private sealed class ImageEqualityComparer : IEqualityComparer<Image>
559 public bool Equals(Image x, Image y)
561 if (ReferenceEquals(x, y))
566 if (ReferenceEquals(x,
null))
571 if (ReferenceEquals(y,
null))
577 DllHelper.ExecuteAndMapReturnCodes(() =>
578 CInterface.peak_icv_Image_Compare(x._handle, y._handle, out isEqual));
583 public int GetHashCode(Image obj)
585 var width = obj.Size.Width;
586 var height = obj.Size.Height;
590 var ptr = (
byte*) obj.Data;
593 var p2 = ptr[width - 1];
594 var p3 = ptr[height / 2 + width / 2];
595 var p4 = ptr[height - 1];
596 var p5 = ptr[height - 1 + (width - 1)];
598 return (obj.Size, obj.PixelFormat, p1, p2, p3, p4, p5).GetHashCode();
607 public static IEqualityComparer<Image>
Comparer {
get; } =
new ImageEqualityComparer();
622 nuint numOutputImages = 0;
624 DllHelper.ExecuteAndMapReturnCodes(() =>
625 CInterface.peak_icv_Image_Deinterleave_GetOutputImageCount(
PixelFormat, ref numOutputImages));
629 DllHelper.ExecuteAndMapReturnCodes(() =>
630 CInterface.peak_icv_Image_Deinterleave_GetOutputPixelFormat(
PixelFormat, ref pixelFormat));
632 var cInputImageSize =
new Backend.Types.peak_common_size { width =
Size.
Width, height = Size.Height };
633 var cOutputImageSize =
new Backend.Types.peak_common_size();
635 DllHelper.ExecuteAndMapReturnCodes(() =>
636 CInterface.peak_icv_Image_Deinterleave_GetOutputImageSize(
PixelFormat, cInputImageSize,
637 out cOutputImageSize));
639 var outputImages =
new List<Image>();
640 for (var i = 0; i < (int) numOutputImages; i++)
642 outputImages.Add(
new Image(pixelFormat,
new Size(cOutputImageSize.width, cOutputImageSize.height)));
645 IntPtr[] outputHandles = SafeHandles.ExtractHandles(
651 DllHelper.ExecuteAndMapReturnCodes(() =>
652 CInterface.peak_icv_Image_Deinterleave(_handle, outputHandles, (nuint) outputHandles.Length));
662 internal sealed class Handle : SafeHandleZeroOrMinusOneIsInvalid
664 public Handle() : base(true)
668 public Handle(IntPtr handle) : base(true)
673 protected override bool ReleaseHandle()
675 return CInterface.peak_icv_Image_Destroy(handle) ==
676 Backend.Types.peak_icv_status.PEAK_ICV_STATUS_SUCCESS;
680 private static class CInterface
682 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
683 public static extern Backend.Types.peak_icv_status peak_icv_Image_SetRegion(Handle image_handle,
684 Region.Handle region_handle);
686 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
687 public static extern Backend.Types.peak_icv_status peak_icv_Image_ResetRegion(Handle image_handle);
689 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
690 public static extern Backend.Types.peak_icv_status peak_icv_Image_Create(out Handle image_handle,
691 PixelFormat pixel_format, Backend.Types.peak_common_size image_size);
693 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
694 public static extern Backend.Types.peak_icv_status peak_icv_Image_CreateFromImageInfo(
695 out Handle image_handle,
696 Backend.Types.peak_icv_image_info image_info, nuint image_info_size);
698 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
699 public static extern Backend.Types.peak_icv_status peak_icv_Image_GetInfo(Handle image_handle,
700 out Backend.Types.peak_icv_image_info image_info, nuint image_info_size);
702 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
703 public static extern Backend.Types.peak_icv_status peak_icv_Image_GetRegion(
704 Handle image_handle, ref Region.Handle region_handle);
706 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
707 public static extern Backend.Types.peak_icv_status peak_icv_Image_Destroy(IntPtr image_handle);
709 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
710 public static extern Backend.Types.peak_icv_status peak_icv_Image_SetCaptureInformation(Handle image_handle,
711 Backend.Types.peak_icv_capture_information capture_information, nuint capture_information_size);
713 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
714 public static extern Backend.Types.peak_icv_status peak_icv_Image_GetCaptureInformation(Handle image_handle,
715 out Backend.Types.peak_icv_capture_information capture_information, nuint capture_information_size);
717 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
718 public static extern Backend.Types.peak_icv_status peak_icv_Image_Compare(Handle image_handle_lhs,
719 Handle image_handle_rhs, [MarshalAs(UnmanagedType.I1)] out
bool is_equal);
721 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
722 public static extern Backend.Types.peak_icv_status peak_icv_Image_IncreaseUseCount(Handle image_handle);
724 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
725 public static extern Backend.Types.peak_icv_status peak_icv_Image_CreateFromFile(out Handle image_handle,
728 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
729 public static extern Backend.Types.peak_icv_status peak_icv_Image_ConvertPixelFormat(Handle input_handle,
732 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
733 public static extern Backend.Types.peak_icv_status peak_icv_Image_ConvertPixelFormatWithFactor(
735 PixelFormat pixel_format,
double factor, Handle output_handle);
737 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
738 public static extern Backend.Types.peak_icv_status peak_icv_Image_Subtract(Handle input_handle,
739 Handle subtrahend_handle, Handle output_handle);
741 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
742 public static extern Backend.Types.peak_icv_status peak_icv_Image_CreateFromFileWithPixelFormat(
743 out Handle image_handle,
746 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
747 public static extern Backend.Types.peak_icv_status peak_icv_Image_Deinterleave_GetOutputImageCount(
748 PixelFormat input_pixel_format, ref nuint output_image_count);
750 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
751 public static extern Backend.Types.peak_icv_status peak_icv_Image_Deinterleave_GetOutputPixelFormat(
754 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
755 public static extern Backend.Types.peak_icv_status peak_icv_Image_Deinterleave_GetOutputImageSize(
756 PixelFormat input_pixel_format, Backend.Types.peak_common_size input_image_size,
757 out Backend.Types.peak_common_size output_image_size);
759 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
760 public static extern Backend.Types.peak_icv_status peak_icv_Image_Deinterleave(
761 Handle input_image_handle, IntPtr[] output_image_handles, nuint output_image_count);
763 [DllImport(Global.LibraryName, CallingConvention = Global.CallingConvention)]
764 public static extern Backend.Types.peak_icv_status peak_icv_Buffer_CutBytes(IntPtr data,
765 nuint line_start_offset, nuint bytes_per_line, nuint valid_bytes_per_line, nuint number_of_lines,
766 Handle output_image_handle);