/// <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 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>
        /// 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="imageHandleIccColorProfile">The image handle ICC color profile.</param>
        /// <param name="imageHandleNclxColorProfile">The image handle NCLX color profile.</param>
        internal HeifImage(SafeHeifImage image,
                           int width,
                           int height,
                           HeifIccColorProfile imageHandleIccColorProfile,
                           HeifNclxColorProfile imageHandleNclxColorProfile)
        {
            Validate.IsNotNull(image, nameof(image));

            this.image = image;
            this.cachedIccColorProfile         = imageHandleIccColorProfile;
            this.cachedNclxColorProfile        = imageHandleNclxColorProfile;
            this.fetchedColorProfilesFromImage = this.cachedIccColorProfile != null || this.cachedNclxColorProfile != 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>
        /// 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));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="HeifImage"/> class.
        /// </summary>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        /// <param name="colorspace">The color space.</param>
        /// <param name="chroma">The chroma.</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.
        /// </exception>
        /// <exception cref="HeifException">
        /// A LibHeif error occurred.
        ///
        /// -or-
        ///
        /// The LibHeif version is not supported.
        /// </exception>
        public HeifImage(int width, int height, HeifColorspace colorspace, HeifChroma chroma)
        {
            Validate.IsPositive(width, nameof(width));
            Validate.IsPositive(height, nameof(height));

            LibHeifVersion.ThrowIfNotSupported();

            var error = LibHeifNative.heif_image_create(width,
                                                        height,
                                                        colorspace,
                                                        chroma,
                                                        out this.image);

            error.ThrowIfError();
            // The caller can set a color profile after the image has been created.
            this.cachedIccColorProfile         = null;
            this.cachedNclxColorProfile        = null;
            this.fetchedColorProfilesFromImage = true;
            this.sync       = new object();
            this.Width      = width;
            this.Height     = height;
            this.Colorspace = colorspace;
            this.Chroma     = chroma;
        }
        /// <summary>
        /// Updates the cached color profiles while locked.
        /// </summary>
        /// <exception cref="HeifException">
        /// The color profile type is not supported.
        ///
        /// -or-
        ///
        /// A LibHeif error occurred.
        /// </exception>
        private void UpdateCachedColorProfilesWhileLocked()
        {
            if (LibHeifVersion.Is1Point12OrLater)
            {
                this.cachedIccColorProfile  = HeifIccColorProfile.TryCreate(this.image);
                this.cachedNclxColorProfile = HeifNclxColorProfile.TryCreate(this.image);
            }
            else
            {
                // LibHeif version 1.11 and earlier will crash when retrieving the NCLX color
                // profile if the image does not have one.
                var colorProfileType = LibHeifNative.heif_image_get_color_profile_type(this.image);

                switch (colorProfileType)
                {
                case heif_color_profile_type.None:
                    this.cachedIccColorProfile  = null;
                    this.cachedNclxColorProfile = null;
                    break;

                case heif_color_profile_type.Nclx:
                    this.cachedIccColorProfile  = null;
                    this.cachedNclxColorProfile = HeifNclxColorProfile.TryCreate(this.image);
                    break;

                case heif_color_profile_type.IccProfile:
                case heif_color_profile_type.RestrictedIcc:
                    this.cachedIccColorProfile  = HeifIccColorProfile.TryCreate(this.image);
                    this.cachedNclxColorProfile = null;
                    break;

                default:
                    throw new HeifException(Resources.ColorProfileTypeNotSupported);
                }
            }
        }
 public ImageHandleColorProfiles(HeifIccColorProfile icc, HeifNclxColorProfile nclx)
 {
     this.Icc  = icc;
     this.Nclx = nclx;
 }