Need C# function to convert grayscale TIFF to black & white (monochrome/1BPP) TIFF

前端 未结 7 1683
清歌不尽
清歌不尽 2021-01-14 09:18

I need a C# function that will take a Byte[] of an 8 bit grayscale TIFF, and return a Byte[] of a 1 bit (black & white) TIFF.

I\'m fairly new to working with TIF

7条回答
  •  说谎
    说谎 (楼主)
    2021-01-14 09:37

    @neodymium has a good answer, but GetPixel/SetPixel will kill performance. Bob Powell has a great method.

    C#:

        private Bitmap convertTo1bpp(Bitmap img)
        {
            BitmapData bmdo = img.LockBits(new Rectangle(0, 0, img.Width, img.Height),
                                           ImageLockMode.ReadOnly, 
                                           img.PixelFormat);
    
            // and the new 1bpp bitmap
            Bitmap bm = new Bitmap(img.Width, img.Height, PixelFormat.Format1bppIndexed);
            BitmapData bmdn = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height),
                                          ImageLockMode.ReadWrite, 
                                          PixelFormat.Format1bppIndexed);
    
            // scan through the pixels Y by X
            for(int y = 0; y < img.Height; y++)
            {
                for(int x = 0; x < img.Width; x++)
                {
                    // generate the address of the colour pixel
                    int index = y * bmdo.Stride + x * 4;
    
                    // check its brightness
                    if(Color.FromArgb(Marshal.ReadByte(bmdo.Scan0, index + 2), 
                                      Marshal.ReadByte(bmdo.Scan0, index + 1), 
                                      Marshal.ReadByte(bmdo.Scan0, index)).GetBrightness() > 0.5F)
                    {
                        setIndexedPixel(x, y, bmdn, true); // set it if its bright.
                    }
                 }
            }
    
            // tidy up
            bm.UnlockBits(bmdn);
            img.UnlockBits(bmdo);
            return bm;
        }
    
        private void setIndexedPixel(int x, int y, BitmapData bmd, bool pixel)
        {
            int index = y * bmd.Stride + (x >> 3);
            byte p = Marshal.ReadByte(bmd.Scan0, index);
            byte mask = (byte)(0x80 >> (x & 0x7));
    
            if (pixel)
            {
                p |= mask;
            }
            else
            {
                p &= (byte)(mask ^ 0xFF);
            }
    
            Marshal.WriteByte(bmd.Scan0, index, p);
        }
    

提交回复
热议问题