openframeworks / openFrameworks

openFrameworks is a community-developed cross platform toolkit for creative coding in C++.
http://openframeworks.cc
Other
9.97k stars 2.55k forks source link

Loading alternative additional pixel types (e.g. signed short) via ofPixels #3249

Open bakercp opened 10 years ago

bakercp commented 10 years ago

Hi all, I'm in the process of loading GeoTIFF images (terrain data from NASA, etc) and found that the images won't load in their native format using the standard ofPixels loading methods. After digging around a little bit, it turns out that it is because the image format (TIFF) uses 16bit signed shorts. I tried to then load it by passing ofPixels_<short> (as opposed to using ofShortPixels (aka ofPixels_<unsigned short>), but putBmpIntoPixels() method doesn't support signed short pixels and fails.

Currently I'm able to successfully load the GeoTIFF images by reimplementing the FreeImage code, but I'm wondering if there would be a way to make putBmpIntoPixels() more flexible to allow data types other than the standard float, unsigned char, and unsigned short when using ofPixels_<>.

I realize there are strategic and style reasons for pre-defining the ofPixel_ types, but just curious. @arturoc do you have any thoughts on this?

bakercp commented 10 years ago

Additionally, if we don't add this to the core, then addons that implement custom FreeImage loading code probably need access to ofInitFreeImage(), which is currently only available in ofImage.

bakercp commented 10 years ago

Also, just a note, I think this could result in a memory leak:

https://github.com/openframeworks/openFrameworks/blob/master/libs/openFrameworks/graphics/ofImage.cpp#L270-L271

Edit: PR here #3250

bilderbuchi commented 10 years ago

does it actually make sense to use signed ints for image data?

bakercp commented 10 years ago

Well, it's a possibility of the TIFF spec and they way they do it with GeoTIFF. For most purposes it probably doesn't make sense, but it does exist and FreeImage knows how to read it. openFrameworks just doesn't allow the possibility of using FreeImage in this way. It's certainly an edge case, and likely doesn't make sense in the context of an ofImage, but perhaps there is a way to make our loading code more generic to pixel types other than the standard?

arturoc commented 10 years ago

i think we only need to have support for 8bits, 16bits and 32bits, in ofImage. The fact that is signed or not shouldn't make any difference. Perhaps the load will be slightly slower because it needs a range conversion but it should work. Also when we load 16bits signed or unsigned in an 8bits ofImage it should do the conversion too. What i'm trying to say is that i don't think we need to give support for signed or unsigned, ust make the load methods convert from whatever format into the right one for the target ofPixels.

the plan is to separate ofImage at some point into ofImageFile which will be able to read any type into any ofPixels_ but in any case i think having 8,16,32 ofImage versions should be enough, we just need to handle the conversion appropriately.

so whenever we have ofImageFile we'll be able to do:

imgFile >> signedShortPixels;

but we'll still have only ofShortImage and that should work too

bakercp commented 10 years ago

That makes sense -- I think we just need to make a case for grayscale (1 channel) and the FIT_INT16 type.

It fails here:

https://github.com/openframeworks/openFrameworks/blob/master/libs/openFrameworks/graphics/ofImage.cpp#L164

The default (else) case, is invalid for the FIT_INT16 type (which is the standard GeoTIFF format).

companje commented 8 years ago

I modified some code in putBmpIntoPixels to be able to load 16 bits grayscale images:

    if(sizeof(PixelType)==1 &&
        (FreeImage_GetColorType(bmp) == FIC_PALETTE || FreeImage_GetBPP(bmp) < 8
        ||  imgType!=FIT_BITMAP)) {
        if(FreeImage_IsTransparent(bmp)) {
            bmpConverted = FreeImage_ConvertTo32Bits(bmp);
////////////////////////////////////////////
// added this to support 16 bit grayscale images
        } else if (FreeImage_GetBPP(bmp)==16) {                     
            bmpConverted = FreeImage_ConvertToType(bmp,FIT_UINT16); 
////////////////////////////////////////////
        } else {
            bmpConverted = FreeImage_ConvertTo24Bits(bmp);
        }
        bmp = bmpConverted;

EDIT: It does not work as expected however.

johanjohan commented 6 years ago

@bakercp : what tools did you use for reading geotiffs and the incorporated metadata? As far as I can see, there are no dedicated ofxAddons for geotiff.

dimitre commented 5 months ago

10 years after. ofPixels used to have an error with memory allocation, addressed recently on this PR