/// <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);
        }
Esempio n. 7
0
        /// <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);
        }
Esempio n. 9
0
        /// <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);
        }
Esempio n. 10
0
 /// <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));
     }
 }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        /// <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);
            }
        }
Esempio n. 13
0
        private static bool CheckErrPtr(IntPtr errPtr)
        {
            var errStruct = Marshal.PtrToStructure <HeifError>(errPtr);
            var result    = errStruct.code != 0;

            LibHeifNative.HeifFreeHeifError(errPtr);
            return(result);
        }
Esempio n. 14
0
        /// <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;
 }
Esempio n. 16
0
        /// <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();
            }
        }
Esempio n. 17
0
        /// <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);
            }
        }
Esempio n. 19
0
        /// <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);
        }
Esempio n. 20
0
        /// <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);
        }
Esempio n. 23
0
        /// <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;
            }
        }
Esempio n. 24
0
        /// <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();
        }
Esempio n. 25
0
        /// <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();
            }
        }
Esempio n. 26
0
        /// <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));
        }
Esempio n. 28
0
        /// <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));
        }
Esempio n. 29
0
        /// <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();
            }
        }
Esempio n. 30
0
        /// <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));
        }