/// <summary> /// Decodes this instance to a <see cref="HeifImage"/>. /// </summary> /// <param name="colorspace">The destination image color space.</param> /// <param name="chroma">The chroma.</param> /// <param name="options">The decoding options.</param> /// <returns>The decoded image.</returns> /// <exception cref="HeifException"> /// A LibHeif error occurred. /// /// -or- /// /// The color profile type is not supported. /// </exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public HeifImage Decode(HeifColorspace colorspace, HeifChroma chroma, HeifDecodingOptions options = null) { VerifyNotDisposed(); HeifImage image = null; SafeHeifImage safeHeifImage = null; var imageHandleColorProfile = GetImageHandleColorProfile(); try { heif_error error; if (options != null) { using (var safeHeifDecodingOptions = options.CreateDecodingOptions()) { error = LibHeifNative.heif_decode_image(this.imageHandle, out safeHeifImage, colorspace, chroma, safeHeifDecodingOptions); } } else { error = LibHeifNative.heif_decode_image(this.imageHandle, out safeHeifImage, colorspace, chroma, IntPtr.Zero); } if (error.IsError) { if (this.decodeErrorHandler != null) { this.decodeErrorHandler.Invoke(error); } else { error.ThrowIfError(); } } // Passing the image handle width and height works around a bug with the // heif_image_get_primary_height method in some versions of libheif. image = new HeifImage(safeHeifImage, this.Width, this.Height, imageHandleColorProfile); safeHeifImage = null; } finally { safeHeifImage?.Dispose(); } return(image); }
/// <summary> /// Create a <see cref="HeifNclxColorProfile"/> from the specified image. /// </summary> /// <param name="image">The image.</param> /// <returns>The created profile.</returns> /// <exception cref="HeifException"> /// A LibHeif error occurred. /// </exception> internal static unsafe HeifNclxColorProfile TryCreate(SafeHeifImage image) { HeifNclxColorProfile profile = null; SafeHeifNclxColorProfile safeNclxProfile = null; try { var error = LibHeifNative.heif_image_get_nclx_color_profile(image, out safeNclxProfile); if (error.ErrorCode == heif_error_code.Ok) { var nclxProfileV1 = (heif_nclx_color_profile_v1 *)safeNclxProfile.DangerousGetHandle(); profile = new HeifNclxColorProfile(nclxProfileV1->colorPrimaries, nclxProfileV1->transferCharacteristics, nclxProfileV1->matrixCoefficients, nclxProfileV1->fullRange != 0); } else { if (!LibHeifVersion.Is1Point10OrLater || error.ErrorCode != heif_error_code.Color_profile_does_not_exist) { error.ThrowIfError(); } } } finally { safeNclxProfile?.Dispose(); } return(profile); }
/// <summary> /// Create a <see cref="HeifIccColorProfile"/> from the specified image. /// </summary> /// <param name="image">The image.</param> /// <returns>The created profile.</returns> /// <exception cref="HeifException"> /// A LibHeif error occurred. /// /// -or- /// /// The ICC profile is larger than 2 GB. /// </exception> internal static unsafe HeifIccColorProfile TryCreate(SafeHeifImage image) { HeifIccColorProfile profile = null; ulong iccProfileSize = LibHeifNative.heif_image_get_raw_color_profile_size(image).ToUInt64(); if (iccProfileSize > 0) { if (iccProfileSize > int.MaxValue) { ExceptionUtil.ThrowHeifException(Resources.IccProfileLargerThan2Gb); } byte[] iccProfileBytes = new byte[iccProfileSize]; fixed(byte *ptr = iccProfileBytes) { var error = LibHeifNative.heif_image_get_raw_color_profile(image, ptr); error.ThrowIfError(); } profile = new HeifIccColorProfile(iccProfileBytes, copyToNewArray: false); } return(profile); }
/// <summary> /// Sets the image color profile. /// </summary> /// <param name="image">The image.</param> /// <exception cref="HeifException">A LibHeif error occurred.</exception> internal override unsafe void SetImageColorProfile(SafeHeifImage image) { fixed(byte *ptr = this.iccProfileBytes) { var profileSize = new UIntPtr((uint)this.iccProfileBytes.Length); var error = LibHeifNative.heif_image_set_raw_color_profile(image, "prof", ptr, profileSize); error.ThrowIfError(); } }
/// <summary> /// Initializes a new instance of the <see cref="HeifImage" /> class. /// </summary> /// <param name="image">The image.</param> /// <param name="width">The width.</param> /// <param name="height">The height.</param> /// <param name="imageHandleColorProfile">The image handle color profile.</param> internal HeifImage(SafeHeifImage image, int width, int height, HeifColorProfile imageHandleColorProfile) { Validate.IsNotNull(image, nameof(image)); this.image = image; this.cachedImageColorProfile = imageHandleColorProfile; this.fetchedColorProfileFromImage = this.cachedImageColorProfile != null; this.sync = new object(); this.Width = width; this.Height = height; this.Colorspace = LibHeifNative.heif_image_get_colorspace(image); this.Chroma = LibHeifNative.heif_image_get_chroma_format(image); }
/// <summary> /// Sets the image color profile. /// </summary> /// <param name="image">The image.</param> /// <exception cref="HeifException"> /// The native NCLX profile creation failed. /// /// -or- /// /// A LibHeif error occurred. /// </exception> internal override unsafe void SetImageColorProfile(SafeHeifImage image) { using (var safeNclxProfile = LibHeifNative.heif_nclx_color_profile_alloc()) { if (safeNclxProfile.IsInvalid) { throw new HeifException(Properties.Resources.NclxProfileCreationFailed); } var nclxProfileV1 = (heif_nclx_color_profile_v1 *)safeNclxProfile.DangerousGetHandle(); nclxProfileV1->colorPrimaries = this.ColorPrimaries; nclxProfileV1->transferCharacteristics = this.TransferCharacteristics; nclxProfileV1->matrixCoefficients = this.MatrixCoefficients; nclxProfileV1->fullRange = (byte)(this.FullRange ? 1 : 0); var error = LibHeifNative.heif_image_set_nclx_color_profile(image, safeNclxProfile); error.ThrowIfError(); } }
/// <summary> /// Initializes a new instance of the <see cref="HeifNclxColorProfile"/> class. /// </summary> /// <param name="image">The image.</param> /// <exception cref="HeifException">A LibHeif error occurred.</exception> internal unsafe HeifNclxColorProfile(SafeHeifImage image) : base(ColorProfileType.Nclx) { SafeHeifNclxColorProfile safeNclxProfile = null; try { var error = LibHeifNative.heif_image_get_nclx_color_profile(image, out safeNclxProfile); error.ThrowIfError(); var nclxProfileV1 = (heif_nclx_color_profile_v1 *)safeNclxProfile.DangerousGetHandle(); this.ColorPrimaries = nclxProfileV1->colorPrimaries; this.TransferCharacteristics = nclxProfileV1->transferCharacteristics; this.MatrixCoefficients = nclxProfileV1->matrixCoefficients; this.FullRange = nclxProfileV1->fullRange != 0; } finally { safeNclxProfile?.Dispose(); } }
/// <summary> /// Scales the image. /// </summary> /// <param name="newWidth">The new width.</param> /// <param name="newHeight">The new height.</param> /// <returns>The scaled image.</returns> /// <exception cref="HeifException">A LibHeif error occurred.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public HeifImage ScaleImage(int newWidth, int newHeight) { VerifyNotDisposed(); HeifImage scaledImage = null; SafeHeifImage safeHeifImage = null; try { var error = LibHeifNative.heif_image_scale_image(this.image, out safeHeifImage, newWidth, newHeight, IntPtr.Zero); error.ThrowIfError(); scaledImage = new HeifImage(safeHeifImage, newWidth, newHeight, this.cachedImageColorProfile); safeHeifImage = null; } finally { safeHeifImage?.Dispose(); } return(scaledImage); }
/// <summary> /// Initializes a new instance of the <see cref="HeifIccColorProfile"/> class. /// </summary> /// <param name="image">The image.</param> /// <exception cref="HeifException"> /// A LibHeif error occurred. /// /// -or- /// /// The ICC profile is zero bytes. /// /// -or- /// /// The ICC profile is larger than 2 GB. /// </exception> internal unsafe HeifIccColorProfile(SafeHeifImage image) : base(ColorProfileType.Icc) { ulong iccProfileSize = LibHeifNative.heif_image_get_raw_color_profile_size(image).ToUInt64(); if (iccProfileSize == 0) { ExceptionUtil.ThrowHeifException(Resources.IccProfileZeroBytes); } else if (iccProfileSize > int.MaxValue) { ExceptionUtil.ThrowHeifException(Resources.IccProfileLargerThan2Gb); } this.iccProfileBytes = new byte[iccProfileSize]; fixed(byte *ptr = this.iccProfileBytes) { var error = LibHeifNative.heif_image_get_raw_color_profile(image, ptr); error.ThrowIfError(); } }
/// <summary> /// Scales the image. /// </summary> /// <param name="newWidth">The new width.</param> /// <param name="newHeight">The new height.</param> /// <returns>The scaled image.</returns> /// <exception cref="HeifException">A LibHeif error occurred.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public HeifImage ScaleImage(int newWidth, int newHeight) { VerifyNotDisposed(); if (!this.fetchedColorProfilesFromImage) { lock (this.sync) { if (!this.fetchedColorProfilesFromImage) { UpdateCachedColorProfilesWhileLocked(); this.fetchedColorProfilesFromImage = true; } } } HeifImage scaledImage = null; SafeHeifImage safeHeifImage = null; try { var error = LibHeifNative.heif_image_scale_image(this.image, out safeHeifImage, newWidth, newHeight, IntPtr.Zero); error.ThrowIfError(); scaledImage = new HeifImage(safeHeifImage, newWidth, newHeight, this.cachedIccColorProfile, this.cachedNclxColorProfile); safeHeifImage = null; } finally { safeHeifImage?.Dispose(); } return(scaledImage); }
internal abstract unsafe void SetImageColorProfile(SafeHeifImage image);