Exemple #1
0
void QuartzBitmap_Output(QuartzDesc_t dev, QuartzBitmapDevice *qbd)
{
    if(qbd->path && qbd->uti) {
        /* On 10.4+ we can employ the CGImageDestination API to create a
           variety of different bitmap formats */
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
	char buf[PATH_MAX+1];
	snprintf(buf, PATH_MAX, qbd->path, qbd->page); buf[PATH_MAX] = '\0';
        CFStringRef pathString = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8*) buf, strlen(buf), kCFStringEncodingUTF8, FALSE);
        CFURLRef path;
        if(CFStringFind(pathString, CFSTR("://"), 0).location != kCFNotFound) {
            CFStringRef pathEscaped = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, pathString, NULL, NULL, kCFStringEncodingUTF8);
            path = CFURLCreateWithString(kCFAllocatorDefault, pathEscaped, NULL);
            CFRelease(pathEscaped);
        } else {
            path = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*) buf, strlen(buf), FALSE);
        }
        CFRelease(pathString);

        CFStringRef scheme = CFURLCopyScheme(path);
       	CFStringRef type  = CFStringCreateWithBytes(kCFAllocatorDefault, (UInt8*) qbd->uti, strlen(qbd->uti), kCFStringEncodingUTF8, FALSE);
    	CGImageRef image = CGBitmapContextCreateImage(qbd->bitmap);
        if(CFStringCompare(scheme,CFSTR("file"), 0) == 0) { /* file output */
            CGImageDestinationRef dest = CGImageDestinationCreateWithURL(path, type, 1, NULL);
	    if(dest) {
		CGImageDestinationAddImage(dest, image, NULL);
		CGImageDestinationFinalize(dest);
		CFRelease(dest);
	    } else 
		error(_("QuartzBitmap_Output - unable to open file '%s'"), buf);
        } else if(CFStringCompare(scheme, CFSTR("clipboard"), 0) == 0) { /* clipboard output */
            CFMutableDataRef      data = CFDataCreateMutable(kCFAllocatorDefault, 0);
            CGImageDestinationRef dest = CGImageDestinationCreateWithData(data, type, 1, NULL);
            CGImageDestinationAddImage(dest, image, NULL);
            CGImageDestinationFinalize(dest);
            CFRelease(dest);
            PasteboardRef pb = NULL;
            if(PasteboardCreate(kPasteboardClipboard, &pb) == noErr) {
                PasteboardClear(pb);
                PasteboardSynchronize(pb);
                PasteboardPutItemFlavor(pb, (PasteboardItemID) 1, type, data, 0);
            }
            CFRelease(data);
        } else
            warning(_("not a supported scheme, no image data written"));
        CFRelease(scheme);
       	CFRelease(type);
        CFRelease(path);
        CFRelease(image);
#endif
    }
}
static void quartz_format(GVJ_t *job)
{
	/* image destination -> data consumer -> job's gvdevice */
	/* data provider <- job's imagedata */
	CGDataConsumerRef data_consumer = CGDataConsumerCreate(job, &device_data_consumer_callbacks);
	CGImageDestinationRef image_destination = CGImageDestinationCreateWithDataConsumer(data_consumer, format_uti[job->device.id], 1, NULL);
	CGDataProviderRef data_provider = CGDataProviderCreateDirect(job->imagedata, BYTES_PER_PIXEL * job->width * job->height, &memory_data_provider_callbacks);
	
	/* add the bitmap image to the destination and save it */
	CGColorSpaceRef color_space = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
	CGImageRef image = CGImageCreate (
		job->width,							/* width in pixels */
		job->height,						/* height in pixels */
		BITS_PER_COMPONENT,					/* bits per component */
		BYTES_PER_PIXEL * 8,				/* bits per pixel */
		BYTES_PER_PIXEL * job->width,		/* bytes per row: exactly width # of pixels */
		color_space,						/* color space: sRGB */
		kCGImageAlphaPremultipliedFirst,	/* bitmap info: corresponds to CAIRO_FORMAT_ARGB32 */
		data_provider,						/* data provider: from imagedata */
		NULL,								/* decode: don't remap colors */
		FALSE,								/* don't interpolate */
		kCGRenderingIntentDefault			/* rendering intent (what to do with out-of-gamut colors): default */
	);
	CGImageDestinationAddImage(image_destination, image, NULL);
	CGImageDestinationFinalize(image_destination);
	
	/* clean up */
	CGImageRelease(image);
	CGColorSpaceRelease(color_space);
	CGDataProviderRelease(data_provider);
	if (image_destination)
		CFRelease(image_destination);
	CGDataConsumerRelease(data_consumer);
}
/*  Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes
    to our SkWStream. Since we don't reference/own the SkWStream, our consumer
    must only live for the duration of the onEncode() method.
 */
bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm,
                                 int quality) {
    CFStringRef type;
    switch (fType) {
        case kJPEG_Type:
            type = kUTTypeJPEG;
            break;
        case kPNG_Type:
            type = kUTTypePNG;
            break;
        default:
            return false;
    }
    
    CGImageDestinationRef dst = SkStreamToImageDestination(stream, type);
    if (NULL == dst) {
        return false;
    }
    SkAutoTCallVProc<const void, CFRelease> ardst(dst);

    CGImageRef image = SkCreateCGImageRef(bm);
    if (NULL == image) {
        return false;
    }
    SkAutoTCallVProc<CGImage, CGImageRelease> agimage(image);
    
	CGImageDestinationAddImage(dst, image, NULL);
	CGImageDestinationFinalize(dst);
    return true;
}
Exemple #4
0
//-----------------------------------------------------------------------------
bool IPlatformBitmap::createMemoryPNGRepresentation (IPlatformBitmap* bitmap, void** ptr, uint32_t& size)
{
	bool result = false;
#if !TARGET_OS_IPHONE
	CGBitmap* cgBitmap = dynamic_cast<CGBitmap*> (bitmap);
	if (cgBitmap)
	{
		CGImageRef image = cgBitmap->getCGImage ();
		if (image)
		{
			CFMutableDataRef data = CFDataCreateMutable (NULL, 0);
			if (data)
			{
				CGImageDestinationRef dest = CGImageDestinationCreateWithData (data, kUTTypePNG, 1, 0);
				if (dest)
				{
					CGImageDestinationAddImage (dest, image, 0);
					if (CGImageDestinationFinalize (dest))
					{
						size = (uint32_t)CFDataGetLength (data);
						*ptr = malloc (size);
						CFDataGetBytes (data, CFRangeMake (0, size), (UInt8*)*ptr);
						result = true;
					}
					CFRelease (dest);
				}
				CFRelease (data);
			}
		}
	}
#endif
	return result;
}
Exemple #5
0
static String CGImageToDataURL(CGImageRef image, const String& mimeType, const double* quality)
{
    RetainPtr<CFMutableDataRef> data(AdoptCF, CFDataCreateMutable(kCFAllocatorDefault, 0));
    if (!data)
        return "data:,";

    RetainPtr<CFStringRef> uti = utiFromMIMEType(mimeType);
    ASSERT(uti);

    RetainPtr<CGImageDestinationRef> destination(AdoptCF, CGImageDestinationCreateWithData(data.get(), uti.get(), 1, 0));
    if (!destination)
        return "data:,";

    RetainPtr<CFDictionaryRef> imageProperties = 0;
    if (CFEqual(uti.get(), jpegUTI()) && quality && *quality >= 0.0 && *quality <= 1.0) {
        // Apply the compression quality to the image destination.
        RetainPtr<CFNumberRef> compressionQuality(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, quality));
        const void* key = kCGImageDestinationLossyCompressionQuality;
        const void* value = compressionQuality.get();
        imageProperties.adoptCF(CFDictionaryCreate(0, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
    }

    // Setting kCGImageDestinationBackgroundColor to black in imageProperties would allow saving some math in the
    // calling functions, but it doesn't seem to work.

    CGImageDestinationAddImage(destination.get(), image, imageProperties.get());
    CGImageDestinationFinalize(destination.get());

    Vector<char> out;
    base64Encode(reinterpret_cast<const char*>(CFDataGetBytePtr(data.get())), CFDataGetLength(data.get()), out);

    return "data:" + mimeType + ";base64," + out;
}
Exemple #6
0
void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
{
    Clear();
    wxBitmapDataObjectBase::SetBitmap( rBitmap );
    if (m_bitmap.IsOk())
    {
        CGImageRef cgImageRef = (CGImageRef) m_bitmap.CreateCGImage();

        CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
        CGImageDestinationRef destination = CGImageDestinationCreateWithData( data , kUTTypeTIFF , 1 , NULL );
        if ( destination )
        {
            CGImageDestinationAddImage( destination, cgImageRef, NULL );
            CGImageDestinationFinalize( destination );
            CFRelease( destination );
        }
        m_pictHandle = NewHandle(CFDataGetLength(data));
        if ( m_pictHandle )
        {
            memcpy( *(Handle)m_pictHandle, (const char *)CFDataGetBytePtr(data), CFDataGetLength(data) );
        }
        CFRelease( data );

        CGImageRelease(cgImageRef);
    }
}
static void printPNG(CGImageRef image)
{
    RetainPtr<CFMutableDataRef> imageData(AdoptCF, CFDataCreateMutable(0, 0));
    RetainPtr<CGImageDestinationRef> imageDest(AdoptCF, CGImageDestinationCreateWithData(imageData.get(), kUTTypePNG, 1, 0));
    CGImageDestinationAddImage(imageDest.get(), image, 0);
    CGImageDestinationFinalize(imageDest.get());
    printf("Content-Length: %lu\n", CFDataGetLength(imageData.get()));
    fwrite(CFDataGetBytePtr(imageData.get()), 1, CFDataGetLength(imageData.get()), stdout);
}
/*  Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes
    to our SkWStream. Since we don't reference/own the SkWStream, our consumer
    must only live for the duration of the onEncode() method.
 */
bool SkEncodeImageWithCG(SkWStream* stream, const SkPixmap& pixmap, SkEncodedImageFormat format) {
    SkBitmap bm;
    if (!bm.installPixels(pixmap)) {
        return false;
    }
    bm.setImmutable();

    CFStringRef type;
    switch (format) {
        case SkEncodedImageFormat::kICO:
            type = kUTTypeICO;
            break;
        case SkEncodedImageFormat::kBMP:
            type = kUTTypeBMP;
            break;
        case SkEncodedImageFormat::kGIF:
            type = kUTTypeGIF;
            break;
        case SkEncodedImageFormat::kJPEG:
            type = kUTTypeJPEG;
            break;
        case SkEncodedImageFormat::kPNG:
            // PNG encoding an ARGB_4444 bitmap gives the following errors in GM:
            // <Error>: CGImageDestinationAddImage image could not be converted to destination
            // format.
            // <Error>: CGImageDestinationFinalize image destination does not have enough images
            // So instead we copy to 8888.
            if (bm.colorType() == kARGB_4444_SkColorType) {
                SkBitmap bitmapN32;
                bitmapN32.allocPixels(bm.info().makeColorType(kN32_SkColorType));
                bm.readPixels(bitmapN32.info(), bitmapN32.getPixels(), bitmapN32.rowBytes(), 0, 0);
                bm.swap(bitmapN32);
            }
            type = kUTTypePNG;
            break;
        default:
            return false;
    }

    CGImageDestinationRef dst = SkStreamToImageDestination(stream, type);
    if (nullptr == dst) {
        return false;
    }
    SkAutoTCallVProc<const void, CFRelease> ardst(dst);

    CGImageRef image = SkCreateCGImageRef(bm);
    if (nullptr == image) {
        return false;
    }
    SkAutoTCallVProc<CGImage, CGImageRelease> agimage(image);

    CGImageDestinationAddImage(dst, image, nullptr);
    return CGImageDestinationFinalize(dst);
}
Exemple #9
0
void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
{
    Clear();
    wxBitmapDataObjectBase::SetBitmap( rBitmap );
    if (m_bitmap.Ok())
    {
#if wxMAC_USE_CORE_GRAPHICS
        CGImageRef cgImageRef = (CGImageRef) m_bitmap.CGImageCreate();
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
        if ( UMAGetSystemVersion() >= 0x1040 )
        {
            CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
            CGImageDestinationRef destination = CGImageDestinationCreateWithData( data , kUTTypeTIFF , 1 , NULL );
            if ( destination )
            {
                CGImageDestinationAddImage( destination, cgImageRef, NULL );
                CGImageDestinationFinalize( destination );
                CFRelease( destination );
            }
            m_pictHandle = NewHandle(CFDataGetLength(data));
            if ( m_pictHandle )
            {
                memcpy( *(Handle)m_pictHandle, (const char *)CFDataGetBytePtr(data), CFDataGetLength(data) );
            }
            CFRelease( data );
        }
        else
#endif
#ifndef __LP64__
        {
            // export as TIFF
            GraphicsExportComponent exporter = 0;
            OSStatus err = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypeTIFF, &exporter);
            if (noErr == err)
            {
                m_pictHandle = NewHandle(0);
                if ( m_pictHandle )
                {
                    err = GraphicsExportSetInputCGImage( exporter, cgImageRef);
                    err = GraphicsExportSetOutputHandle(exporter, (Handle)m_pictHandle);
                    err = GraphicsExportDoExport(exporter, NULL);
                }
                CloseComponent( exporter );
            }
        }
#endif
        CGImageRelease(cgImageRef);
#else
        m_pictHandle = m_bitmap.GetBitmapData()->GetPictHandle();
        m_pictCreated = false;
#endif
    }
}
err_t MacCGEncoder::writeImage(const Image& image)
{
  Image tmp;
  if (image.isEmpty())
    return ERR_IMAGE_INVALID_SIZE;

  err_t err = ERR_OK;

  CGDataConsumerRef cgConsumer = NULL;
  CGImageDestinationRef cgDestination = NULL;
  CGImageRef cgImage = NULL;

  cgConsumer = CGDataConsumerCreate(this, &_consumerCallbacks);
  if (FOG_IS_NULL(cgConsumer))
  {
    err = ERR_RT_OUT_OF_MEMORY;
    goto _End;
  }

  cgDestination = CGImageDestinationCreateWithDataConsumer(cgConsumer,
    static_cast<MacCGCodecProvider*>(_provider)->getUTType(), 1, NULL);
  CFRelease(cgConsumer);

  if (FOG_IS_NULL(cgDestination))
  {
    err = ERR_RT_OUT_OF_MEMORY;
    goto _End;
  }

  if (image.getType() == IMAGE_TYPE_MAC_CG)
    cgImage = static_cast<CGImageRef>(const_cast<Image&>(image).getHandle());

  if (FOG_IS_NULL(cgImage))
  {
    err = image.toCGImage(&cgImage);
    if (FOG_IS_ERROR(err))
      goto _End;
  }

  CGImageDestinationAddImage(cgDestination, cgImage, NULL);
  if (!CGImageDestinationFinalize(cgDestination))
  {
    err = ERR_IO_CANT_WRITE;
  }

_End:
  CFRelease(cgDestination);

  if (err == ERR_OK)
    updateProgress(1.0f);
  return err;
}
static void dumpBitmap(CGContextRef bitmapContext, const char* checksum)
{
    RetainPtr<CGImageRef> image = adoptCF(CGBitmapContextCreateImage(bitmapContext));
    RetainPtr<CFMutableDataRef> imageData = adoptCF(CFDataCreateMutable(0, 0));
    RetainPtr<CGImageDestinationRef> imageDest = adoptCF(CGImageDestinationCreateWithData(imageData.get(), kUTTypePNG, 1, 0));
    CGImageDestinationAddImage(imageDest.get(), image.get(), 0);
    CGImageDestinationFinalize(imageDest.get());

    const unsigned char* data = CFDataGetBytePtr(imageData.get());
    const size_t dataLength = CFDataGetLength(imageData.get());

    printPNG(data, dataLength, checksum);
}
int main(int argc, char** argv) {
    if (argc <= 1 || !*(argv[1]) || 0 == strcmp(argv[1], "-")) {
        fprintf(stderr, "usage:\n\t%s INPUT_PDF_FILE_PATH [OUTPUT_PNG_PATH]\n", argv[0]);
        return 1;
    }
    const char* output = argc > 2 ? argv[2] : nullptr;
    CGDataProviderRef data = CGDataProviderCreateWithFilename(argv[1]);
    ASSERT(data);
    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithProvider(data);
    CGDataProviderRelease(data);
    ASSERT(pdf);
    CGPDFPageRef page = CGPDFDocumentGetPage(pdf, PAGE);
    ASSERT(page);
    CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
    int w = (int)CGRectGetWidth(bounds);
    int h = (int)CGRectGetHeight(bounds);
    CGBitmapInfo info = kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast;
    CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
    ASSERT(cs);
    std::unique_ptr<uint32_t[]> bitmap(new uint32_t[w * h]);
    memset(bitmap.get(), 0xFF, 4 * w * h);
    CGContextRef ctx = CGBitmapContextCreate(bitmap.get(), w, h, 8, w * 4, cs, info);
    ASSERT(ctx);
    CGContextDrawPDFPage(ctx, page);
    CGPDFDocumentRelease(pdf);
    CGImageRef image = CGBitmapContextCreateImage(ctx);
    ASSERT(image);
    CGDataConsumerCallbacks procs;
    procs.putBytes = [](void* f, const void* buf, size_t s) {
        return fwrite(buf, 1, s, (FILE*)f);
    };
    procs.releaseConsumer = [](void* info) {
        fclose((FILE*)info);
    };
    FILE* ofile = (!output || !output[0] || 0 == strcmp(output, "-"))
                  ? stdout : fopen(output, "wb");
    ASSERT(ofile);
    CGDataConsumerRef consumer = CGDataConsumerCreate(ofile, &procs);
    ASSERT(consumer);
    CGImageDestinationRef dst =
        CGImageDestinationCreateWithDataConsumer(consumer, kUTTypePNG, 1, nullptr);
    CFRelease(consumer);
    ASSERT(dst);
    CGImageDestinationAddImage(dst, image, nullptr);
    ASSERT(CGImageDestinationFinalize(dst));
    CFRelease(dst);
    CGImageRelease(image);
    CGColorSpaceRelease(cs);
    CGContextRelease(ctx);
    return 0;
}
Exemple #13
0
/*  Encode bitmaps via CGImageDestination. We setup a DataConsumer which writes
    to our SkWStream. Since we don't reference/own the SkWStream, our consumer
    must only live for the duration of the onEncode() method.
 */
bool SkImageEncoder_CG::onEncode(SkWStream* stream, const SkBitmap& bm,
                                 int quality) {
    // Used for converting a bitmap to 8888.
    const SkBitmap* bmPtr = &bm;
    SkBitmap bitmap8888;

    CFStringRef type;
    switch (fType) {
        case kICO_Type:
            type = kUTTypeICO;
            break;
        case kBMP_Type:
            type = kUTTypeBMP;
            break;
        case kGIF_Type:
            type = kUTTypeGIF;
            break;
        case kJPEG_Type:
            type = kUTTypeJPEG;
            break;
        case kPNG_Type:
            // PNG encoding an ARGB_4444 bitmap gives the following errors in GM:
            // <Error>: CGImageDestinationAddImage image could not be converted to destination
            // format.
            // <Error>: CGImageDestinationFinalize image destination does not have enough images
            // So instead we copy to 8888.
            if (bm.colorType() == kARGB_4444_SkColorType) {
                bm.copyTo(&bitmap8888, kN32_SkColorType);
                bmPtr = &bitmap8888;
            }
            type = kUTTypePNG;
            break;
        default:
            return false;
    }

    CGImageDestinationRef dst = SkStreamToImageDestination(stream, type);
    if (NULL == dst) {
        return false;
    }
    SkAutoTCallVProc<const void, CFRelease> ardst(dst);

    CGImageRef image = SkCreateCGImageRef(*bmPtr);
    if (NULL == image) {
        return false;
    }
    SkAutoTCallVProc<CGImage, CGImageRelease> agimage(image);

    CGImageDestinationAddImage(dst, image, NULL);
    return CGImageDestinationFinalize(dst);
}
Exemple #14
0
static void quartzgen_end_job(GVJ_t *job)
{
	CGContextRef context = (CGContextRef)job->context;
	if (!job->external_context) {
		switch (job->device.id) {
		
		case FORMAT_PDF:
			/* save the PDF */
			CGPDFContextClose(context);
			break;
				
		case FORMAT_CGIMAGE:
			break;
			
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040
		default:	/* bitmap formats */
			{
				/* create an image destination */
				CGDataConsumerRef data_consumer = CGDataConsumerCreate(job, &device_data_consumer_callbacks);
				CGImageDestinationRef image_destination = CGImageDestinationCreateWithDataConsumer(data_consumer, format_uti[job->device.id], 1, NULL);
				
				/* add the bitmap image to the destination and save it */
				CGImageRef image = CGBitmapContextCreateImage(context);
				CGImageDestinationAddImage(image_destination, image, NULL);
				CGImageDestinationFinalize(image_destination);
				
				/* clean up */
				if (image_destination)
					CFRelease(image_destination);
				CGImageRelease(image);
				CGDataConsumerRelease(data_consumer);
			}
			break;
#endif
		}
		CGContextRelease(context);
	}
	else if (job->device.id == FORMAT_CGIMAGE)
	{
		/* create an image and save it where the window field is, which was set to the passed-in context at begin job */
		*((CGImageRef*)job->window) = CGBitmapContextCreateImage(context);
#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000
		void* context_data = CGBitmapContextGetData(context);
		size_t context_datalen = CGBitmapContextGetBytesPerRow(context) * CGBitmapContextGetHeight(context);
#endif
		CGContextRelease(context);
#if __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000
		munmap(context_data, context_datalen);
#endif
	}
}
static void exportCGImageToFileWithDestination(CGImageRef image, CFURLRef url,
					    CFStringRef outputFormat,
					    float dpi)
{
    CFTypeRef keys[2]; 
    CFTypeRef values[2];
    CFDictionaryRef options = NULL;
    
    // Create an image destination at the supplied URL that
    // corresponds to the output image format. The destination will
    // only contain 1 image.
    CGImageDestinationRef imageDestination = 
		CGImageDestinationCreateWithURL(url, outputFormat, 1, NULL);
		
    if(imageDestination == NULL){
		fprintf(stderr, "Couldn't create image destination!\n");
		return;
    }

    // Set the keys to be the x and y resolution of the image.
    keys[0] = kCGImagePropertyDPIWidth;
    keys[1] = kCGImagePropertyDPIHeight;

    // Create a CFNumber for the resolution and use it as the 
    // x and y resolution.
    values[0] = values[1] = CFNumberCreate(NULL, kCFNumberFloatType, &dpi);
    
    // Create an options dictionary with these keys.
    options = CFDictionaryCreate(NULL, 
		    (const void **)keys, 
		    (const void **)values, 
		    2,  
		    &kCFTypeDictionaryKeyCallBacks,
		    &kCFTypeDictionaryValueCallBacks); 
    
    // Release the CFNumber the code created.
    CFRelease(values[0]);
    
    // Add the image with the options dictionary to the destination.
    CGImageDestinationAddImage(imageDestination, image, options);

    // Release the options dictionary this code created.
    CFRelease(options);

    // When all the images are added to the destination, finalize it. 
    CGImageDestinationFinalize(imageDestination);
    
    // Release the destination when done with it.
    CFRelease(imageDestination);
}
Exemple #16
0
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
{
    ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));

    RetainPtr<CGImageRef> image;
    if (!m_accelerateRendering)
        image.adoptCF(CGBitmapContextCreateImage(context()->platformContext()));
#if USE(IOSURFACE_CANVAS_BACKING_STORE)
    else
        image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext()));
#endif

    if (!image)
        return "data:,";

    RetainPtr<CFMutableDataRef> data(AdoptCF, CFDataCreateMutable(kCFAllocatorDefault, 0));
    if (!data)
        return "data:,";

    RetainPtr<CFStringRef> uti = utiFromMIMEType(mimeType);
    ASSERT(uti);

    RetainPtr<CGImageDestinationRef> destination(AdoptCF, CGImageDestinationCreateWithData(data.get(), uti.get(), 1, 0));
    if (!destination)
        return "data:,";

    RetainPtr<CFDictionaryRef> imageProperties = 0;
    if (CFEqual(uti.get(), jpegUTI()) && quality && *quality >= 0.0 && *quality <= 1.0) {
        // Apply the compression quality to the image destination.
        RetainPtr<CFNumberRef> compressionQuality(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, quality));
        const void* key = kCGImageDestinationLossyCompressionQuality;
        const void* value = compressionQuality.get();
        imageProperties.adoptCF(CFDictionaryCreate(0, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
    }

    CGImageDestinationAddImage(destination.get(), image.get(), imageProperties.get());
    CGImageDestinationFinalize(destination.get());

    Vector<char> out;
    base64Encode(reinterpret_cast<const char*>(CFDataGetBytePtr(data.get())), CFDataGetLength(data.get()), out);

    return makeString("data:", mimeType, ";base64,", out);
}
Exemple #17
0
int main (int argc, const char * argv[])
{
    if(argc >= 2) {
        CGPDFDocumentRef doc = CGPDFDocumentCreateWithProvider(CGDataProviderCreateWithFilename(argv[1]));
        size_t pages = CGPDFDocumentGetNumberOfPages(doc);
        
        printf("%lu pages\n", pages);
        
        for(size_t i = 1; i <= pages; i++) {
            char filename[1024];
            
            snprintf(filename, 1024, "%s.%03lu.png", argv[1], i);
            
            printf("writing file: %s\n", filename);
         
            CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
            CGContextRef context = CGBitmapContextCreate(NULL, SIZE, SIZE, 8, 4 * SIZE, colorSpace, kCGImageAlphaPremultipliedLast);
            CGColorSpaceRelease(colorSpace);
            
            CGContextDrawPDFDocument(context, CGRectMake(0, 0, SIZE, SIZE), doc, (int)i);
            
            CGImageRef image = CGBitmapContextCreateImage(context);
            
            CGImageDestinationRef dest = CGImageDestinationCreateWithURL(CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFStringCreateWithCString(kCFAllocatorDefault, filename, kCFStringEncodingASCII), kCFURLPOSIXPathStyle, false), kUTTypePNG, 1, NULL);
            
            CGImageDestinationAddImage(dest, image, NULL);
            
            CGImageDestinationFinalize(dest);
            
            CGImageRelease(image);
            CGContextRelease(context);
        }
        
        CGPDFDocumentRelease(doc);
    } else {
        printf("pdf2png [filename]\n");
        return 1;
    }
    
    return 0;
}
Exemple #18
0
String ImageBuffer::toDataURL(const String& mimeType) const
{
    ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));

    RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(context()->platformContext()));
    if (!image)
        return "data:,";

    size_t width = CGImageGetWidth(image.get());
    size_t height = CGImageGetHeight(image.get());

    OwnArrayPtr<uint32_t> imageData(new uint32_t[width * height]);
    if (!imageData)
        return "data:,";
    
    RetainPtr<CGImageRef> transformedImage(AdoptCF, CGBitmapContextCreateImage(context()->platformContext()));
    if (!transformedImage)
        return "data:,";

    RetainPtr<CFMutableDataRef> transformedImageData(AdoptCF, CFDataCreateMutable(kCFAllocatorDefault, 0));
    if (!transformedImageData)
        return "data:,";

    RetainPtr<CGImageDestinationRef> imageDestination(AdoptCF, CGImageDestinationCreateWithData(transformedImageData.get(),
        utiFromMIMEType(mimeType).get(), 1, 0));
    if (!imageDestination)
        return "data:,";

    CGImageDestinationAddImage(imageDestination.get(), transformedImage.get(), 0);
    CGImageDestinationFinalize(imageDestination.get());

    Vector<char> in;
    in.append(CFDataGetBytePtr(transformedImageData.get()), CFDataGetLength(transformedImageData.get()));

    Vector<char> out;
    base64Encode(in, out);
    out.append('\0');

    return String::format("data:%s;base64,%s", mimeType.utf8().data(), out.data());
}
Exemple #19
0
void os_image_save_to_file(const char* filename, unsigned char* data, int width, int height, int channels) {
  assert((channels == 3) || (channels == 4));

  const int bytesPerRow = (width * channels);
  const int bytesPerImage = (bytesPerRow * height);
  const int bitsPerChannel = 8;
  const int bitsPerPixel = (bitsPerChannel * channels);

  CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
  CFDataRef rgbData = CFDataCreate(NULL, data, bytesPerImage);
  CGDataProviderRef provider = CGDataProviderCreateWithCFData(rgbData);
  CGImageRef imageRef = CGImageCreate(
    width,
    height,
    bitsPerChannel,
    bitsPerPixel,
    bytesPerRow,
    colorspace,
    kCGBitmapByteOrderDefault,
    provider,
    NULL,
    true,
    kCGRenderingIntentDefault);
  CFRelease(rgbData);
  CGDataProviderRelease(provider);
  CGColorSpaceRelease(colorspace);

  CFURLRef url = CFURLCreateFromFileSystemRepresentation(NULL, (const uint8_t*)filename, (CFIndex)strlen(filename), false);
  CGImageDestinationRef destination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, NULL);
  CGImageDestinationAddImage(destination, imageRef, nil);

  if (!CGImageDestinationFinalize(destination)) {
    fprintf(stderr, "Failed to write image to %s\n", filename);
  }

  CFRelease(destination);
  CFRelease(url);
  CGImageRelease(imageRef);
}
Exemple #20
0
int main(int argc, const char * argv[])
{
    size_t width = 2000;
    size_t height = 2000;
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(nullptr, width, height, 8, width * 4, colorSpace, kCGImageAlphaNoneSkipLast);
    CGColorSpaceRelease(colorSpace);
    const std::vector<uint8_t> fontVector = generateFont();
    std::ofstream outputFile("/Volumes/Data/home/mmaxfield/tmp/output.otf", std::ios::out | std::ios::binary);
    for (uint8_t b : fontVector)
        outputFile << b;
    outputFile.close();
    
    CFDataRef fontData = CFDataCreate(kCFAllocatorDefault, fontVector.data(), fontVector.size());
    CTFontDescriptorRef fontDescriptor = CTFontManagerCreateFontDescriptorFromData(fontData);
    CFRelease(fontData);

    CFTypeRef featureValues[] = { CFSTR("liga"), CFSTR("clig"), CFSTR("dlig"), CFSTR("hlig"), CFSTR("calt"), CFSTR("subs"), CFSTR("sups"), CFSTR("smcp"), CFSTR("c2sc"), CFSTR("pcap"), CFSTR("c2pc"), CFSTR("unic"), CFSTR("titl"), CFSTR("onum"), CFSTR("pnum"), CFSTR("tnum"), CFSTR("frac"), CFSTR("afrc"), CFSTR("ordn"), CFSTR("zero"), CFSTR("hist"), CFSTR("jp78"), CFSTR("jp83"), CFSTR("jp90"), CFSTR("jp04"), CFSTR("smpl"), CFSTR("trad"), CFSTR("fwid"), CFSTR("pwid"), CFSTR("ruby") };
    CFArrayRef features = CFArrayCreate(kCFAllocatorDefault, featureValues, 30, &kCFTypeArrayCallBacks);

    for (CFIndex i = 0; i < CFArrayGetCount(features); ++i) {
        drawTextWithFeature(context, fontDescriptor, static_cast<CFStringRef>(CFArrayGetValueAtIndex(features, i)), 1, CGPointMake(25, 1950 - 50 * i));
        drawTextWithFeature(context, fontDescriptor, static_cast<CFStringRef>(CFArrayGetValueAtIndex(features, i)), 0, CGPointMake(25, 1925 - 50 * i));
    }

    CFRelease(features);
    CFRelease(fontDescriptor);
    CGImageRef image = CGBitmapContextCreateImage(context);
    CGContextRelease(context);
    CFURLRef url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/Volumes/Data/home/mmaxfield/tmp/output.png"), kCFURLPOSIXPathStyle, FALSE);
    CGImageDestinationRef imageDestination = CGImageDestinationCreateWithURL(url, kUTTypePNG, 1, nullptr);
    CFRelease(url);
    CGImageDestinationAddImage(imageDestination, image, nullptr);
    CGImageRelease(image);
    CGImageDestinationFinalize(imageDestination);
    CFRelease(imageDestination);
    return 0;
}
Exemple #21
0
static bool CGImageEncodeToData(CGImageRef image, CFStringRef uti, const double* quality, CFMutableDataRef data)
{
    if (!image || !uti || !data)
        return false;

    RetainPtr<CGImageDestinationRef> destination = adoptCF(CGImageDestinationCreateWithData(data, uti, 1, 0));
    if (!destination)
        return false;

    RetainPtr<CFDictionaryRef> imageProperties = 0;
    if (CFEqual(uti, jpegUTI()) && quality && *quality >= 0.0 && *quality <= 1.0) {
        // Apply the compression quality to the JPEG image destination.
        RetainPtr<CFNumberRef> compressionQuality = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, quality));
        const void* key = kCGImageDestinationLossyCompressionQuality;
        const void* value = compressionQuality.get();
        imageProperties = adoptCF(CFDictionaryCreate(0, &key, &value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
    }

    // Setting kCGImageDestinationBackgroundColor to black for JPEG images in imageProperties would save some math
    // in the calling functions, but it doesn't seem to work.

    CGImageDestinationAddImage(destination.get(), image, imageProperties.get());
    return CGImageDestinationFinalize(destination.get());
}
Exemple #22
0
QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav)
{
    QList<QByteArray> ret;
    if (!canConvert(mime, flav))
        return ret;

    QImage img = qvariant_cast<QImage>(variant);
    QCFType<CGImageRef> cgimage = qt_mac_createCGImageFromQImage(img);
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
    if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {
        QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
        QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0);
        if (imageDestination != 0) {
            CFTypeRef keys[2];
            QCFType<CFTypeRef> values[2];
            QCFType<CFDictionaryRef> options;
            keys[0] = kCGImagePropertyPixelWidth;
            keys[1] = kCGImagePropertyPixelHeight;
            int width = img.width();
            int height = img.height();
            values[0] = CFNumberCreate(0, kCFNumberIntType, &width);
            values[1] = CFNumberCreate(0, kCFNumberIntType, &height);
            options = CFDictionaryCreate(0, reinterpret_cast<const void **>(keys),
                                         reinterpret_cast<const void **>(values), 2,
                                         &kCFTypeDictionaryKeyCallBacks,
                                         &kCFTypeDictionaryValueCallBacks);
            CGImageDestinationAddImage(imageDestination, cgimage, options);
            CGImageDestinationFinalize(imageDestination);
        }
        QByteArray ar(CFDataGetLength(data), 0);
        CFDataGetBytes(data,
                CFRangeMake(0, ar.size()),
                reinterpret_cast<UInt8 *>(ar.data()));
        ret.append(ar);
    } else
#endif
    {
#ifdef Q_WS_MAC32
        Handle tiff = NewHandle(0);
        if (resolveMimeQuickTimeSymbols()) {
            GraphicsExportComponent graphicsExporter;
            ComponentResult result = OpenADefaultComponent(GraphicsExporterComponentType,
                                                           kQTFileTypeTIFF, &graphicsExporter);
            if (!result) {
                unsigned long sizeWritten;
                result = ptrGraphicsExportSetInputCGImage(graphicsExporter, cgimage);
                if (!result)
                    result = ptrGraphicsExportSetOutputHandle(graphicsExporter, tiff);
                if (!result)
                    result = ptrGraphicsExportDoExport(graphicsExporter, &sizeWritten);

                CloseComponent(graphicsExporter);
            }
        }
        int size = GetHandleSize((Handle)tiff);
        QByteArray ar(reinterpret_cast<char *>(*tiff), size);
        ret.append(ar);
        DisposeHandle(tiff);
#endif
    }
    return ret;
}
Exemple #23
0
// save the image
void save_image (vImage_Buffer *src_i, img_prop o, float compression, char *o_file) {
	
	// Create a CFDataRef from the rotated data in the destination vImage_Buffer
	CFDataRef output_Data = CFDataCreate (NULL, src_i->data, src_i->height * src_i->rowBytes);
	
	if (o->bits_ppixel == 32) {
		
		// convert from 24bit to 32bit by adding the alpha channel.
		output_Data = convert32_24bit (output_Data, o);
		src_i->rowBytes = src_i->width * 3;
	}

    
	// Check for a NULL value.
	if (NULL == output_Data) {
		printf ("Could not create CFDataRef from vImage_Buffer.\n"); 
		exit (0);
	}
	
	// Create a Data provider from the rotated data
	CGDataProviderRef destination_data_provider = CGDataProviderCreateWithCFData (output_Data);
	
	// Check for null
	if (NULL == destination_data_provider) {
		printf ("Could not create CGDataProviderRef from CGDataRef.\n"); 
		exit (0);
	}
  
    CGImageRef processed_image;

  
    // Create the image with sRGB for the colour space
    processed_image = CGImageCreate (src_i->width, // 1 width
                                                src_i->height, // 2 height
                                                (size_t)o->bits_ppixel/ (o->bits_ppixel/8), // bitsPerComponent
                                                (size_t)o->bits_ppixel, //bitsPerPixel
                                                src_i->rowBytes, // bytesPerRow
                                                CGColorSpaceCreateDeviceRGB(), // Generic ColourSpace
                                                kCGBitmapByteOrder32Big, // bitmapInfo
                                                destination_data_provider, // Data provider ** DataProviderRef 
                                                NULL, // decode
                                                0, // Interpolate
                                                kCGRenderingIntentSaturation); // rendering intent
  	if (NULL == processed_image) exit (0);
/*    
  } else {

    // release the reference colour space
    CGColorSpaceRelease(rgb);

    // Create the image with sRGB for the colour space
    processed_image = CGImageCreate (src_i->width, // 1 width
                                     src_i->height, // 2 height
                                     (size_t)o->bits_ppixel/ (o->bits_ppixel/8), // bitsPerComponent
                                     (size_t)o->bits_ppixel, //bitsPerPixel
                                     src_i->rowBytes, // bytesPerRow
                                     o->colorSpace, // ColourSpace of original
                                     kCGBitmapByteOrder32Big, // bitmapInfo
                                     destination_data_provider, // Data provider ** DataProviderRef 
                                     NULL, // decode
                                     0, // Interpolate
                                     kCGRenderingIntentSaturation); // rendering intent
  	if (NULL == processed_image) exit (0);
    
  }*/
  
	// create a CFStringRef from the C string
	CFStringRef fn = CFStringCreateWithCString (NULL, o_file, kCFStringEncodingUTF8);
	if (NULL == fn) exit (0);
	
	// Convert the CFStringRef to a CFURLRef
	CFURLRef fon = CFURLCreateWithFileSystemPath (NULL, fn, kCFURLPOSIXPathStyle, false);
	if (NULL == fon) exit (0);

	// Create an image destination
	CGImageDestinationRef image_destination = CGImageDestinationCreateWithURL (fon, kUTTypeJPEG, 1, NULL);

	// Release the CFURLRef
	CFRelease (fon);
	fon = NULL;
	
	// release the CFStringRef
	CFRelease (fn);
	fn = NULL;

	// Check for a NULL value in image_destination
	if (NULL == image_destination) {
		printf ("Null Image_destination: Could not create the CGImageDestinationRef from the supplied URL.\n");
		exit (0);
	}

	// Set the compression factor for the images
	CFStringRef keys[1];
	CFTypeRef value[1];
	
	// Use compression key
	keys[0] = kCGImageDestinationLossyCompressionQuality;

	// set the compression amount. 1 = no compression 0 = max compression
	value[0] = CFNumberCreate (NULL, kCFNumberFloatType, &compression);
	
	// Pointer to the image attribs dictionary
	CFDictionaryRef options;
	
	// create the dictionary
	options = CFDictionaryCreate (kCFAllocatorDefault, (void *)keys, (void *)value, 1, NULL, NULL);
	
	// Copy data to the output information to the destination
	CGImageDestinationAddImage (image_destination, processed_image, options);
	
	// Check for a NULL value in image_destination
	if (NULL == image_destination) {
		printf ("Null Image_destination: Could not add the rotated image.\n"); 
		exit (0);
	}
	
	// Write the image to disk
	if (!CGImageDestinationFinalize (image_destination)) {
		// Could not write the file for some reason
		printf ("Could not write the file to disk.\n"); 
		exit (1);
	}

	// Release the pointer the the scaled buffer
	CFRelease (output_Data);
	output_Data = NULL;
	
	// Release the dictionary
	CFRelease (keys[0]);
	CFRelease (value[0]);
	CFRelease (options);
	options = NULL;
	
	// Release the rotated image.
	CGImageRelease (processed_image);
	processed_image = NULL;
	
	// Release a data provider
	CGDataProviderRelease (destination_data_provider);
	destination_data_provider = NULL;
	
	// Release the image destination
	CFRelease (image_destination);
	image_destination = NULL;

} // save_image
/* write image file */
int BIWriteFile(
	const char			*fileName,
	BIFileType			fileType,
	const BIImageInfo	*imageInfo,
	const unsigned char *bitmap)
{
	int						ourRtn = 0;
	CGImageAlphaInfo		alpha;
	CGBitmapInfo			bitmapInfo = 0;
	CGContextRef			bitmapContextRef = NULL;
	CGImageRef				imageRef = NULL;
	CFURLRef				fileURL = NULL;
	CGImageDestinationRef	imageDestRef = NULL;
	CGColorSpaceRef			rgbColorSpaceRef = NULL;
	CFStringRef				uti = NULL;
	CFDictionaryRef			propDict = NULL;
	
	if(imageInfo->bitsPerPixel == 8) {
		/* grayscale image */
		rgbColorSpaceRef = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
		alpha = kCGImageAlphaNone;
		bitmapInfo = 0;
	}
	else {
		/* RGB no alpha */
        rgbColorSpaceRef = CGColorSpaceCreateDeviceRGB();
		alpha = kCGImageAlphaNoneSkipLast;
		bitmapInfo = kCGBitmapByteOrder32Big | alpha;
	}
	if(rgbColorSpaceRef == NULL) {
		fprintf(stderr, "***BIWriteFile: Error on CGColorSpaceCreateWithName\n");
		ourRtn = 1;
		goto errOut;
	}
	
	/* A bitmap-oriented CGContextRef based on bitmap data */
	bitmapContextRef = CGBitmapContextCreate((void *)bitmap, 
		imageInfo->imageWidth, imageInfo->imageHeight, 
		imageInfo->bitsPerComponent, imageInfo->bytesPerRow, 
		rgbColorSpaceRef, 
		bitmapInfo);
	if(bitmapContextRef == NULL) {
		fprintf(stderr, "***BIWriteFile: Error creating CGBitmapContext\n");
		ourRtn = 1;
		goto errOut;
	}
	
	/* CGContextRef --> CGImageRef */
    imageRef = CGBitmapContextCreateImage(bitmapContextRef);

	fileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, 
		(unsigned char*)fileName, strlen(fileName), FALSE);
	if(fileURL == NULL) {
		fprintf(stderr, "***BIWriteFile: Error on CFURLCreateFromFileSystemRepresentation\n");
		ourRtn = 1;
		goto errOut;
	}

	uti = BIGetUTI(fileURL, fileType);
	if(uti == NULL) {
		ourRtn = 1;
		goto errOut;
	}
	imageDestRef = CGImageDestinationCreateWithURL(fileURL, 
		uti, 
		1, NULL );
	if(imageDestRef == NULL) {
		fprintf(stderr, "***BIWriteFile: Error on CGImageDestinationCreateWithURL\n");
		ourRtn = 1;
		goto errOut;
	}
	
	/* Some BIFileTypes require the specification of a "Lossless" property */
	switch(fileType) {
		case BI_FT_JPEG2000_Lossless:
		case BI_FT_JPEG_Lossless:
		{
			CFStringRef key = kCGImageDestinationLossyCompressionQuality;
			float valf = 1.0;
			CFNumberRef val = CFNumberCreate(NULL, kCFNumberFloatType, &valf);
			propDict = CFDictionaryCreate(NULL, (const void **)&key, (const void **)&val, 1, 
				&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
			/* 
			 * The docs say we should be able to set these properties like this,
			 * but that has no effect. We need to pass it as the 'properties' argument
			 * to CGImageDestinationAddImage(), below. 
			 * See <rdar://problem/5670614> 
			 */
			//CGImageDestinationSetProperties(imageDestRef, propDict);
			CFRelease(val);
			break;
		}
		default:
			break;
	}
	
	CGImageDestinationAddImage(imageDestRef, imageRef, propDict);
	
	/* Write the image to disk */
	if(!CGImageDestinationFinalize(imageDestRef)) {
		fprintf(stderr, "***BIWriteFile: Error on CGImageDestinationFinalize\n");
		ourRtn = 1;
	}
	if(propDict != NULL) {
		CFRelease(propDict);
	}
errOut:
	CFRELEASE(bitmapContextRef);
	CFRELEASE(imageRef);
	CFRELEASE(fileURL);
	CFRELEASE(imageDestRef);
	CFRELEASE(rgbColorSpaceRef);
	return ourRtn;
}
bool  ImageIOEncoder::write( const Mat& img, const vector<int>& 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;
}