I have an NSImage from NSImage *myImage = [[NSBitmapImageRep alloc] initWithFocusedViewRect:[outputView bounds]]; and I need to save it to a file. I havent been able to find anything about saving NSImage in any format. Has anyone done this? Is it even possible?
Thanks
The way you say you're making an NSImage doesn't make sense. You show how to create an NSBitmapImageRep, not an NSImage.
Before you save it to a file, you convert to NSData. There is an NSImage method to convert to TIFF data, and there is an NSBitmapImageRep method to convert to data in several formats.
If you're creating a snapshot of an actual view (as opposed to an image that you've locked focus on), then an alternative to creating a bitmap image rep would be to ask the view for PDF data of the desired rectangle. This will be vector rather than raster (except where the view itself draws an image), which will scale more nicely to higher resolutions. You would then write that data to a file the same as you would any other data.
Having an NSBitmapImageRep (as JWWalker pointed out, that code doesn't create an NSImage instance), you can ask the image rep for a CGImage version of itself, and then create a CGImageDestination to write that image to a file. This may be more efficient than obtaining a data object (which will hold the raster data in memory) and provides more options.
Related
I have an NSImage instance and I'd like to identify the type of image it is (JPG, PNG, GIF, etc.).
Is the original format of the image preserved and possible to retrieve somehow?
EDIT:
Answers in other questions mention using CGImageSource. However, there does not seem to be a way of extracting the original data from the NSImage - only TIFFRepresentation, which will always return the TIFF image type via CGImageSource.
EDIT 2:
I think my suspicions may be true in that NSImage does not maintain the original format of the image. Everything is converted to bitmap representation. Therefore it is not possible to retrieve the original format without keeping track of it yourself. See similar answer from iOS equivalent: Detect whether an UIImage is PNG or JPEG?
Very weird behavior, but I have narrowed the problem down as far as I can go I think
I have a NSImage, let's call it inputImage. It is represented by a NSBitmapImageRep in a CGColorSpaceCreateDeviceGray, if that matters
I want to create a CGImageRef from it, but with inverted colors.
NSData *data = [inputImage TIFFRepresentation];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
NSBitmapImageRep *maskedRep = (NSBitmapImageRep*)[inputImage representations][0];
CGFloat decode[] = {0.0, 1.0};
maskRef = CGImageMaskCreate(maskedRep.pixelsWide,
maskedRep.pixelsHigh,
8,
maskedRep.bitsPerPixel,
maskedRep.bytesPerRow,
provider,
decode,
false);
NSImage *testImage = [[NSImage alloc] initWithCGImage:maskRef size:NSMakeSize(1280,1185)]; //the size of the image, hard-coded for testing
NSLog(#"testimage: %#", testImage);
The problem is when I look at testImage, all of the pixels are slightly offset to the right from the original image.
inputImage:
testImage:
It's much easier to see if you save the pictures off, but you'll notice that everything in testImage is offset to the right by about 5 pixels or so. You'll see a white gap to the left of the black content in testImage
Somewhere in my 5 lines of code I am somehow moving my image over. Does anybody have any idea how this could be happening? I'm currently suspecting TIFFRepresentation
The data provider you pass to CGImageMaskCreate() is supposed to be raw pixels in the form specified by the other parameters, not an image file format. You shouldn't be passing TIFF data. Frankly, I'm surprised you got anything remotely resembling your original image, rather than noise/garbage. I'm guessing the TIFF data wasn't compressed, by sheer chance. You can actually see a bit of noise, which is the TIFF header interpreted as pixels, at the upper-left of your mask.
Probably, your best bet is to create a CGImage from your inputImage (or, depending on how inputImage was created, skip NSImage and create the CGImage directly from a file using the CGImageSource API or CGImageCreateWith{JPEG,PNG}DataProvider()). To get a CGImage from an NSImage, use -CGImageForProposedRect:context:hints:.
Then, get the data provider from that CGImage and create the mask CGImage from that, using the various properties (width, height, bpp, etc.) queried from the first CGImage using the various CGImageGet... functions.
I need to be able take a video from Photos and re-rendering, both clipping it in time, changing the width and height, and frame rate. Certainly I need to start with:
PHContentEditingInputRequestOptions *options = [[PHContentEditingInputRequestOptions alloc] init];
[self.asset requestContentEditingInputWithOptions:options completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info) {
// Get full image
NSURL *url = [contentEditingInput fullSizeImageURL];
}];
And I should be able to adjust width, height and duration. Grab an NSData from that, write that out to the file syset.m
But the url is nil, which implies to me that I can't edit videos with the new Photos framework. (ALAsset didn't have a problem with this using AVAssetExportSession.) This makes sense since the Apple Dev sample code can't edit videos either.
Now, to make life easier I could just pass that url to an AVAssetExportSession but I can't, because it is nil. If I just modified width, height and duration I'd still need to grab an NSData from it, write that out to the file system.
I do not need to write the modified video back to Photos, I actually need the video on the file system since I'll be uploading it to our servers.
fullSizeImageURL is for working with Photo assets. You want the avAsset property when working with a video. Modify the actual video, not the metadata, by writing a new video file.
To do that, you could use that avAsset in an AVMutableComposition:
Insert the appropriate time range of the avAsset's video track (AVAssetTrack) into an AVMutableCompositionTrack. That'll do your trimming.
Place/size it appropriately using layer instructions. (AVMutableVideoCompositionLayerInstruction) to do your cropping and scaling.
Can someone point out a comprehensive example on Image processing using cocoa API? I am developing an application for the Mac, and not for the iphone device. I usually come across with UIImage manipulation which provides an intuitive set of methods to achieve task such as per pixel manipulation and saving into file at different format. In the case with Appkit, NSImage I really find it hard to manipulate per pixel data of the images and saving to different file formats such as PNG not just TIFF.
If you want to work with pixels, CGImage and CGImageSource and CGImageDestination are the way to go. Unlike AppKit's NSImage, which is designed generally in order to handle any kind of image, the CGImage classes are specifically designed for raster images.
You can retrieve a bitmap representation of your image object and modify its data
NSBitmapImageRep *rep = [[image representations] objectAtIndex: 0];
unsigned char *bmpData = [rep bitmapData];
To save modified representation in PNG format do the following:
NSData *data = [bits representationUsingType: NSPNGFileType properties: nil];
[data writeToFile: #"/path-to-your-file/image.png" atomically: NO];
I need to save the contents of a pixel editor application into a .png file but I am having trouble finding the best way to accomplish this. The pixel data is stored in a 32 bit RGBA buffer. Can anyone suggest any good tools I could use to accomplish this?
EDIT:
Unfortunately, CGImage and representationUsingType: are not supported by cocotron and I need to be able to target my app for PC release as well, can anyone suggest a third way of accomplishing this task?
NSBitmapImageRep should get you what you need. Load the data up into the NSBitmapImageRep
and then use representationUsingType:properties: to get it out as a PNG. A quick example:
NSBitmapImageRep *imageRep =
[[NSBitmapImageRep alloc] initWithBitmapDataPlanes:imageBuffer
pixelsWide:imageWidth
pixelsHigh:imageHeight
bitsPerSample:8
samplesPerPixel:4
hasAlpha:YES
isPlanar:NO
colorSpaceName:NSDeviceRGBColorSpace
bitmapFormat:NSAlphaFirstBitmapFormat
bytesPerRow:imageWidth * 4
bitsPerPixel:32];
NSData *pngData = [imageRep representationUsingType:NSPNGFileType
properties:propertyDictionary];
If you can't use these Cocoa methods, check out libpng.
Create a CGImage from the pixel data and feed it to a CGImageDestination.
Don't forget to finalize the destination before releasing it. That step is mandatory, and very easy to forget.