Exemple #1
0
        public void Serialize()
        {
            MemoryStream stream = new MemoryStream();
            ImageFormat  format = null;

            switch (this.Type)
            {
            case ICOImageType.BMP:
                format = ImageFormat.Bmp;
                break;

            case ICOImageType.PNG:
                format = ImageFormat.Png;
                break;

            default:
                throw new FormatException("Invalid image format type");
            }
            this.Image.Save(stream, format);
            serialized = stream.ToArray();
            // For BMP images, strip BITMAPFILEHEADER + add AND mask
            if (Type == ICOImageType.BMP)
            {
                // Generate AND mask: false for transparent, true for opaque
                bool[] ANDmask = new bool[this.Height * this.Width];
                for (int i = 0; i < ANDmask.Length; i++)
                {
                    ANDmask[i] = ((this.Image.GetPixel(i % this.Width, i / this.Width).A == 0) ? false : true);
                }
                serialized = BMP.ToICO(serialized, ANDmask);
            }
        }
Exemple #2
0
 private static int GetRowSize(int width, int bpp)
 {
     if (bpp < 8 || bpp % 8 != 0)
     {
         throw new FormatException(string.Format("Invalid BMP bpp: {0}", bpp));
     }
     if (width < 0)
     {
         throw new FormatException(string.Format("Invalid BMP width: {0}", width));
     }
     return(width * bpp / 8 + BMP.GetRowAlignmentBytes(width, bpp));
 }
Exemple #3
0
        public static byte[] ToICO(byte[] BMPData, bool[] ANDmask)
        {
            byte[] result = Bytes.Subset(BMPData, BITMAPFILEHEADER_SIZE, BMPData.Length - BITMAPFILEHEADER_SIZE);

            /*
             * wikipedia.org/wiki/ICO_(file_format)
             *
             * Images with less than 32 bits of color depth follow a particular format: the image is encoded as
             * a single image consisting of a color mask (the "XOR mask") together with an opacity mask (the "AND mask").
             * The XOR mask must precede the AND mask inside the bitmap data;
             * if the image is stored in bottom-up order (which it most likely is), the XOR mask would be drawn below the AND mask.
             * The AND mask is 1 bit per pixel, regardless of the color depth specified by the BMP header, and specifies
             * which pixels are fully transparent and which are fully opaque.
             * The XOR mask conforms to the bit depth specified in the BMP header
             * and specifies the numerical color or palette value for each pixel.
             * Together, the AND mask and XOR mask make for a non-transparent image representing an image with 1-bit transparency;
             * they also allow for inversion of the background.
             *
             * The height for the image in the ICONDIRENTRY structure of the ICO/CUR file takes on that of the intended image dimensions
             * (after the masks are composited), whereas the height in the BMP header takes on that of the two mask images combined
             * (before they are composited). Therefore, the masks must each be of the same dimensions, and the height
             * specified in the BMP header must be exactly twice the height specified in the ICONDIRENTRY structure.
             */
            int bpp    = BMP.GetBitsPerPixel(result);
            int height = Bytes.FromBytes(result, BITMAPINFOHEADER_HEIGHT_OFFSET, 4);

            byte[] heightBytes = Bytes.FromInt(height * 2, 4);
            Bytes.Replace(result, heightBytes, BITMAPINFOHEADER_HEIGHT_OFFSET);
            if (bpp < 32)
            {
                // Create and append AND mask after the bitmap data

                /*
                 * int width = Bytes.FromBytes(result, BITMAPINFOHEADER_WIDTH_OFFSET, 4);
                 * int BytesPerPixel = bpp / 8;
                 * int RowAlignment = BMP.GetRowAlignmentBytes(width, bpp);
                 * byte[] ANDbytes = new byte[ANDmask.Length * BytesPerPixel + height * RowAlignment];
                 * for (int i = 0; i < ANDmask.Length; i++)
                 *  for (int j = 0; j < BytesPerPixel; j++)
                 *      ANDbytes[i * BytesPerPixel + j] = ANDmask[i] ? (byte)0xFF : (byte)0x00;
                 * result = Bytes.Merge(result, ANDbytes);
                 */
            }
            return(result);
        }
Exemple #4
0
        internal ICOImage(ICOType type, ICONDIRENTRY icondirentry, byte[] icoData)
        {
            byte[] imageData = Bytes.Subset(icoData, icondirentry.Image.Offset, icondirentry.Image.Size);
            if (BMP.isStrippedBMP(imageData))
            {
                imageData = BMP.FromICO(icondirentry, imageData);
                this.Type = ICOImageType.BMP;
            }
            else
            {
                this.Type = ICOImageType.PNG;
            }
            MemoryStream stream = new MemoryStream(imageData);

            this.Image    = new Bitmap(System.Drawing.Image.FromStream(stream));
            this.HotspotX = icondirentry.Image.HotspotX;
            this.HotspotY = icondirentry.Image.HotspotY;
        }
Exemple #5
0
        public static byte[] Get24bppBMP(Bitmap image)
        {
            int        bpp         = 24;
            int        headersSize = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE;
            int        fileSize    = BMP.GetSize(image.Width, image.Height, bpp);
            ByteStream stream      = new ByteStream(fileSize);

            // BMP file header
            stream.Write16(0x4D42);
            stream.Write32(fileSize);
            stream.Write16(0);
            stream.Write16(0);
            stream.Write32(headersSize);
            // BMP info header
            stream.Write32(BITMAPINFOHEADER_SIZE);
            stream.Write32(image.Width);
            stream.Write32(image.Height);
            stream.Write16(1);
            stream.Write16(bpp);
            stream.Write32(0);
            stream.Write32(fileSize - headersSize);
            stream.Write32(0);
            stream.Write32(0);
            stream.Write32(0);
            stream.Write32(0);
            // BMP image data
            int alignmentBytes = BMP.GetRowAlignmentBytes(image.Width, bpp);

            byte[] rowAlignment = new byte[alignmentBytes];
            for (int y = image.Height - 1; y >= 0; y--)
            {
                for (int x = 0; x < image.Width; x++)
                {
                    Color  color = image.GetPixel(x, y);
                    byte[] pixel = { color.R, color.G, color.B };
                    stream.Write(pixel);
                }
                stream.Write(rowAlignment);
            }
            return(stream.Buffer);
        }