16acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/* 26acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * grfmt_imageio.cpp 36acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * 46acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * 56acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * Created by Morgan Conbere on 5/17/07. 66acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn * 76acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn */ 86acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 96acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "_highgui.h" 106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#ifdef HAVE_IMAGEIO 126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include "grfmt_imageio.h" 146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#include <iostream> 156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennusing namespace std; 166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn// ImageIO filter factory 186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtImageIO::GrFmtImageIO() 206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m_sign_len = 0; 226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m_signature = NULL; 236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m_description = "Apple ImageIO (*.bmp;*.dib;*.exr;*.jpeg;*.jpg;*.jpe;*.jp2;*.pdf;*.png;*.tiff;*.tif)"; 246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtImageIO::~GrFmtImageIO() 286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool GrFmtImageIO::CheckFile( const char* filename ) 336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !filename ) return false; 356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // If a CFImageRef can be retrieved from an image file, it is 376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // readable by ImageIO. Effectively this is using ImageIO 386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // to check the signatures and determine the file format for us. 396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CFURLRef imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL, 406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (const UInt8*)filename, 416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn strlen( filename ), 426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn false ); 436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !imageURLRef ) return false; 446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGImageSourceRef sourceRef = CGImageSourceCreateWithURL( imageURLRef, NULL ); 466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CFRelease( imageURLRef ); 476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !sourceRef ) return false; 486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGImageRef imageRef = CGImageSourceCreateImageAtIndex( sourceRef, 0, NULL ); 506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CFRelease( sourceRef ); 516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !imageRef ) return false; 526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return true; 546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtReader* GrFmtImageIO::NewReader( const char* filename ) 586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return new GrFmtImageIOReader( filename ); 606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtWriter* GrFmtImageIO::NewWriter( const char* filename ) 646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return new GrFmtImageIOWriter( filename ); 666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/////////////////////// GrFmtImageIOReader /////////////////// 706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtImageIOReader::GrFmtImageIOReader( const char* filename ) : GrFmtReader( filename ) 726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Nothing to do here 746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtImageIOReader::~GrFmtImageIOReader() 786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn Close(); 806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennvoid GrFmtImageIOReader::Close() 846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGImageRelease( imageRef ); 866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn GrFmtReader::Close(); 886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool GrFmtImageIOReader::ReadHeader() 926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CFURLRef imageURLRef; 946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGImageSourceRef sourceRef; 956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn imageRef = NULL; 966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL, 986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (const UInt8*)m_filename, 996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn strlen(m_filename), 1006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn false ); 1016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn sourceRef = CGImageSourceCreateWithURL( imageURLRef, NULL ); 1036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CFRelease( imageURLRef ); 1046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if ( !sourceRef ) 1056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 1066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn imageRef = CGImageSourceCreateImageAtIndex( sourceRef, 0, NULL ); 1086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CFRelease( sourceRef ); 1096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !imageRef ) 1106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 1116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m_width = CGImageGetWidth( imageRef ); 1136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m_height = CGImageGetHeight( imageRef ); 1146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGColorSpaceRef colorSpace = CGImageGetColorSpace( imageRef ); 1166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !colorSpace ) 1176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 1186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m_iscolor = ( CGColorSpaceGetNumberOfComponents( colorSpace ) > 1 ); 1206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return true; 1226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 1236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool GrFmtImageIOReader::ReadData( uchar* data, int step, int color ) 1266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 1276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int bpp; // Bytes per pixel 1286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Set color to either CV_IMAGE_LOAD_COLOR or CV_IMAGE_LOAD_GRAYSCALE if unchanged 1306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn color = color > 0 || ( m_iscolor && color < 0 ); 1316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Get Height, Width, and color information 1336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !ReadHeader() ) 1346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 1356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGContextRef context = NULL; // The bitmap context 1376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGColorSpaceRef colorSpace = NULL; 1386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* bitmap = NULL; 1396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGImageAlphaInfo alphaInfo; 1406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // CoreGraphics will take care of converting to grayscale and back as long as the 1426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // appropriate colorspace is set 1436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( color == CV_LOAD_IMAGE_GRAYSCALE ) 1446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn colorSpace = CGColorSpaceCreateDeviceGray(); 1466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bpp = 1; 1476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn alphaInfo = kCGImageAlphaNone; 1486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( color == CV_LOAD_IMAGE_COLOR ) 1506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn colorSpace = CGColorSpaceCreateDeviceRGB(); 1526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bpp = 4; /* CG only has 8 and 32 bit color spaces, so we waste a byte */ 1536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn alphaInfo = kCGImageAlphaNoneSkipLast; 1546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !colorSpace ) 1566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 1576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bitmap = (uchar*)malloc( bpp * m_height * m_width ); 1596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !bitmap ) 1606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGColorSpaceRelease( colorSpace ); 1626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 1636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn context = CGBitmapContextCreate( (void *)bitmap, 1666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m_width, /* width */ 1676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m_height, /* height */ 1686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn m_bit_depth, /* bit depth */ 1696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bpp * m_width, /* bytes per row */ 1706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn colorSpace, /* color space */ 1716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn alphaInfo); 1726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGColorSpaceRelease( colorSpace ); 1746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !context ) 1756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free( bitmap ); 1776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 1786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Copy the image data into the bitmap region 1816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGRect rect = {{0,0},{m_width,m_height}}; 1826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGContextDrawImage( context, rect, imageRef ); 1836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* bitdata = (uchar*)CGBitmapContextGetData( context ); 1856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !bitdata ) 1866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free( bitmap); 1886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGContextRelease( context ); 1896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 1906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 1916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Move the bitmap (in RGB) into data (in BGR) 1936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int bitmapIndex = 0; 1946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( color == CV_LOAD_IMAGE_COLOR ) 1966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 1976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar * base = data; 1986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (int y = 0; y < m_height; y++) 2006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar * line = base + y * step; 2026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (int x = 0; x < m_width; x++) 2046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Blue channel 2066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn line[0] = bitdata[bitmapIndex + 2]; 2076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Green channel 2086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn line[1] = bitdata[bitmapIndex + 1]; 2096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Red channel 2106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn line[2] = bitdata[bitmapIndex + 0]; 2116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn line += 3; 2136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bitmapIndex += bpp; 2146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( color == CV_LOAD_IMAGE_GRAYSCALE ) 2186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (int y = 0; y < m_height; y++) 2206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memcpy (data + y * step, bitmap + y * m_width, m_width); 2216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free( bitmap ); 2246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGContextRelease( context ); 2256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return true; 2266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn/////////////////////// GrFmtImageIOWriter /////////////////// 2306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtImageIOWriter::GrFmtImageIOWriter( const char* filename ) : GrFmtWriter( filename ) 2326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 2336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Nothing to do here 2346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennGrFmtImageIOWriter::~GrFmtImageIOWriter() 2386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 2396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Nothing to do here 2406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennstatic 2446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius RennCFStringRef FilenameToUTI( const char* filename ) 2456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 2466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const char* ext = filename; 2476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for(;;) 2486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const char* temp = strchr( ext + 1, '.' ); 2506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !temp ) break; 2516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn ext = temp; 2526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 2536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CFStringRef imageUTI = NULL; 2556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !strcmp(ext, ".bmp") || !strcmp(ext, ".dib") ) 2576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn imageUTI = CFSTR( "com.microsoft.bmp" ); 2586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( !strcmp(ext, ".exr") ) 2596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn imageUTI = CFSTR( "com.ilm.openexr-image" ); 2606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( !strcmp(ext, ".jpeg") || !strcmp(ext, ".jpg") || !strcmp(ext, ".jpe") ) 2616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn imageUTI = CFSTR( "public.jpeg" ); 2626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( !strcmp(ext, ".jp2") ) 2636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn imageUTI = CFSTR( "public.jpeg-2000" ); 2646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( !strcmp(ext, ".pdf") ) 2656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn imageUTI = CFSTR( "com.adobe.pdf" ); 2666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( !strcmp(ext, ".png") ) 2676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn imageUTI = CFSTR( "public.png" ); 2686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( !strcmp(ext, ".tiff") || !strcmp(ext, ".tif") ) 2696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn imageUTI = CFSTR( "public.tiff" ); 2706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return imageUTI; 2726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 2736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Rennbool GrFmtImageIOWriter::WriteImage( const uchar* data, int step, 2766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int width, int height, int /*depth*/, int _channels ) 2776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn{ 2786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Determine the appropriate UTI based on the filename extension 2796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CFStringRef imageUTI = FilenameToUTI( m_filename ); 2806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Determine the Bytes Per Pixel 2826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int bpp = (_channels == 1) ? 1 : 4; 2836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Write the data into a bitmap context 2856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGContextRef context; 2866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGColorSpaceRef colorSpace; 2876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn uchar* bitmapData = NULL; 2886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( bpp == 1 ) 2906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericGray ); 2916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if( bpp == 4 ) 2926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn colorSpace = CGColorSpaceCreateWithName( kCGColorSpaceGenericRGB ); 2936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !colorSpace ) 2946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 2956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 2966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bitmapData = (uchar*)malloc( bpp * height * width ); 2976acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !bitmapData ) 2986acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 2996acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGColorSpaceRelease( colorSpace ); 3006acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 3016acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3026acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3036acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn context = CGBitmapContextCreate( bitmapData, 3046acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn width, 3056acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn height, 3066acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 8, 3076acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bpp * width, 3086acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn colorSpace, 3096acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (bpp == 1) ? kCGImageAlphaNone : 3106acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn kCGImageAlphaNoneSkipLast ); 3116acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGColorSpaceRelease( colorSpace ); 3126acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !context ) 3136acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3146acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free( bitmapData ); 3156acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 3166acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3176acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3186acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Copy pixel information from data into bitmapData 3196acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if (bpp == 4) 3206acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3216acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn int bitmapIndex = 0; 3226acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const uchar * base = data; 3236acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3246acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (int y = 0; y < height; y++) 3256acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3266acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn const uchar * line = base + y * step; 3276acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3286acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (int x = 0; x < width; x++) 3296acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3306acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Blue channel 3316acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bitmapData[bitmapIndex + 2] = line[0]; 3326acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Green channel 3336acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bitmapData[bitmapIndex + 1] = line[1]; 3346acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Red channel 3356acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bitmapData[bitmapIndex + 0] = line[2]; 3366acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3376acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn line += 3; 3386acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn bitmapIndex += bpp; 3396acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3406acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3416acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3426acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn else if (bpp == 1) 3436acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3446acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn for (int y = 0; y < height; y++) 3456acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn memcpy (bitmapData + y * width, data + y * step, width); 3466acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3476acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3486acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Turn the bitmap context into an imageRef 3496acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGImageRef imageRef = CGBitmapContextCreateImage( context ); 3506acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGContextRelease( context ); 3516acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !imageRef ) 3526acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3536acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free( bitmapData ); 3546acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 3556acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3566acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3576acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn // Write the imageRef to a file based on the UTI 3586acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CFURLRef imageURLRef = CFURLCreateFromFileSystemRepresentation( NULL, 3596acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn (const UInt8*)m_filename, 3606acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn strlen(m_filename), 3616acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn false ); 3626acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !imageURLRef ) 3636acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3646acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGImageRelease( imageRef ); 3656acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free( bitmapData ); 3666acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 3676acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3686acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3696acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGImageDestinationRef destRef = CGImageDestinationCreateWithURL( imageURLRef, 3706acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn imageUTI, 3716acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 1, 3726acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn NULL); 3736acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CFRelease( imageURLRef ); 3746acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !destRef ) 3756acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3766acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGImageRelease( imageRef ); 3776acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free( bitmapData ); 3786acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn std::cerr << "!destRef" << std::endl << std::flush; 3796acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 3806acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3816acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3826acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGImageDestinationAddImage(destRef, imageRef, NULL); 3836acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn if( !CGImageDestinationFinalize(destRef) ) 3846acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn { 3856acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn std::cerr << "Finalize failed" << std::endl << std::flush; 3866acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return false; 3876acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn } 3886acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3896acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CFRelease( destRef ); 3906acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn CGImageRelease( imageRef ); 3916acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn free( bitmapData ); 3926acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3936acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn return true; 3946acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn} 3956acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn 3966acb9a7ea3d7564944e12cbc73a857b88c1301eeMarius Renn#endif /* HAVE_IMAGEIO */ 397