For many images, this code works fine to convert a PNG image to JPG:
Thumbnails.of(pngIn)
.outputFormat("jpg")
.scale(1.0)
.toFile(jpgOut);
But for this specific image:
the code results in an all-white JPG image. If someone can point me to the right way of doing things in Thumbnailator, I would very much appreciate it. Cheers!
EDIT: Well, something in the image upload / download process makes things work for the attached image! (The downloaded image is 50K while the original image is 41K, so clearly there's some funkiness going on there.) But I promise that the original PNG really does not work.
EDIT 2: This link to Google images can be used to download the 920x900 PNGWing image (41K) on the right side of the page.
The above syntax seems to be correct for converting PNG to JPG. The problem is that when the referenced image is read into a BufferedImage object, the image's type is BufferedImage.TYPE_BYTE_BINARY. While such images can be 1, 2, or 4-bit images, Thumbnailator doesn't handle 2- or 4-bit images correctly, essentially assuming that the image is a 1-bit image.
In short: the syntax is correct, but there appears to be a Thumbnailator bug that hinders successful processing of some PNG files.
Related
I'm trying to get the cropped version of an image that's pulled using ALAsset. Specifically, I'm selecting items from the user's Photo Library and then uploading them. The issue is that in the library thumbnail view, iOS is showing us the cropped version. When you select that thumbnail and pull that image's asset using ALAsset, I get the full resolution version.
I did some research and couldn't find anything that helps in getting a second coordinate system of where the cropping happens.
To test it, you need iOS5 to edit the image in your library. Select an image in your image library, select "Edit", and crop the image. When you get the ALAsset you'll get the full image, and if you sync using iPhoto, iPhoto also pulls the full image. Also, you can re-edit the image and undo your crop.
This is how I'm getting the image:
UIImage *tmpImage = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullResolutionImage]];
That gives me the full resolution image, obviously. There's a fullScreenImage flag which scales the full resolution image to the size of the screen. That's not what I want.
The ALAssetRepresenation class has a scale field, but that's a float value, which is also what I don't want.
If anyone can tell me where this cropped coordinate system can be found, I'd appreciate it.
Your Options:
Option 1 (ALAssetLibrary)
Use the - (CGImageRef)fullScreenImage method of AlAssetRepresentation.
Pros:
All the hard work is done for you, you get an image that looks just like the one in the Photos app. This includes cropping, and other changes. Easy.
Cons:
The resolution is "screen size", only as big as the device you are using, not the full possible resolution of the cropped image. If this doesn't concern you, then this is the perfect option.
Option 2 (ALAssetLibrary)
Extract the cropping data using the AdjustmentXMP key in the image's metadata (what #tom is referring to). Apply the crop.
Benefit:
It is possible to get a cropped image at the best possible resolution
Cons
You only get the cropping edits, not any other adjustments (like red-eye)
Who knows what Apple will support in the future in "Edit" mode, you may have to apply more edits in the future.
It's complicated, you first have to parse the XML data to read the crop rectangle, crop the unrotated image, and then apply the rotation.
Option 3 (Wishful Thinking)
Beg Apple to include a method like fullResolutionEditedImage which gives you the best possible quality photo, with all edits applied.
Pros:
Everything magically solved.
Cons:
Apple may never add this method.
Option 4 (UIImagePickerController)
This option only applies if you are using the image picker, you can't use it directly with the asset library
In the NSDictionary returned by -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
You can extract the full sized, adjusted image from the UIImagePickerControllerOriginalImage key. Save this image somewhere. Then, instead of retrieving the image from the asset library, load the copy you made.
Pros:
You get the full size image, with adjustments
This is the only option Apple gives us for getting the full size image with all adjustments (like red-eye, etc), and not just the crop. This is particularly important in iOS 7 with the introduction of filters that can drastically alter the image.
Cons:
Can only be used with the image picker (not ALAssetRepresentation)
You must keep around a full-sized copy of the image. Depending on the number of such images, the disk usage by your app could grow substantially.
Update for iOS 7: you may wish to consider Option 4, or Option 1, as iOS 7 supports many operations now like filters, and your users will probably notice if they are missing. These two options support filters (and other edits), with Option 4 giving you a higher resolution result.
When a photo has been cropped with the iOS Photos App, the cropping coordinates can be found in the ALAssetRepresentation's metadata dictionary. fullResolutionImage will give you the uncropped photo, you have to perform the cropping yourself.
The AdjustmentXMP metadata contains not only the cropping coordinates but also indicates if auto-enhance or remove-red-eyes has been applied.
As of iOS 6.0 CIFilter provides filterArrayFromSerializedXMP:inputImageExtent:error: Probably you can use the ALAssetRepresentation's AdjustmentXMP metadata here and apply the CIFilter onto the ALAssetRepresentation's fullResolutionImage to recreate the modified image.
Be aware that the iOS Photos App handles JPG and RAW images differently. For JPG images a new ALAsset with the XMP metadata is stored in the Camera Roll. For RAW images an ALAssetRepresentation is added to the original ALAsset. I'm not sure if this additional ALAssetRepresentation is the modified image and if it has the AdjustmentXMP metadata. In addition to JPG and RAW images you should also test the behaviour for RAW+JPG images.
I realize that PNG is normally the web standard, but I might have a bit of a unique situation. I'm building an app that downloads lots of images from a server. The download needs to be as quick as possible, especially over 3G connections. I've been looking into the best compression for the images on the server. Ideally, every image I use can be quickly resized for the app using a drag and drop converter of some sort. When I convert one of the images to a PNG, the file size is around 130KB. When converted to an acceptable JPG quality however, the file size comes in at well under 50KB. Should I use JPGs in the application?
Thanks in advance,
It actually depends on the type of images.
The basic rule is to use JPEG for photos and PNG for everything else.
Why is it so?
JPEG compression is designed for photos - photos can handle lossy compression. On the other hand, PNG is compression designed for images which have similar pixels close to each other (straight lines, areas filled with one color, texts, etc.). If you try to use JPEG on an image which is not a photo, you'll be surprised - it won't look very good.
PNG is a standard - but for icons, backgrounds, patterns etc; not for photos.
Yes you can use jpg. You will not encounter any problem. It is a tradeoff between quality and size. Jpeg is usually smaller because it is compressed so as to reduce size. Png is lossless compressed.
I have made applications that use both png and jpeg and they both work like a charm.
EDIT: You can also check out this link PNG vs JPEG
PNG images are huge in size, use JPG as long as it's possible (when you don't need transparency)
I noticed that some article talking about crushed PNG images and how to uncrush them. What's the purpose of crush the images in the first hand? And also can the crushed images still be loaded using [UIImage imageWithName:]?
It's used to reduce the file's size, using lossless optimizations and/or compression.
It can evaluate your input image using several optimizations. Basic example: If your input is grayscale and saved as color, it may output a grayscale image. Of course, there are more complex optimizations which it uses.
can the crushed images still be loaded using [UIImage imageWithName:]?
Yes
It's basically a form of compression that doesn't involve any data loss (that is, you don't lose any image quality). Compressing any data reduces it's size that's the reason for actually doing it.
I've read many of the png vs. jpg threads here and elsewhere. I didn't find this aspect covered for small images that are downloaded from a server.
A short recap:
Xcode optimizes png images that are delivered with the app bundle in a way that they are optimized for the iOS hardware ("png magic")
png images support transparency (which I don't need)
png is the better choice from graphics, jpg for pictures (we have pictures)
I'm building an app that periodically downloads feeds that contain links to thumbnail images (size 80x80). These images are presented side by side the text content in a tableview. I can influence which format is used (jpg, png) on the server side.
If I use an uncompressed png format, it will have about 17k size for one image. This is quite large. And since this png doesn't use the "png magic" of Xcode, the iPhone still might need quite some cpu to get them into the table view compared to an "Xcode prepared" png.
The same image as a compressed jpg is only 3k which is great.
Question: are there lab comparisons that show the real world performance of these 2 formats?
Another one: has anyone used jpgs of a similar size (80x80, 3k) successfully in a table-view?
Many thanks in advance
What do you mean "lab comparisons"? PNG is going to do better with flat colors -- it uses variations on run-length and dictionary encoding as I understand. JPEG will be better with images containing subtle gradients, and loses data mostly in jumps in luminosity which are hard for the human eye to see. "Better" here refers only to file size. It sounds like you would want JPEGs here.
I have an iPhone application that downloads images from the internet and saves them for display later.
The user can select the images to view from a UITableView, the table view has custom cells which display thumbnails of the original images in varying sizes.
When the large image is first downloaded it is scaled to thumbnail size and the thumbnail is saved using UIImagePNGRepresentation.
What I would like to do is save the thumbnail in the optimized iPhone PNG format. How can I do that? does it happen magically just by loading the original large image into memory and saving it? Do I have to do any further processing on the thumbnail before saving?
Chances are the UIImagePNGRepresentation does not create the images, as they are non-comformant PNGs, and can't be read by anything else. If they API generated PNGs that could not be read I think it would document that, and anyone who uploads PNGs from the phone would notice that they did not work.
The optimization is useful, but most of the optimized PNGs are part of the UI where the optimization is done as part of the build process. Chances are the cost of performing the optimization will offset any gains you get from it.
So it turns out that the RGB565 colorspace used in the optimized format is simply not available in a CGGraphicsContext, which is the rendering class used by all the UIwhatever components.
So if I DID write some code to change the color space of the image before saving it, I couldn't get the texture back into a UI class. The only way to use it is to load it directly into the OpenGL innards and use OpenGL in my app.
Don't worry about the "optimized PNG" format, as it isn't making any significant difference.
It does not affect rendering speed at all, and loading speed is dictated by file size more than file format.
So simply save it in a format that will give you smallest files. If you're not using transparency, then it might be JPEG.
If you need transparency, and can spend more CPU time when saving images, then include pngquant in your program (it's under BSD-like license) and shrink those PNGs to 8-bit palette.