Create a gist now

Instantly share code, notes, and snippets.

Embed
Decoding JPEG 2000 files to UIImage
#import <Foundation/Foundation.h>
extern UIImage * UIImageWithJPEG2000Data( NSData * data ) ;
#import "UIImage+JPEG2000.h"
#import <objc/runtime.h>
#import "openjpeg.h"
static UIImage * UIImageWithJPEG2000File( id self, SEL selector, NSString * name ) ;
@implementation NSObject (UIImage_JPEG2000)
static UIImage * (*old_UIImage_imageNamed)(id target, SEL selector, NSString * name ) = NULL ;
+(void)load
{
NSAutoreleasePool * pool = [[ NSAutoreleasePool alloc ] init ] ;
Method m = class_getClassMethod( [ UIImage class ], @selector( imageNamed: )) ;
old_UIImage_imageNamed = (UIImage *(*)(id, SEL, NSString*))method_setImplementation( m, (IMP)UIImageWithJPEG2000File ) ;
DebugAssert( old_UIImage_imageNamed ) ;
[ pool release ] ;
}
@end
static CGImageRef CGImageCreateWithJPEG2000Image( opj_image_t * image )
{
long w = image->comps[0].w ;
long h = image->comps[0].h ;
DebugAssert( w > 0 && h > 0 ) ;
CGColorSpaceRef cs = NULL ;
BOOL hasAlpha = NO ;
if ( image->numcomps == 1 )
{
cs = CGColorSpaceCreateDeviceGray() ;
}
else
{
// only support 3 (RGB) or 4 (RGBA) component images
DebugAssert( image->numcomps == 3 || image->numcomps == 4 ) ;
hasAlpha = image->numcomps == 4 ;
cs = CGColorSpaceCreateDeviceRGB() ;
}
DebugAssert( cs ) ;
for( int index=0; index < image->numcomps; ++index )
{
DebugAssert( image->comps[ index ].prec == 8 &&
w == image->comps[index].w
&& h == image->comps[index].h ) ;
}
size_t bitmapNumBytes = w * h * 4;//image->numcomps ;
CFMutableDataRef bitmapCFData = CFDataCreateMutable( kCFAllocatorDefault, 0 ) ;
CFDataSetLength( bitmapCFData, bitmapNumBytes ) ;
DebugAssert( bitmapCFData ) ;
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Big ;
if ( image->numcomps == 1 )
{
uint8_t * p = (uint8_t*)CFDataGetMutableBytePtr( bitmapCFData ) ;
uint32_t * s = (uint32_t*)image->comps[0].data ;
for( int index=0, count = w * h; index < count; ++index )
{
*p = *s ;
++p ;
++s ;
}
}
else
{
uint8_t * p = (uint8_t*)CFDataGetMutableBytePtr( bitmapCFData ) ;
uint32_t * r = (uint32_t *)image->comps[0].data ;
uint32_t * g = (uint32_t *)image->comps[1].data ;
uint32_t * b = (uint32_t *)image->comps[2].data ;
if ( hasAlpha )
{
bitmapInfo |= kCGImageAlphaPremultipliedLast ;
uint32_t * a = (uint32_t *)image->comps[3].data ;
for( int index=0, count = w * h; index < count; ++index )
{
*p++ = *r++ ;
*p++ = *g++ ;
*p++ = *b++ ;
*p++ = *a++ ;
}
}
else
{
bitmapInfo |= kCGImageAlphaNoneSkipLast ;
for( int index=0, count = w * h; index < count; ++index )
{
*p++ = *r++ ;
*p++ = *g++ ;
*p++ = *b++ ;
*p++ = 0xFF ;
}
}
}
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData( bitmapCFData ) ;
if ( bitmapCFData ) { CFRelease( bitmapCFData ) ; }
DebugAssert( dataProvider ) ;
int bpc = image->comps[0].prec ; // bits per component
int bpp = image->numcomps == 1 ? bpc : (4 * bpc) ; // bits per pixel
int bpr = bpp * w / 8 ; // bytes per row
CGImageRef cgImage = CGImageCreate(w, h, bpc, bpp, bpr, cs, bitmapInfo, dataProvider, NULL, false, kCGRenderingIntentDefault ) ;
CGDataProviderRelease( dataProvider ) ;
CGColorSpaceRelease( cs ) ;
DebugAssert( cgImage ) ;
return cgImage ;
}
UIImage * UIImageWithJPEG2000Data( NSData * data )
{
if ( data.length == 0 )
{
DebugLog(@"%s data is empty\n", __PRETTY_FUNCTION__ ) ;
return nil ;
}
opj_dinfo_t * decompressor = opj_create_decompress(CODEC_JP2) ; // CODEC_JP2? Just a guess.
DebugAssert( decompressor ) ;
opj_dparameters_t params ;
opj_set_default_decoder_parameters( & params );
opj_setup_decoder( decompressor, & params ) ;
opj_cio_t * cio = opj_cio_open( (opj_common_struct_t*)decompressor, (unsigned char *)data.bytes, data.length ) ;
DebugAssert( cio ) ;
// opj_set_event_mgr( (opj_common_ptr)decompressor, & (opj_event_mgr_t){ error_handler, warning_handler, info_handler }, NULL ) ;
opj_image_t * image = opj_decode( decompressor, cio ) ;
CGImageRef cgImage = nil ;
if ( image )
{
cgImage = CGImageCreateWithJPEG2000Image( image ) ;
opj_image_destroy( image ) ;
}
opj_cio_close( cio ) ;
opj_destroy_decompress( decompressor ) ;
if ( !cgImage )
{
return nil ;
}
UIImage * result = [ UIImage imageWithCGImage:cgImage ] ;
CGImageRelease( cgImage ) ;
return result ;
}
static UIImage * UIImageWithJPEG2000File( id self, SEL selector, NSString * name )
{
UIImage * result = (*old_UIImage_imageNamed)( self, selector, name ) ;
if ( !result )
{
NSError * error = nil ;
NSString * baseName = [ name stringByDeletingPathExtension ] ;
NSString * extension = [ name pathExtension ] ;
NSString * path = [ [ NSBundle mainBundle ] pathForResource:baseName ofType:extension ] ;
if ( path )
{
NSData * data = [ NSData dataWithContentsOfFile:path options:NSDataReadingMapped error:&error ] ;
DebugAssert( data ) ;
result = UIImageWithJPEG2000Data( data ) ;
}
}
return result ;
}
#import "UIImage+JPEG2000.h"
#import <objc/runtime.h>
#import "openjpeg.h"
static UIImage * UIImageWithJPEG2000File( id self, SEL selector, NSString * name ) ;
@implementation NSObject (UIImage_JPEG2000)
static UIImage * (*old_UIImage_imageNamed)(id target, SEL selector, NSString * name ) = NULL ;
+(void)load
{
NSAutoreleasePool * pool = [[ NSAutoreleasePool alloc ] init ] ;
Method m = class_getClassMethod( [ UIImage class ], @selector( imageNamed: )) ;
old_UIImage_imageNamed = (UIImage *(*)(id, SEL, NSString*))method_setImplementation( m, (IMP)UIImageWithJPEG2000File ) ;
DebugAssert( old_UIImage_imageNamed ) ;
[ pool release ] ;
}
@end
static CGImageRef CGImageCreateWithJPEG2000Image( opj_image_t * image )
{
long w = image->comps[0].w ;
long h = image->comps[0].h ;
DebugAssert( w > 0 && h > 0 ) ;
CGColorSpaceRef cs = NULL ;
BOOL hasAlpha = NO ;
if ( image->numcomps == 1 )
{
cs = CGColorSpaceCreateDeviceGray() ;
}
else
{
// only support 3 (RGB) or 4 (RGBA) component images
DebugAssert( image->numcomps == 3 || image->numcomps == 4 ) ;
hasAlpha = image->numcomps == 4 ;
cs = CGColorSpaceCreateDeviceRGB() ;
}
DebugAssert( cs ) ;
for( int index=0; index < image->numcomps; ++index )
{
DebugAssert( image->comps[ index ].prec == 8 &&
w == image->comps[index].w
&& h == image->comps[index].h ) ;
}
size_t bitmapNumBytes = w * h * 4;//image->numcomps ;
CFMutableDataRef bitmapCFData = CFDataCreateMutable( kCFAllocatorDefault, 0 ) ;
CFDataSetLength( bitmapCFData, bitmapNumBytes ) ;
DebugAssert( bitmapCFData ) ;
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Big ;
if ( image->numcomps == 1 )
{
uint8_t * p = (uint8_t*)CFDataGetMutableBytePtr( bitmapCFData ) ;
uint32_t * s = (uint32_t*)image->comps[0].data ;
for( int index=0, count = w * h; index < count; ++index )
{
*p = *s ;
++p ;
++s ;
}
}
else
{
uint8_t * p = (uint8_t*)CFDataGetMutableBytePtr( bitmapCFData ) ;
uint32_t * r = (uint32_t *)image->comps[0].data ;
uint32_t * g = (uint32_t *)image->comps[1].data ;
uint32_t * b = (uint32_t *)image->comps[2].data ;
if ( hasAlpha )
{
bitmapInfo |= kCGImageAlphaPremultipliedLast ;
uint32_t * a = (uint32_t *)image->comps[3].data ;
for( int index=0, count = w * h; index < count; ++index )
{
*p++ = *r++ ;
*p++ = *g++ ;
*p++ = *b++ ;
*p++ = *a++ ;
}
}
else
{
bitmapInfo |= kCGImageAlphaNoneSkipLast ;
for( int index=0, count = w * h; index < count; ++index )
{
*p++ = *r++ ;
*p++ = *g++ ;
*p++ = *b++ ;
*p++ = 0xFF ;
}
}
}
CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData( bitmapCFData ) ;
if ( bitmapCFData ) { CFRelease( bitmapCFData ) ; }
DebugAssert( dataProvider ) ;
int bpc = image->comps[0].prec ; // bits per component
int bpp = image->numcomps == 1 ? bpc : (4 * bpc) ; // bits per pixel
int bpr = bpp * w / 8 ; // bytes per row
CGImageRef cgImage = CGImageCreate(w, h, bpc, bpp, bpr, cs, bitmapInfo, dataProvider, NULL, false, kCGRenderingIntentDefault ) ;
CGDataProviderRelease( dataProvider ) ;
CGColorSpaceRelease( cs ) ;
DebugAssert( cgImage ) ;
return cgImage ;
}
UIImage * UIImageWithJPEG2000Data( NSData * data )
{
if ( data.length == 0 )
{
DebugLog(@"%s data is empty\n", __PRETTY_FUNCTION__ ) ;
return nil ;
}
opj_dinfo_t * decompressor = opj_create_decompress(CODEC_JP2) ; // CODEC_JP2? Just a guess.
DebugAssert( decompressor ) ;
opj_dparameters_t params ;
opj_set_default_decoder_parameters( & params );
opj_setup_decoder( decompressor, & params ) ;
opj_cio_t * cio = opj_cio_open( (opj_common_struct_t*)decompressor, (unsigned char *)data.bytes, data.length ) ;
DebugAssert( cio ) ;
// opj_set_event_mgr( (opj_common_ptr)decompressor, & (opj_event_mgr_t){ error_handler, warning_handler, info_handler }, NULL ) ;
opj_image_t * image = opj_decode( decompressor, cio ) ;
CGImageRef cgImage = nil ;
if ( image )
{
cgImage = CGImageCreateWithJPEG2000Image( image ) ;
opj_image_destroy( image ) ;
}
opj_cio_close( cio ) ;
opj_destroy_decompress( decompressor ) ;
if ( !cgImage )
{
return nil ;
}
UIImage * result = [ UIImage imageWithCGImage:cgImage ] ;
CGImageRelease( cgImage ) ;
return result ;
}
static UIImage * UIImageWithJPEG2000File( id self, SEL selector, NSString * name )
{
UIImage * result = (*old_UIImage_imageNamed)( self, selector, name ) ;
if ( !result )
{
NSError * error = nil ;
NSString * baseName = [ name stringByDeletingPathExtension ] ;
NSString * extension = [ name pathExtension ] ;
NSString * path = [ [ NSBundle mainBundle ] pathForResource:baseName ofType:extension ] ;
if ( path )
{
NSData * data = [ NSData dataWithContentsOfFile:path options:NSDataReadingMapped error:&error ] ;
DebugAssert( data ) ;
result = UIImageWithJPEG2000Data( data ) ;
}
}
return result ;
}
@samsonrck48

This comment has been minimized.

Show comment
Hide comment
@samsonrck48

samsonrck48 May 22, 2012

Hi,

Thankyou so much for you information.

Can you please guide me from where i can get the "UIImage+JPEG2000.h".

Hope for your help.

Samson

Hi,

Thankyou so much for you information.

Can you please guide me from where i can get the "UIImage+JPEG2000.h".

Hope for your help.

Samson

@nielsbot

This comment has been minimized.

Show comment
Hide comment
@nielsbot

nielsbot May 22, 2012

I added it--but as you can see there is nothing there. :)

Owner

nielsbot commented May 22, 2012

I added it--but as you can see there is nothing there. :)

@samsonrck48

This comment has been minimized.

Show comment
Hide comment
@samsonrck48

samsonrck48 May 22, 2012

Thanks a lot for your quick turnaround.

We can't find a method like "UIImageWithJPEG2000File" OpenJpeg.h file we have.

So Can you please kindly guide us in how to call the method.

Is there any file like "UIImageWithJPEG2000File.h" so that we can call those methods.

Hoping for your help.

Thanks a lot for your quick turnaround.

We can't find a method like "UIImageWithJPEG2000File" OpenJpeg.h file we have.

So Can you please kindly guide us in how to call the method.

Is there any file like "UIImageWithJPEG2000File.h" so that we can call those methods.

Hoping for your help.

@samsonrck48

This comment has been minimized.

Show comment
Hide comment
@samsonrck48

samsonrck48 May 23, 2012

Hi I am still waiting for your reply. When we added these files and tried to compile following errors occured:

ld: duplicate symbol _UIImageWithJPEG2000Data in /Users/user/Library/Developer/Xcode/DerivedData/ImageDecoder-cdbtscpixkufnxdtohvztbkldnzd/Build/Intermediates/ImageDecoder.build/Debug-iphonesimulator/ImageDecoder.build/Objects-normal/i386/UIImageJPEG2000.o and /Users/user/Library/Developer/Xcode/DerivedData/ImageDecoder-cdbtscpixkufnxdtohvztbkldnzd/Build/Intermediates/ImageDecoder.build/Debug-iphonesimulator/ImageDecoder.build/Objects-normal/i386/UIImage+JPEG2000.o for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I couldn't figure out where it went wrong. Hope you got a solution in handy and will show up with it. :)

Hi I am still waiting for your reply. When we added these files and tried to compile following errors occured:

ld: duplicate symbol _UIImageWithJPEG2000Data in /Users/user/Library/Developer/Xcode/DerivedData/ImageDecoder-cdbtscpixkufnxdtohvztbkldnzd/Build/Intermediates/ImageDecoder.build/Debug-iphonesimulator/ImageDecoder.build/Objects-normal/i386/UIImageJPEG2000.o and /Users/user/Library/Developer/Xcode/DerivedData/ImageDecoder-cdbtscpixkufnxdtohvztbkldnzd/Build/Intermediates/ImageDecoder.build/Debug-iphonesimulator/ImageDecoder.build/Objects-normal/i386/UIImage+JPEG2000.o for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I couldn't figure out where it went wrong. Hope you got a solution in handy and will show up with it. :)

@nielsbot

This comment has been minimized.

Show comment
Hide comment
@nielsbot

nielsbot May 30, 2012

Owner

nielsbot commented May 30, 2012

@srijithv

This comment has been minimized.

Show comment
Hide comment
@srijithv

srijithv May 30, 2012

Hey,
Sorry for that comment. Removed it now. That was completely my mistake! It works like a gem!! Apologies! Memory was loosing on my end, and instrument pointed it to your code :-)

Hey,
Sorry for that comment. Removed it now. That was completely my mistake! It works like a gem!! Apologies! Memory was loosing on my end, and instrument pointed it to your code :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment