python PIL acces multiple images from a single image file - python

I have written a python script to Delta compress an image. The image file format is .tif which contains 8 images. When I use the normal code ...
org_Image = Image.open(image)
org_Data = org_Image.load()
... I can only access the first image. How do I go about accessing the other ones?

You use org_Image.seek(org_Image.tell() + 1) to get the next one.
In PIL seek moves you to a given frame, (with an IO_Error if it doesn't exist), and tell reports the current frame number.

Related

Python/Opencv save multiple images to folder with different names

I am working on image processing, I have a folder with all of the images that needs to be processed, and I want to save all the processed images to another folder. How do I do that?
for img in glob.glob("Img/*.png"):
path = '/result'
image = cv2.imread(img)
angle, rotated = correct_skew(image)
print(angle)
cv2.imwrite(os.path.join(path , 'img.png'), rotated)
cv2.waitKey(1)
This code can read the image and process it, but I can't figure out how to save all the images with different names, like I want it to be img1.png, img2.png, etc.
Or is there anyway that I can save the images to another folder with the same names as before?
In order to save your processed images in a serial manner, you can use enumerate. When a loop is initiated using enumerate, a counter is also initiated. And each iteration yields an integer number.
In the following case i is the integer value which increments for each iteration. i is used as part of the file name to save the processed image
path = '/result'
for i, img in enumerate(glob.glob("Img/*.png"), 1):
image = cv2.imread(img)
angle, rotated = correct_skew(image)
print(angle)
cv2.imwrite(os.path.join(output_path, 'img_{}.png'.format(i)), rotated)
Save the last line as a variable wrapped in a string()
Then cv2.imwrite(variable)for the last line.
#My thought is to change the type to a string and then write the file as originally desired. When you save as a string you can change whatever type it is turning into inside the for statement.

Convert mp3 song image from png to jpg

I have a set of many songs, some of which have png images in metadata, and I need to convert these to jpg.
I know how to convert png images to jpg in general, but I am currently accessing metadata using eyed3, which returns ImageFrame objects, and I don't know how to manipulate these. I can, for instance, access the image type with
print(img.mime_type)
which returns
image/png
but I don't know how to progress from here. Very naively I tried loading the image with OpenCV, but it is either not a compatible format or I didn't do it properly. And anyway I wouldn't know how to update the old image with the new one either!
Note: While I am currently working with eyed3, it is perfectly fine if I can solve this any other way.
I was finally able to solve this, although in a not very elegant way.
The first step is to load the image. For some reason I could not make this work with eyed3, but TinyTag does the job:
from PIL import Image
from tinytag import TinyTag
tag = TinyTag.get(mp3_path, image=True)
image_data = tag.get_image()
img_bites = io.BytesIO(image_data)
photo = Image.open(im)
Then I manipulate it. For example we may resize it and save it as jpg. Because we are using Pillow (PIL) for these operations, we actually need to save the image and finally load it back to get the binary data (this detail is probably what should be improved in the process).
photo = photo.resize((500, 500)) # suppose we want 500 x 500 pixels
rgb_photo = photo.convert("RGB")
rgb_photo.save(temp_file_path, format="JPEG")
The last step is thus to load the image and set it as metadata. You have more details about this step in this answer.:
audio_file = eyed3.load(mp3_path) # this has been loaded before
audio_file.tag.images.set(
3, open(temp_file_path, "rb").read(), "image/jpeg"
)
audio_file.tag.save()

How to change the value of each pixel in an image in python?

in order to make a filter for an image softwares change the value of pixels in an image .
when i tried this code
file = open("hey.jpg" , "rb") #opening file
x = file.read() #reading from file
for i in range(len(x)):
print(x[i]) #cordinate of each pixel
file.close() #closing file
i knew it was ouputing the informations of each pixel by the output because no value was above 255 or lower then 0 .
example of ouput from my image:
240 -> R
255 -> G
0 -> B
i want to change the value for each one and save it in a new image
i tried the following code but it doesn't work
file = open("hey.jpg" , "rb") #opening file
x = file.read() #reading from file
file.close() #closing file
file = open("new.jpg" , "wb") #the new image
for i in range(len(x)): #writing the new data with filter
if x[i] !=255: #pixels RGB cant be 256
file.write(bytes(x[i] + 1)) #bytes because when doig write(x[i]+1) it gives mes an error that a bytee object is required not int
else: #if it is 255 then do nothing
file.write(bytes(x[i]))
file.close()#closing the new image
no need to read this:
PS:
windows 10 , python3.8 .
i tried to make everything simplified .
by doesn't work i mean that there was no errors but OS can't decode it and output an image
i don't want to use any third party library like PIL .
this code copy the binary data of an image and make a new one sucessfully .
file = open("hey.jpg" , "rb") #opening file
x = file.read() #reading from file
file.close() #closing file
file = open("new.jpg" , "wb")
file.write(x)
file.close()
JPEG, PNG and most image file formats don't work like that. They have headers at the start with metadata in, like the date you took the picture, your camera model, your GPS coordinates, the image height, its width and copyright information. After that, they normally store the pixels in a heavily optimised, compressed format so you can't alter the pixels without first decompressing the data. You can then edit them and write them back, with new headers and recompressed. So you would be well advised to use a library.
If you really, really don't want to use a Python library, you could use ImageMagick (a command-line tool) in the Terminal to convert your image into pure RGB pixels. So, if your image is called input.jpg, you could run this in Terminal:
magick input.jpg -depth 8 RGB:pixels.dat
And then if your image was 640x480 pixels, your file called pixels.dat will just be exactly 640x480x3 bytes long with no headers or metadata or compression. You could then process this exactly as you initially envisaged. Afterwards, you could make it back into a JPEG or PNG with:
magick -depth 8 -size 640x480 RGB:pixels.dat output.jpg
Notice how you have to tell ImageMagick the height and width of the image for the return journey from RGB bytes to JPEG, because there is no header at the start of the file saying its height and width.
i knew it was ouputing the informations of each pixel by the output because no value was above 255 or lower then 0
Cause of this behavior is different than being "informations of each pixel" - you did simply accessed individual bytes of your file and 1 byte value is always from 0x00 (inclusive) to 0xFF (inclusive). Result will be similar if you do this on file of other type (for example text one).
this code copy the binary data of an image and make a new one sucessfully .
Your code simply copied content of file into another file. Note that it will work regardless of file type.
i don't want to use any third party library like PIL
Do as you wish, but keep in mind that without "any third party library" you must implement processing of every image format yourself from scratch.

Is there a way to convert bitmap into instructions, or easily read it?

I have code that takes an image and converts it into a bitmap. I was wondering if there was a way to save the bitmap in a separate file to be used later. I would like to also be able to open that file in plain text and not an actual image so that I can read the bitmap.
code:
image_file = Image.open("edge.png")
image_file = image_file.convert('1')
print(image_file.mode)
print(type(image_file.tobitmap()))
tobit_image = image_file.tobitmap() # convert image to bitmap
print(tobit_image)
I think you are looking for "Chain Codes", or "Freeman Chain Codes". Basically, you store a direction, which is one of the 8 points of the compass encoded as a digit at each location to tell you how to get get to the next point, i.e. which direction your turtle must move.
Try looking here and also Googling.
OpenCV can generate them too with findContours()
Or, you may be looking for potrace which is a tool that converts images into vector paths.

how to reduce png image filesize in PIL

I have used PIL to convert and resize JPG/BMP file to PNG format. I can easily resize and convert it to PNG, but the file size of the new image is too big.
im = Image.open('input.jpg')
im_resize = im.resize((400, 400), Image.ANTIALIAS) # best down-sizing filter
im.save(`output.png')
What do I have to do to reduce the image file size?
PNG Images still have to hold all data for every single pixel on the image, so there is a limit on how far you can compress them.
One way to further decrease it, since your 400x400 is to be used as a "thumbnail" of sorts, is to use indexed mode:
im_indexed = im_resize.convert("P")
im_resize.save(... )
*wait *
Just saw an error in your example code:
You are saving the original image, not the resized image:
im=Image.open(p1.photo)
im_resize = im.resize((400, 400), Image.ANTIALIAS) # best down-sizing filter
im.save(str(merchant.id)+'_logo.'+'png')
When you should be doing:
im_resize.save(str(merchant.id)+'_logo.'+'png')
You are just saving back the original image, that is why it looks so big. Probably you won't need to use indexed mode them.
Aother thing: Indexed mode images can look pretty poor - a better way out, if you come to need it, might be to have your smalle sizes saved as .jpg instead of .png s - these can get smaller as you need, trading size for quality.
You can use other tools like PNGOUT

Categories

Resources