#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
using namespace std;
#include <Quicktime/Quicktime.h>
#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);
}
syntax highlighted by Code2HTML, v. 0.9.1