By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,243 Members | 1,141 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,243 IT Pros & Developers. It's quick & easy.

Converting to ARGB and writing to a bitmap

P: n/a
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

Mar 17 '06 #1
Share this Question
Share on Google+
2 Replies


P: n/a
he*********@gmail.com wrote:
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.

--
Steve Juranich
Tucson, AZ
USA

Mar 17 '06 #2

P: n/a
he*********@gmail.com wrote:

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 '*',
--
- Tim Roberts, ti**@probo.com
Providenza & Boekelheide, Inc.
Mar 19 '06 #3

This discussion thread is closed

Replies have been disabled for this discussion.