Converting to ARGB and writing to a bitmap

H

heathimself

Hi,
I don't know what type of files they are, but the script allows me to
save to a bitmap just fine. But I do know they need to be in RGBA 4444
format, so I've followed what most of the tutorials for RGBA
conversions said to do...shifting the bytes.

The major problem is that everything is in green, it's shifted up by x
pixels, and it's..um..flipped from left to right. I've been working on
this for a few weeks now and any insight to the problem is greatly
appreciated.

http://www.geocities.com/fisherdude_99/TestImg.zip


import struct
import sys
import Image


if len(sys.argv) < 3:
print "usage: tobmp.py <file> <width>"
sys.exit(1)

width = int(sys.argv[2])

f1 = open(sys.argv[1], "rb")
f1.seek(0, 2)
size = f1.tell()
f1.seek(0)

### write BITMAPFILEHEADER ###
f2 = open(sys.argv[1] + ".bmp", "wb")
f2.write("BM")

bfSize = size+54
f2.write(struct.pack("L", bfSize))

# bfReserved1 and 2
f2.write("\x00\x00\x00\x00")

bfOffBits = 54
f2.write(struct.pack("L", bfOffBits))

### write BITMAPINFOHEADER ###
biSize = 40
f2.write(struct.pack("L", biSize))

biWidth = width
f2.write(struct.pack("L", biWidth))

biHeight = (size/ 2/ width)
f2.write(struct.pack("L", biHeight))

biPlanes = 1
f2.write(struct.pack("H", biPlanes))

biBitCount = 32
f2.write(struct.pack("H", biBitCount))

# biCompression
f2.write("\x00\x00\x00\x00")

# biSizeImage
f2.write("\x00\x00\x00\x00")

# biXPelsPerMeter
f2.write("\x00\x00\x00\x00")

# biYPelsPerMeter
f2.write("\x00\x00\x00\x00")

# biClrUsed
f2.write("\x00\x00\x00\x00")

# biClrImportant
f2.write("\x00\x00\x00\x00")

### write the bitmap data ###
print f2.tell() ##must be 54

# since bitmaps are upside down, gotta flip it over
data = f2.read()

i = size-21
while i >= 0:
nm = 0x100

f1.seek(i)
temp1 = struct.unpack('B', f1.read(1))[0]

peek = temp1

a = nm*(peek >> 24) & 0xff
r = nm*(peek >> 16) & 0xff
g = nm*(peek >> 8 ) & 0xff
b = nm*(peek & 0xff)

sh = (a<<24)|(r<<16)|(g<<8)|b

f2.write(struct.pack('H', sh))
i -= 1

f1.close()
f2.close()


Usage: bmpcon.py testimg 100

Thanks a lot
 
S

Steve Juranich

Hi,
I don't know what type of files they are, but the script allows me to
save to a bitmap just fine. But I do know they need to be in RGBA 4444
format, so I've followed what most of the tutorials for RGBA
conversions said to do...shifting the bytes.

The major problem is that everything is in green, it's shifted up by x
pixels, and it's..um..flipped from left to right. I've been working on
this for a few weeks now and any insight to the problem is greatly
appreciated.

http://www.geocities.com/fisherdude_99/TestImg.zip

This doesn't really answer your question, but have you looked into PIL yet?

http://www.pythonware.com/products/pil/index.htm
(except, hmmm.... it looks like the web site is down right now. Check back
later?)

It's got a bunch of different formats supported natively and makes image
processing work a lot easier in some respects.
 
T

Tim Roberts

I don't know what type of files they are, but the script allows me to
save to a bitmap just fine. But I do know they need to be in RGBA 4444
format, so I've followed what most of the tutorials for RGBA
conversions said to do...shifting the bytes.

It wasn't until I looked at your sample image that I realized you meant the
INCOMING image is ARGB 4444, and you're trying to convert it to ARGB 8888.
The major problem is that everything is in green, it's shifted up by x
pixels, and it's..um..flipped from left to right. I've been working on
this for a few weeks now and any insight to the problem is greatly
appreciated.

There are a couple of issues here. Depth 32 is not one of the standard
formats for DIBs. 24 is (B G R B G R), but not 32. To create 32-bit DIBs,
you are supposed to set biCompression to BI_BITFIELDS, and then supply
bitmasks in the three dwords that follow the BITMAPINFOHEADER telling
exactly where the R, G, and B values can be found. However, NT happens to
handle the format as you have it, so we'll leave it alone.

DIBs have no concept of an alpha channel. What are you going to use to
read this?
# since bitmaps are upside down, gotta flip it over
data = f2.read()

i = size-21
while i >= 0:
nm = 0x100

f1.seek(i)
temp1 = struct.unpack('B', f1.read(1))[0]

This reads one 8 bit value, and then tries to pull 32 bits of information
from it. You need to read a 16-bit value and crack it 4 bits at a time,
not 8 bits.
peek = temp1

a = nm*(peek >> 24) & 0xff
r = nm*(peek >> 16) & 0xff
g = nm*(peek >> 8 ) & 0xff
b = nm*(peek & 0xff)

What is the "multiply by 0x100" supposed to be doing? As near as I can
tell, since "*" binds more tightly than "&", this will result in a, r, and
always being 0.
sh = (a<<24)|(r<<16)|(g<<8)|b

f2.write(struct.pack('H', sh))

"sh" is a 32-bit value. You almost certainly want 'L' here, not 'H'.

Here is one that works, although it creates the DIB upside down, as you
note. I'll leave that as an exercise for the reader.

import os
import struct
import array

IN = 'testimg'
OUT = 'xxx.bmp'

fin = file(IN,'rb')

width = 100
insize = os.stat(IN)[6]
height = insize / width / 2

fout = file(OUT,'wb')

# Do the BITMAPFILEHEADER.

fout.write('BM')
bmfh = struct.pack( 'LLL', insize*2 + 14 + 40, 0, 14+40 )
fout.write(bmfh)

# Do the BITMAPINFOHEADER.

bmih = struct.pack('LLLHHLLLLLL',
40,
width,
height,
1,
32,
0, 0, 0, 0, 0, 0 )
fout.write(bmih)

# Expand the pixels, scan by scan.

for i in range(height):
words = array.array('H')
words.fromfile( fin, width )
rgba = array.array('B')
for word in words:
a = ((word >> 12) & 0xf) * 0x11
r = ((word >> 8) & 0xf) * 0x11
g = ((word >> 4) & 0xf) * 0x11
b = ((word >> 0) & 0xf) * 0x11
rgba.extend( [b,g,r,a] )
rgba.tofile(fout)
print '*',
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,067
Latest member
HunterTere

Latest Threads

Top