c# - Compressing a bitmap with Run Length Encoding [RLE] using GDI+ -
i tried lot searching on google before posting question here. want compress 8bpp bitmap using rle [run length encoding] compression in win forms application.
of results found vc++ code, can perform compression using gdi+ ? gdi+ provide such classes or methods ?
found 1 link on msdn doesn't helped much.
also, tried write below code using "system.drawing.imaging.encoder" output image
has same size.
private void button1_click(object sender, eventargs e) { bitmap mybitmap; imagecodecinfo myimagecodecinfo; encoder myencoder; encoderparameter myencoderparameter; encoderparameters myencoderparameters; // create bitmap object based on bmp file. mybitmap = new bitmap("d:\\8bppimage.bmp"); // imagecodecinfo object represents bmp codec. myimagecodecinfo = getencoderinfo("image/bmp"); // create encoder object based on guid // compression parameter category. myencoder = encoder.compression; // create encoderparameters object. myencoderparameters = new encoderparameters(1); myencoderparameter = new encoderparameter( myencoder,(long)encodervalue.compressionrle); myencoderparameters.param[0] = myencoderparameter; mybitmap.save("d:\\encoderimg.bmp", myimagecodecinfo, myencoderparameters); } private static imagecodecinfo getencoderinfo(string mimetype) { int j; imagecodecinfo[] encoders; encoders = imagecodecinfo.getimageencoders(); (j = 0; j < encoders.length; ++j) { if (encoders[j].mimetype == mimetype) return encoders[j]; } return null; }
am missing ? can me ?
i've submitted answer compressing 8bpp images in c# using rle on question: how compress image run-length encoding using c#?
i believe attempting not work because encodervalue.compressionrle applies .tiff images.
here code used perform compression:
private enum compression { // others not necessary 8bpp compression, left reference //bi_rgb = 0x0000, bi_rle8 = 0x0001, //bi_rle4 = 0x0002, //bi_bitfields = 0x0003, //bi_jpeg = 0x0004, //bi_png = 0x0005, //bi_cmyk = 0x000b, //bi_cmykrle8 = 0x000c, //bi_cmykrle4 = 0x000d } private enum bitcount { // others not necessary 8bpp compression, left reference //undefined = (ushort)0x0000, //twocolors = (ushort)0x0001, //max16colors = (ushort)0x0004, max256colors = (ushort)0x0008, //max32kbcolors = (ushort)0x0010, //max16mbcolors = (ushort)0x0018, //max16mbcolors_compressed = (ushort)0x0020 } private struct rlecompressedbmpheader { // before headersize technically not part of header (it's not included in headersize calculation) /// <summary> /// size of .bmp file. /// header size (40), plus palette size, plus image size, plus pre-header size (14); /// </summary> public uint size; /// <summary> /// offset start of image data in bytes start of file /// </summary> public uint offset; /// <summary> /// size of header in bytes. (always 40) /// </summary> public uint headersize; // 4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4 /// <summary> /// width of bitmap in pixels /// </summary> public int width; /// <summary> /// height of bitmap in pixels /// </summary> public int height; /// <summary> /// number of planes (layers). 1. /// </summary> public ushort planes; /// <summary> /// number of bits define each pixel , maximum number of colors /// </summary> public bitcount bitcount; /// <summary> /// defines compression mode of bitmap. /// </summary> public compression compression; /// <summary> /// size, in bytes, of image. /// </summary> public uint imagesize; // these shouldn't important public uint xpixelspermeter; public uint ypixelspermeter; /// <summary> /// number of indexes in color table used bitmap. /// <para>0 - use max available</para> /// <para>if bitcount less 16, number of colors used bitmap</para> /// <para>if bitcount 16 or greater, specifies size of color table used optimize performance of system palette.</para> /// </summary> public uint colorused; /// <summary> /// number of color indexes required displaying bitmap. 0 means color indexes required. /// </summary> public uint colorimportant; public byte[] tobytes() { var swap = bitconverter.islittleendian; var result = new list<byte>(); result.addrange(new byte[] { 0x42, 0x4d }); // signature (bm) result.addrange(bitconverter.getbytes(size)); result.addrange(new byte[4]); // reserved result.addrange(bitconverter.getbytes(offset)); result.addrange(bitconverter.getbytes(headersize)); result.addrange(bitconverter.getbytes(width)); result.addrange(bitconverter.getbytes(height)); result.addrange(bitconverter.getbytes(planes)); result.addrange(bitconverter.getbytes((ushort)bitcount)); result.addrange(bitconverter.getbytes((uint)compression)); result.addrange(bitconverter.getbytes(imagesize)); result.addrange(bitconverter.getbytes(xpixelspermeter)); result.addrange(bitconverter.getbytes(ypixelspermeter)); result.addrange(bitconverter.getbytes(colorused)); result.addrange(bitconverter.getbytes(colorimportant)); return result.toarray(); } } public unsafe byte[] runlengthencodebitmap(bitmap bmp) { if (bmp.pixelformat != pixelformat.format8bppindexed) { throw new argumentexception("the image must in 8bppindexed pixelformat", "bmp"); } var data = bmp.lockbits(new rectangle(0, 0, bmp.width, bmp.height), imagelockmode.readonly, pixelformat.format8bppindexed); list<byte> result = new list<byte>(); // actual rle algorithm. bottom of image first stored row, start bottom. (var rowindex = bmp.height - 1; rowindex >= 0; rowindex--) { byte? storedpixel = null; var curpixelrepititions = 0; var imagerow = (byte*)data.scan0.topointer() + (rowindex * data.stride); (var pixelindex = 0; pixelindex < bmp.width; pixelindex++) { var curpixel = imagerow[pixelindex]; if (!storedpixel.hasvalue) { curpixelrepititions = 1; storedpixel = curpixel; } else if (storedpixel.value != curpixel || curpixelrepititions == 255) { result.add(convert.tobyte(curpixelrepititions)); result.add(storedpixel.value); curpixelrepititions = 1; storedpixel = curpixel; } else { curpixelrepititions++; } } if (curpixelrepititions > 0) { result.add(convert.tobyte(curpixelrepititions)); result.add(storedpixel.value); } if (rowindex == 0) { // eof flag result.add(0x00); result.add(0x01); } else { // end of line flag result.add(0x00); result.add(0x00); } } bmp.unlockbits(data); var palettesize = (uint)bmp.palette.entries.length * 4; var header = new rlecompressedbmpheader(); header.headersize = 40; header.size = header.headersize + palettesize + (uint)result.count + 14; header.offset = header.headersize + 14 + palettesize; // total header size + palette size header.width = bmp.width; header.height = bmp.height; header.planes = 1; header.bitcount = bitcount.max256colors; // far can tell, pixelspermeter not terribly important header.xpixelspermeter = 0x10000000; header.ypixelspermeter = 0x10000000; header.compression = compression.bi_rle8; header.colorused = 256; header.colorimportant = 0; // use available colors header.imagesize = header.headersize + (uint)result.count; var headerbytes = header.tobytes(); var palettebytes = convertpalettetobytes(bmp.palette); return headerbytes.concat(palettebytes).concat(result).toarray(); } private byte[] convertpalettetobytes(colorpalette colorpalette) { return colorpalette.entries.selectmany(c => new byte[] { c.b, c.g, c.r, 0 }).toarray(); }
Comments
Post a Comment