How to create a progressive JPEG image on Android - java

I need to send images over a very low-bandwidth connection from an android phone (down to 10kByte/s) and would like to send them in progressive (interlaced) mode so that the user at the other end starts seeing the image already during the lengthy transfer. Right now, I am creating the image with the regular photo app:
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
But this creates non-progressive photos and I have not been able to discover how to convince it to do otherwise. The second option I explored (reading and re-compressing the taken image) got foiled because the Bitmap's compress method does not allow any encoding parameters besides format name and compression factor as far as I could determine:
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
My preferred solution would be to instruct the photo app to save in progressive mode.
The next best option would be a Java algorithm that losslessly converts the stored jpeg to progressive (jpegtran does this on Linux, but it is in C and relies on libjepeg).
The next best would a method to specify the relevant encoding parameters to android allowing me to re-compress it, or an alternative Java library that does the same.
Further research revealed that the algorithms are already there (/system/lib/libjpeg.so) with the sources in ~/android-sdk-linux/source-tree/external/jpeg -- but there do not seem to be JNI wrappers readily available.

Have you seen this document?
http://docs.oracle.com/javase/6/docs/api/javax/imageio/plugins/jpeg/JPEGImageWriteParam.html
It seems to have write progressive support.
Alternatively, you could use e.g. OpenJPEG through JNI. See http://www.linux-mag.com/id/7697/ as a start.

Related

Suprema Biomini,How to Generate template from image

Is it possible to generate the template from an image using Suprema sdk BioMini V3.7.5?
I have read the documentation but I can not find the option
The function is not supported even in the current version.
UFS_Extract and UFS_ExtractEx is for the image captured by using the BioMini device.
The below is just my opinion.
It may be hard to support the function. The resolution of the image is
very important factor on processing to convert from an image to a
template.

Pure Java alternative to JAI ImageIO for detecting CMYK images

first I'd like to explain the situation/requirements that lead to the question:
In our web application we can't support CMYK images (JPEG) since IE 8 and below can't display them.
Thus we need to detect when someone wants to upload such an image and deny it.
Unfortunately, Java's ImageIO won't read those images or would not enable me to get the detected color space. From debugging it seems like JPEGImageReader internally gets the color space code 11 (which would mean JCS_YCCK) but I can't safely access that information.
When querying the reader for the image types I get nothing for CMYK, so I might assume no image types = unsupported image.
I converted the source CMYK image to RGB using an imaging tool in order to test whether it would then be readable (I tried to simulate the admin's steps when getting the message "No CMYK supported"). However, JPEGImageReader would not read that image, since it assumes (comment in the source!)3-component RGB color space but the image header reports 4 components (maybe RGBA or ARGB) and thus an IllegalArgumentException is thrown.
Thus, ImageIO is not an option since I can't reliably get the color space of an image and I can't tell the admin why an otherwise fine image (it can be displayed by the browser) would not be accepted due to some internal error.
This led me to try JAI ImageIO whose CLibJPEGImageReader does an excellent job and correctly reads all my test images.
However, since we're deploying our application in a JBoss that might host other applications as well, we'd like to keep them as isolated as possible. AFAIK, I'd need to install JAI ImageIO to the JRE or otherwise make the native libs available in order to use them, and thus other applications might get access to them as well, which might cause side effects (at least we'd have to test a lot to ensure that's not the case).
That's the explanation for the question, and here it comes again:
Is there any pure Java alternative to JAI ImageIO which reliably detects and possibly converts CMYK images?
Thanks in advance,
Thomas
I found a solution that is ok for our needs: Apache Commons Sanselan. This library reads JPEG headers quite fast and accurate (at least all my test images) as well as a number of other image formats.
The downside is that it won't read JPEG image data, but I can do that with the basic JRE tools.
Reading JPEG images for conversion is quite easy (the ones that ImageIO refuses to read, too):
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new FileInputStream( new File(pFilename) ) );
BufferedImage sourceImg = decoder.decodeAsBufferedImage();
Then if Sanselan tells me the image is actually CMYK, I get the source image's raster and convert myself:
for( /*each pixel in the raster, which is represented as int[4]*/ )
{
double k = pixel[3] / 255.0;
double r = (255.0 - pixel[0])*k;
double g = (255.0 - pixel[1])*k;
double b = (255.0 - pixel[2])*k;
}
This give quite good results in the RGB images not being too bright or dark. However, I'm not sure why multiplying with k prevents the brightening. The JPEG is actually decoded in native code and the CMYK->RGB conversion I got states something different, I just tried the multiply to see the visual result.
If anybody could shed some light on this, I'd be grateful.
I've posted a pure Java solution for reading all sorts of JPEG images and converting them to RGB.
It's built on the following facts:
While ImageIO cannot read JPEG images with CMYK as a buffered image, it can read the raw pixel data (raster).
Sanselan (or Apache Commons Imaging as it's called now) can be used to read the details of CMYK images.
There are images with inverted CMYK values (an old Photoshop bug).
There are images with YCCK instead of CMYK (can easily be converted).
Beware of another post as the Java 7 does not allow to use directly Sun's implementation without special parameters as indicated in import com.sun.image.codec.jpeg.*.
In our web application we can't support CMYK images (JPEG) since
IE 8 and below can't display them. Thus we need to detect when someone
wants to upload such an image and deny it.
I don't agree with your "Thus we need to detect when someone wants to upload such an image and deny it". A much more user-friendly policy would be to convert it to something else than CMYK.
The rest of your post is a bit confusing in that regards seen that you ask both for detection and conversion, which are two different things. Once again, I think converting the image is much more user-friendly.
No need to write in bold btw:
Is there any pure Java alternative to JAI ImageIO which reliably
detects and possibly converts CMYK images?
Pure Java I don't know, but ImageMagick works fine to convert CMYK image to RGB ones. Calling ImageMagick on the server-side from Java really isn't complicated. I used to do it manually by calling an external process but nowadays there are wrappers like JMagick and im4java.

Picture.writeToStream() not writing out all bitmaps

I'm using webview.capturePicture() to create a Picture object that contains all the drawing objects for a webpage.
I can successfully render this Picture object to a bitmap using the canvas.drawPicture(picture, dst) with no problems.
However when I use picture.writeToStream(fos) to serialize the picture object out to file, and then
Picture.createFromStream(fis) to read the data back in and create a new picture object, the resultant bitmap when rendered as above is missing any larger images (anything over around 20KB! by observation).
This occurs on all the Android OS platforms that I have tested 1.5, 1.6 and 2.1.
Looking at the native code for Skia which is the underlying Android graphics library and the output file produced from the picture.writeToStream() I can see how the file format is constructed.
I can see that some of the images in this Skia spool file are not being written out (the larger ones), the code that appears to be the problem is in skBitmap.cpp in the method
void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const;
It writes out the bitmap fWidth, fHeight, fRowBytes, FConfig and isOpaque values but then just writes out SERIALIZE_PIXELTYPE_NONE (0). This means that the spool file does not contain any pixel information about the actual image and therefore cannot restore the picture object correctly.
Effectively this renders the writeToStream and createFromStream() APIs useless as they do not reliably store and recreate the picture data.
Has anybody else seen this behaviour and if so am I using the API incorrectly, can it be worked around, is there an explanation i.e. incomplete API / bug and if so are there any plans for a fix in a future release of Android?
Thanks in advance.
That's the way the API is meant to work. It was never intended for long term storage, but to store flattened in the current process, or to send to another process. What you are asking for will not be supported.
On the Honeycomb platform it appears that writeToStream() and createFromStream() now store and recreate the Picture object including large image data.
However it does come with the following caveats:
The image data used in a picture must be of an immutable type.
The image data must have been created with the following BitmapFactory.Options set to true, inInputShareable and inPurgeable. This can be done by using BitmapFactory.decodeResource() passing in the BitmapFactory.Options.
It so happens that Pictures created by WebView 'do' contain suitable images that meet this criteria and therefore can be serialized and restored.
I have not confirmed as yet that Ice Cream Sandwich also works but I am assuming/hoping that it will.

How can I do image manipulation on a very large BMP?

I am trying to do some manipulation (specifically, conversion to a different type of splitting into tiles) on a set of very large (a few GB) BMP image files.
I'm not sure I understand the BMP file format, but is it necessary to load the entire file into memory? I was unable to find any API that didn't require loading the entire file at some point. ImageMagick wasn't able to do it either.
Java would be the best tool of choice for me, but any other solution including command line tools or desktop software would be acceptable.
Based on this, it should be reasonably apparent that you can use the fact that it's row-packed. You should be able to read part of a row, store it, advance to the same position in the next row and repeat until you have completed a tile of the desired size. Obviously you may be able to do multiple tiles at once if you can store an entire row worth of tiles in memory all at once.
It is not necessary to load more than the header of the file at once. The header format is describe in the linked Wikipedia entry. It's probably worth paying attention to any compression schemes being used - compression is likely to make this task a bit harder (though still not impossible) :)
Not sure about 2011 year of this questing, but Java 7 (and possibly 6) has good approach for such pleasure.
Use ImageReader and ImageReadParam classes, they allow to read any rectangular part of source image if needed. Set source rectangle and read
... // initialization
private javax.imageio.ImageReadParam m_params;
private javax.imageio.ImageReader m_reader;
... // reading
m_params.setSourceRegion( readRect );
BufferedImage rdImg = m_reader.read( i, m_params );
... // processing/displaying etc
As BMP (it works too for any standard Java image type) is very planar format without any compression in 99.99% cases, to read any its part such way is very fast process with low memory consumption except resulted BufferedImage. Or you can even reuse previous BufferedImage on consequent request with the rect of same dimensions. See ImageReadParam.setDestination(BufferedImage destination). But I didn't test this option.
Also I found one small reading bug namely in BMP reader class implementation of Java runtime lib. If somebody be interested in this, I'll show simple way to correct it.

Most advanced image compression today (not on browser)?

I am writing an application in Java to view images which contain a lot of text and graphics, like a screenshot of a webpage, actually its a image of a magazine article. Some parts are text, some parts are graphics.
My client program is written in Java, I can use any image format, what is the best image compression format I can get my hands on in Java? So I can compress and de-compress?
It would be nice if the image became clearly as it loaded, but thats not necessary, its not 1997 anymore (remember gif loading).
You haven't supplied one key piece of information: does the compression need to be lossless or is lossy fine? And if lossy is fine withint what tolerance?
You can reduce an entire image to a single bit of information if you're prepared to a highly lossy compression format. :-)
Seriously though, the two main lossless formats are GIF and PNG (both in browser and out of) and the biggest (by far) lossy format is JPG. Other formats like BMP and TIF are nowhere near as efficient.
all three of these formats are well-supported in Java (either directly or with readily-available third party libraries). PNG tends to be better compression ratios than GIF.
See:
PNG vs. GIF compression
GIF vs. PNG: this one gives reference to (and measures0 the PNGpong format;
DjVu (http://djvu.org/) is probably one of the smartest format to compress / store text oriented images. It actually stores the text as text and adds images for backgrounds. This means that you can partily treat your documents as text (full text search, copy/paste of thetext, ...). The viewing part is probably well suported in Java.
The biggest problem is the lack of good free support for encoding the documents. There is some open source tools available, but last time I checked none of them was very user friendly, nor very developer friendly either. There are very good commercial tools, but pretty expensive.
For lossy compression, you might also want to consider Jpeg 2000. It's much more efficient than standard JPEG compression, especially at very low quality settings, it's relatively widely adopted and there are plenty of coding / decoding libraries out already.
In addition to cletus' points
There are tools like pngout, pngcrush and optipng to still compress the images
I prefer PNG for any internet image work I'm doing, as GIF has a limited palette and JPG doesn't handle transparency.
DLI image compression is the best available out there. It isn't a standard.
But still a lot of fun to play with.
https://sites.google.com/site/dlimagecomp/
Have a look at 'http://www.jpegmini.com/main/home' .
Recompress the jpg file with one of these 'http://www.maximumcompression.com/data/jpg.php'
A noise filter can be used to further improve signal to noise ratio.
'http://compression.ru/video/deblocking/index_en.html'
This is just for research purpose, i can't think of a way how you can implement this in java.

Categories