# Bad conversion to jpg from 16UC1 image or jpg compression artifacts?

**URL:** <https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737>\
**Category:** Python\
**Tags:** depth, programming\
**Created:** [April 4, 2025, 10:23am UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737 "2025-04-04T10:23:13Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![galou](https://avatars.discourse-cdn.com/v4/letter/g/858c86/32.png) [@galou](https://forum.opencv.org/u/galou)\
**Post date:** [April 4, 2025, 10:23am UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/1 "2025-04-04T10:23:13Z")

</div>

I use 16UC1 images in the context of depth cameras that produce a monochrome depth image, where typically an intensity of 1 represents a distance of 1 mm.

This small script generates a correct PNG image but incorrect JPG with the same source.

```python
import cv2

import numpy as np

# Create a 100x100 image with uint16 type.
width = 100
height = 100
image = np.empty((height, width), dtype=np.uint16)

# Define some intensities.
intensities = [65535, 32767, 127, 0]

# Fill the regions with the corresponding values.
n_regions = 2 * (len(intensities) - 1) + 1
for i, intensity in enumerate(intensities):
    h_margin = round(i * width / n_regions)
    w_margin = round(i * height / n_regions)
    image[h_margin:height-h_margin, w_margin:width-w_margin] = intensity

cv2.imwrite('output_image.png', image)
cv2.imwrite('output_image.jpg', image)

```

The correct image are 4 squares from white (large square, intensity 65535) to black (smallest square, intensity 0).

When I export the PNG to JPEG from Gimp, the result is correct.

Is it a bad conversion to JPEG from 16UC1 image or JPEG compression artifacts?

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [April 4, 2025, 11:31am UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/2 "2025-04-04T11:31:15Z")

</div>

are 16-bit per channel JPEG files even a thing? that would be news to me.

can you show us the artefacts you speak of?

---

<div class="post-metadata">

**Author:** ![galou](https://avatars.discourse-cdn.com/v4/letter/g/858c86/32.png) [@galou](https://forum.opencv.org/u/galou)\
**Post date:** [April 9, 2025, 9:05am UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/3 "2025-04-09T09:05:00Z")

</div>

JPEG

 ![output_image](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/c/cdb9b662da7ffa3f4121eb20abe75bdd2835fdf0.jpeg)

---

<div class="post-metadata">

**Author:** ![galou](https://avatars.discourse-cdn.com/v4/letter/g/858c86/32.png) [@galou](https://forum.opencv.org/u/galou)\
**Post date:** [April 9, 2025, 9:05am UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/4 "2025-04-09T09:05:38Z")

</div>

PNG

 ![output_image](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/1/10f7e651f7dc5ea77b5e3908b6f90f8812c6346f.png)

---

<div class="post-metadata">

**Author:** ![galou](https://avatars.discourse-cdn.com/v4/letter/g/858c86/32.png) [@galou](https://forum.opencv.org/u/galou)\
**Post date:** [April 9, 2025, 9:07am UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/5 "2025-04-09T09:07:11Z")

</div>

I have no clew about the JPEG format but `imwrite` should either transform the data or refuse to convert them if the conversion does not make sense.

---

<div class="post-metadata">

**Author:** ![berak](https://avatars.discourse-cdn.com/v4/letter/b/85f322/32.png) [@berak](https://forum.opencv.org/u/berak)\
**Post date:** [April 9, 2025, 10:00am UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/6 "2025-04-09T10:00:09Z")

</div>

> [@galou](#):
>
> ```auto
> image[h_margin:height-h_margin, w_margin:width-w_margin] = intensity
> 
> ```

If you apply a margin, rather apply a symmetric formula:

```
I[m:height-2*m, m:width-2*m]

```

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [April 9, 2025, 10:25am UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/7 "2025-04-09T10:25:51Z")

</div>

no, that was correct.

---

<div class="post-metadata">

**Author:** ![crackwitz](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/crackwitz/32/14_2.png) [@crackwitz](https://forum.opencv.org/u/crackwitz)\
**Post date:** [April 9, 2025, 10:26am UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/8 "2025-04-09T10:26:44Z")

</div>

I see nothing wrong here.

JPEG is a lossy format. did you know that?

---

<div class="post-metadata">

**Author:** ![galou](https://avatars.discourse-cdn.com/v4/letter/g/858c86/32.png) [@galou](https://forum.opencv.org/u/galou)\
**Post date:** [April 9, 2025, 12:36pm UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/9 "2025-04-09T12:36:46Z")

</div>

For me, JPEG is able to represent this since I can convert from the PNG and get “normal” results.

So, according to you @crackwitz, the wrong result is due to JPEG’s lossy format?

---

<div class="post-metadata">

**Author:** ![BadTrip](https://avatars.discourse-cdn.com/v4/letter/b/e99b99/32.png) [@BadTrip](https://forum.opencv.org/u/BadTrip)\
**Post date:** [April 9, 2025, 5:11pm UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/10 "2025-04-09T17:11:52Z")

</div>

as far as I know, there’s something called Losless JPEG and that’s the only jpeg that supports 16BIT

If i try it with C, I get a `[WARN:0@0.025] global loadsave.cpp:848 cv::imwrite_ Unsupported depth image for selected encoder is fallbacked to CV_8U.` warning when saving it to PNG and no warning when saving it to JPEG. But in the end, both are 8Bit

but check the [documentation](https://docs.opencv.org/4.x/d4/da8/group__imgcodecs.html#ga8ac397bd09e48851665edbe12aa28f25)

```auto

* With JPEG 2000 encoder, 8-bit unsigned (CV_8U) and 16-bit unsigned (CV_16U) images can be saved.

* With JPEG XL encoder, 8-bit unsigned (CV_8U), 16-bit unsigned (CV_16U) and 32-bit float(CV_32F) images can be saved.

```

//Edit: I did a mistake with the file format, this happens when using CV\_16FC1 instead of CV\_16U. Now the correction: With CV\_16U, PNG get saved as 16Bit and I get this warning for writing JPG instead of PNG.

//Edit2: I think GIMP is simply norming the values before saving it to a 8Bit JPEG. I don’t have python but what happens if you divide your image by 256 before saving it to JPEG, does it look correct to you?

---

<div class="post-metadata">

**Author:** ![galou](https://avatars.discourse-cdn.com/v4/letter/g/858c86/32.png) [@galou](https://forum.opencv.org/u/galou)\
**Post date:** [April 11, 2025, 5:56am UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/11 "2025-04-11T05:56:22Z")

</div>

If I save the JPG image with `cv2.imwrite('output_image.jpg', (image / 256).astype(np.uint8))`, then the image is correct (even without `.astype(np.uint8)`).

---

<div class="post-metadata">

**Author:** ![BadTrip](https://avatars.discourse-cdn.com/v4/letter/b/e99b99/32.png) [@BadTrip](https://forum.opencv.org/u/BadTrip)\
**Post date:** [April 11, 2025, 9:41am UTC](https://forum.opencv.org/t/bad-conversion-to-jpg-from-16uc1-image-or-jpg-compression-artifacts/20737/12 "2025-04-11T09:41:22Z")

</div>

I did some further tests with Gimp and MATLAB. Matlab can save 16-bit jpegs, its help says

```auto
'BitDepth' A scalar value indicating desired bitdepth;
                   for grayscale images this can be 8, 12, or 16;
                   for truecolor images this can be 8 or 12. Only
                   lossless mode is supported for 16-bit images.

```

But only Matlab can read these 16-Bit JPEGs. Gimp, IrfanView, Windows Paint, [Paint.NET](http://Paint.NET) and OpenCV failed to read this file.

If you load a 16Bit-Mono-PNG to Gimp and save it as JPEG, your saved jpeg file will be 8Bit.

So if you need a precision of 16Bit, then better stay with PNG, it can keep the information and compared with JPEG you don’t have annoying artefacts. But don’t forget to set the `IMREAD_ANYDEPTH` parameter for `imread`, when trying to read them, or they will be 8-Bit again
