hope to save NSImage without image size change - macos

what I hope to get is
1.load image to a NSImage
2.draw some text on the NSImage
3.save the NSImage to a image file
so I used code below to load image to NSImage
NSData *data = [NSData dataWithContentsOfFile:[asset fullFilename]];
NSImage *img = [[NSImage alloc] initWithData:data] ;
if the original image size is
imageOriginalWidth, imageOriginalHeight
the size(width, height) of img will be smaller than original image size, it means that
imgWidth<imageOriginalWidth
imgHeight<imageOriginalHeight
it also means that if I save the NSImage with text to a image file, the new image is smaller than the original one
Your comment welcome

Related

How to get CGImageForProposedRect to provide 1:1 pixel data on Retina Mac

In our app, we're creating an PDF NSImage (therefore scalable) and then using CGImage routines to write that data to a TIFF file. This works fine on non-retina display Macintoshes, but on retina machines, the data that is returned is twice the resolution we expect (just like the screen).
The code we're using works takes a newly formed NSView subclass referencing the data to draw (not the original on-screen view) as printingMapView.
NSData *pdfData = [printingMapView dataWithPDFInsideRect: frame];
NSImage *image = [[NSImage alloc] initWithData: pdfData];
[image setSize: size];
NSRect pRect = NSMakeRect( 0, 0, [image size].width, [image size].height);
CGImageRef cgImage = [image CGImageForProposedRect: &pRect context: NULL hints:NULL];
I have looked around for any hints that could be handed to the CGImageForProposedRect:context:hints call, but there's nothing in the Apple documentation relating to content scale.
Is there any way to do this other than creating an NSBitmapImageRep of the full size and passing that in as the context parameter to CGImageForProposedRect:context:hints?
That seems like it's likely to use a lot of memory during the operation.
So CGImageForProposedRect does return 1:1 pixel data, if you are getting a CGImage out of the function that is doubled in size the NSImageRep of that NSImage must also be doubled in size. Check your code to see if you have any calls to NSImage drawInRect where you are writing to an retina context. That is what was happening to me.

NSImage and PDFImageRep caching still draws at only one resolution

I have an NSImage, initialized with PDF data, created like this:
NSData* data = [view dataWithPDFInsideRect:view.bounds];
slideImage = [[NSImage alloc] initWithData:data];
The slideImage is now the size of the view.
When I try to render the image in an NSImageView, it only draws sharp when the image view is exactly the original size of the image, even if you clear the cache or change the image size. I tried setting the cacheMode to NSImageCacheNever, which also didn't work. The only image rep in the image is the PDF one, and when I render it to a PDF file it shows that it's vector.
As a workaround, I create a NSBitmapImageRep with a different size, call drawInRect on the original image, and put the bitmap representation inside a new NSImage and render that, which works, but it feels like it's not optimal:
- (NSBitmapImageRep*)drawToBitmapOfWidth:(NSInteger)width
andHeight:(NSInteger)height
withScale:(CGFloat)scale
{
NSBitmapImageRep *bmpImageRep = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes:NULL
pixelsWide:width * scale
pixelsHigh:height * scale
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSCalibratedRGBColorSpace
bitmapFormat:NSAlphaFirstBitmapFormat
bytesPerRow:0
bitsPerPixel:0
];
bmpImageRep = [bmpImageRep bitmapImageRepByRetaggingWithColorSpace:
[NSColorSpace sRGBColorSpace]];
[bmpImageRep setSize:NSMakeSize(width, height)];
NSGraphicsContext *bitmapContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:bmpImageRep];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:bitmapContext];
[self drawInRect:NSMakeRect(0, 0, width, height) fromRect:NSZeroRect operation:NSCompositeCopy fraction:1];
[NSGraphicsContext restoreGraphicsState];
return bmpImageRep;
}
- (NSImage*)rasterizedImageForSize:(NSSize)size
{
NSImage* newImage = [[NSImage alloc] initWithSize:size];
NSBitmapImageRep* rep = [self drawToBitmapOfWidth:size.width andHeight:size.height withScale:1];
[newImage addRepresentation:rep];
return newImage;
}
How can I get the PDF to render nicely at any size without resorting to hacks like mine?
The point of NSImage is that you create it with the size (in points) that you want it to be. The backing representation can be vector based (e.g. PDF), and the NSImage is resolution independent (i.e. it supports different pixels per point), but the NSImage still has a fixed size (in points).
One one the points of an NSImage is that it will / can add a cache representation to speed up subsequent drawing.
If you need to draw a PDF to multiple sizes, and you want to use an NSImage, you're probably best of creating an NSImage for your given target size. If you want to, you can keep the NSPDFImageRef around -- I don't think it'll save you much.
We tried the following:
NSPDFImageRep* rep = self.representations.lastObject;
return [NSImage imageWithSize:size flipped:NO drawingHandler:^BOOL (NSRect dstRect)
{
[[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
[rep drawInRect:dstRect fromRect:NSZeroRect operation:NSCompositeCopy fraction:1 respectFlipped:YES hints:#{
NSImageHintInterpolation: #(NSImageInterpolationHigh)
}];
return YES;
}];
And that does give you nice results when scaling up, but makes for blurry images
when scaling down.

Rescale image in imageview

In my app I can take a photo from the camera and display it in an imageview, but what I want to be able to do is rescale/resize the resolution of the image so it's not as big and does not take up so much memory in the app.
Here is the code I use for displaying the image in the imageview:
image = [info objectForKey:UIImagePickerControllerOriginalImage];
[ImageView1 setImage:image]; // "ImageView1" name of any UImageView.
[self dismissViewControllerAnimated:YES completion:NULL];
I want the image scaled down as the image can also be sent via email, so it must be nice and small.
You can try this code:
+ (UIImage*)imageWithImage:(UIImage*)image
scaledToSize:(CGSize)newSize;
{
UIGraphicsBeginImageContext( newSize );
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
As far as storage of the image, the fastest image format to use with the iPhone is PNG, because it has optimizations for that format. However, if you want to store these images as JPEGs, you can take your UIImage and do the following:
NSData *dataForJPEGFile = UIImageJPEGRepresentation(theImage, 0.6);
This creates an NSData instance containing the raw bytes for a JPEG image at a 60% quality setting. The contents of that NSData instance can then be written to disk or cached in memory.
You can refer this link also: UIImage: Resize, then Crop
Hope this will helps you.

Getting bitmap data from JPEG image using Cocoa

I need to extract the raw RGB bitmap data from a JPEG or PNG file, with all the bits in the file, not a window or color converted version.
I'm new to Cocoa, but it looks like I open an image using NSImage like this:
NSString* imageName=[[NSBundle mainBundle] pathForResource:#"/Users/me/Temp/oxberry.jpg" ofType:#"JPG"];
NSImage* tempImage=[[NSImage alloc] initWithContentsOfFile:imageName];
NSBitmapImageRep* imageRep=[[[NSBitmapImageRep alloc] initWithData:[tempImage TIFFRepresentation]] autorelease];
unsigned char* bytes=[imageRep bitmapData];
int bits=[imageRep bitsPerPixel];
Then to get the bitmap data there seems to be lots of options: Bitmapimage, CGImage, etc.
What is the simplest approach and if there was a code snippet, that would be great.
Thanks!
You're on the right track. As you noticed, there are lot of ways to do this.
Once you have an NSImage, you can create a bitmap representation, and access its bytes directly. An easy way to get a NSBitmapImageRep is to do this:
NSBitmapImageRep* imageRep = [[[NSBitmapImageRep alloc] initWithData:[tempImage TIFFRepresentation]] autorelease];
unsigned char* bytes = [imageRep bitmapData];
int bitsPerPixel = [imageRep bitsPerPixel];
// etc
Going through the TIFFRepresentation step is safer than accessing the NSImage's representations directly.

NSBitmapImageRep data Format as application icon image?

i have a char* array of data that was in RGBA and then moved to ARGB
Bottom line is the set application image looks totally messed up and i cant put my finger on why?
//create a bitmap representation of the image data.
//The data is expected to be unsigned char**
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc]
initWithBitmapDataPlanes : (unsigned char**) &dest
pixelsWide:width pixelsHigh:height
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bitmapFormat: NSAlphaFirstBitmapFormat
bytesPerRow: bytesPerRow
bitsPerPixel:32 ];
//allocate the image
NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
[image addRepresentation:bitmap];
if( image == NULL) {
printf("image is null\n");
fflush(stdout);
}
//set the icon image of the application
[NSApp setApplicationIconImage :image];
//tell the image to autorelease when done
[image autorelease];
What in these values is not right? the image looks very multicolored and pixelated, with transparent parts/lines as well.
EDIT: after changing bytes per row to width*4 (scanline), this is the image i get.
![alt text][1]
The original image is just an orange square.
EDIT2: updated image and some of the parameters.
Thanks!
alt text http://www.freeimagehosting.net/uploads/3793520d98.png
It is only useful to specify 0 for bytesPerRow if you're also passing NULL for the data (and thus letting the rep allocate it itself). If you pass zero, you're asking the system to use the "best" bytesPerRow, which is not stable between architectures and OS versions. It isn't width*bitsPerPixel, it's padded out for alignment.
This is one that that is wrong, at least.

Resources