Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Custom black and white Image Format

4.00/5 (3 votes)
20 Nov 2022CPOL 5.3K  
Custom black and white image format
This class was created to find a way to write/read PBM Image format.
C#
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.Serialization.Formatters.Binary;
namespace Chico
{
    [Serializable]
    public sealed class CPBM
    {
        private bool[,] pixels;
        /// <summary>
        /// Represents a <see langword="null"/> <see cref="CPBM"/>.
        /// </summary>
        public static readonly CPBM Null = new CPBM(0, 0);
        private CPBM(int width, int height)
        {
            if (width <= 0 || height <= 0)
                return;
            this.pixels = new bool[width, height];
        }
        /// <summary>
        /// Load a <see cref="CPBM"/> from the specified stream.
        /// </summary>
        /// <returns>The cpbm from stream.</returns>
        /// <param name="stream">Stream.</param>
        public static CPBM Load(Stream stream)
        {
            BinaryFormatter decompressionFormatter = new BinaryFormatter();
            byte[] compressedBytes = null;
            using (MemoryStream compressionReader = new MemoryStream())
            {
                stream.CopyTo(compressionReader);
                compressedBytes = compressionReader.ToArray();
            }
            Array.Reverse(compressedBytes);
            using (MemoryStream decompressionStream = new MemoryStream(compressedBytes.Decompress()))
                return (CPBM)decompressionFormatter.Deserialize(decompressionStream);
        }
        /// <summary>
        /// Save this <see cref="CPBM"/> to the specified stream.
        /// </summary>
        /// <param name="stream">Stream.</param>
        public void Save(Stream stream)
        {
            byte[] cpbmData = null;
            using (MemoryStream cpbmWriter = new MemoryStream())
            {
                BinaryFormatter cpbmFormatter = new BinaryFormatter();
                cpbmFormatter.Serialize(cpbmWriter, this);
                cpbmData = cpbmWriter.ToArray();
            }
            byte[] compressedCpbm = cpbmData.Compress();
            Array.Reverse(compressedCpbm);
            stream.Write(compressedCpbm, 0, compressedCpbm.Length);
        }
        /// <summary>
        /// Gets or sets the level.
        /// </summary>
        /// <value>The level.</value>
        public int Level { get; set; }
        /// <summary>
        /// Gets the width of this <see cref="CPBM"/>.
        /// </summary>
        /// <value>The width.</value>
        public int Width => this.pixels.GetLength(0);
        /// <summary>
        /// Gets the height of this <see cref="CPBM"/>.
        /// </summary>
        /// <value>The height.</value>
        public int Height => this.pixels.GetLength(1);
        /// <summary>
        /// Gets the pixel at the specified coordinates of this <see cref="CPBM"/>.
        /// </summary>
        /// <returns><c>true</c>, if pixel was gotten, <c>false</c> otherwise.</returns>
        /// <param name="x">The x coordinate.</param>
        /// <param name="y">The y coordinate.</param>
        public bool GetPixel(int x, int y) => this.pixels[x, y];
        /// <summary>
        /// Sets the requested pixel at the specified coordinates.
        /// </summary>
        /// <param name="x">The x coordinate.</param>
        /// <param name="y">The y coordinate.</param>
        /// <param name="value">If set to <c>true</c> value.</param>
        public void SetPixel(int x, int y, bool value) => this.pixels[x, y] = value;
        private Color GetColor(int x, int y) => this.pixels[x, y] ? Color.White : Color.Black;
        /// <summary>
        /// Load a <see cref="CPBM"/> from the specified bitmap.
        /// </summary>
        /// <param name="bitmap">Bitmap.</param>
        /// <param name="useColorCorrectionProfile">If set to <c>true</c> use Color Correction Profile.</param>
        public void FromBitmap(Bitmap bitmap, bool useColorCorrectionProfile = false)
        {
            if (bitmap == null)
                return;
            this.pixels = new bool[bitmap.Width, bitmap.Height];
            for (int x = 0; x < bitmap.Width; x++)
            {
                for (int y = 0; y < bitmap.Height; y++)
                {
                    Color c = bitmap.GetPixel(x, y);
                    bool adjust = (c.R + c.G + c.B) >= Level;
                    if (!useColorCorrectionProfile)
                        this.SetPixel(x, y, !adjust);
                    else
                        this.SetPixel(x, y, adjust);
                }
            }
        }
        /// <summary>
        /// Saves a copy of this <see cref="CPBM"/> as a <see cref="Bitmap"/>.
        /// </summary>
        /// <param name="path">Path.</param>
        public void ToBitmap(string path)
        {
            try
            {
                this.ToBitmap().Save(path);
            }
            catch
            {
                return;
            }
        }
        public static explicit operator Bitmap(CPBM cPBM) => cPBM?.ToBitmap();
        private Bitmap ToBitmap()
        {
            Bitmap bitmap = new Bitmap(Width, Height);
            for (int x = 0; x < bitmap.Width; x++)
            {
                for (int y = 0; y < bitmap.Height; y++)
                {
                    bitmap.SetPixel(x, y, this.GetColor(x, y));
                }
            }
            using (MemoryStream ms = new MemoryStream())
            {
                bitmap.Save(ms, ImageFormat.Gif);
                ms.Seek(0, SeekOrigin.Begin);
                return (Bitmap)Image.FromStream(ms);
            }
        }
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)