bugGNU Octave - Bugs: bug #67052, imread not reading same color data...

 
 

bug #67052: imread not reading same color data as matlab for JPEG images

Submitter:  None
Submitted:  Fri 25 Apr 2025 01:25:26 PM UTC
   
 
Category:  None Severity:  3 - Normal
Priority:  5 - Normal Item Group:  Incorrect Result
Status:  Need Info Assigned to:  None
Originator Name:  DIV Originator Email:  -email is unavailable-
Open/Closed:  * Open Release:  * 10.1.0
Release:  Operating System:  * Microsoft Windows
Fixed Release:  None Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Wed 07 May 2025 06:46:27 AM UTC, comment #36: 

FWIW, here are the statistics I calculated for one test RGB image. 

STATISTICS:  Octave JPG versus Matlab JPG
Differences range between -34 and 38.
The mean absolute difference is 0.323563.
The root mean squared difference is 1.008235.
The peak signal-to-noise ratio is 110.661241.
The percentage of discrepant elements is 16.532954.

—DIV

Anonymous
Wed 07 May 2025 06:25:43 AM UTC, comment #35: 

Just FYI:

> The JPEG 1 standard (ISO/IEC 10918) was created in 1992 (latest version, 1994) as the result of a process that started in 1986.

https://jpeg.org/jpeg/index.html

> the decoder will be tested against the error bounds for ISO/IEC 18477-1 (JPEG XT Part 1) with the codestreams provided for this part in ISO/IEC 18477-4. Note that ISO/IEC 18477-1 (JPEG XT Part 1) is a subset of the JPEG standard

https://jpeg.org/downloads/jpeg/wg1n76028-CfP-JPEG-reference-software.pdf

> JPEG XT (ISO/IEC 18477) specifies a series of backwards compatible extensions to the legacy JPEG standard (ITU Recommendation T.81 | ISO/IEC 10918-1).

https://jpeg.org/jpegxt/index.html

[Emphasis added.]

The ISO/IEC 18477 standard seems to be dated 2017, with a review almost completed.  The associated executable test suites are available at
https://standards.iso.org/iso-iec/18477/-4/ed-1/en/
(I don't know whether they would be useful to apply in the context of the current discussion.)

FWIW, I also thought that decoding should be relatively robust (that is, with negligible discrepancy). 

—DIV

Anonymous
Thu 01 May 2025 08:58:29 PM UTC, comment #34: 

Speaking for myself, we should probably prioritize Octave dev time and resources, so if a task that Octave outsources to a library gives different results for different platforms, so be it. Taking BLAS as an example, Octave only checks against reference BLAS and OpenBlas, with all other implementations being up to the individual machine and user, and that is with tight numerical tolerances. If the JPG spec is loose enough to allow for as much leeway in the libraries as seen here, it is not Octave's place to change upstream libraries to get predefined behavior on such loosely defined specs. Interested users can file bug reports with those libraries directly.

Arun Giridhar <arungiridhar>
Group Member
Thu 01 May 2025 05:21:34 PM UTC, comment #33: 

If I understand correctly, the decision would come down to what we prioritize:

  • Is getting the same decoding results as some other programs more important?
  • Or is getting more complete support of the JPEG standard more important? If I understand the README of the jpeg-turbo project correctly, they opted to not support some parts of the standard (e.g., lossless RGB JPEG or other newer parts of the JPEG standard).


I don't know how widespread standard-conformant JPEG images are that can't be decoded with libjpeg-turbo. But if we change MXE Octave from the IJG implementation to jpeg-turbo now, it might mean that some users will no longer be able to decode their JPEG images (with the version of Octave for Windows that we distribute).

Markus Mützel <mmuetzel>
Group administrator
Thu 01 May 2025 02:31:32 PM UTC, comment #32: 

Should Octave for Windows distribution just the bandwagon and use jpeg-turbo or stay with reference implementation?
I personally do not have a strong opinion either way.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Thu 01 May 2025 02:01:37 PM UTC, comment #31: 

ok.  so confirmed the two libraries on mac are doing different decodings.

is there anything octave can/needs to do?

Nicholas Jankowski <nrjank>
Group Member
Mon 28 Apr 2025 08:36:36 PM UTC, comment #30: 

There is nothing special about this particular jpeg. Situation is much worse if you line graphis image. E.g. in octave: "demo patch 4; print t1.jpg".

Now convert this to bitmap using djpeg from each library, and compare them:


% djpeg -bmp t1.jpg > t1.bmp
% /opt/homebrew/Cellar/jpeg/9f/bin/djpeg -bmp t1.jpg > t11.bmp
% ls -l t*.bmp
-rw-r--r--  1 dmitri  staff  1710918 Apr 28 16:26 t1.bmp
-rw-r--r--  1 dmitri  staff  1710918 Apr 28 16:27 t11.bmp
% gm compare -metric mse t1.bmp t11.bmp
Image Difference (MeanSquaredError):
           Normalized    Absolute
          ============  ==========
     Red: 0.0000192730        1.3
   Green: 0.0000135136        0.9
    Blue: 0.0001046640        6.9
   Total: 0.0000458169        3.0
% magick compare t1.bmp t11.bmp tdiff.jpg


(file tdiff.jpg) is attached.

Dmitri.
--




Dmitri A. Sergatskov <dasergatskov>
Mon 28 Apr 2025 08:17:56 PM UTC, comment #29: 

I downloaded it from flikr link.
The file name is "32679472687_a155fdb3e8_o.jpg"

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Mon 28 Apr 2025 08:09:11 PM UTC, comment #28: 

sorry for not following what are the sources of those orig image files? the only ones uploaded here are pngs, and the rest are all jpegs

Nicholas Jankowski <nrjank>
Group Member
Mon 28 Apr 2025 04:21:13 PM UTC, comment #27: 

I have both reference and jpeg-turbo on Mac.
I used their respective `djpeg` utils to convert this jpeg into bitmaps ("djpeg -bmp orig.jpg > orig.bmp" and orig1.bmp)

% ls -n *.bmp
-rw-r--r--  1 501  20  58285710 Apr 28 11:39 orig.bmp
-rw-r--r--  1 501  20  58285710 Apr 28 11:43 orig2.bmp
% gm compare -metric mse orig.bmp orig2.bmp
Image Difference (MeanSquaredError):
           Normalized    Absolute
          ============  ==========
     Red: 0.0000053795        0.4
   Green: 0.0000019809        0.1
    Blue: 0.0000072247        0.5
   Total: 0.0000048617        0.3


So the files are different and octave has nothing to do with this.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Mon 28 Apr 2025 03:18:29 PM UTC, comment #26: 

@OP: Octave outsources it to the GraphicsMagick library but evidently that library is configured / built differently on different platforms, yielding different results. This might be as simple as whether GraphicsMagick in turn subcontracts JPG processing to the reference JPG library or to the turbojpg library or something else. Think of it as similar to replacing one BLAS implementation with another and getting different results.

There is likely no direct way that Octave (or any other program using such libraries) can detect and correct for this automatically outside a test scenario with known outputs. Given that the JPG standard evidently allows for some leeway, it's arguably not a bug anywhere but just the way that JPG seems to be defined. That reduces the choices to these:

  • Retain the current behavior and document the difference per comment #24.


  • See whether it is possible for the user to preload a different jpg library using LD_PRELOAD. (Not sure how this works on Windows).


  • Package MXE Octave with a different jpg library if that is even possible.
Arun Giridhar <arungiridhar>
Group Member
Mon 28 Apr 2025 03:04:12 PM UTC, comment #25: 

A motivated person can post an "issue" at
https://github.com/libjpeg-turbo/libjpeg-turbo/issues

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Mon 28 Apr 2025 02:54:15 PM UTC, comment #24: 

typically we default to 'matlab compatibility' being 'right'. if there is a way for us to better match their output, it could be worthwhile if it's not actually degrading accuracy. Now, i had always though "de"coding was supposed to be deterministic with an acutal 'right' answer. If that's what our current implementation is doing, and others are throwing away detail for performance, then I'd vote to keep the more 'accurate' one and maybe just document the potential differences.

Nicholas Jankowski <nrjank>
Group Member
Mon 28 Apr 2025 02:52:33 PM UTC, comment #23: 

comment #4:

> "Another important aspect of JPEG is that decoders can trade off
> decoding speed against image quality, by using fast but inaccurate
> approximations to the required calculations. Some viewers obtain
> remarkable speedups in this way."

[...]

>  the expectation for different decoders to produce identical results is an invalid expectation.


comment #19:

> I still do not think that the current result (of Win Octave) is "wrong", it is just different. But since everyone seems to move to "jpeg-turbo" as the default "JPEG" codec, may be our Windows distribution should do too, just for the concistency sake.
> Dmitri.


I am not expert in this, but here is what I found from a quick search: 

https://www.cmlab.csie.ntu.edu.tw/cml/dsp/training/coding/jpeg/jpeg/encoder.htm

> Because the DCT equations contain transcendental functions, no physical implementation can compute them with perfect accuracy. Besides, JPEG does not specify unique DCT algorithm in its propsed standard. This , however, makes compliance more difficult to confirm since two compliant encoders ( or decoders ) generally will not produce identical outputs given identical inputs.


https://photo.stackexchange.com/questions/83745/is-a-jpg-guaranteed-to-produce-the-same-pixels (2016)

> Appropriate accuracy is very strict. Any converter following these specifications has to be compared to a reference algorithm. For a single pixel, each component can only differ by one bit from the reference. Furthermore, the (squared) error over each 8x8 pixel block and over the whole image needs to be very low.


https://stackoverflow.com/questions/23565889/jpeg-images-have-different-pixel-values-across-multiple-devices (2014)

> The JPEG standard does not require that decoder implementations produce bit-for-bit identical output images. [...]  Wikipedia says:
> > ...the JPEG standard [...] includes some precision requirements for the decoding, [...]; 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


The Wikipedia description survived for a decade or so until 2022
https://en.wikipedia.org/w/index.php?title=JPEG&diff=prev&oldid=1086656713 (07 May 2022)
when it was amended by an anonymous editor, accompanied by the following assertion:
"The description in this paragraph is simply wrong. It applies to MPEG, but not to JPEG where conformance is defined both for the encoder and the decoder."

https://en.wikipedia.org/wiki/JPEG#Required_precision (2022–2025)

> For example, the output of a decoder implementation must not exceed an error of one quantization unit in the DCT domain when applied to the reference testing codestreams provided as part of the above standard. While unusual, and unlike many other and more modern standards, ITU.T T.83 | ISO/IEC 10918-2 does not formulate error bounds in the image domain.

(emphasis added). 

I can't say for sure what a difference of "one quantization unit in the DCT domain" might look like in the image domain, but I wouldn't have expected such large (visually apparent) differences as I observed. 

I also note from the discussion that there seems to be inconsistency between Octave's handling of this on different platforms, and that is surely not desirable. 
Or, put another way, Octave on Windows is performing differently from IrfanView and all four online tools that I checked and Octave on Linux and Octave on Mac? 

—DIV

Anonymous
Mon 28 Apr 2025 02:20:10 PM UTC, comment #22: 

Octave for Windows is using the reference implementation for JPEG from the IJG:
https://jpegclub.org/reference/reference-sources/

If other implementations give different results, one could argue which one is "right". Is it the reference implementation or some other implementation (jpeg-turbo if I understood correctly)?

Markus Mützel <mmuetzel>
Group administrator
Mon 28 Apr 2025 02:02:28 PM UTC, comment #21: 

comment #14:

> "This Toolbox should be expected to be used for serious (i.e., scientific) image processing".
>
> Red herring, serious data is not stored as JPG. JPG is lossy format.


That is a comment made out of ignorance.  I can think of many instances where serious work might be done on images saved in JPG format. 

—DIV

Anonymous
Mon 28 Apr 2025 01:59:37 PM UTC, comment #20: 

Hi, Arun Giridhar <arungiridhar>

comment #15:

> On my Linux system, the Magick installation says "Q16" in the first line, so the requirement is satisfied.

[...]

> @OP and anyone who can see a different number of unique colors: pls see what the first line of "magick --version" returns for you, especially the Q-number.


Could you please explain how to check this on a Windows system?

Anonymous
Sun 27 Apr 2025 03:09:54 AM UTC, comment #19: 


comment #17:

> In any event, this bug report looks like something that shows up with how a third party library was built. What should Octave do? We can add a check to make check. But that won't help the user in this case.


I still do not think that the current result (of Win Octave) is "wrong", it is just different. But since everyone seems to move to "jpeg-turbo" as the default "JPEG" codec, may be our Windows distribution should do too, just for the concistency sake.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sun 27 Apr 2025 03:02:15 AM UTC, comment #18: 

Graphicsmagick is a tricky beast. It has most/all of its decoders  as "delegates". On my computer:


 ldd /usr/lib64/GraphicsMagick-1.3.45/modules-Q16/coders/jpeg.so | grep jpeg
        libjpeg.so.62 => /lib64/libjpeg.so.62 (0x00007fa451aa9000)
$ rpm -qf /lib64/libjpeg.so.62
libjpeg-turbo-3.1.0-2.fc42.x86_64


Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sun 27 Apr 2025 02:41:02 AM UTC, comment #17: 

But ldd isn't seeing the turbojpeg library in the chain either. It says Octave libraries link to graphicsmagick library which links to various other libraries but none have turbo or jpeg in them. Does that mean that graphics Magick is doing jpeg decoding natively?

In any event, this bug report looks like something that shows up with how a third party library was built. What should Octave do? We can add a check to make check. But that won't help the user in this case.

Arun Giridhar <arungiridhar>
Group Member
Sat 26 Apr 2025 08:22:38 PM UTC, comment #16: 

You are you using "wrong" Magick :)

I do not think you can build build Octave against ImageMagick now days.

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sat 26 Apr 2025 07:03:19 PM UTC, comment #15: 

Works for me on Linux with both the default branch and the stable branch. Getting 244323 colors:


octave:5> foo = imread ("32679472687_a155fdb3e8_o.jpg"); fooflat = reshape (foo, rows(foo) * columns(foo), []); u = unique (fooflat, "rows"); whos
Variables visible from the current scope:

variables in scope: top scope

  Attr   Name           Size                     Bytes  Class
  ====   ====           ====                     =====  =====
         foo         3663x5303x3              58274667  uint8
         fooflat 19424889x3                   58274667  uint8
         u         244323x3                     732969  uint8

Total is 117282303 elements using 117282303 bytes

octave:6> u(1:10,:)
ans =
   0   0   0
   0   0   2
   0   0   4
   0   0   5
   0   0  10
   0   0  12
   0   1   0
   0   1   2
   0   1   3
   0   1   4


There are several comments in _magick_read_.cc about the quantum depth setting of the Magick library, and it should evidently be at least 16 (not 8). (Per comment #3, this is done in the MXE build settings for Octave on Windows).

On my Linux system, the Magick installation says "Q16" in the first line, so the requirement is satisfied.


$ magick --version
Version: ImageMagick 7.1.1-47 Q16-HDRI x86_64 22763 https://imagemagick.org
Copyright: (C) 1999 ImageMagick Studio LLC
License: https://imagemagick.org/script/license.php
Features: Cipher DPC HDRI Modules OpenCL OpenMP(4.5)
Delegates (built-in): bzlib cairo djvu fftw fontconfig freetype heic jbig jng jp2 jpeg jxl lcms lqr ltdl lzma openexr pangocairo png raqm raw rsvg tiff uhdr webp wmf x xml zip zlib zstd
Compiler: gcc (14.2)


@OP and anyone who can see a different number of unique colors: pls see what the first line of "magick --version" returns for you, especially the Q-number.

I also checked the library dependencies with `ldd` on the Octave binary and the four Octave libraries (liboctave, liboctinterp, liboctgui, and liboctmex). They linked to libGraphicsMagick.so but nothing with "turbo" or "jp" in its name. In turn, libGraphicsMagick.so did not link to "turbo" or "jp" anything. There is a "libturbojpeg.so" required by unrelated programs, but Octave does not seem to be using it as far as I could tell as described.

Arun Giridhar <arungiridhar>
Group Member
Sat 26 Apr 2025 11:13:18 AM UTC, comment #14: 

"This Toolbox should be expected to be used for serious (i.e., scientific) image processing".

Red herring, serious data is not stored as JPG. JPG is lossy format.

Anonymous
Sat 26 Apr 2025 06:03:33 AM UTC, comment #13: 

I do not think this code changed much lately. Here is on linux with 9.4.0 (also using jpeg-turbo):

ctave:5> size(uniquecolors)
ans =

   244323        3

octave:6> ver
----------------------------------------------------------------------
GNU Octave Version: 9.4.0 (hg id: df465cbba05a)
GNU Octave License: GNU General Public License
Operating System: Linux 6.14.3-300.fc42.x86_64 #1 SMP PREEMPT_DYNAMIC Sun Apr 20 16:08:39 UTC 2025 x86_64
----------------------------------------------------------------------


Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sat 26 Apr 2025 05:49:09 AM UTC, comment #12: 

Hi, Dmitri A. Sergatskov <dasergatskov>. 
Are you able to test with Octave 10.1.0, as I had used? 
—DIV

Anonymous
Sat 26 Apr 2025 03:29:58 AM UTC, comment #11: 

Se also on Mathemtical Compatibility":
https://github.com/ImageMagick/jpeg-turbo

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sat 26 Apr 2025 03:05:10 AM UTC, comment #10: 

Mac's graphicsMagick is compiled against jpeg-turbo:
https://formulae.brew.sh/formula/graphicsmagick

May bee Windows version should do the same?

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sat 26 Apr 2025 02:52:37 AM UTC, comment #9: 

I tried it on macOs with octave 11:

octave:5> size(aflat)
ans =

   1.9425e+07   3.0000e+00

octave:6> uniquecolors = unique (aflat, 'rows', 'sorted');
octave:7> size(uniquecolors)
ans =

   244323        3


I guess it may depends on hoe GraphicsMagick was compiled?

Dmitri.
--

Dmitri A. Sergatskov <dasergatskov>
Sat 26 Apr 2025 01:34:33 AM UTC, comment #8: 

Uploading two cropped images to compare. 
—DIV


Anonymous
Sat 26 Apr 2025 01:27:57 AM UTC, comment #7: 

Sorry, there is a typo in my previous comment (#5). 
I accidentally typed "imshow".  Actually, the problem lies with "imread", as per my original submission.  Sorry for any confusion caused! 

In fact, this suggests that Octave should be less concerned about JPEG decoding than an application like IrfanView. 

IrfanView would commonly be used just for viewing photographs, with users maybe viewing in slideshow mode, quickly proceeding from one image to the next.  So frequent decoding could be required. 

In Octave the decoding only needs to happen once, when the file is read from the disk.  And I suspect that the I/O operations would typically be slower than the decoding operations.  Once imread has performed the decoding, the data are stored as a 3D RGB array.  Then imshow just displays whatever is in the array:  thus, in Octave displaying a 3D array of RGB data does not involve JPEG decoding. 
Maybe other users are different, but from my experience of image processing, the time-consuming steps would be things like pattern recognition, rather than JPEG decoding. 

—DIV

Anonymous
Sat 26 Apr 2025 01:00:49 AM UTC, comment #6: 

Also, in that forum, please read on: 
"Although what it says is that there is one correct way, but decoders may [ opt to ] not use that [ correct ] route because it's slower than some simplifications."

Emphasis and insertions in brackets are mine. 

—DIV

Anonymous
Sat 26 Apr 2025 12:57:24 AM UTC, comment #5: 

Hi, Nicholas Jankowski <nrjank> and all. 

Thanks for the quick response. 

Sorry, it only occurred to me just now that I could have submitted a simpler workflow to test based on just the original image. 
For me Octave also reports 250366 unique colours for the original image, but IrfanView reports 244323. 
Intuitively we might expect that the larger tally reflects greater accuracy.  However, from my middling knowledge of JPEG I think it actually reflects a lower fidelity. 

I am willing to concede your point about the ability for JPEG decoders to opt to trade off quality to gain speed. 

However, I have a few concerns related to the remarks "visually, the images render with similar accuracy. the expectation for different decoders to produce identical results is an invalid expectation."

Firstly, all four online tools that I tried AND IrfanView AND Matlab are all consistent in the way they load JPEGs.  Octave is the only odd one out. 
So although theoretically it is understandable that different results could be obtained from different decoders, those six diverse tools/applications all produce the same result;  thus, with such experience, practically users might indeed expect identical results. 

Secondly, for some images the differences are visually perceptible, which indicates a serious problem, because the human eye is less sensitive than you might think. 

Thirdly, and most importantly, imshow is not merely part of a workflow to display pictures.  Rather, imshow is part of the Image Processing Toolbox.  This Toolbox should be expected to be used for serious (i.e., scientific) image processing, not just mucking around to display pretty pictures. 
I believe the ideal of Octave should be that it would perform the same (or better) than code written for MATLAB.  In some cases it may not be practical to reach that ideal, but that should be acknowledged as a (justifiable?) deficiency, not dismissed as unimportant.

—DIV

Anonymous
Fri 25 Apr 2025 09:38:12 PM UTC, comment #4: 

Also relevant:
https://groups.google.com/g/rec.photo.digital/c/yAxoW9HyHPQ/m/7AUjzSnsU1wJ


> Is there only one mathematically correct decoding of a JPEG?
No. From the JPEG FAQ:

"Another important aspect of JPEG is that decoders can trade off
decoding speed against image quality, by using fast but inaccurate
approximations to the required calculations. Some viewers obtain
remarkable speedups in this way."

Plus, given the complexities of the JPEG format, I'd expect decoding
libraries to do things in slightly different orders. That would
introduce rounding differences in the real number maths.


visually, the images render with similar accuracy. the expectation for different decoders to produce identical results is an invalid expectation.

So the last question remains - are we sure we aren't doing anything to specifically cause a difference in Octave? Or is it all graphicsmagick?

Nicholas Jankowski <nrjank>
Group Member
Fri 25 Apr 2025 06:27:20 PM UTC, comment #3: 

As far as I can see is IrfanView using libjpeg-turbo (https://libjpeg-turbo.org/). From what I read it's highly optimized for speed, not for accuracy.

GNU Octave built for windows uses graphicsmagick --with-quantum-depth=16
see here: https://hg.octave.org/mxe-octave/file/tip/src/graphicsmagick.mk

Andreas Weber <andy1978>
Group Member
Fri 25 Apr 2025 05:26:00 PM UTC, comment #2: 

playing around a bit with the original image (no editing).

Octave 10.1.1 (hg id: 886270cfcf8b)

a = imread('original.jpg');

size(a)

ans =

   3663   5303      3

aflat = reshape (a, prod(size(a)(1:2)), 3);

size(aflat)

ans =

   19424889          3

uniquecolors = unique (aflat, 'rows', 'sorted');

size(uniquecolors)

ans =

   250366        3

>> uniquecolors (1:10,:)
ans =

   0   0   0
   0   0   2
   0   0   4
   0   0   5
   0   0   7
   0   0   8
   0   0  10
   0   0  13
   0   1   0
   0   1   2


and doing the same exercise in Matlab:

>> a = imread('original.jpg');
>> sza = size(a)

sza =

        3663        5303           3

>> aflat = reshape (a, prod(sza(1:2)), 3);
>> size(aflat)

ans =

    19424889           3

>> uniquecolors = unique (aflat, 'rows', 'sorted');
>> size(uniquecolors)

ans =

      244323           3

>> uniquecolors(1:10,:)

ans =

  10×3 uint8 matrix

    0    0    0
    0    0    2
    0    0    4
    0    0    5
    0    0   10
    0    0   12
    0    1    0
    0    1    2
    0    1    3
    0    1    4


So, just from this small test, we are reading in a different set of colors than Matlab. In this case, of course, Octave is actually registering more unique colors than matlab. not sure what the exact difference is, I don't know anything about JPEG data storage/compression/decompression algorithms.

Peeking at the first color 'missing' [0 0 7] in the matlab data:

Octave:

find(prod(aflat == [0 0 7],2))
ans =

    4893002
    4896665
   16179392

>> aflat(ans,:)
ans =

  0  0  7
  0  0  7
  0  0  7


Matlab:

>> aflat([4893002,4896665,16179392],:)

ans =

  3×3 uint8 matrix

   0   0   5
   0   0   5
   1   0   2


So, yes, the two programs are reading color data in differently from the jpeg file, in this case near-blacks are getting slightly different values.  I'll need someone familiar with jpeg image data reading to determine the severity of this.

Nicholas Jankowski <nrjank>
Group Member
Fri 25 Apr 2025 04:44:29 PM UTC, comment #1: 

I don't have the tools to repeat your image modifications prior to attempting to check in Octave. For us to have a simpler set of reproducible steps to troubleshoot, is it possible to attach your sample images, or maybe you can just crop to the area of the image where you're finding color discrepancy, if those cropped images exhibit the problem?  then we may be able to do comparison loads in octave and matlab, and possibly an external image tool like infranview to look at image details (color count, etc.)

Nicholas Jankowski <nrjank>
Group Member
Fri 25 Apr 2025 01:25:26 PM UTC, original submission:  

There is apparently a severe bug in imread for JPEG images. 

From IrfanView I downscaled an online photograph (full-size) to 10% of the original size. 
Source:  https://www.flickr.com/photos/146721572@N04/32679472687/

I saved it as JPEG with 80% quality. 
I reopened the downsized JPEG in IrfanView, and then resaved that as PNG (compression = 9). 

I loaded the two small images into Octave with imshow(filename). 
I found element-by-element differences by casting each 3D input array to double, then subtracting. 
The pixel-by-pixel RGB differences should all be zero, but are actually between -35 and +37! 

Just for good measure I also check equality without casting to double: 

veracity = inJPG(:)==inPNG(:);

All elements of veracity should be 1 (true), but 125437 (~21.6%) are not.

The discrepancy is most obvious in the bright light refracted onto the gentleman's nose. 
The mismatch is so bad that it is clearly visible when zooming in on pixels in this region when displaying using imshow in Octave. 

The mismatch is the fault of Octave, not IrfanView. 
I manually counted the number of unique colours in Octave:


    newArray = [reshape(img(:,:,1), [],1), reshape(img(:,:,2), [],1), reshape(img(:,:,3), [],1)];
    n = length(unique(newArray, 'rows'));


For each image I know the correct value for the number of unique colours, because it is reported by IrfanView and confirmed with four online tools
https://townsean.github.io/canvas-pixel-color-counter/
https://onlinetools.com/image/analyze-image
https://planetcalc.com/10185/
https://www.imgonline.com.ua/eng/unique-colors-number.php
All, except Octave, agree unanimously that both images have 59279 unique colours. 

Octave yields the correct number for the PNG (59279), but not for the JPEG (61682)! 

Conclusion:  Octave is doing something wrong when reading in JPEG images.  Octave reads PNG images correctly. 

Speculation:  maybe Octave is using an old/wrong 'protocol' or 'standard'? 

Note:  I have not explicitly specified the image format in imshow, but Octave should handle that OK, as the filenames end in either "jpeg" or "png". 

Note:  I have not checked what MATLAB does, but I would be surprised if if exhibits the same error. 


Freshly installed the latest release of Octave today (by 7z) onto Windows 10 x64.

Anonymous

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #57179:  tdiff.jpg added by dasergatskov (113KiB - image/jpeg)
file #57170:  20250426_Octave_image_correct.png added by None (13KiB - image/png - Cropped results from Octave. JPEG version has orange tinge just to the left of bright refracted light. )
file #57171:  20250426_Octave_image_wrong.png added by None (14KiB - image/png - Cropped results from Octave. JPEG version has orange tinge just to the left of bright refracted light. )

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by mmuetzel (Posted a comment)
  • -email is unavailable- added by arungiridhar (Posted a comment)
  • -email is unavailable- added by dasergatskov (Posted a comment)
  • -email is unavailable- added by andy1978 (Posted a comment)
  • -email is unavailable- added by nrjank (Posted a comment)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 6 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2025-04-28 dasergatskov Attached File- Added tdiff.jpg, #57179
    2025-04-26 None Attached File- Added 20250426_Octave_image_correct.png, #57170
        Attached File- Added 20250426_Octave_image_wrong.png, #57171
    2025-04-25 nrjank Summaryimread not reading full color data for JPEG images imread not reading same color data as matlab for JPEG images
    2025-04-25 nrjank SummarySerious bug with imread for JPEG images imread not reading full color data for JPEG images
    2025-04-25 nrjank StatusNone Need Info

    Back to the top

    Powered by Savane 3.15-e283.
    Corresponding source code