5 * Created by Morgan Conbere on 5/17/07.
13 #include "grfmt_imageio.h"
16 // ImageIO filter factory
18 GrFmtImageIO::GrFmtImageIO()
22 m_description = "Apple ImageIO (*.bmp;*.dib;*.exr;*.jpeg;*.jpg;*.jpe;*.jp2;*.pdf;*.png;*.tiff;*.tif)";
26 GrFmtImageIO::~GrFmtImageIO()
31 bool GrFmtImageIO::CheckFile( const char* filename )
33 if( !filename ) return false;
35 // If a CFImageRef can be retrieved from an image file, it is
36 // readable by ImageIO. Effectively this is using ImageIO
37 // to check the signatures and determine the file format for us.
38 CFURLRef imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL,
39 (const UInt8*)filename,
42 if( !imageURLRef ) return false;
44 CGImageSourceRef sourceRef = CGImageSourceCreateWithURL( imageURLRef, NULL );
45 CFRelease( imageURLRef );
46 if( !sourceRef ) return false;
48 CGImageRef imageRef = CGImageSourceCreateImageAtIndex( sourceRef, 0, NULL );
49 CFRelease( sourceRef );
50 if( !imageRef ) return false;
56 GrFmtReader* GrFmtImageIO::NewReader( const char* filename )
58 return new GrFmtImageIOReader( filename );
62 GrFmtWriter* GrFmtImageIO::NewWriter( const char* filename )
64 return new GrFmtImageIOWriter( filename );
68 /////////////////////// GrFmtImageIOReader ///////////////////
70 GrFmtImageIOReader::GrFmtImageIOReader( const char* filename ) : GrFmtReader( filename )
76 GrFmtImageIOReader::~GrFmtImageIOReader()
82 void GrFmtImageIOReader::Close()
84 CGImageRelease( imageRef );
90 bool GrFmtImageIOReader::ReadHeader()
93 CGImageSourceRef sourceRef;
96 imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL,
97 (const UInt8*)m_filename,
101 sourceRef = CGImageSourceCreateWithURL( imageURLRef, NULL );
102 CFRelease( imageURLRef );
106 imageRef = CGImageSourceCreateImageAtIndex( sourceRef, 0, NULL );
107 CFRelease( sourceRef );
111 m_width = CGImageGetWidth( imageRef );
112 m_height = CGImageGetHeight( imageRef );
114 CGColorSpaceRef colorSpace = CGImageGetColorSpace( imageRef );
118 m_iscolor = ( CGColorSpaceGetNumberOfComponents( colorSpace ) > 1 );
124 bool GrFmtImageIOReader::ReadData( uchar* data, int step, int color )
126 int bpp; // Bytes per pixel
128 // Set color to either CV_IMAGE_LOAD_COLOR or CV_IMAGE_LOAD_GRAYSCALE if unchanged
129 color = color > 0 || ( m_iscolor && color < 0 );
131 // Get Height, Width, and color information
135 CGContextRef context = NULL; // The bitmap context
136 CGColorSpaceRef colorSpace = NULL;
137 uchar* bitmap = NULL;
138 CGImageAlphaInfo alphaInfo;
140 // CoreGraphics will take care of converting to grayscale and back as long as the
141 // appropriate colorspace is set
142 if( color == CV_LOAD_IMAGE_GRAYSCALE )
144 colorSpace = CGColorSpaceCreateDeviceGray();
146 alphaInfo = kCGImageAlphaNone;
148 else if( color == CV_LOAD_IMAGE_COLOR )
150 colorSpace = CGColorSpaceCreateDeviceRGB();
151 bpp = 4; /* CG only has 8 and 32 bit color spaces, so we waste a byte */
152 alphaInfo = kCGImageAlphaNoneSkipLast;
157 bitmap = (uchar*)malloc( bpp * m_height * m_width );
160 CGColorSpaceRelease( colorSpace );
164 context = CGBitmapContextCreate( (void *)bitmap,
166 m_height, /* height */
167 m_bit_depth, /* bit depth */
168 bpp * m_width, /* bytes per row */
169 colorSpace, /* color space */
172 CGColorSpaceRelease( colorSpace );
179 // Copy the image data into the bitmap region
180 CGRect rect = {{0,0},{m_width,m_height}};
181 CGContextDrawImage( context, rect, imageRef );
183 uchar* bitdata = (uchar*)CGBitmapContextGetData( context );
187 CGContextRelease( context );
191 // Move the bitmap (in RGB) into data (in BGR)
195 // We make the assumption that the step is the number of colors * the width
196 assert( ( color ? 3 : 1 )*m_width == step );
198 if( color == CV_LOAD_IMAGE_COLOR ) {
199 for( int i = 0; i < m_width * m_height; ++i) {
201 data[dataIndex + 0] = bitdata[bitmapIndex + 2];
203 data[dataIndex + 1] = bitdata[bitmapIndex + 1];
205 data[dataIndex + 2] = bitdata[bitmapIndex + 0];
211 else if( color == CV_LOAD_IMAGE_GRAYSCALE )
213 // the bitmap representation is exactly what we want in data
214 memcpy( data, bitmap, m_width*m_height );
218 CGContextRelease( context );
223 /////////////////////// GrFmtImageIOWriter ///////////////////
225 GrFmtImageIOWriter::GrFmtImageIOWriter( const char* filename ) : GrFmtWriter( filename )
227 // Nothing to do here
231 GrFmtImageIOWriter::~GrFmtImageIOWriter()
233 // Nothing to do here
238 CFStringRef FilenameToUTI( const char* filename )
240 const char* ext = filename;
243 const char* temp = strchr( ext + 1, '.' );
248 CFStringRef imageUTI = NULL;
250 if( !strcmp(ext, ".bmp") || !strcmp(ext, ".dib") )
251 imageUTI = CFSTR( "com.microsoft.bmp" );
252 else if( !strcmp(ext, ".exr") )
253 imageUTI = CFSTR( "com.ilm.openexr-image" );
254 else if( !strcmp(ext, ".jpeg") || !strcmp(ext, ".jpg") || !strcmp(ext, ".jpe") )
255 imageUTI = CFSTR( "public.jpeg" );
256 else if( !strcmp(ext, ".jp2") )
257 imageUTI = CFSTR( "public.jpeg-2000" );
258 else if( !strcmp(ext, ".pdf") )
259 imageUTI = CFSTR( "com.adobe.pdf" );
260 else if( !strcmp(ext, ".png") )
261 imageUTI = CFSTR( "public.png" );
262 else if( !strcmp(ext, ".tiff") || !strcmp(ext, ".tif") )
263 imageUTI = CFSTR( "public.tiff" );
269 bool GrFmtImageIOWriter::WriteImage( const uchar* data, int step,
270 int width, int height, int /*depth*/, int _channels )
272 // Determine the appropriate UTI based on the filename extension
273 CFStringRef imageUTI = FilenameToUTI( m_filename );
275 // Determine the Bytes Per Pixel
276 int bpp = (_channels == 1) ? 1 : 4;
278 // Write the data into a bitmap context
279 CGContextRef context;
280 CGColorSpaceRef colorSpace;
281 uchar* bitmapData = NULL;
284 colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericGray );
286 colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGB );
290 bitmapData = (uchar*)malloc( bpp * height * width );
293 CGColorSpaceRelease( colorSpace );
297 context = CGBitmapContextCreate( bitmapData,
303 (bpp == 1) ? kCGImageAlphaNone :
304 kCGImageAlphaNoneSkipLast );
305 CGColorSpaceRelease( colorSpace );
312 // Copy pixel information from data into bitmapData
317 for( int i = 0; i < width * height; ++i)
320 bitmapData[bitmapIndex + 2] = data[dataIndex + 0];
322 bitmapData[bitmapIndex + 1] = data[dataIndex + 1];
324 bitmapData[bitmapIndex + 0] = data[dataIndex + 2];
332 // the bitmap representation is exactly what we want in data
333 memcpy( bitmapData, data, width * height );
336 // Turn the bitmap context into an imageRef
337 CGImageRef imageRef = CGBitmapContextCreateImage( context );
338 CGContextRelease( context );
345 // Write the imageRef to a file based on the UTI
346 CFURLRef imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL,
347 (const UInt8*)m_filename,
352 CGImageRelease( imageRef );
357 CGImageDestinationRef destRef = CGImageDestinationCreateWithURL( imageURLRef,
361 CFRelease( imageURLRef );
364 CGImageRelease( imageRef );
366 std::cerr << "!destRef" << std::endl << std::flush;
370 CGImageDestinationAddImage(destRef, imageRef, NULL);
371 if( !CGImageDestinationFinalize(destRef) )
373 std::cerr << "Finalize failed" << std::endl << std::flush;
377 CFRelease( destRef );
378 CGImageRelease( imageRef );
384 #endif /* HAVE_IMAGEIO */