#include #include #include #include #include using namespace std; #include #include "xpUtil.h" typedef struct { size_t width; size_t height; size_t bitsPerComponent; size_t bitsPerPixel; size_t bytesPerRow; size_t size; CGImageAlphaInfo ai; CGColorSpaceRef cs; unsigned char *data; CMProfileRef prof; } BitmapInfo; bool WriteImage(const char *filename, const int width, const int height, unsigned char * const rgb_data, unsigned char * const png_alpha, const int quality) { const char *extension = strrchr(filename, '.'); char *lowercase = (char *) malloc(strlen(extension) + 1); strcpy(lowercase, extension); char *ptr = lowercase; while (*ptr != '\0') *ptr++ = (char) tolower(*extension++); OSType fileType = 0; if (strcmp(lowercase, ".bmp") == 0) { fileType = kQTFileTypeBMP; } else if (strcmp(lowercase, ".gif") == 0) { fileType = kQTFileTypeGIF; } else if ((strcmp(lowercase, ".jpg") == 0) ||(strcmp(lowercase, ".jpeg") == 0)) { fileType = kQTFileTypeJPEG; } else if (strcmp(lowercase, ".png") == 0) { fileType = kQTFileTypePNG; } else if ((strcmp(lowercase, ".tif") == 0) ||(strcmp(lowercase, ".tiff") == 0)) { fileType = kQTFileTypeTIFF; } if (fileType == 0) { ostringstream errStr; errStr << "Invalid file type for " << filename << endl; return(false); } BitmapInfo bi; bi.width = width; bi.height = height; bi.bitsPerComponent = 8; bi.bitsPerPixel = 32; bi.bytesPerRow = (bi.bitsPerPixel * bi.width + 7)/8; bi.size = bi.bytesPerRow * bi.height; bi.ai = (png_alpha == NULL ? kCGImageAlphaNoneSkipFirst : kCGImageAlphaFirst); bi.data = (unsigned char *) malloc(bi.size); int area = width * height; if (bi.ai == kCGImageAlphaFirst) { unsigned char *rgbPtr = rgb_data; unsigned char *pngPtr = png_alpha; unsigned char *bitPtr = bi.data; for (int i = 0; i < area; i++) { *bitPtr++ = *pngPtr++; memcpy(bitPtr, rgbPtr, 3); rgbPtr += 3; bitPtr += 3; } } else // no alpha channel { unsigned char *rgbPtr = rgb_data; unsigned char *bitPtr = bi.data; bitPtr++; for (int i = 0; i < area; i++) { memcpy(bitPtr, rgbPtr, 3); rgbPtr += 3; bitPtr += 4; } } //Create a CGImage from the bitmap data using the DeviceRGB color space CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB(); CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bi.data, bi.size, NULL); CGImageRef imageRef = CGImageCreate(bi.width, bi.height, bi.bitsPerComponent, bi.bitsPerPixel, bi.bytesPerRow, cs, bi.ai, provider, NULL, 0, kCGRenderingIntentDefault); CGColorSpaceRelease(cs); Handle dataRef = NULL; OSType dataRefType; GraphicsExportComponent graphicsExporter; unsigned long sizeWritten; CFStringRef path = CFStringCreateWithCString(NULL, filename, kCFStringEncodingUTF8); ComponentResult result = QTNewDataReferenceFromFullPathCFString(path, kQTNativeDefaultPathStyle, 0, &dataRef, &dataRefType); if (result != noErr) { ostringstream errStr; errStr << "Can't create data reference for " << filename << "\n"; errStr << "Did you specify the full path?\n"; xpWarn(errStr.str(), __FILE__, __LINE__); return(false); } result = OpenADefaultComponent(GraphicsExporterComponentType, fileType, &graphicsExporter); if (result != noErr) { ostringstream errStr; errStr << "Can't create GraphicsExporter for " << filename << "\n"; xpWarn(errStr.str(), __FILE__, __LINE__); return(false); } result = GraphicsExportSetInputCGImage(graphicsExporter, imageRef); if (result != noErr) { ostringstream errStr; errStr << "Can't set input for " << filename << "\n"; xpWarn(errStr.str(), __FILE__, __LINE__); return(false); } result = GraphicsExportSetOutputDataReference(graphicsExporter, dataRef, dataRefType); if (result != noErr) { ostringstream errStr; errStr << "Can't set output for " << filename << "\n"; xpWarn(errStr.str(), __FILE__, __LINE__); return(false); } result = GraphicsExportDoExport(graphicsExporter, &sizeWritten); if (result != noErr) { ostringstream errStr; errStr << "Can't export image for " << filename << "\n"; xpWarn(errStr.str(), __FILE__, __LINE__); return(false); } CloseComponent(graphicsExporter); DisposeHandle(dataRef); CGImageRelease(imageRef); CGDataProviderRelease(provider); free(bi.data); return(true); }