changing image resolution in Python for a .bmp file - python

I want to change the resolution of the .bmp image in python. ( i.e. the pixel/inch information) . Using PIL, for jpg image, for instance, the following code works fine
import Image
im = Image.open("myImg.jpg)
im.save("output.jpg", dpi = (75, 75) )
If you view this in some image editing software like GIMP, it shows the Pixel per inch as 75, 75.
But the above code doesn't work when the input image is a .bmp file.
Could someone tell me how to change image resolution for any image in python?

I suspect that there aren't many programs out there that respect bmp resolution. Windows bitmaps are all 96 dpi.
Also, It looks as though PIL doesn't support a resolution parameter for bitmaps. My PIL/BmpImagePlugin.py just writes in $01000000 for the x & y resolution (i'm not sure what that translates to, but I'd guess "96 dpi").
There are docs which tell you how to write your own extension .. I'd guess it would be pretty simple to make a copy of the PIL bitmap plugin which accepted resolution as a parameter.

I think input file can be any valid format and output need to be, jpg, pcx, png, tiff, wmf for dpi parameter I think, may be I am wrong, but when I looked at PIL source files, I don't see one for BMP files.

Related

python: when reading and saving a image the color change

I tried loading and saving images with python using cv2,PIL, scipy , but the saved image has a bit different color compare to the original.
I am loading and saving tif format, so i expect no color change.
link to the image I am using:
https://data.csail.mit.edu/graphics/fivek/img/tiff16_c/a0486-jmac_MG_0791.tif
the difference between loaded image and saved image is:
can you help me understand what I am doing wrong? why the color change?
update:
the problem is because the image is prophoto rgb color.
does anyone knows how can i convert a batch of images from prophoto rgb to rgb?
thanks,
yoav
option 1:
img = imread(file_name)
imsave('imread.tif', img)
option 2:
img = cv2.imread(file_name)
cv2.imwrite('cv2.tif', img)
option 3:
img = Image.open(file_name)
img.save('pil.tif')
I think OpenCV is more interested in Computer Vision - i.e. detecting and measuring objects etc than printing or high quality image reproduction, editing and printing, so it pretty much ignores ICC profiles. If anyone knows better, I am happy to be corrected.
You can use ImageMagick to convert images from one format to another, and to do many, many other things, one of which is changing colour profiles. So, I think, if you go to this website and download an sRGB profile (I chose the first one with "preference" in its name) and save it as sRGB.icc, you can change one of your ProPhoto images to a normal sRGB image with the following command in Terminal:
convert input.tif -profile sRGB.icc output.tiff
Try that and see if it works. If so, make a copy of your images and on a copy, you can run mogrify to do the whole lot in one go - beware and make a copy like I suggest because it will very quickly alter all your images...
magick mogrify -profile sRGB.icc *tif
You can see the embedded profile and loads of other information about an image using ImageMagick's identify command:
magick identify -verbose OneOfYourImages.tiff

How to convert an .eps file into a .png in Python 3.6

With Python turtle I'm trying to save the canvas as a png. I've researched it and found a way to save it as an eps file without any modules, but I'm finding it hard to convert the eps file into a png.
Is there a way to convert eps to png without downloading another module? If not can someone tell me more about ImageMagick, because I have looked at it, but I'm confused how to use it? I've also seen it being linked to linux and is it outdated?
If not converting eps to png, is there a even simpler way to save the canvas as a png?
Btw I have seen this, but I don't understand it :/
How to convert a .eps file to a high quality 1024x1024 .jpg?
From the link you show, there is this Imagemagick command:
convert -density 300 image.eps -resize 1024x1024 image.jpg
Most EPS files are vector images. They have no physical size in pixels, since it a vector drawing with commands that describe how to draw each object. It is not a raster image containing pixels and does not have any particular pixel set of dimensions.
So with vector files, you set the printing density to tell Imagemagick (which passes it off to Ghostscript to do the rasterizing work) to convert the vector data to raster data and then save it as a raster format output image. Nominal density is 72 dpi (sometimes 92 or 96). So if you use -density 288 with the following command:
convert -density 288 image.eps image.png
It would result in an image that is 4 times larger in each dimension than if you just did
convert image.eps image.png
which for default dpi of 72 would be the same as
convert -density 72 image.eps image.png
Note that 72*4=288.
Now you have a large high quality raster png, especially if the eps file was line drawing with thin lines like blue-prints.
However if that is too large and you want to reduce it back to its nominal size by 1/4, you could do (note 1/4 = 25%)
convert -density 288 image.eps -resize 25% image.png
This process is sometimes called supersampling and would produce a better looking result than just doing
convert image.eps image.png
In the original command, they decide to get a high quality raster image and just resize to 1024x1024.
So you can resize to any size you want after producing a high definition raster image from the EPS vector image.
The larger the density you use, the higher the quality will be in the PNG, but it will take longer to process. So you have to trade time vs quality and pick the smallest density that produces good enough quality in a reasonable amount of time.
I do not know if Python Wand supports setting the density or if it supports reading PDF file, which requires Ghostscript. But you can use Python Subprocess module to make a call to an Imagemagick command line. See https://www.imagemagick.org/discourse-server/viewtopic.php?f=4&t=32920
I've been having problems with ImageMagick having had its security policy changed so it can't interact with Ghostscript. (for good reason... but it's questionable that it doesn't allow you to locally override the default policy so web apps can be protected while whitelisted uses can still work.)
For anyone else slamming into convert: not authorized, here's how to invoke Ghostscript directly:
gs -dSAFER -dEPSCrop -r300 -sDEVICE=jpeg -o image.png image.eps
-dSAFER puts Ghostscript into sandboxed mode so you can interpret untrusted Postscript. (It should be default, but backwards compatibility.)
-dEPSCrop asks Ghostscript to not pad it out to the size of a printable page. (details)
ImageMagick's -density 300 becomes -r300 when it invokes Ghostscript. (details)
-sDEVICE is how you set the output format (See the Devices section of the manual for other choices.)
-o is a shorthand for -dBATCH -dNOPAUSE -sOutputFile= (details)
You could then use ImageMagick's mogrify command to resize it to fit exact pixel dimensions:
mogrify -resize 1024x1024 image.png
(mogrify is like convert but replaces the input file rather than writing to a new file.)
UPDATE: In hindsight, I should have checked whether Pillow supported EPS before posting that first answer.
The native Python solution would be to use Pillow's support for invoking Ghostscript (like ImageMagick in that respect, but with a native Python API).
However, Pillow's docs don't explain how they arrive at a size in pixels and only take an optional multiplier (scale) for the default size rather than an absolute DPI value.
If that doesn't bother you, and you've got both Pillow and Ghostscript installed, here's how to do it without ImageMagick:
#!/usr/bin/env python3
from PIL import Image
TARGET_BOUNDS = (1024, 1024)
# Load the EPS at 10 times whatever size Pillow thinks it should be
# (Experimentaton suggests that scale=1 means 72 DPI but that would
# make 600 DPI scale=8⅓ and Pillow requires an integer)
pic = Image.open('image.eps')
pic.load(scale=10)
# Ensure scaling can anti-alias by converting 1-bit or paletted images
if pic.mode in ('P', '1'):
pic = pic.convert("RGB")
# Calculate the new size, preserving the aspect ratio
ratio = min(TARGET_BOUNDS[0] / pic.size[0],
TARGET_BOUNDS[1] / pic.size[1])
new_size = (int(pic.size[0] * ratio), int(pic.size[1] * ratio))
# Resize to fit the target size
pic = pic.resize(new_size, Image.ANTIALIAS)
# Save to PNG
pic.save("image.png")

SVG/PNG files open differently in the browser

I am working on a project where our database is on svg format. Now, the weird thing (I don't know much about image formats) is that the image looks totally different if I open it on a computer program like Image Viewer, ImageMagick or Pinta, to how the image looks when I open it on a browser (be it Mozilla or Chrome). I am attaching an image (converted from svg to png) for convenience and you can see that the difference is really big if you open it on a browser compared to a normal program (if you download it and open it on your computer).
Now, I opened it on Python to see what is going on, and apparently the image is on RBGA format. I thought to convert it to RGB, and did it using the following code:
img = Image.open(os.path.join(PNG_REPO, page)[:-4] + ".png")
arr = np.array(img)
rgbImage = cv2.cvtColor(arr, cv2.COLOR_RGBA2RGB)
img = Image.fromarray(rgbImage)
img.save("please.png")
and then, weird stuff happened. The image seems to have become completely black (attached below) and opening it on Python, a local program or a browser doesn't make any difference anymore.
Anyone has any idea what is going on? I think that I am losing it and I am completely stucked.
In fact, SVG and PNG are totally different.
SVG (Scallable vector graphics) is not a standard image format : the image is not stored as an raay of pixel (or derivative), but as a vectorized format. To display it, you would have to render the vectors into pixels, then display them. The big assets of this approach are the quality vs. size : for illustrations, you can have a fantastic quality for almost nothing in size, however, it requires more time to process, and the decoding is very different from other image formats, thus it is often not supported by image viewers, and the renders can depend a bit on the renderer.
PNG (Portable network graphics) on the other hand is still based on pixel, and is very widely supported.
As for your question, your image have an alpha (transparency) channel. When converting it to RGB, you are getting rid of this transparency, which opencv translates into a fixed color. Here, this color is (0,0,0), that is to say black.
You should try this :
img = Image.open(os.path.join(PNG_REPO, page)[:-4] + ".png")
img.load()
new_img = Image.new("RGB", img.size, (255, 255, 255))
new_img.paste(img, mask=img.split()[3]) # 3 is the alpha channel
new_img.save("should_be_good.png")

Color in image gets dull after saving it in OpenCV

I am using opencv module to read and write the image. here is the code and below is the image i am reading and second image is after saving it on disk using cv2.imwrite().
import cv2
img = cv2.imread('originalImage.jpg')
cv2.imwrite('test.jpg',img)
It is significantly visible that colors are dull in second image. Is there any workaround to this problem or I am missing on some sort of setting parameters..?
I have done a bit of research on the point #mark raised about ICC profile. I have figured out a way to handle this in python PIL module. here is the code that worked for me. I have also learned to use PNG file format rather JPEG to do lossless conversion.
import Image
img = Image.open('originalImage.jpg')
img.save('test.jpg',icc_profile=img.info.get('icc_profile'))
I hope this will help others as well.
The difference is that the initial image (on the left in the diagram) has an attached ICC profile whereas the second one (on the right) does not.
I obtained the above image by running the ImageMagick utility called identify like this:
identify -verbose first.jpg > 1.txt
identify -verbose second.jpg > 2.txt
Then I ran the brilliant opendiff tool (which is part of macOS) like this:
opendiff [12].txt
You can extract the ICC profile from the first image also with ImageMagick like this:
convert first.jpg profile.icc
Your first input image has some icc-Profile associated in the meta-data, which is an optional attribute and most devices may not inject it in the first place. The ICC profile basically performs a sort of color correction, and the correction coefficients are calculated for each unique device during calibration.
Modern Web Browsers, Image Viewing utilities mainly take into account this ICC profile information before rendering the image onto the screen, that is the reason why there is a diff in both the images.
But Unfortunately OpenCV doesn't reads the ICC config from the meta data of the image to perform any color correction.

Image resize using PIL changes colors drastically

I am using the following code to resize an image using PIL
img = Image.open("in.png")
resized = ImageOps.fit(img, (200, 200), method=Image.ANTIALIAS)
resized.save("out.png")
But the output image colors look very different. Here they are for comparison, the big one is the original:
What's even stranger is that when I open them using the image viewer in ubuntu, they look the same. But not in Windows or MacOS.
The larger image is using the Adobe RGB color profile. It is omitted from the smaller image, which means the color correction system will use some default (probably sRGB), which likely has a smaller gamut. This will cause the colors to appear duller.
Solution 1: Create the original image using sRGB instead of Adobe RGB.
Solution 2: Copy the color profile from the larger image to the smaller image.
Most Linux systems do not support color correction, at least not on the same scope that OS X or Windows do. So the fact that they appear the same in Ubuntu's image viewer is really a limitation of the image viewer program, which is unable to understand color profiles.

Categories

Resources