How to create a PDFNet Image object from a UIImage on iOS

Q: How can I create an Image object from a UIImage without writing it to disk?

A:

You can create an Image object using an NSData buffer via he class method CreateImageWithData. Below is some sample code showing how to do so. Note that PDF images do not support alpha directly (you would need to construct a soft mask), so you will need to strip out the alpha channel, as shown below.

SDFDoc* doc = [[m_pdfViewCtrl GetDoc] GetSDFDoc];
NSData* data = [self getNSDataFromUIImage:myUIImage];
Obj* o = [[Obj alloc] init];

Image* trnImage = [Image CreateWithData:doc image_data:data image_data_size:data.length width:image.size.width height:image.size.heightbpc:8 color_space:[ColorSpace CreateDeviceRGB] encoder_hints:o];

where getNSDataFromUIImage is:

-(NSData*)getNSDataFromUIImage:(UIImage*)image
{

CGImageRef imageRef = [image CGImage];
NSUInteger width = CGImageGetWidth(imageRef);
NSUInteger height = CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
unsigned char rawData = (unsigned char) malloc(height * width * 4 * sizeof(unsigned char));
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = bytesPerPixel * width;
NSUInteger bitsPerComponent = 8;

CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);

unsigned char noAlpha = (unsigned char) malloc(height * width * 3* sizeof(unsigned char));

for(int pix = 0; pix < height * width * 4; pix += bytesPerPixel)
{
memcpy((noAlpha+pix/bytesPerPixel*3), (rawData+pix), 3);

}

NSData* data = [[NSData alloc] initWithBytesNoCopy:noAlpha length:heightwidth3*sizeof(unsigned char) freeWhenDone:YES];
free(rawData);

return data;

}

Example from UIImage. The project’s PNG build settings aren’t important, because getting PNG data from a UIImage object is always in a standard PNG format. This also preserves transparency.

PTElementBuilder* builder = [[PTElementBuilder alloc] init];
PTElementWriter* writer = [[PTElementWriter alloc] init];

PTPDFDoc* doc = [self.pdfViewCtrl GetDoc];

// will write image to page 1
PTPage* page = [doc GetPage:1];

[writer WriterBeginWithPage: page placement: e_ptoverlay page_coord_sys: YES compress: YES];

//get a UIImage representation of the image
UIImage *bundleImage = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@“mov” ofType:@“png”]];

// translate UIImage to a PNG
NSData *bundleImageData = UIImagePNGRepresentation(bundleImage);

// used to write image using flate (lossless) compression
PTObjSet* hint_set = [[PTObjSet alloc] init];
PTObj* enc = [hint_set CreateArray];
[enc PushBackName: @“Flate”];

// create a PTImage object from the PNG data and add it as a resource to the PDF file
PTImage *img = [PTImage CreateWithDataSimple:[doc GetSDFDoc] image_data:bundleImageData image_data_size:bundleImageData.length encoder_hints:enc];

// place image 100 units up and over from left hand corner
PTElement* element = [builder CreateImageWithMatrix: img mtx: [[PTMatrix2D alloc] initWithA: 100 b: 0 c: 0 d: 100 h: [img GetImageWidth] v: [img GetImageHeight]]];

[writer WritePlacedElement: element];
[writer End];

Example from disk. Note that the project’s build settings “Compress PNG Files” and “Remove Text Metadata From PNG Files” must both be set to NO. Otherwise Xcode will compress the images into a proprietary non-standard “PNG” format which results in an exception.

PTElementBuilder* builder = [[PTElementBuilder alloc] init];
PTElementWriter* writer = [[PTElementWriter alloc] init];

PTPDFDoc* doc = [self.pdfViewCtrl GetDoc];

// will write image to page 1
PTPage* page = [doc GetPage:1];

[writer WriterBeginWithPage: page placement:e_ptoverlay page_coord_sys:YES compress:YES];

NSString* imagePath = [[NSBundle mainBundle] pathForResource:@“mov” ofType:@“png”];

// create a PTImage object and add it as a resource to the PDF file
PTImage* img = [PTImage Create: [doc GetSDFDoc] filename: imagePath];

// place the image 100 units up and over from left hand corner
PTElement* element = [builder CreateImageWithMatrix: img mtx: [[PTMatrix2D alloc] initWithA: 100 b: 0 c: 0 d: 100 h:[img GetImageWidth] v:[img GetImageHeight]]];

[writer WritePlacedElement: element];
[writer End];