Ejemplo n.º 1
0
        /// <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);
        }
Ejemplo n.º 3
0
        /// <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);
        }
Ejemplo n.º 4
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();
            }
        }
Ejemplo n.º 5
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);
        }
Ejemplo n.º 6
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();
            }
        }
Ejemplo n.º 7
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();
            }
        }
Ejemplo n.º 8
0
        /// <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);
        }
Ejemplo n.º 9
0
        /// <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();
            }
        }
Ejemplo n.º 10
0
        /// <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);
        }
Ejemplo n.º 11
0
 internal abstract unsafe void SetImageColorProfile(SafeHeifImage image);