I had noticed that when reading in an identical photograph across devices in the JPEG format, the pixel values do not match up. They are close, but different. When convert
Re-size the media to the required size or use HTML attributes to disable scaling of the image.
Another option would be to allow the user to decide after loading a thumbnail representation to save bandwidth.
The JPEG standard does not require that decoder implementations produce bit-for-bit identical output images. Unfortunately the standards document specifying decoder requirements, ISO 10918-2, is apparently not freely available online but Wikipedia says:
...the JPEG standard (and the similar MPEG standards) includes some precision requirements for the decoding, including all parts of the decoding process (variable length decoding, inverse DCT, dequantization, renormalization of outputs); the output from the reference algorithm must not exceed:
- a maximum 1 bit of difference for each pixel component
- low mean square error over each 8×8-pixel block
- [etc.]
Differences between different decoder outputs using the same input are generally due to differing levels of internal precision, particularly in performing the IDCT. Another possible source of differences is smoothing, which attempts to reduce "blockiness" artifacts.
Like you, I would expect that setting inPreferQualityOverSpeed
would produce the same output but nothing actually guarantees that. I can think of at least a couple ways that you could get small variations on two different phones:
BitmapFactory
changed (e.g. perhaps inPreferQualityOverSpeed
was broken and then fixed, or vice versa), orBitmapFactory
leverages. Even differences in scalar floating-point units can cause discrepancies, especially with JIT compilation producing the actual machine instructions.Given the wiggle room in the standard plus your experimental observations, it appears the only way to guarantee bit-for-bit agreement is to perform decoding within your own application. Perhaps you can find some alternative Android-compatible library.
I suppose you should also check if compressed PNGs appear the same way across devices.
http://pngquant.org/
If the answer is yes, then the only thing remaining would be to figure out how to convert programmatically on the phone those images to that same kind of compressed png.
I was having the same problem. PNG and JPEG images seems to be rendered with approximation by different devices. We solved the problem using BMP images (whose dimensions are unfortunately a lot bigger).
Yes, the pixel color values are different across devices. This is very annoying especially if you want to compare colors. The solution is to compare visually equal colors (by human perception).
One of the best methods to compare two colors by human perception is CIE76. The difference is called Delta-E. When it is less than 1, the human eye can not recognize the difference.
You can find wonderful color utilities class (ColorUtils), which includes CIE76 comparison methods. It is written by Daniel Strebel,University of Zurich.
From ColorUtils.class I use the method:
static double colorDifference(int r1, int g1, int b1, int r2, int g2, int b2)
r1,g1,b1 - RGB values of the first color
r2,g2,b2 - RGB values ot the second color that you would like to compare
If you work with Android, you can get these values like this:
r1 = Color.red(pixel);
g1 = Color.green(pixel);
b1 = Color.blue(pixel);
Much of a JPEG decoder's work involves real number calculations. Usually this is done using fixed point integer arithmetic for performance. This introduces rounding errors. Slight variations are a natural part of working with JPEG.