Exemplo n.º 1
0
        /* Input: filename of a bitmap file
         * Output: byte array of the same bitmap with 1 bit per pixel
         *
         * Theoretically works with 8, 16, 24, or 32 bit input files;
         * I've only tested with 32. Returns null on 4bpp, file itself
         * if image is already 1bpp.
         *
         * Uncompressed DIB3 only. Returns null otherwise.
         *
         * May not deal well with an existing color palette.
         *
         * No support for endianess or negative height.
         */
        public static byte[] To1bpp(string filename)
        {
            byte[] data = System.IO.File.ReadAllBytes(filename);

            int raw_loc = BitmapConverter.GetInt(data, 0xa, 0xd);
            int width   = BitmapConverter.GetInt(data, 0x12, 0x15);
            int height  = BitmapConverter.GetInt(data, 0x16, 0x19);
            int bpp     = BitmapConverter.GetInt(data, 0x1c, 0x1d);
            int comp    = BitmapConverter.GetInt(data, 0x1e, 0x21);

            // 1 bpp => done
            // 4 bpp => unimplemented
            if (bpp == 1)
            {
                return(data);
            }
            if (bpp == 4)
            {
                return(null);
            }
            // compression => unimplemented
            if (comp != 0)
            {
                return(null);
            }

            byte[,] pixels = new byte[width, height];

            int raw_size    = data.Length - raw_loc;
            int bytesPerRow = raw_size / height;

            /* read the existing pixel values into a
             * 2-dimensional array. */
            int x        = 0;
            int y        = 0;
            int pix_size = bpp / 8;
            int pixcount = 0;

            for (int i = 0; i < raw_size; i += 0)
            {
                if (i > 0 && i % bytesPerRow == 0)
                {
                    x = 0;
                    y++;
                }
                if (x < width)
                {
                    int pixel = BitmapConverter.GetInt(data,
                                                       i + raw_loc, i + raw_loc + pix_size - 1);
                    i    += pix_size;
                    pixel = pixel & 0xffffff;             // no alpha
                    if (pixel < 0xeeeeee)
                    {
                        pixels[x, y] = 1;
                    }
                    else
                    {
                        pixels[x, y] = 0;
                    }
                    pixcount++;
                }
                else
                {
                    i++;             // row padding
                }
                x++;
            }

            /* create a new byte array to hold 1 bit pixels
             * and add them all to it*/
            int newRowBytes = (int)((width + 31) / 32.0) * 4;

            byte[] newdata = new byte[newRowBytes * height];
            int    bits    = 0;

            for (int i = 0; i < newdata.Length; i++)
            {
                int x1  = (i % newRowBytes) * 8;
                int y1  = i / newRowBytes;
                int val = 0;
                for (int j = 0; j < 8; j++)
                {
                    if (x1 + j >= width)          // end of pixel row, rest gets padded
                    {
                        break;
                    }
                    val = val | ((pixels[x1 + j, y1]) << (7 - j));
                    bits++;
                }
                newdata[i] = (byte)val;
            }

            byte[] newbmp = new byte[14 + 40 + 8 + newdata.Length];

            // BMP Header
            newbmp[0x0] = 0x42;
            newbmp[0x1] = 0x4D;
            BitmapConverter.PutInt(ref newbmp, newbmp.Length, 0x2, 0x5); // filesize
            BitmapConverter.PutInt(ref newbmp, 0, 0x6, 0x9);             // irrelevant
            BitmapConverter.PutInt(ref newbmp, 14 + 40 + 8, 0xa, 0xd);   // image data offset

            // DIB Header
            BitmapConverter.PutInt(ref newbmp, 40, 0xe, 0x11);     // DIB3
            BitmapConverter.PutInt(ref newbmp, width, 0x12, 0x15);
            BitmapConverter.PutInt(ref newbmp, height, 0x16, 0x19);
            BitmapConverter.PutInt(ref newbmp, 1, 0x1a, 0x1b);              // planes, always 1
            BitmapConverter.PutInt(ref newbmp, 1, 0x1c, 0x1d);              // bpp
            BitmapConverter.PutInt(ref newbmp, 0, 0x1e, 0x21);              // no compression
            BitmapConverter.PutInt(ref newbmp, newdata.Length, 0x22, 0x25); // image data size
            int dpi = (int)(72 * 39.97 + 0.5);

            BitmapConverter.PutInt(ref newbmp, dpi, 0x26, 0x29);   // horizontal dpi
            BitmapConverter.PutInt(ref newbmp, dpi, 0x2a, 0x2d);   // vertical dpi
            BitmapConverter.PutInt(ref newbmp, 2, 0x2e, 0x31);     // number of colors
            BitmapConverter.PutInt(ref newbmp, 0, 0x32, 0x35);     // usually ignored

            // Color Palette
            newbmp[0x36] = 0xff;     // white
            newbmp[0x37] = 0xff;
            newbmp[0x38] = 0xff;
            newbmp[0x39] = 0x0;
            newbmp[0x3a] = 0x0;     // black
            newbmp[0x3b] = 0x0;
            newbmp[0x3c] = 0x0;
            newbmp[0x3d] = 0x0;

            // raw image data
            Array.Copy(newdata, 0, newbmp, 0x3e, newdata.Length);

            return(newbmp);
        }