X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fhighgui%2Fgrfmt_imageio.cpp;fp=src%2Fhighgui%2Fgrfmt_imageio.cpp;h=bb2492f63acb8a2c964ed0afdeae949d5b12ccd5;hb=e4c14cdbdf2fe805e79cd96ded236f57e7b89060;hp=0000000000000000000000000000000000000000;hpb=454138ff8a20f6edb9b65a910101403d8b520643;p=opencv diff --git a/src/highgui/grfmt_imageio.cpp b/src/highgui/grfmt_imageio.cpp new file mode 100644 index 0000000..bb2492f --- /dev/null +++ b/src/highgui/grfmt_imageio.cpp @@ -0,0 +1,382 @@ +/* + * grfmt_imageio.cpp + * + * + * Created by Morgan Conbere on 5/17/07. + * + */ + +#include "_highgui.h" + +#ifdef HAVE_IMAGEIO + +#include "grfmt_imageio.h" + +namespace cv +{ + +/////////////////////// ImageIODecoder /////////////////// + +ImageIODecoder::ImageIODecoder() +{ + imageRef = NULL; +} + +ImageIODecoder::~ImageIODecoder() +{ + close(); +} + + +void ImageIODecoder::close() +{ + CGImageRelease( imageRef ); + imageRef = NULL; +} + + +size_t ImageIODecoder::signatureLength() const +{ + return 12; +} + +bool ImageIODecoder::checkSignature( const string& signature ) const +{ + // TODO: implement real signature check + return true; +} + +ImageDecoder ImageIODecoder::newDecoder() const +{ + return new ImageIODecoder; +} + +bool ImageIODecoder::readHeader() +{ + CFURLRef imageURLRef; + CGImageSourceRef sourceRef; + // diciu, if ReadHeader is called twice in a row make sure to release the previously allocated imageRef + if (imageRef != NULL) + CGImageRelease(imageRef); + imageRef = NULL; + + imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL, + (const UInt8*)m_filename.c_str(), m_filename.size(), false ); + + sourceRef = CGImageSourceCreateWithURL( imageURLRef, NULL ); + CFRelease( imageURLRef ); + if ( !sourceRef ) + return false; + + imageRef = CGImageSourceCreateImageAtIndex( sourceRef, 0, NULL ); + CFRelease( sourceRef ); + if( !imageRef ) + return false; + + m_width = CGImageGetWidth( imageRef ); + m_height = CGImageGetHeight( imageRef ); + + CGColorSpaceRef colorSpace = CGImageGetColorSpace( imageRef ); + if( !colorSpace ) + return false; + + m_type = CGColorSpaceGetNumberOfComponents( colorSpace ) > 1 ? CV_8UC3 : CV_8UC1; + + return true; +} + + +bool ImageIODecoder::readData( Mat& img ) +{ + uchar* data = img.data; + int step = img.step; + bool color = img.channels() > 1; + int bpp; // Bytes per pixel + int bit_depth = 8; + + // Get Height, Width, and color information + if( !readHeader() ) + return false; + + CGContextRef context = NULL; // The bitmap context + CGColorSpaceRef colorSpace = NULL; + uchar* bitmap = NULL; + CGImageAlphaInfo alphaInfo; + + // CoreGraphics will take care of converting to grayscale and back as long as the + // appropriate colorspace is set + if( color == CV_LOAD_IMAGE_GRAYSCALE ) + { + colorSpace = CGColorSpaceCreateDeviceGray(); + bpp = 1; + alphaInfo = kCGImageAlphaNone; + } + else if( color == CV_LOAD_IMAGE_COLOR ) + { + colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGBLinear ); + bpp = 4; /* CG only has 8 and 32 bit color spaces, so we waste a byte */ + alphaInfo = kCGImageAlphaNoneSkipLast; + } + if( !colorSpace ) + return false; + + bitmap = (uchar*)malloc( bpp * m_height * m_width ); + if( !bitmap ) + { + CGColorSpaceRelease( colorSpace ); + return false; + } + + context = CGBitmapContextCreate( (void *)bitmap, + m_width, /* width */ + m_height, /* height */ + bit_depth, /* bit depth */ + bpp * m_width, /* bytes per row */ + colorSpace, /* color space */ + alphaInfo); + + CGColorSpaceRelease( colorSpace ); + if( !context ) + { + free( bitmap ); + return false; + } + + // Copy the image data into the bitmap region + CGRect rect = {{0,0},{m_width,m_height}}; + CGContextDrawImage( context, rect, imageRef ); + + uchar* bitdata = (uchar*)CGBitmapContextGetData( context ); + if( !bitdata ) + { + free( bitmap); + CGContextRelease( context ); + return false; + } + + // Move the bitmap (in RGB) into data (in BGR) + int bitmapIndex = 0; + + if( color == CV_LOAD_IMAGE_COLOR ) + { + uchar * base = data; + + for (int y = 0; y < m_height; y++) + { + uchar * line = base + y * step; + + for (int x = 0; x < m_width; x++) + { + // Blue channel + line[0] = bitdata[bitmapIndex + 2]; + // Green channel + line[1] = bitdata[bitmapIndex + 1]; + // Red channel + line[2] = bitdata[bitmapIndex + 0]; + + line += 3; + bitmapIndex += bpp; + } + } + } + else if( color == CV_LOAD_IMAGE_GRAYSCALE ) + { + for (int y = 0; y < m_height; y++) + memcpy (data + y * step, bitmap + y * m_width, m_width); + } + + free( bitmap ); + CGContextRelease( context ); + return true; +} + + +/////////////////////// ImageIOEncoder /////////////////// + +ImageIOEncoder::ImageIOEncoder() +{ + m_description = "Apple ImageIO (*.bmp;*.dib;*.exr;*.jpeg;*.jpg;*.jpe;*.jp2;*.pdf;*.png;*.tiff;*.tif)"; +} + + +ImageIOEncoder::~ImageIOEncoder() +{ +} + + +ImageEncoder ImageIOEncoder::newEncoder() const +{ + return new ImageIOEncoder; +} + +static +CFStringRef FilenameToUTI( const char* filename ) +{ + const char* ext = filename; + char* ext_buf; + int i; + CFStringRef imageUTI = NULL; + + for(;;) + { + const char* temp = strchr( ext + 1, '.' ); + if( !temp ) break; + ext = temp; + } + + if(!ext) + return NULL; + + ext_buf = (char*)malloc(strlen(ext)+1); + for(i = 0; ext[i] != '\0'; i++) + ext_buf[i] = (char)tolower(ext[i]); + ext_buf[i] = '\0'; + ext = ext_buf; + + if( !strcmp(ext, ".bmp") || !strcmp(ext, ".dib") ) + imageUTI = CFSTR( "com.microsoft.bmp" ); + else if( !strcmp(ext, ".exr") ) + imageUTI = CFSTR( "com.ilm.openexr-image" ); + else if( !strcmp(ext, ".jpeg") || !strcmp(ext, ".jpg") || !strcmp(ext, ".jpe") ) + imageUTI = CFSTR( "public.jpeg" ); + else if( !strcmp(ext, ".jp2") ) + imageUTI = CFSTR( "public.jpeg-2000" ); + else if( !strcmp(ext, ".pdf") ) + imageUTI = CFSTR( "com.adobe.pdf" ); + else if( !strcmp(ext, ".png") ) + imageUTI = CFSTR( "public.png" ); + else if( !strcmp(ext, ".tiff") || !strcmp(ext, ".tif") ) + imageUTI = CFSTR( "public.tiff" ); + + free(ext_buf); + + return imageUTI; +} + + +bool ImageIOEncoder::write( const Mat& img, const vector& params ) +{ + int width = img.cols, height = img.rows; + int _channels = img.channels(); + const uchar* data = img.data; + int step = img.step; + + // Determine the appropriate UTI based on the filename extension + CFStringRef imageUTI = FilenameToUTI( m_filename.c_str() ); + + // Determine the Bytes Per Pixel + int bpp = (_channels == 1) ? 1 : 4; + + // Write the data into a bitmap context + CGContextRef context; + CGColorSpaceRef colorSpace; + uchar* bitmapData = NULL; + + if( bpp == 1 ) + colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericGray ); + else if( bpp == 4 ) + colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGBLinear ); + if( !colorSpace ) + return false; + + bitmapData = (uchar*)malloc( bpp * height * width ); + if( !bitmapData ) + { + CGColorSpaceRelease( colorSpace ); + return false; + } + + context = CGBitmapContextCreate( bitmapData, + width, + height, + 8, + bpp * width, + colorSpace, + (bpp == 1) ? kCGImageAlphaNone : + kCGImageAlphaNoneSkipLast ); + CGColorSpaceRelease( colorSpace ); + if( !context ) + { + free( bitmapData ); + return false; + } + + // Copy pixel information from data into bitmapData + if (bpp == 4) + { + int bitmapIndex = 0; + const uchar * base = data; + + for (int y = 0; y < height; y++) + { + const uchar * line = base + y * step; + + for (int x = 0; x < width; x++) + { + // Blue channel + bitmapData[bitmapIndex + 2] = line[0]; + // Green channel + bitmapData[bitmapIndex + 1] = line[1]; + // Red channel + bitmapData[bitmapIndex + 0] = line[2]; + + line += 3; + bitmapIndex += bpp; + } + } + } + else if (bpp == 1) + { + for (int y = 0; y < height; y++) + memcpy (bitmapData + y * width, data + y * step, width); + } + + // Turn the bitmap context into an imageRef + CGImageRef imageRef = CGBitmapContextCreateImage( context ); + CGContextRelease( context ); + if( !imageRef ) + { + free( bitmapData ); + return false; + } + + // Write the imageRef to a file based on the UTI + CFURLRef imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL, + (const UInt8*)m_filename.c_str(), m_filename.size(), false ); + if( !imageURLRef ) + { + CGImageRelease( imageRef ); + free( bitmapData ); + return false; + } + + CGImageDestinationRef destRef = CGImageDestinationCreateWithURL( imageURLRef, + imageUTI, + 1, + NULL); + CFRelease( imageURLRef ); + if( !destRef ) + { + CGImageRelease( imageRef ); + free( bitmapData ); + fprintf(stderr, "!destRef\n"); + return false; + } + + CGImageDestinationAddImage(destRef, imageRef, NULL); + if( !CGImageDestinationFinalize(destRef) ) + { + fprintf(stderr, "Finalize failed\n"); + return false; + } + + CFRelease( destRef ); + CGImageRelease( imageRef ); + free( bitmapData ); + + return true; +} + +} + +#endif /* HAVE_IMAGEIO */