ATTENTION ALL FANS!!! THIS BLOG HAS MOVED!!!
go to: http://www.taotekaching.com

Showing posts with label bitmap. Show all posts
Showing posts with label bitmap. Show all posts

Wednesday, January 21, 2009

In the name of Science, and Me…

All programmers, at one point or another, have dreamt of this:

3M TA3

Of course, you know what this is, right? It’s a file. Duh, you say? No, you don’t understand. Each pixel represents 4 bytes of a file. I used the first two pixels to “store” the number of bytes of the actual file, then the rest up to that white line at the end, is the file.

Brilliant? Yes, yes I know. I have not been able to purge my mind of this ridiculously stupid project / experiment for years. Every now and then, it’s very “what if” resurfaces like a slightly annoyed blackhead. It needed popping…

Needless to say, it is not very good for compressing. Zipping the image actually increases it’s size slightly. I was skeptical of this, though (this is SCIENCE), so I decided to try it on a PCLinuxOS Mini-Me 2008 ISO image I had laying around on my desktop, which is around 296MB. The bmp generated is quite large – 8821 x 8821. The compression results:

  • PCLOS ISO: 311,207,936 bytes
  • PCLOS ISO bitmapped: 309,407,681 bytes
  • PCLOS ISO zipped: 307,880,700 bytes
  • PCLOS ISO bitmapped & zipped: 309,407,811 bytes

There. Finally. Purged from my mind…but…

WHAT IF I GENERATED A SERIES OF 50 x 50 BITMAPS OF THE ISO AND STRUNG THEM INTO AN AVI?

Not going there. If you do, please dear God and baby Jesus let me know how it goes. Here’s my dumb code if it’ll help, or get it from here:

file

But that’s not all I did in the name of science tonight! I went out to have a cigarette (in our 15 degree weather) in celebration of lobotomizing the bitmap wart from my mind to discover this:

lite-off

In the name of science, I had to know what it would look like lit up. I knew the dangers. I knew I might, potentially, kill the power to our house, destroy my beloved TV, and black out the neighborhood.

lite-on

Eh, boring. Thought all the ice would light up or something…

~zagnut

Submit this story to DotNetKicks

Thursday, January 08, 2009

Device Independent Bitmaps, C#, and Me…REDUX!


Well, after using the previously posted code in some projects at work, some limitations arose quickly. The two biggest were support for 8-bit bitmaps, and support for both 5-5-5 and 5-6-5 16-bit bitmaps.

The new code looks like the following:

using System;

using System.Collections.Generic;

using System.Drawing;

using System.Drawing.Imaging;

using System.Runtime.InteropServices;

using System.IO;

namespace DIBitmaps

{

static public class DIB

{

// our BITMAPINFOHEADER struct, as per gdi

// use LayoutKind to make sure data is marshalled as we've laid it out

[StructLayout(LayoutKind.Sequential)]

public struct BITMAPINFOHEADER

{

public uint biSize;

public int biWidth;

public int biHeight;

public ushort biPlanes;

public ushort biBitCount;

public uint biCompression;

public uint biSizeImage;

public int biXPelsPerMeter;

public int biYPelsPerMeter;

public uint biClrUsed;

public uint biClrImportant;

//public void Init()

//{

// biSize = (uint)Marshal.SizeOf(this);

//}

}

public static Bitmap BitmapFromDIB(MemoryStream dib)

{

// get byte array of device independent bitmap

byte[] dibBytes = dib.ToArray();

// get the handle for the byte array and "pin" that memory (i.e. prevent

// garbage collector from gobbling it up right away)...

GCHandle hdl = GCHandle.Alloc(dibBytes, GCHandleType.Pinned);

// marshal our data into a BITMAPINFOHEADER struct per Win32

// definition of BITMAPINFOHEADER

BITMAPINFOHEADER dibHdr = (BITMAPINFOHEADER)Marshal.PtrToStructure

(hdl.AddrOfPinnedObject(), typeof(BITMAPINFOHEADER));

bool is555 = true;

Bitmap bmp = null;

if (dibHdr.biBitCount == 8)

{

// set our pointer to end of BITMAPINFOHEADER

Int64 jumpTo = hdl.AddrOfPinnedObject().ToInt64() + dibHdr.biSize;

bmp = new Bitmap(dibHdr.biWidth, dibHdr.biHeight, PixelFormat.Format8bppIndexed);

bmp.SetResolution((100f * (float)dibHdr.biXPelsPerMeter) / 2.54f,

(100f * (float)dibHdr.biYPelsPerMeter) / 2.54f);

// set the colors in our palette

ColorPalette palette = bmp.Palette;

IntPtr ptr = IntPtr.Zero;

int colors = (int)(dibBytes.Length - (bmp.Width * bmp.Height) - dibHdr.biSize);

for (int i = 0; i < 256; i++)

{

ptr = new IntPtr(jumpTo);

uint bmiColor = (uint)Marshal.ReadInt32(ptr);

int r = (int)((bmiColor & 0xFF0000) >> 16),

g = (int)((bmiColor & 0xFF00) >> 8),

b = (int)((bmiColor & 0xFF));

palette.Entries[i] = Color.FromArgb(r, g, b);

jumpTo += 4;

}

bmp.Palette = palette;

// now write the remaining bmp data to our bitmap

BitmapData _8bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),

ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);

jumpTo -= hdl.AddrOfPinnedObject().ToInt64();

Marshal.Copy(dibBytes, (int)jumpTo, _8bd.Scan0, _8bd.Stride * _8bd.Height);

bmp.UnlockBits(_8bd);

}

else if ((dibHdr.biBitCount == 16) && (dibHdr.biCompression == 3))

{

Int64 jumpTo = (Int64)(dibHdr.biClrUsed * (uint)4 + dibHdr.biSize);

IntPtr ptr = new IntPtr(hdl.AddrOfPinnedObject().ToInt64() + jumpTo);

ushort redMask = (ushort)Marshal.ReadInt16(ptr);

ptr = new IntPtr(ptr.ToInt64() + (2 * Marshal.SizeOf(typeof(UInt16))));

ushort greenMask = (ushort)Marshal.ReadInt16(ptr);

ptr = new IntPtr(ptr.ToInt64() + (2 * Marshal.SizeOf(typeof(UInt16))));

ushort blueMask = (ushort)Marshal.ReadInt16(ptr);

is555 = ((redMask == 0x7C00) && (greenMask == 0x03E0) && (blueMask == 0x001F));

}

// go ahead and release the "pin" from our handle on that memory

hdl.Free();

// If the target device does not have one plane, or we're working with a bitmap other

// than a non-compressed (BI_RGB) bitmap, we're not gonna work woith it

if (dibHdr.biPlanes != 1 || (dibHdr.biCompression != 0 && dibHdr.biCompression != 3))

return null;

if (bmp == null)

{

// we need to know beforehand the pixel-depth of our bitmap

PixelFormat fmt = PixelFormat.Format24bppRgb;

switch (dibHdr.biBitCount)

{

case 32:

fmt = PixelFormat.Format32bppRgb;

break;

case 24:

fmt = PixelFormat.Format24bppRgb;

break;

case 16:

fmt = (is555) ? PixelFormat.Format16bppRgb555 :

PixelFormat.Format16bppRgb565;

break;

default:

return null;

}

// prepare for our output bitmap

bmp = new Bitmap(dibHdr.biWidth, dibHdr.biHeight, fmt);

// load our "empty" bitmap into memory and lock it for

// writing in the format we specified

BitmapData bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),

ImageLockMode.WriteOnly, fmt);

// marshal our device independent bitmap data over to our output bitmap

Marshal.Copy(dibBytes, Marshal.SizeOf(dibHdr), bd.Scan0, bd.Stride * bd.Height);

// we're done marshalling, so release our bitmapdata lock

bmp.UnlockBits(bd);

}

if (dibHdr.biHeight > 0)

{

// DIB data is upside-down for some reason, so flip it

bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);

}

// return our bitmap

return bmp;

}

}

}

The adjusted code can be downloaded here.

If you find any other issues, please let me know and I’ll get it updated ASAP.

~ZagNUT

Submit this story to DotNetKicks

Monday, November 24, 2008

DIB, C#, and Me...

Ok, after pulling out my hair trying to generate thumbnails from device-independent bitmaps stored by a CArchive in an "old" MFC program, I finally got help here at the workplace on this.

I must say I could not find this easily with much Googling, ergo I'm gonna post this up here with comments for anyone else out there looking for the same thing.

Please suggest any updations to comments and / or code, if you see the need...

NOTE: This code has been updated. Look here for it.

// our BITMAPINFOHEADER struct, as per gdi
// use LayoutKind to make sure data is marshalled as we've laid it out
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFOHEADER
{
public uint biSize;
public int biWidth;
public int biHeight;
public ushort biPlanes;
public ushort biBitCount;
public uint biCompression;
public uint biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public uint biClrUsed;
public uint biClrImportant;
public void Init()
{
biSize = (uint)Marshal.SizeOf(this);
}
}

public static Bitmap BitmapFromDIB(MemoryStream dib)
{
// get byte array of device independent bitmap
byte[] dibBytes = dib.ToArray();

// get the handle for the byte array and "pin" that memory (i.e. prevent garbage collector from
// gobbling it up right away)...
GCHandle hdl = GCHandle.Alloc(dibBytes, GCHandleType.Pinned);

// marshal our data into a BITMAPINFOHEADER struct per Win32 definition of BITMAPINFOHEADER
BITMAPINFOHEADER dibHdr = (BITMAPINFOHEADER)Marshal.PtrToStructure(hdl.AddrOfPinnedObject(), typeof(BITMAPINFOHEADER));

// go ahead and release the "pin" from our handle on that memory
hdl.Free();

// If the target device does not have one plane, or we're working with a bitmap other than a
// non-compressed (BI_RGB) bitmap, we're not gonna work woith it
if (dibHdr.biPlanes != 1 || dibHdr.biCompression != 0)
return null;

// we need to know beforehand the pixel-depth of our bitmap
PixelFormat fmt = PixelFormat.Format24bppRgb;
switch (dibHdr.biBitCount)
{
case 32:
fmt = PixelFormat.Format32bppRgb;
break;
case 24:
fmt = PixelFormat.Format24bppRgb;
break;
case 16:
fmt = PixelFormat.Format16bppRgb555;
break;
default:
return null;
}

// prepare for our output bitmap
Bitmap bmp = new Bitmap(dibHdr.biWidth, dibHdr.biHeight, fmt);

// load our "empty" bitmap into memory and lock it for writing in the format we specified
BitmapData bd = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, fmt);

// marshal our device independent bitmap data over to our output bitmap
Marshal.Copy(dibBytes, Marshal.SizeOf(dibHdr), bd.Scan0, bd.Stride * bd.Height);

// we're done marshalling, so release our bitmapdata lock
bmp.UnlockBits(bd);

// DIB data is upside-down for some reason, so flip it
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);

// return our bitmap
return bmp;
}


~simon

Submit this story to DotNetKicks

Thursday, September 04, 2008

Flash RGB, C#, and Me...

Greetings,

So a co-worker of mine had to translate Flash RGB data into a Bitmap. He noted that finding that out was difficult, ergo, for your coding pleasure, here's a tasty little static function you can use just for that:




static Bitmap BmpOut(string rgb, int width, int height)
{
Bitmap bmp = null;
try
{
int bytes = (rgb.Length / (width * height));
bool IsArgb = (bytes == 8);
double dWidth = (double)width;
bmp = new Bitmap(width, height);
int counter = -1;
for (int i = 0; i < rgb.Length; i += bytes)
bmp.SetPixel(++counter % width, (int)Math.Floor((double)counter / dWidth),
Color.FromArgb(int.Parse(((!IsArgb) ? "FF" + rgb.Substring(i, 6) : rgb.Substring(i, 8)), System.Globalization.NumberStyles.HexNumber)));
}
catch { bmp = null; }
return bmp;
}


enjoy...

Submit this story to DotNetKicks