Load a rectangular section of an image

BlitzMax Forums/BlitzMax Programming/Load a rectangular section of an image

GfK(Posted 2013) [#1]
Just wondering - if I have a massive image of arbitrary size (say, 3000x3000), is it possible to load, for example, a 512x512 portion from anywhere within that image (without loading the entire 3000x3000 image as a pixmap first)?

I'm thinking not, but figured I'd ask.


Brucey(Posted 2013) [#2]
You could probably do it with an uncompressed bmp, knowing its dimensions and whatnot.


computercoder(Posted 2013) [#3]
I don't think that is possible - at least not feasible due to the idea that you need to know specific bounds of the image itself and the rectangle you are needing to grab.

My only thought is to evaluate the image as its loading and possibly keep track of the content as it loads? In the end, I believe you'd be better off just loading the image into a pixmap, ripping out what you need into a new pixmap (or set of pixmaps) and then release it after you are done with that (assuming you are looking to save resources).


ImaginaryHuman(Posted 2013) [#4]
You can likely find out the dimensions of the image from the file data. You will need to parse through the file format structure yourself. But extracting a portion depends on the format. Most formats are based on rows, and some have compression algorithms. JPEG is based on blocks and I think I've seen it possible to extract individual blocks, which allows things like rotation without quality loss. If its a PNG you have to decompress the whole row to get the original data. Like Brucey said BMP is uncompressed so would let you more easily lookup only the stuff you want. GIF similarly would require whole rows, or worse.

Within the code that actually loads an image, usually like for PNG it'll read a row into a buffer and then decode it and then output it to the pixmap... you could discard part of the buffer and end up with just the pixmap you want but it still has to read the entire file.


GfK(Posted 2013) [#5]
I already kind of discounted the uncompressed bitmap idea. I was going to store the image data in a proprietary format, 3000x3000 pixels, 4 bytes per pixel comes to over 36MB.

I'll have to think of something else. Thanks all!


TomToad(Posted 2013) [#6]
If you are making a proprietary format, you might be able to come up with an efficient compression scheme that will also allow you to grab random parts of the image. For example, you could compress by row and have a pointer at the start of each row pointing to the next. So, for example, you could have 00 0A 15 13 D3 4F AA 12 3E 44 92 01 00 09... The first 2 bytes is the compressed byte count of the row followed by the compressed bytes. 00 0A means the row is compressed in 10 bytes. the next 10 bytes are the pixel data compressed, then an 00 09 showing the next 9 bytes make up the next row, and so on. So, to load only part of the image, you could do something like this
//pseudocode

Top = 10
Left = 15
Right = 115
Bottom = 210

ImageStream = ReadImageFile()
for i = 1 to Top
    Skip = ReadInt(ImageStream)
   SeekStream(StreamPos()+Skip)
next

For i = Top to Bottom
    CompressedBytes = ReadInt(ImageStream)
    RowOfPixels = Uncompress(CompressedBytes)
    CopyPixels(RowOfPixels,Left,Right,NewImage)
Next
Close ImageStream



jsp(Posted 2013) [#7]
When reading this I remembered an code archive entry from BlitzSupport, to get the picture size without loading the image:
http://www.blitzmax.com/codearcs/codearcs.php?code=2477