5 * Created by Morgan Conbere on 5/17/07.
13 #include "grfmt_imageio.h"
18 /////////////////////// ImageIODecoder ///////////////////
20 ImageIODecoder::ImageIODecoder()
25 ImageIODecoder::~ImageIODecoder()
31 void ImageIODecoder::close()
33 CGImageRelease( imageRef );
38 size_t ImageIODecoder::signatureLength() const
43 bool ImageIODecoder::checkSignature( const string& signature ) const
45 // TODO: implement real signature check
49 ImageDecoder ImageIODecoder::newDecoder() const
51 return new ImageIODecoder;
54 bool ImageIODecoder::readHeader()
57 CGImageSourceRef sourceRef;
58 // diciu, if ReadHeader is called twice in a row make sure to release the previously allocated imageRef
60 CGImageRelease(imageRef);
63 imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL,
64 (const UInt8*)m_filename.c_str(), m_filename.size(), false );
66 sourceRef = CGImageSourceCreateWithURL( imageURLRef, NULL );
67 CFRelease( imageURLRef );
71 imageRef = CGImageSourceCreateImageAtIndex( sourceRef, 0, NULL );
72 CFRelease( sourceRef );
76 m_width = CGImageGetWidth( imageRef );
77 m_height = CGImageGetHeight( imageRef );
79 CGColorSpaceRef colorSpace = CGImageGetColorSpace( imageRef );
83 m_type = CGColorSpaceGetNumberOfComponents( colorSpace ) > 1 ? CV_8UC3 : CV_8UC1;
89 bool ImageIODecoder::readData( Mat& img )
91 uchar* data = img.data;
93 bool color = img.channels() > 1;
94 int bpp; // Bytes per pixel
97 // Get Height, Width, and color information
101 CGContextRef context = NULL; // The bitmap context
102 CGColorSpaceRef colorSpace = NULL;
103 uchar* bitmap = NULL;
104 CGImageAlphaInfo alphaInfo;
106 // CoreGraphics will take care of converting to grayscale and back as long as the
107 // appropriate colorspace is set
108 if( color == CV_LOAD_IMAGE_GRAYSCALE )
110 colorSpace = CGColorSpaceCreateDeviceGray();
112 alphaInfo = kCGImageAlphaNone;
114 else if( color == CV_LOAD_IMAGE_COLOR )
116 colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGBLinear );
117 bpp = 4; /* CG only has 8 and 32 bit color spaces, so we waste a byte */
118 alphaInfo = kCGImageAlphaNoneSkipLast;
123 bitmap = (uchar*)malloc( bpp * m_height * m_width );
126 CGColorSpaceRelease( colorSpace );
130 context = CGBitmapContextCreate( (void *)bitmap,
132 m_height, /* height */
133 bit_depth, /* bit depth */
134 bpp * m_width, /* bytes per row */
135 colorSpace, /* color space */
138 CGColorSpaceRelease( colorSpace );
145 // Copy the image data into the bitmap region
146 CGRect rect = {{0,0},{m_width,m_height}};
147 CGContextDrawImage( context, rect, imageRef );
149 uchar* bitdata = (uchar*)CGBitmapContextGetData( context );
153 CGContextRelease( context );
157 // Move the bitmap (in RGB) into data (in BGR)
160 if( color == CV_LOAD_IMAGE_COLOR )
164 for (int y = 0; y < m_height; y++)
166 uchar * line = base + y * step;
168 for (int x = 0; x < m_width; x++)
171 line[0] = bitdata[bitmapIndex + 2];
173 line[1] = bitdata[bitmapIndex + 1];
175 line[2] = bitdata[bitmapIndex + 0];
182 else if( color == CV_LOAD_IMAGE_GRAYSCALE )
184 for (int y = 0; y < m_height; y++)
185 memcpy (data + y * step, bitmap + y * m_width, m_width);
189 CGContextRelease( context );
194 /////////////////////// ImageIOEncoder ///////////////////
196 ImageIOEncoder::ImageIOEncoder()
198 m_description = "Apple ImageIO (*.bmp;*.dib;*.exr;*.jpeg;*.jpg;*.jpe;*.jp2;*.pdf;*.png;*.tiff;*.tif)";
202 ImageIOEncoder::~ImageIOEncoder()
207 ImageEncoder ImageIOEncoder::newEncoder() const
209 return new ImageIOEncoder;
213 CFStringRef FilenameToUTI( const char* filename )
215 const char* ext = filename;
218 CFStringRef imageUTI = NULL;
222 const char* temp = strchr( ext + 1, '.' );
230 ext_buf = (char*)malloc(strlen(ext)+1);
231 for(i = 0; ext[i] != '\0'; i++)
232 ext_buf[i] = (char)tolower(ext[i]);
236 if( !strcmp(ext, ".bmp") || !strcmp(ext, ".dib") )
237 imageUTI = CFSTR( "com.microsoft.bmp" );
238 else if( !strcmp(ext, ".exr") )
239 imageUTI = CFSTR( "com.ilm.openexr-image" );
240 else if( !strcmp(ext, ".jpeg") || !strcmp(ext, ".jpg") || !strcmp(ext, ".jpe") )
241 imageUTI = CFSTR( "public.jpeg" );
242 else if( !strcmp(ext, ".jp2") )
243 imageUTI = CFSTR( "public.jpeg-2000" );
244 else if( !strcmp(ext, ".pdf") )
245 imageUTI = CFSTR( "com.adobe.pdf" );
246 else if( !strcmp(ext, ".png") )
247 imageUTI = CFSTR( "public.png" );
248 else if( !strcmp(ext, ".tiff") || !strcmp(ext, ".tif") )
249 imageUTI = CFSTR( "public.tiff" );
257 bool ImageIOEncoder::write( const Mat& img, const vector<int>& params )
259 int width = img.cols, height = img.rows;
260 int _channels = img.channels();
261 const uchar* data = img.data;
264 // Determine the appropriate UTI based on the filename extension
265 CFStringRef imageUTI = FilenameToUTI( m_filename.c_str() );
267 // Determine the Bytes Per Pixel
268 int bpp = (_channels == 1) ? 1 : 4;
270 // Write the data into a bitmap context
271 CGContextRef context;
272 CGColorSpaceRef colorSpace;
273 uchar* bitmapData = NULL;
276 colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericGray );
278 colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGBLinear );
282 bitmapData = (uchar*)malloc( bpp * height * width );
285 CGColorSpaceRelease( colorSpace );
289 context = CGBitmapContextCreate( bitmapData,
295 (bpp == 1) ? kCGImageAlphaNone :
296 kCGImageAlphaNoneSkipLast );
297 CGColorSpaceRelease( colorSpace );
304 // Copy pixel information from data into bitmapData
308 const uchar * base = data;
310 for (int y = 0; y < height; y++)
312 const uchar * line = base + y * step;
314 for (int x = 0; x < width; x++)
317 bitmapData[bitmapIndex + 2] = line[0];
319 bitmapData[bitmapIndex + 1] = line[1];
321 bitmapData[bitmapIndex + 0] = line[2];
330 for (int y = 0; y < height; y++)
331 memcpy (bitmapData + y * width, data + y * step, width);
334 // Turn the bitmap context into an imageRef
335 CGImageRef imageRef = CGBitmapContextCreateImage( context );
336 CGContextRelease( context );
343 // Write the imageRef to a file based on the UTI
344 CFURLRef imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL,
345 (const UInt8*)m_filename.c_str(), m_filename.size(), false );
348 CGImageRelease( imageRef );
353 CGImageDestinationRef destRef = CGImageDestinationCreateWithURL( imageURLRef,
357 CFRelease( imageURLRef );
360 CGImageRelease( imageRef );
362 fprintf(stderr, "!destRef\n");
366 CGImageDestinationAddImage(destRef, imageRef, NULL);
367 if( !CGImageDestinationFinalize(destRef) )
369 fprintf(stderr, "Finalize failed\n");
373 CFRelease( destRef );
374 CGImageRelease( imageRef );
382 #endif /* HAVE_IMAGEIO */