Posted: Thu Jun 21, 2012 12:34 am
Joined: 21 Jun 2012
Posts: 4
I'm trying to export image data from blender. Getting width, height and size works fine but something is wrong when I write the pixels to file.
This is the image I have loaded in blender:
http://localhostr.com/files/6WHyRnC/Crate.jpg
this is how it looks in my game engine when I load it:
http://localhostr.com/files/l4oWGWF/Untitled.png
I know I can just load the texture file from my game but I want to have the images packed inside the model file along with the vertices, normals etc...
This is how I export the image data from blender, am I doing something completely wrong here?
| Code: |
# Write number of images
WriteInt(File, len(bpy.data.images))
for i, Image in enumerate(bpy.data.images):
# Write width
WriteInt(File, Image.size[0])
# Write height
WriteInt(File, Image.size[1])
# Write size
WriteInt(File, len(Image.pixels))
# Write pixels
Pixels = array('f', Image.pixels)
Pixels.tofile(File) |
Posted: Thu Jun 21, 2012 3:24 pm
Joined: 05 Aug 2003
Posts: 3491
If you are writing PNGs, they have a header and a bunch of chunks, not just a linear stream of pixels.
Posted: Thu Jun 21, 2012 9:54 pm
Joined: 21 Jun 2012
Posts: 4
I'm not writing as a image file so I don't need the header. I want the raw pixels only.
Posted: Fri Jun 22, 2012 10:48 am
Joined: 05 Apr 2009
Posts: 694
looks like the byte order is messed up...
i've done this to export to bmp:
| Code: |
import bpy
import struct
def hx(float_color):
return int(float_color * 255)
with open("D:\\imgg.bmp", "wb") as f:
i = bpy.data.images[0]
p = i.pixels
w, h = i.size
f.write(bytearray("BM", 'ASCII'))
f.write(struct.pack("iiiiiihhiiiiii",
(54+len(p)*3), 0, 54, 40, w, h, 1, 24, 0, 0, 0, 0,
0, 0 ))
c = 0
for i in range(len(p)//4):
f.write(struct.pack("BBB", hx(p[c+2]), hx(p[c+1]), hx(p[c])))
c += 4
|
as you see, i need to process the values (float to int, different order)
i had similar stripes like you in my first attempt, 'cause Blender's Image.pixels are stored like
RGBA RGBA RGBA ...
but the output format was bitmap 24bpp, which is like:
BGR BGR BGR ...
see the mismatch:
| Code: |
BGR BGR BGR BGR
RGB ARG BAR GBA
|
so you may have to pick the proper data type (e.g. 32bpp) or process the input before outputting
_________________
I'm sitting, waiting, wishing, building Blender in superstition...
Posted: Sat Jun 23, 2012 12:51 am
Joined: 10 Sep 2011
Posts: 22
Interesting topic. Anyway, I tried your code and it works.
But srsly.... but it's just slow. And with slow I mean it's freaking mighty slow.
Why is that?
Posted: Sat Jun 23, 2012 10:49 pm
Joined: 21 Jun 2012
Posts: 4
| CoDEmanX wrote: |
looks like the byte order is messed up...
i've done this to export to bmp:
| Code: | import bpy
import struct
def hx(float_color):
return int(float_color * 255)
with open("D:\\imgg.bmp", "wb") as f:
i = bpy.data.images[0]
p = i.pixels
w, h = i.size
f.write(bytearray("BM", 'ASCII'))
f.write(struct.pack("iiiiiihhiiiiii",
(54+len(p)*3), 0, 54, 40, w, h, 1, 24, 0, 0, 0, 0,
0, 0 ))
c = 0
for i in range(len(p)//4):
f.write(struct.pack("BBB", hx(p[c+2]), hx(p[c+1]), hx(p[c])))
c += 4
|
as you see, i need to process the values (float to int, different order)
i had similar stripes like you in my first attempt, 'cause Blender's Image.pixels are stored like
RGBA RGBA RGBA ...
but the output format was bitmap 24bpp, which is like:
BGR BGR BGR ...
see the mismatch:
| Code: |
BGR BGR BGR BGR
RGB ARG BAR GBA
|
so you may have to pick the proper data type (e.g. 32bpp) or process the input before outputting |
Thanks, it works! To bad though that it's so slow :/
Posted: Sun Jun 24, 2012 8:31 pm
Joined: 05 Apr 2009
Posts: 694
it's not optimized, could be improved i bet
however, i rather switched to TGA format, as it officially supports alpha (RGBA)
did some speed tests and came up with this:
| Code: |
import bpy
import struct, time
def write_tga(image_index, filepath):
with open(filepath, "wb") as f:
try:
img = bpy.data.images[image_index]
except IndexError:
print("Error: bpy.data.images[%i] does not exist!" % image_index)
return
w, h = img.size
f.write(struct.pack("<HBIIBHHBB", 0, 2, 0, 0, 0, w, h, 32, 8))
f.write(bytes([int(pix*255) for pix in img.pixels]))
f.close()
filepath = "D:\\imgg.tga"
t = time.clock()
write_tga(0, filepath)
print("Time: %.2f" % (time.clock() - t)) |
with comments (incl. other methods i tried out):
http://www.pasteall.org/33208/python
struct.pack byte for byte was really slow, all others varying between 6.4 and 7.5 seconds
the one i finally put takes 6.1 - 6.5, for a 1024*1024 pixel image
_________________
I'm sitting, waiting, wishing, building Blender in superstition...
Posted: Wed Jun 27, 2012 1:17 pm
Joined: 21 Jun 2012
Posts: 4
Thanks

works perfect now!
Posted: Tue Aug 14, 2012 12:19 pm
Joined: 10 Sep 2011
Posts: 22
Woah it's fast now.
Can you make it so Red channel is swapped with Blue? I mean convert RGBA -> BGRA.
Posted: Tue Aug 14, 2012 1:25 pm
Joined: 10 Sep 2011
Posts: 22
Ok, to answer my own question: need to convert bytearray instead and then it's free to manipulate in any way to wish.