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?
Related
I'm working on a photo viewer. In this context, I wrote a small class to be able to read and use some EXIF data, as e.g. image orientation. This class works well for reading.
However, I would add a new option to rotate photos. I want to rotate and write the photo data itself, not just rewrite the orientation tag. I already wrote the code to rotate and save the primary JPEG image, and it works well. But I also need to rotate the thumbnail contained in the EXIF data, if any, to keep the image coherent. For this reason I need to write in the EXIF data, to replace the existing thumbnail.
But this raises some questions, that I've some trouble answering, namely:
Can the EXIF data contains more than 1 thumbnail, and if yes, what is the maximum thumbnail count that an image can contain?
What are the supported formats for thumbnails? (I found JPEG and TIFF, are there other?)
Is there any guarantee in the EXIF standards that the thumbnails are always written in the late EXIF data, just before the primary image?
If not, then each tags containing an offset that points to a location beyond the thumbnail to replace should be updated. So, is there a standard way to iterate through all tags and sub-directories, to recognize which EXIF tags contain offsets, and to update them if needed? Or the only way is to read a maximum of tags and rewrite only that are known?
Or is there a way to guarantee that the size of the newly rotated thumbnail will be smaller or equal to previous thumbnail size to replace with?
Regards
Here are some answers for your questions:
1) The EXIF data is laid out like a TIFF file with 2 pages. The first page is the camera information and the second page is the thumbnail. If you add more pages (with thumbnails), 99.99% of the applications probably won't notice since you'll be doing it differently than the "standard" way. As far as "maximum count", you have 64k of data that can be stored in any JFIF tag. You can put what you want in that 64k.
2) There is only 1 supported EXIF thumbnail format: TIFF. Inside the TIFF there can be compressed (JPEG) or uncompressed data. Again, you're welcome to stick LZW-compressed data in there, but most apps probably won't be prepared to display it properly.
3) The JFIF container format allows for tags with metadata to appear before the main image. The APPx tags contain metadata that can follow the standard or not. You're welcome to stick multiple EXIF APP1 tags into your files, but again, most apps won't be able to properly handle that situation. So the simple answer is that the EXIF data (including thumbnail) must come before the main image and if you put more than 1 thumbnail it will most likely be ignored.
4) If you are modifying a JFIF (including the metadata), you must rewrite the metadata. It's actually quite simple because each tag is independent and has a simple length value instead of relative offsets.
5) You can do anything you want with the size/orientation of your thumbnail as long as you make the EXIF APP1 tag data total size fit within 64k.
Here's what you need to do...
1) Read the source image (and thumbnail if present).
2) Prepare your rotated image (and thumbnail).
3) Write the new metadata with the new thumbnail image.
4) Write the new main image.
If you want to preserve the original metadata along with your new thumbnail, it's pretty easy. Just read the original tags and hold on to them, then write them in the new image. Each JFIF tag is just a 2 byte identifier (FFxx) followed by a 2 byte length and then the data. They can be packed in almost any order and there's no hard limit on how many total tags can appear before the main image.
Here is an image:
This image is a simple black-to-transparent gradient saved in full RGBA PNG.
Here is the same image, converted to indexed-alpha PNG by GIMP (Photoshop produces the same result)
As you can see, the gradient is now half-opaque, half-transparent.
Here is the same image again, only this time it was converted to indexed-alpha PNG by a PHP script I wrote:
So my question is: Why are GIMP and Photoshop unable to support partial transparency in indexed images, when the PHP script clearly shows that such an image can be created with no problems?
Is there anything "wrong" with an image whose pallette contains alpha information?
A more programming-related question: Does this transparency in the last image work in Internet Explorer 6?
I've finally found the actual answer: There is a metadata entry that allows you to define the alpha value of each colour in the colour table. Most graphics programs don't make use of this, but it does exist and can be used, in particular by GD.
Another option besides fireworks is pngquant, a command line application that will convert a rgba png into an indexed png with transparency.
I found this post which talks some more about how to use it.
IE6 and earlier in windows does not support variable transparency PNGs without annoying workarounds. An indexed PNG will only show the fully opaque parts which usually works pretty well. A drop shadow would disappear but the opaque parts of the logo or icon would continue to show.
This page has a better explanation and instructions with more png compression and quantization tools: http://calendar.perfplanet.com/2010/png-that-works/
For the record, PNG does not literally support indexed images with an alpha channel. What is really happening is that PNG allows you to add additional colors to the color table (i.e. index) with alpha values in those colors... not a complete alpha channel. FWIW...
Yeah I know what you mean. Fireworks is the only image editing program that I know of that can create and edit PNG8+Alpha without problems. I wish more paint programs would support this format cause Fireworks is expensive!
I found a way in GIMP to create or convert an image with reduced color palette and alpha channel.
The trick is to add a mask to the layer.
Full steps to reproduce:
Have your image in one layer
Add a mask to the layer. Select Transfer layer's alpha channel.
Convert to Indexed (Image -> Mode -> Indexed...)
Save as PNG
Now your image has reduced colors and reduced size, but it keeps your smooth transparency.
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.
I'm trying to use cocoa to grab images from a webcam. I'm able to get the image in RGBA format using the QTKit and the didOutputVideoFrame delegate call, and converting the CVImageBuffer to a CIImage and then to a NSBitmapImageRep.
I know my camera grabs natively in YUV, what I want is to get the YUV data directly from the CVImageBuffer, and proccess the YUV frame before displaying it.
My question is: How can I get the YUV data from the CVImageBuffer?
thanks.
You might be able to create a CIImage from the buffer using +[CIImage imageWithCVBuffer:] and then render that CIImage into a CGBitmapContext of the desired pixel format.
Note, I have not tested this solution.
I asked what I thought was a different question, but it turned out to have the same answer as this one: raw data from CVImageBuffer without rendering?
I'm using an image loader (DevIL) for image loading. Im just wondering if the image format (the uncompressed format in memory) loaded from files (.jpg, .png, .bmp etc) is determined by the image loading program itself, or is some way contingent upon the actual image file.
All of the images I have looked at so far seem to be loaded into the RGBA / UNSIGNED_BYTE format. However I am wondering if I can always rely on this. Is it conceivable that an image might actually be loaded into the RGBA / FLOAT format instead? (NOTE: i am hoping that the loaded image format will always be the same, i want to rely on it:)
I can't find any docs in DevIL that explains this point, so I'm hoping anyone experienced with imaging / image loading could give me an answer just based on their experience / common sense.
Thanks
I don't know DevIL, but nearly any imaging library is going to provide you with an image object that has some concept of Pixel Format. The pixel format tells you how the image is laid out in memory. Looking quickly at the docs, I see that IlTexImage has a property called Format which can be one of IL_COLOUR_INDEX, IL_RGB, IL_RGBA, etc. The docs say
The format of the image data. Formats accepted are listed here and
are self-explanatory