Write Extra Channel With Display Info

TIFF Extra Channels Adobe Resources Write Pipeline

Saves extra channels with display info to Adobe Resources.

Сode Snippet

public enum DisplayInfoMode
{
    Alpha = 0,
    InvertedAlpha = 1,
    Spot = 2,
}

public enum AdobeColorSpace
{
    RGB = 0,
    CMYK = 2,
    LAB = 7,
    Grayscale = 8,
}

public static void Run()
{
    var imageSize = new System.Drawing.Size(1000, 1000);

    using (var bitmap = new Bitmap(imageSize.Width, imageSize.Height, PixelFormat.Format8bppGrayscale, RgbColor.White))
    using (var tiffWriter = new TiffWriter("AdobeResourcesWithDisplayInfo.tif"))
    {
        var colors = new Color[]
        {
            RgbColor.Violet,
            new CmykColor(255, 0, 0, 0),
            new LabColor(140, 62, -39),
            new GrayscaleColor(222),
        };

        foreach (var color in colors)
        {
            tiffWriter.ExtraChannels.Add(new TiffExtraChannelEntry(CreateEllipse(imageSize), TiffChannelType.Color));
        }

        const byte solidity = 50;

        var displayInfoBlock = CreateDisplayInfoBlock(colors, solidity);

        tiffWriter.AdobeResources = new AdobeResourceDictionary();

        // https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/
        const int displayInfo = 0x0435;

        tiffWriter.AdobeResources.Add(displayInfo, displayInfoBlock);

        Pipeline.Run(bitmap + tiffWriter);
    }
}

public static Bitmap CreateEllipse(System.Drawing.Size size)
{
    var bitmap = new Bitmap(size.Width, size.Height, PixelFormat.Format8bppGrayscale);

    var fillRect = new System.Drawing.Rectangle(new System.Drawing.Point(0, 0), size);

    using (var gr = bitmap.GetAdvancedGraphics())
    {
        bitmap.Fill(RgbColor.White);
        gr.FillEllipse(new SolidBrush(RgbColor.Black), fillRect);
    }

    return bitmap;
}

public static AdobeResourceBlock CreateDisplayInfoBlock(Color[] colors, byte solidity)
{
    if (solidity < 0 || solidity > 100)
    {
        throw new System.ArgumentOutOfRangeException("solidity");
    }

    List<byte> blockData = new List<byte>();
    blockData.AddRange(new byte[] { 0, 0, 0, 1 });

    foreach (var c in colors)
    {
        switch (c.ColorSpace)
        {
            case ColorSpace.Rgb:
                {
                    var color = c as RgbColor;
                    blockData.AddRange(new byte[] { 0, (byte)AdobeColorSpace.RGB });
                    blockData.AddRange(new byte[] { color.R, 0 });
                    blockData.AddRange(new byte[] { color.G, 0 });
                    blockData.AddRange(new byte[] { color.B, 0 });
                    blockData.AddRange(new byte[] { 0, 0 });
                    break;
                }

            case ColorSpace.Cmyk:
                {
                    var color = c as CmykColor;
                    blockData.AddRange(new byte[] { 0, (byte)AdobeColorSpace.CMYK });
                    blockData.AddRange(new byte[] { (byte)(255 - color.C), 0 });
                    blockData.AddRange(new byte[] { (byte)(255 - color.M), 0 });
                    blockData.AddRange(new byte[] { (byte)(255 - color.Y), 0 });
                    blockData.AddRange(new byte[] { (byte)(255 - color.K), 0 });
                    break;
                }

            case ColorSpace.Lab:
                {
                    var color = c as LabColor;
                    blockData.AddRange(new byte[] { 0, (byte)AdobeColorSpace.LAB });

                    var l = (ushort)(color.L / 2.55f * 100f);
                    blockData.AddRange(new byte[] { (byte)(l >> 8), (byte)(l & 255) });

                    var a = (ushort)(short)(color.A * 100);
                    blockData.AddRange(new byte[] { (byte)(a >> 8), (byte)(a & 255) });

                    var b = (ushort)(short)(color.B * 100);
                    blockData.AddRange(new byte[] { (byte)(b >> 8), (byte)(b & 255) });

                    blockData.AddRange(new byte[] { 0, 0 });
                    break;
                }

            case ColorSpace.Grayscale:
                {
                    var gray = c as GrayscaleColor;
                    blockData.AddRange(new byte[] { 0, (byte)AdobeColorSpace.Grayscale });

                    var l = (ushort)((255 - gray.L) / 2.55f * 100f);
                    blockData.AddRange(new byte[] { (byte)(l >> 8), (byte)(l & 255) });

                    blockData.AddRange(new byte[] { 0, 0 });
                    blockData.AddRange(new byte[] { 0, 0 });
                    blockData.AddRange(new byte[] { 0, 0 });

                    break;
                }

            default:
                throw new System.ArgumentException("Invalid color space");
        }

        blockData.AddRange(new byte[] { solidity, 0 });
        blockData.Add((byte)DisplayInfoMode.Spot);
    }

    return new AdobeResourceBlock(string.Empty, blockData.ToArray());
}

Output

AdobeResourcesWithDisplayInfo.tif

Download

For AI-assisted development: Download Graphics Mill Code Samples XML Catalog