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 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); }
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; }
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); }
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; }
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; }
/* 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; }
// 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