0

I would like to know what am I doing wrong with this code :

if self.digital:
   im = Image.open(os.path.join(folder, filename))
   width, height = im.size
   image_info["width"] = round(width / 37.79527559055, 0)

I would like to use this code to convert the pixel size of a picture into centimeters, but I don't understand why it returns me this issue :

Python311\Lib\site-packages\PIL\Image.py:3167: DecompressionBombWarning: Image size (130437549 pixels) exceeds limit of 89478485 pixels, could be decompression bomb DOS attack.

I don't want to use DPI, in my script 1cm = 37.79527559055 pixels.

I'm going to use a temporary list to write pixels value in then convert but I would like to know if there is a faster way or not, and why exactly is it making a zip bomb.

Thanks !

NIKUNJ PATEL
  • 2,034
  • 1
  • 7
  • 22
Pythonmaru
  • 17
  • 4
  • 3
    Where exactly does the error occur? On the `open()` call? – B Remmelzwaal Feb 03 '23 at 19:28
  • It's not the opening method or the image, so the entire script still opens images and returns the pixel size. For this reason, I didn't include the entire code; the problem solely stems from the lines I wrote here. – Pythonmaru Feb 03 '23 at 19:34
  • @Pythonmaru Have you looked at my answer? Did it solve your problem? – GIZ Feb 03 '23 at 19:40
  • 2
    So if error is not in `open`, and can't obviously be in the line after, it has to be in `image_info` assignment. What is this `image_info`? an alias of `im.info`? It would be easier with a [mre]. It is hard to debug when we can't be sure where the error occur (even if we trust you about where it **does not** occur), and can't experiment. – chrslg Feb 03 '23 at 20:28
  • You're right, I thought the problem wasn't coming from the other lines of the script but finally it was, I've posted the solution in the comment of the next answer, but thanks for your help @chrslg , next time I will publish the whole part ^^' – Pythonmaru Feb 03 '23 at 20:50

1 Answers1

2

The issue is that the image you are trying to open is too large and its decompression would consume a lot of memory, which can be a potential security risk (known as "Decompression bomb"). To avoid this, you can increase the maximum size limit of the image in PIL by modifying the Image.MAX_IMAGE_PIXELS attribute:

Image.MAX_IMAGE_PIXELS = None # No Limit

It is important to consider the memory usage and performance of your script when using large images.

Regarding the conversion of pixels to centimeters, using a fixed number of pixels per centimeter is not the recommended approach as it depends on the display resolution and the physical size of the display. Instead, you should use the DPI (dots per inch) information embedded in the image file to perform the conversion. You can retrieve the DPI information using the 'info' attribute of the Image object and then use it to calculate the size in centimeters.

Here is an example of how you could do the conversion with DPI information:

from PIL import Image

im = Image.open(os.path.join(folder, filename))
width, height = im.size
dpi = im.info.get("dpi", (72, 72))
width_cm = width / dpi[0] * 2.54
height_cm = height / dpi[1] * 2.54

image_info["width_cm"] = width_cm
image_info["height_cm"] = height_cm

You can resize the image to a smaller size before processing it. You can use the Image.thumbnail() method provided by PIL to resize the image.

GIZ
  • 4,409
  • 1
  • 24
  • 43
  • Sorry but nope. That's why I said I will not use the DPI method : I still get the same error. The problem isn't coming from the size of the image ( I tried with a simple screenshot 450x265), and as I wrote before, the script is perfectly running to return the pixel size in pixels, so I really don't get where the bad is ^^' But thanks for your answer ! I don't want to resize, or break the limit, I've already tried that – Pythonmaru Feb 03 '23 at 19:43
  • 2
    In that case, the issue seems to be with the constant that you are using to convert the pixels to centimeters. 37.79527559055 is an incorrect conversion factor. The correct conversion factor would be the number of pixels per centimeter. For example, if the image has a resolution of 72 DPI, you can calculate the pixels per centimeter by dividing the DPI by 2.54 (number of inches per centimeter). `pixels_per_centimeter = 72 / 2.54` and then `width_in_cm = width / pixels_per_centimeter` – GIZ Feb 03 '23 at 19:45
  • As I indicated, I just want it to transform the pixels values returned into cms. That's a decent technique, but I have to convert several images with variable DPI. I believe the problem stems from that all picture size are added to one size because variables have poor assignments, I will try some things and I'll post the solution if I find but thank you very much for your answer, I think it would work for a single image. – Pythonmaru Feb 03 '23 at 20:00
  • @Pythonmaru You could try using the `dpi` attribute of the `Image` object to get the DPI of each image, and use that information to convert the pixels to centimeters. – GIZ Feb 03 '23 at 20:02
  • Finally the problem cames from my loop, not from the lines I wrote, I still don't really understand why it was working for pixels and not for cms, but now I fixed the issue. I think for the problem I described, use the DPI method would be a good solution anyway. – Pythonmaru Feb 03 '23 at 20:43