Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
Hi, i am still new at mac and objective-c.
I searched a few hours to answer my question, but i did not get anywhere.
I want to draw some simple 2D path / object and save it to a svg or pdf file.
My plan was to create a CGPath (i already know how to do that) and afterwards export it to svg or pdf file on my disk.
I would be very thankful if anyone has some kind of code snippet or tutorial, where this is explained.
Hopefully, NL.
You can create a CGPDFContext and draw into it using Core Graphics commands (like CGPath stuff).
I used the Tipp of user1118321 and searched in the Core Graphics.
Sadly it still took me a lot of time and somehow i can not add an existing path to the context ... somehow i can't get it stroked.
In my case this is no problem, since i want to draw a new one. Core Graphics does offer functions similar to CGPaths drawing functions in CGContext.
This is my code i use to create a pdf file and draw a new path in it:
-(void) createPDFwithSize:(CGRect) size andFilename: (const char *) filename;
{
CGContextRef pdfContext;
CFStringRef path;
CFURLRef url;
CFDataRef boxData = NULL;
CFMutableDictionaryRef myDictionary = NULL;
CFMutableDictionaryRef pageDictionary = NULL;
path = CFStringCreateWithCString (NULL, filename, kCFStringEncodingUTF8);
url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle, 0);
CFRelease (path);
myDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(myDictionary, kCGPDFContextTitle, CFSTR("My PDF File"));
CFDictionarySetValue(myDictionary, kCGPDFContextCreator, CFSTR("My Name"));
pdfContext = CGPDFContextCreateWithURL (url, &size, myDictionary);
CFRelease(myDictionary);
CFRelease(url);
pageDictionary = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
boxData = CFDataCreate(NULL,(const UInt8 *)&size, sizeof (CGRect));
CFDictionarySetValue(pageDictionary, kCGPDFContextMediaBox, boxData);
CGPDFContextBeginPage (pdfContext, pageDictionary);
// -----------------------------------------------------------------------------------------------------------------
// Draw stuff ...
CGContextSetLineWidth(pdfContext, 1);
CGContextSetStrokeColorWithColor(pdfContext, CGColorCreateGenericRGB(0, 0, 0, 1));
CGContextBeginPath(pdfContext);
CGContextMoveToPoint(pdfContext, 100, 100);
CGContextAddLineToPoint(pdfContext, 100, 150);
CGContextAddLineToPoint(pdfContext, 125, 175);
CGContextAddLineToPoint(pdfContext, 150, 150);
CGContextAddLineToPoint(pdfContext, 150, 100);
CGContextAddLineToPoint(pdfContext, 100, 150);
CGContextAddLineToPoint(pdfContext, 150, 150);
CGContextAddLineToPoint(pdfContext, 100, 100);
CGContextAddLineToPoint(pdfContext, 150, 100);
CGContextStrokePath(pdfContext); // don't forget this
CGContextClosePath(pdfContext);
// -----------------------------------------------------------------------------------------------------------------
CGPDFContextEndPage (pdfContext);
CGContextRelease (pdfContext);
CFRelease(pageDictionary);
CFRelease(boxData);
}
Related
I'm new to CoreGraphics framework.
We have used ILPDFKit library to render PDF or form
We embedded the drawn paths to existing PDF.Here is the code
-(NSData *)embededPdfAnnotationPointsInPdfAtPath:(NSString *)pdfPath
{
NSURL *pdfUrl = [NSURL fileURLWithPath:pdfPath];
CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfUrl);
NSMutableData *data = [NSMutableData new];
UIGraphicsBeginPDFContextToData(data, CGRectZero, nil);
for(NSUInteger pageIndex = 1; pageIndex <= [self pdfDrawViewInfo].count; pageIndex ++)
{
// Get the current page and page frame
CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdf, pageIndex);
const CGRect pageFrame = CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox);
UIGraphicsBeginPDFPageWithInfo(pageFrame, nil);
// Draw the page (flipped)
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextScaleCTM(ctx, 1, -1);
CGContextTranslateCTM(ctx, 0, -pageFrame.size.height);
CGContextDrawPDFPage(ctx, pdfPage);
CGContextRestoreGState(ctx);
UIImage *drawViewImage = [self annotatedImageForPdfPageAtIndex:(pageIndex - 1)];
UIImage *annotatedImgForPdfPage = [self imageWithImage:drawViewImage scaledToSize:pageFrame.size] ;
[annotatedImgForPdfPage drawInRect:pageFrame];
}
UIGraphicsEndPDFContext();
// CGPDFDocumentRelease(pdf);
// CGImageRelease(annotatedImgCGref);
return data;
}
Above code indicates, we are just pasting image(drawn paths) on existing PDF.
Later functionality changed as "After saving PDF with annotations(freehand drawing), we need to have control over annotated stuff"
Question:
Edit PDF with annotation(freehand drawing), save it.After saving the PDF with annotated stuff, we need to again gain its editing capability. We need to know the saving mechanism and steps of this process.Please put your views here, so that it help me a lot.
Thanks inadvance
I would probably conserve the pdf original version, and store the edits in another file.
Than each time the user save, the app apply the annotations and other stuff to original version and generate the final pdf (in case of sharing or exportation features)
That would give you a complete control, (i guess this is also the same way "apple photo", "iPhoto" and "Aperture" manage the pictures modifications...)
I like to display .cpbitmap (its the file formate iOS saves the wallpapers) in a UIImageView. The problem is I need to convert it. I already figure out that if you get its Data (NSData) and convert every bit you get the UIColor, so the first Bit is R, then B, then G and then Alpha (I think). Now I need to "draw" an UIImage out of the info. Does anyone know how to do this?
Here is the link to the .cpbitmap file: https://www.dropbox.com/s/s9v4lahixm9cuql/LockBackground.cpbitmap
It would be really cool if someone can help me,
Thanks
EDIT
I found a working python script, is someone able to translate it to Objective
#!/usr/bin/python
from PIL import Image,ImageOps
import struct
import sys
if len(sys.argv) < 3:
print "Need two args: filename and result_filename\n";
sys.exit(0)
filename = sys.argv[1]
result_filename = sys.argv[2]
with open(filename) as f:
contents = f.read()
unk1, width, height, unk2, unk3, unk4 = struct.unpack('<6i', contents[-24:])
im = Image.fromstring('RGBA', (width,height), contents, 'raw', 'RGBA', 0, 1)
r,g,b,a = im.split()
im = Image.merge('RGBA', (b,g,r,a))
im.save(result_filename)
The basic process of converting RGBA data into an image is to create a CGDataProviderRef with the raw data, and then use CGImageCreate to create a CGImageRef, from which you can easily generate a UIImage. So, that gives you something like:
- (UIImage *) imageForBitmapData:(NSData *)data size:(CGSize)size
{
void * bitmapData;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
int bitmapBytesPerRow = (size.width * 4);
int bitmapByteCount = (bitmapBytesPerRow * size.height);
bitmapData = malloc( bitmapByteCount );
NSAssert(bitmapData, #"Unable to create buffer");
[data getBytes:bitmapData length:bitmapByteCount];
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, bitmapData, bitmapByteCount, releasePixels);
CGImageRef imageRef = CGImageCreate(size.width,
size.height,
8,
32,
bitmapBytesPerRow,
colorSpace,
(CGBitmapInfo)kCGImageAlphaLast,
provider,
NULL,
NO,
kCGRenderingIntentDefault);
UIImage *image = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGColorSpaceRelease(colorSpace);
CGDataProviderRelease(provider);
return image;
}
With a releasePixels function defined as follows:
void releasePixels(void *info, const void *data, size_t size)
{
free((void*)data);
}
The only trick was identifying the dimensions of the bitmap. There are 4,142,592 bytes of image data (there is some extra stuff at the end of the file, which is self evident if you examine the file in hexadecimal in Xcode). That doesn't correlate to any standard device dimensions. But if you look at the possible values that divide evenly into 4,142,592, you get a couple of promising ones (496, 522, 558, 576, 696, 744, 899, 928, and 992). And if you just try those out, it becomes obvious that the image is 744 x 1392.
You can then use those dimensions with the above method, and you get your image.
While I discovered the size of the image empirically, I noticed that those dimensions were encoded at the end of the file. This is confirmed by your Python code, which suggests that the image width is the fifth from the last UInt32, and the height is the fourth from the last UInt32. Thus, you can use the above routine like so, extracting the dimensions from those two 32-bit integers encoded near the end of the file:
NSString *path = [[NSBundle mainBundle] pathForResource:#"LockBackground" ofType:#"cpbitmap"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSAssert(data, #"no data found");
UInt32 width;
UInt32 height;
[data getBytes:&width range:NSMakeRange([data length] - sizeof(UInt32) * 5, sizeof(UInt32))];
[data getBytes:&height range:NSMakeRange([data length] - sizeof(UInt32) * 4, sizeof(UInt32))];
self.imageView.image = [self imageForBitmapData:data size:CGSizeMake(width, height)];
I am trying to create a CVPixelBuffer to allocate a bitmap in it and bind it to an OpenGL texture under IOS 5, but I having some problems on it. I can generate the pixel buffer but the IOSurface is always null, so I can not use it with CVOpenGLESTextureCacheCreateTextureFromImage. Since I am not using a Camera or a Video, but an self generated bitmap I can not use CVSampleBufferRef to get the pixel buffer from it.
I let you my code in case some of you knows how to solve this issue.
CVPixelBufferRef renderTarget = nil;
CFDictionaryRef empty; // empty value for attr value.
CFMutableDictionaryRef attrs;
empty = CFDictionaryCreate(kCFAllocatorDefault, // our empty IOSurface properties dictionary
NULL,
NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
attrs = CFDictionaryCreateMutable(kCFAllocatorDefault,
2,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(attrs,
kCVPixelBufferIOSurfacePropertiesKey,
empty);
CFDictionarySetValue(attrs, kCVPixelBufferOpenGLCompatibilityKey, [NSNumber numberWithBool:YES]);
CVReturn err = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, tmpSize.width, tmpSize.height, kCVPixelFormatType_32ARGB, imageData, tmpSize.width*4, 0, 0, attrs, &renderTarget);
If I dump the new PixelBufferRef I get:
1 : <CFString 0x3e43024c [0x3f8f8650]>{contents = "OpenGLCompatibility"} = <CFBoolean 0x3f8f8a10 [0x3f8f8650]>{value = true}
2 : <CFString 0x3e43026c [0x3f8f8650]>{contents = "IOSurfaceProperties"} = <CFBasicHash 0xa655750 [0x3f8f8650]>{type = immutable dict, count = 0,
entries =>
}
}
And I get an -6683 error (kCVReturnPixelBufferNotOpenGLCompatible) if I try to use it with a TextureCache, this way:
CVOpenGLESTextureCacheCreateTextureFromImage (
kCFAllocatorDefault,
self.eagViewController.textureCache,
renderTarget,
nil, // texture attributes
GL_TEXTURE_2D,
GL_RGBA, // opengl format
tmpSize.width,
tmpSize.height,
GL_BGRA, // native iOS format
GL_UNSIGNED_BYTE,
0,
&renderTextureTemp);
OK this is what I want :
Take some NSImages
Add them to an ICNS file
Save it
This is what I've done so far (purely as a test) :
- (CGImageRef)refFromImage:(NSImage*)img
{
CGImageSourceRef source;
source = CGImageSourceCreateWithData((CFDataRef)[img TIFFRepresentation], NULL);
CGImageRef maskRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
return maskRef;
}
- (void)awakeFromNib
{
NSImage* img1 = [NSImage imageNamed:#"image1"];
NSImage* img2 = [NSImage imageNamed:#"image2"];
NSLog(#"%#",img1);
CGImageRef i1 = [self refFromImage:img1];
CGImageRef i2 = [self refFromImage:img2];
NSURL *fileURL = [NSURL fileURLWithPath:[#"~/Documents/final.icns" stringByExpandingTildeInPath]];
CGImageDestinationRef dr = CGImageDestinationCreateWithURL((__bridge CFURLRef)fileURL, kUTTypeAppleICNS , 1, NULL);
CGImageDestinationAddImage(dr, i1, NULL);
CGImageDestinationAddImage(dr, i2, NULL);
/* Even tried adding 'multiple' times
CGImageDestinationAddImage(dr, i1, NULL);
CGImageDestinationAddImage(dr, i2, NULL);
CGImageDestinationAddImage(dr, i1, NULL);
CGImageDestinationAddImage(dr, i2, NULL);
*/
CGImageDestinationFinalize(dr);
CFRelease(dr);
}
But, it still keeps throwing an error :
ImageIO: CGImageDestinationFinalize image destination does
not have enough images
What's wrong with my code?
I've had a look at the answers below, but still nothing :
Save CGImageRef to PNG file errors? (ARC Caused?)
How exactly to make a CGImageRef from an image on disk
You can use IconFamily.
IconFamily is a Cocoa/Objective-C wrapper for the Mac OS X Carbon
API's "icon family" data type. Its main purpose is to enable Cocoa
applications to easily create custom file icons from NSImage
instances, and thus take advantage of Mac OS X's high-resolution RGBA
"thumbnail" icon formats to provide richly detailed thumbnail previews
of the files' contents.
NSImage *mImage = [[NSImage alloc] initWithContentsOfFile:#"/Users/Username/Desktop/WhiteTiger.jpg"];
IconFamily *fam = [IconFamily iconFamilyWithThumbnailsOfImage:mImage];
[fam writeToFile:#"/Users/Username/Desktop/WhiteTiger.icns"];
I am trying to integrate the glGrab code for screen capture on Mac OS under mentioned config and I am currently stuck at an all blue screen being rendered inside my window. I believe that there is some issue with how the image texture has been created, but can't tell what. I am just a couple of weeks old in OpenGL so please go easy on me if I missed something obvious.
I am using the glGrab code as it is except CGLSetFullScreen method (and not even CGLSetFullScreenOnDisplay) because these methods are now deprecated. So this one line of code has been commented out for the time being.
I have been doing some research on this topic since some time now and found another thread on stackoverflow which possibly could have been the complete answer, but it helped much nonetheless. Convert UIImage to CVImageBufferRef
A direct reference to the glGrab code is http://code.google.com/p/captureme/source/browse/trunk/glGrab.c
The answer to my above question is present below. So no more opengl or glGrab. Use what's best optimized for Mac OSX. This doesn't include the code for capturing the mouse pointer also, but I am sure that if you have landed on this page you're smart enough to figure it out by yourself. Or if someone reading this knows the solution then it's your chance to help the fraternity :) Also this code returns a CVPixelBufferRef. You may choose to send back either the CGImageRef or even the bytestream as it is, just tweak it to your liking. :
void swizzleBitmap(void *data, int rowBytes, int height) {
int top, bottom;
void * buffer;
void * topP;
void * bottomP;
void * base;
top = 0;
bottom = height - 1;
base = data;
buffer = malloc(rowBytes);
while (top < bottom) {
topP = (void *)((top * rowBytes) + (intptr_t)base);
bottomP = (void *)((bottom * rowBytes) + (intptr_t)base);
bcopy( topP, buffer, rowBytes );
bcopy( bottomP, topP, rowBytes );
bcopy( buffer, bottomP, rowBytes );
++top;
--bottom;
}
free(buffer);
}
CVImageBufferRef grabViaOpenGL() {
int bytewidth;
CGImageRef image = CGDisplayCreateImage(kCGDirectMainDisplay); // Main screenshot capture call
CGSize frameSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image)); // Get screenshot bounds
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:NO], kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
CVPixelBufferRef pxbuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, frameSize.width,
frameSize.height, kCVPixelFormatType_32ARGB, (CFDictionaryRef) options,
&pxbuffer);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata, frameSize.width,
frameSize.height, 8, 4*frameSize.width, rgbColorSpace,
kCGImageAlphaNoneSkipLast);
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
CGImageGetHeight(image)), image);
bytewidth = frameSize.width * 4; // Assume 4 bytes/pixel for now
bytewidth = (bytewidth + 3) & ~3; // Align to 4 bytes
swizzleBitmap(pxdata, bytewidth, frameSize.height); // Solution for ARGB madness
CGColorSpaceRelease(rgbColorSpace);
CGImageRelease(image);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}