/// <summary> /// Create a <see cref="HeifNclxColorProfile"/> from the specified image handle. /// </summary> /// <param name="handle">The handle.</param> /// <returns>The created profile.</returns> /// <exception cref="HeifException"> /// A LibHeif error occurred. /// </exception> internal static unsafe HeifNclxColorProfile TryCreate(SafeHeifImageHandle handle) { HeifNclxColorProfile profile = null; SafeHeifNclxColorProfile safeNclxProfile = null; try { var error = LibHeifNative.heif_image_handle_get_nclx_color_profile(handle, 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> /// Gets the type identifier for the auxiliary image. /// </summary> /// <returns>The type identifier for the auxiliary image.</returns> /// <exception cref="HeifException">A LibHeif error occurred.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public string GetAuxiliaryType() { VerifyNotDisposed(); string type = string.Empty; if (this.auxiliaryImageType == AuxiliaryImageType.VendorSpecific) { var error = LibHeifNative.heif_image_handle_get_auxiliary_type(this.imageHandle, out var typePtr); error.ThrowIfError(); try { type = typePtr.GetStringValue(); } finally { LibHeifNative.heif_image_handle_free_auxiliary_types(this.imageHandle, ref typePtr); } } return(type); }
/// <summary> /// Gets the depth representation information. /// </summary> /// <param name="id">The depth image id.</param> /// <returns>The depth representation information.</returns> /// <exception cref="HeifException">A LibHeif error occurred.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public HeifDepthRepresentationInfo GetDepthRepresentationInfo(HeifItemId id) { VerifyNotDisposed(); HeifDepthRepresentationInfo depthRepresentationInfo = null; SafeDepthRepresentationInfo safeDepthRepresentationInfo = null; try { if (LibHeifNative.heif_image_handle_get_depth_image_representation_info(this.imageHandle, id, out safeDepthRepresentationInfo)) { unsafe { var info = (heif_depth_representation_info *)safeDepthRepresentationInfo.DangerousGetHandle(); depthRepresentationInfo = new HeifDepthRepresentationInfo(info); } } } finally { safeDepthRepresentationInfo?.Dispose(); } return(depthRepresentationInfo); }
/// <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); }
private static unsafe HeifIntegerEncoderParameter CreateIntegerParameter(SafeHeifEncoder encoder, heif_encoder_parameter nativeParameter, string name, bool hasDefaultValue) { int defaultValue = 0; if (hasDefaultValue) { // The error value is ignored because some encoders return an error // when getting the value of a valid command. _ = LibHeifNative.heif_encoder_get_parameter_integer(encoder, name, out defaultValue); } int minimum = 0; int maximum = 0; var error = LibHeifNative.heif_encoder_parameter_get_valid_integer_range(nativeParameter, out bool haveMinimumMaximum, ref minimum, ref maximum); error.ThrowIfError(); return(new HeifIntegerEncoderParameter(name, hasDefaultValue, defaultValue, haveMinimumMaximum, minimum, maximum)); }
/// <summary> /// Gets the meta-data bytes. /// </summary> /// <param name="id">The identifier.</param> /// <returns>The meta-data bytes.</returns> /// <exception cref="HeifException"> /// A LibHeif error occurred. /// /// -or- /// /// The meta-data block is larger than 2 GB. /// </exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public byte[] GetMetadata(HeifItemId id) { VerifyNotDisposed(); ulong size = LibHeifNative.heif_image_handle_get_metadata_size(this.imageHandle, id).ToUInt64(); if (size == 0) { return(null); } if (size > int.MaxValue) { ExceptionUtil.ThrowHeifException(Resources.MetadataBlockLargerThan2Gb); } byte[] metadata = new byte[size]; unsafe { fixed(byte *ptr = metadata) { var error = LibHeifNative.heif_image_handle_get_metadata(this.imageHandle, id, ptr); error.ThrowIfError(); } } return(metadata); }
/// <summary> /// Create a <see cref="HeifIccColorProfile"/> from the specified image handle. /// </summary> /// <param name="handle">The handle.</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(SafeHeifImageHandle handle) { HeifIccColorProfile profile = null; ulong iccProfileSize = LibHeifNative.heif_image_handle_get_raw_color_profile_size(handle).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_handle_get_raw_color_profile(handle, ptr); error.ThrowIfError(); } profile = new HeifIccColorProfile(iccProfileBytes, copyToNewArray: false); } return(profile); }
/// <summary> /// Gets a list of the thumbnail image ids. /// </summary> /// <returns>A list of the thumbnail image ids.</returns> /// <exception cref="HeifException">Could not get all of the thumbnail image ids.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public IReadOnlyList <HeifItemId> GetThumbnailImageIds() { VerifyNotDisposed(); int count = LibHeifNative.heif_image_handle_get_number_of_thumbnails(this.imageHandle); if (count == 0) { return(Array.Empty <HeifItemId>()); } var ids = new HeifItemId[count]; unsafe { fixed(HeifItemId *ptr = ids) { int filledCount = LibHeifNative.heif_image_handle_get_list_of_thumbnail_IDs(this.imageHandle, ptr, count); if (filledCount != count) { ExceptionUtil.ThrowHeifException(Resources.CannotGetAllThumbnailIds); } } } return(ids); }
/// <summary> /// Gets image color profile. /// </summary> /// <returns>The image color profile.</returns> /// <exception cref="HeifException"> /// The color profile type is not supported. /// /// -or- /// /// A LibHeif error occurred. /// </exception> private unsafe HeifColorProfile GetImageColorProfile() { HeifColorProfile profile = null; var colorProfileType = LibHeifNative.heif_image_get_color_profile_type(this.image); switch (colorProfileType) { case heif_color_profile_type.None: break; case heif_color_profile_type.Nclx: profile = new HeifNclxColorProfile(this.image); break; case heif_color_profile_type.IccProfile: case heif_color_profile_type.RestrictedIcc: profile = new HeifIccColorProfile(this.image); break; default: throw new HeifException(Resources.ColorProfileTypeNotSupported); } return(profile); }
/// <summary> /// Determines whether LibHeif has an encoder for the specified <see cref="HeifCompressionFormat"/>. /// </summary> /// <param name="format">The compression format.</param> /// <returns> /// <see langword="true" /> if LibHeif an encoder for the specified <see cref="HeifCompressionFormat"/>; /// otherwise, <see langword="false" />. /// </returns> public static bool HaveEncoder(HeifCompressionFormat format) { lock (nativeCallLock) { return(LibHeifNative.heif_have_encoder_for_format(format)); } }
internal unsafe SafeHeifDecodingOptions CreateDecodingOptions() { var decodingOptions = LibHeifNative.heif_decoding_options_alloc(); if (decodingOptions.IsInvalid) { ExceptionUtil.ThrowHeifException(Properties.Resources.HeifDecodingOptionsCreationFailed); } byte version = Marshal.ReadByte(decodingOptions.DangerousGetHandle()); if (version >= 2) { var options = (DecodeOptionsVersion2 *)decodingOptions.DangerousGetHandle(); options->ignore_transformations = (byte)(this.IgnoreTransformations ? 1 : 0); options->convert_hdr_to_8bit = (byte)(this.ConvertHdrToEightBit ? 1 : 0); } else { var options = (DecodeOptionsVersion1 *)decodingOptions.DangerousGetHandle(); options->ignore_transformations = (byte)(this.IgnoreTransformations ? 1 : 0); } return(decodingOptions); }
/// <summary> /// Gets the auxiliary image handle. /// </summary> /// <param name="id">The auxiliary image id.</param> /// <returns>The auxiliary image handle.</returns> /// <exception cref="HeifException">A LibHeif error occurred.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> /// <seealso cref="GetAuxiliaryImageIds"/> public HeifImageHandle GetAuxiliaryImage(HeifItemId id) { VerifyNotDisposed(); if (LibHeifVersion.Is1Point11OrLater) { HeifImageHandle aux = null; SafeHeifImageHandle auxSafeHandle = null; try { var error = LibHeifNative.heif_image_handle_get_auxiliary_image_handle(this.imageHandle, id, out auxSafeHandle); error.ThrowIfError(); aux = new HeifImageHandle(auxSafeHandle, this.decodeErrorHandler, AuxiliaryImageType.VendorSpecific); auxSafeHandle = null; } finally { auxSafeHandle?.Dispose(); } return(aux); } else { throw new HeifException(Resources.AuxiliaryImageAPINotSupported); } }
private static bool CheckErrPtr(IntPtr errPtr) { var errStruct = Marshal.PtrToStructure <HeifError>(errPtr); var result = errStruct.code != 0; LibHeifNative.HeifFreeHeifError(errPtr); return(result); }
/// <summary> /// Sets the lossless compression support. /// </summary> /// <param name="lossless"><c>true</c> [lossless].</param> /// <exception cref="HeifException">A LibHeif error occurred.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public void SetLossless(bool lossless) { VerifyNotDisposed(); var error = LibHeifNative.heif_encoder_set_lossless(this.encoder, lossless); error.ThrowIfError(); }
/// <summary> /// Initializes a new instance of the <see cref="HeifEncoderDescriptor"/> class. /// </summary> /// <param name="descriptor">The descriptor.</param> internal HeifEncoderDescriptor(heif_encoder_descriptor descriptor) { this.Name = LibHeifNative.heif_encoder_descriptor_get_name(descriptor).GetStringValue(); this.IdName = LibHeifNative.heif_encoder_descriptor_get_id_name(descriptor).GetStringValue(); this.CompressionFormat = LibHeifNative.heif_encoder_descriptor_get_compression_format(descriptor); this.SupportsLossyCompression = LibHeifNative.heif_encoder_descriptor_supports_lossy_compression(descriptor); this.SupportsLosslessCompression = LibHeifNative.heif_encoder_descriptor_supports_lossless_compression(descriptor); this.Descriptor = descriptor; }
/// <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> /// Sets a string encoder parameter. /// </summary> /// <param name="name">The parameter name.</param> /// <param name="value">The parameter value.</param> /// <param name="coerceParameterType"> /// <see langword="true"/> if the parameter should be coerced to the correct type; otherwise, <see langword="false"/>. /// </param> /// <exception cref="ArgumentNullException"> /// <paramref name="name"/> is null. /// /// -or- /// /// <paramref name="value"/> is null. /// </exception> /// <exception cref="HeifException"> /// A LibHeif error occurred. /// /// -or- /// /// Unable to convert the parameter to the correct type. /// </exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> private void SetStringParameter(string name, string value, bool coerceParameterType) { Validate.IsNotNull(name, nameof(name)); Validate.IsNotNull(value, nameof(value)); VerifyNotDisposed(); if (coerceParameterType) { // Some encoders expect the method that is called to match the parameter type. // Attempting to set a Boolean or Integer parameter as a string will cause an invalid parameter error. if (this.encoderParameterTypes.Value.TryGetValue(name, out var type)) { switch (type) { case HeifEncoderParameterType.Boolean: if (TryConvertStringToBoolean(value, out bool boolValue)) { SetBooleanParameter(name, boolValue); } else { throw new HeifException(string.Format(CultureInfo.CurrentCulture, Resources.CoerceStringValueToBooleanFailedFormat, nameof(value))); } return; case HeifEncoderParameterType.Integer: if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out int intValue)) { SetIntegerParameter(name, intValue); } else { throw new HeifException(string.Format(CultureInfo.CurrentCulture, Resources.CoerceStringValueToIntegerFailedFormat, nameof(value))); } return; case HeifEncoderParameterType.String: // The parameter is the correct type. break; default: throw new HeifException($"Unknown { nameof(HeifEncoderParameterType) }: { type }."); } } } var error = LibHeifNative.heif_encoder_set_parameter_string(this.encoder, name, value); error.ThrowIfError(); }
/// <summary> /// Gets a list of the meta-data block ids. /// </summary> /// <param name="type">The meta-data block type.</param> /// <param name="contentType">The meta-data block content type.</param> /// <returns>A list of the meta-data block ids.</returns> /// <exception cref="HeifException">Could not get all of the meta-data block ids.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public IReadOnlyList <HeifItemId> GetMetadataBlockIds(string type = null, string contentType = null) { VerifyNotDisposed(); int count = LibHeifNative.heif_image_handle_get_number_of_metadata_blocks(this.imageHandle, type); if (count == 0) { return(Array.Empty <HeifItemId>()); } var ids = new HeifItemId[count]; unsafe { fixed(HeifItemId *ptr = ids) { int filledCount = LibHeifNative.heif_image_handle_get_list_of_metadata_block_IDs(this.imageHandle, type, ptr, count); if (filledCount != count) { ExceptionUtil.ThrowHeifException(Resources.CannotGetAllMetadataBlockIds); } } } // The type must be defined in order to filter by content type. if (type != null && contentType != null) { var matchingItems = new List <HeifItemId>(); for (int i = 0; i < ids.Length; i++) { var id = ids[i]; var metadataContentType = LibHeifNative.heif_image_handle_get_metadata_content_type(this.imageHandle, id); if (contentType.Equals(metadataContentType.GetStringValue(), StringComparison.Ordinal)) { matchingItems.Add(id); } } return(matchingItems); } else { return(ids); } }
/// <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 encoder lossy quality. /// </summary> /// <param name="quality">The quality.</param> /// <exception cref="ArgumentOutOfRangeException">The quality parameter is not in the range of [0, 100] inclusive.</exception> /// <exception cref="HeifException">A LibHeif error occurred.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public void SetLossyQuality(int quality) { if (quality < 0 || quality > 100) { ExceptionUtil.ThrowArgumentOutOfRangeException(nameof(quality), "Must be in the range of [0, 100]."); } VerifyNotDisposed(); var error = LibHeifNative.heif_encoder_set_lossy_quality(this.encoder, quality); error.ThrowIfError(); }
private static HeifBooleanEncoderParameter CreateBooleanParameter(SafeHeifEncoder encoder, string name, bool hasDefaultValue) { bool defaultValue = false; if (hasDefaultValue) { // The error value is ignored because some encoders return an error // when getting the value of a valid command. _ = LibHeifNative.heif_encoder_get_parameter_boolean(encoder, name, out defaultValue); } return(new HeifBooleanEncoderParameter(name, hasDefaultValue, defaultValue)); }
/// <summary> /// Creates the encoding options. /// </summary> /// <returns>The encoding options.</returns> /// <exception cref="HeifException">Unable to create the native HeifEncodingOptions.</exception> internal unsafe SafeHeifEncodingOptions CreateEncodingOptions() { var encodingOptions = LibHeifNative.heif_encoding_options_alloc(); if (encodingOptions.IsInvalid) { ExceptionUtil.ThrowHeifException(Properties.Resources.HeifEncodingOptionsCreationFailed); } var options = (EncodingOptionsVersion1 *)encodingOptions.DangerousGetHandle(); options->save_alpha_channel = (byte)(this.SaveAlphaChannel ? 1 : 0); return(encodingOptions); }
/// <summary> /// Sets the lossless compression support. /// </summary> /// <param name="lossless"> /// <see langword="true"/> if the encoder should use lossless compression; otherwise, <see langword="false"/>. /// </param> /// <exception cref="HeifException">A LibHeif error occurred.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public void SetLossless(bool lossless) { VerifyNotDisposed(); var error = LibHeifNative.heif_encoder_set_lossless(this.encoder, lossless); error.ThrowIfError(); if (lossless && !this.lossyQualitySet) { // LibHeif requires the lossy quality to be always be set, if it has // not been set the encoder will produce a corrupted image. error = LibHeifNative.heif_encoder_set_lossy_quality(this.encoder, 50); error.ThrowIfError(); this.lossyQualitySet = true; } }
/// <summary> /// Adds a plane to the image. /// </summary> /// <param name="channel">The channel.</param> /// <param name="width">The width.</param> /// <param name="height">The height.</param> /// <param name="bitDepth">The bit depth.</param> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="width"/> is less than or equal to zero. /// /// -or- /// /// <paramref name="height"/> is less than or equal to zero. /// /// -or- /// /// <paramref name="bitDepth"/> is less than or equal to zero. /// </exception> /// <exception cref="HeifException">A LibHeif error occurred.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public void AddPlane(HeifChannel channel, int width, int height, int bitDepth) { Validate.IsPositive(width, nameof(width)); Validate.IsPositive(height, nameof(height)); Validate.IsPositive(bitDepth, nameof(bitDepth)); VerifyNotDisposed(); var error = LibHeifNative.heif_image_add_plane(this.image, channel, width, height, bitDepth); error.ThrowIfError(); }
/// <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> /// Gets the encoder parameter list. /// </summary> /// <returns>The encoder parameter list.</returns> /// <exception cref="HeifException">An error occurred when creating the encoder parameter.</exception> private unsafe ReadOnlyCollection <IHeifEncoderParameter> GetEncoderParameterList() { var encoderParameters = new List <IHeifEncoderParameter>(); var parameterList = LibHeifNative.heif_encoder_list_parameters(this.encoder); if (parameterList.Value != IntPtr.Zero) { var encoderParameter = (heif_encoder_parameter *)parameterList.Value; while (*encoderParameter != heif_encoder_parameter.Null) { encoderParameters.Add(HeifEncoderParameterFactory.Create(this.encoder, *encoderParameter)); encoderParameter++; } } return(encoderParameters.AsReadOnly()); }
private static unsafe HeifStringEncoderParameter CreateStringParameter(SafeHeifEncoder encoder, heif_encoder_parameter nativeParameter, string name, bool hasDefaultValue) { string defaultValue = string.Empty; if (hasDefaultValue) { byte[] bytes = new byte[256]; fixed(byte *ptr = bytes) { // The error value is ignored because some encoders return an error // when getting the value of a valid command. _ = LibHeifNative.heif_encoder_get_parameter_string(encoder, name, ptr, bytes.Length); } int count = bytes.Length; // Look for the NUL terminator at the end of the string. for (int i = 0; i < bytes.Length; i++) { if (bytes[i] == 0) { count = i; break; } } defaultValue = System.Text.Encoding.ASCII.GetString(bytes, 0, count); } var error = LibHeifNative.heif_encoder_parameter_get_valid_string_values(nativeParameter, out var stringArray); error.ThrowIfError(); var validItems = stringArray.ToReadOnlyCollection(); return(new HeifStringEncoderParameter(name, hasDefaultValue, defaultValue, validItems)); }
/// <summary> /// Gets the image data for the specified plane. /// </summary> /// <param name="channel">The channel.</param> /// <returns>The image plane data.</returns> /// <exception cref="HeifException">The image does not contain the specified channel.</exception> /// <exception cref="ObjectDisposedException">The object has been disposed.</exception> public HeifPlaneData GetPlane(HeifChannel channel) { VerifyNotDisposed(); if (!LibHeifNative.heif_image_has_channel(this.image, channel)) { ExceptionUtil.ThrowHeifException(Resources.ImageDoesNotContainChannel); } int width = LibHeifNative.heif_image_get_width(this.image, channel); int height = LibHeifNative.heif_image_get_height(this.image, channel); var scan0 = LibHeifNative.heif_image_get_plane(this.image, channel, out int stride); if (scan0 == IntPtr.Zero || width == -1 || height == -1) { ExceptionUtil.ThrowHeifException(Resources.ImageDoesNotContainChannel); } return(new HeifPlaneData(width, height, stride, channel, scan0)); }
/// <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> /// Gets image handle color profiles. /// </summary> /// <returns>The image handle color profiles.</returns> /// <exception cref="HeifException"> /// The color profile type is not supported. /// /// -or- /// /// A LibHeif error occurred. /// </exception> private unsafe ImageHandleColorProfiles GetImageHandleColorProfiles() { HeifIccColorProfile iccProfile; HeifNclxColorProfile nclxProfile; if (LibHeifVersion.Is1Point10OrLater) { iccProfile = HeifIccColorProfile.TryCreate(this.imageHandle); nclxProfile = HeifNclxColorProfile.TryCreate(this.imageHandle); } else { // LibHeif versions prior to 1.10 only support one color profile per image. var colorProfileType = LibHeifNative.heif_image_handle_get_color_profile_type(this.imageHandle); switch (colorProfileType) { case heif_color_profile_type.None: iccProfile = null; nclxProfile = null; break; case heif_color_profile_type.Nclx: iccProfile = null; nclxProfile = HeifNclxColorProfile.TryCreate(this.imageHandle); break; case heif_color_profile_type.IccProfile: case heif_color_profile_type.RestrictedIcc: iccProfile = HeifIccColorProfile.TryCreate(this.imageHandle); nclxProfile = null; break; default: throw new HeifException(Resources.ColorProfileTypeNotSupported); } } return(new ImageHandleColorProfiles(iccProfile, nclxProfile)); }