/// <summary> /// Function to convert the image data into a premultiplied format. /// </summary> /// <param name="baseImage">The image to convert.</param> /// <returns>A <see cref="IGorgonImage"/> containing the image data with the premultiplied alpha pixel data.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="baseImage"/> is <b>null</b>.</exception> /// <exception cref="ArgumentException">Thrown when image format is compressed.</exception> /// <remarks> /// <para> /// Use this to convert an image to a premultiplied format. This takes each Red, Green and Blue element and multiplies them by the Alpha element. /// </para> /// <para> /// If the image does not contain alpha then the method will return right away and no alterations to the image will be performed. /// </para> /// </remarks> public static IGorgonImage ConvertToPremultipliedAlpha(this IGorgonImage baseImage) { IGorgonImage newImage = null; GorgonNativeBuffer <byte> imageData = null; if (baseImage == null) { throw new ArgumentNullException(nameof(baseImage)); } if (!baseImage.FormatInfo.HasAlpha) { return(baseImage); } if (baseImage.FormatInfo.IsCompressed) { throw new ArgumentException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, baseImage.Format), nameof(baseImage)); } try { var cloneImageInfo = new GorgonImageInfo(baseImage) { HasPreMultipliedAlpha = true }; imageData = new GorgonNativeBuffer <byte>(baseImage.ImageData.Length); baseImage.ImageData.CopyTo(imageData); unsafe { newImage = new GorgonImage(cloneImageInfo, new GorgonReadOnlyPointer((void *)imageData, imageData.SizeInBytes)); int arrayOrDepth = newImage.ImageType == ImageType.Image3D ? newImage.Depth : newImage.ArrayCount; for (int mip = 0; mip < newImage.MipCount; ++mip) { for (int i = 0; i < arrayOrDepth; ++i) { IGorgonImageBuffer buffer = newImage.Buffers[mip, i]; byte *ptr = (byte *)buffer.Data; int rowPitch = buffer.PitchInformation.RowPitch; for (int y = 0; y < buffer.Height; ++y) { ImageUtilities.SetPremultipliedScanline(ptr, rowPitch, ptr, rowPitch, buffer.Format); ptr += rowPitch; } } } } newImage.CopyTo(baseImage); return(baseImage); } finally { imageData?.Dispose(); newImage?.Dispose(); } }