how to create BMP image from binary data in Python? - python

Suppose I already read binary data from a binary file, how can I create a BMP image from that binary data?

You can find a definition of the bitmap file format on Wikipedia among other places. Use the struct module to create the necessary headers. Because the format is uncompressed it is very easy to write out. The color information must come in BGR order, bottom line to top line, and each line must be padded with zeros to a multiple of 4 bytes.
Or if you'd rather do it the easy way, PIL knows how to read and write BMP.

Related

How to find the original format of images (pages) present in a tiff file using python?

I have a multi-page tiff file (merged.tiff) out of which I need to extract individual images in their original format. PIL allows you to iterate through pages and writing them to disk in a format I need (png/jpg).
Ex:
from PIL import Image
img = Image.open('merged.tiff')
for i in range(img.n_frames):
try:
img.seek(i)
img.save(f'individual_{i}.jpg')
img.save(f'individual_{i}.png')
except EOFError:
break
But is there a way to know the original format of those images?
I have tried with tifffile and tiffany which allow me to convert the pages to a numpy array and then write to disk as an image, but they don't allow me to know the source format of the images contained in the TIFF file.
In the most general case, I believe this is impossible, because it is perfectly feasible to take, say, a JPEG image and include it in the TIFF file as an uncompressed RGB array.
Realistically, though, you should be able to look at some of the tags of the TIFF file, e.g. Compression, to make an educated guess about what the image used to be. Tools like tiffinfo and tiffdump (from the libtiff package) can be used to examine the TIFF file.

simple-itk: reading a sequence from a single tiff file

I've got a tif file which contains a series of images. It is a 3D volume of pixels, produced by a CT-scan.
But after reading the image with simple-itk, there is only a single layer:
reader = sitk.ImageFileReader()
reader.SetFileName("FILENAME.tif")
img = reader.Execute()
img.GetDepth() # 0
arr = sitk.GetArrayFromImage(img)
arr.shape # (512, 512, 4)
How can I configure simple-itk to read the whole sequence of images from the tif file ?
Reading the docs for simple-itk shows how to read sequences of images, from sequences of files. That's not what I need, there is a single tif file for the 3D data.
I am able to read this with the tifffile module, it is able to see the correct number of slices and the plots look good, too. So the data itself seems to be valid.
I'm afraid since this is medical data, it's not possible for me to provide a sample. I'm just interested in the corresponding simple-itk documentation.
Likely the Tiff tags are not fully supported by ITK's ImageIO. Providing a sample data file would be best to determine the structure of the tiff file. Without that some information can be obtained with the command line tool tiffinfo from the libtiff tools to share to reveal the structure of the file.

How to save jpeg data that is identical to the original jpeg file using OpenCV

I'm using OpenCV and Python. I have loaded a jpeg image into a numpy array. Now i want to save it back into jpeg format, but since the image was not modified, I don't want to compress it again. Is it possible to create a jpeg from the numpy array that is identical with the jpeg that it was loaded from?
I know this workflow (decode-encode without doing anything) sounds a bit stupid, but keeping the original jpeg data is not an option. I'm interested if it is possible to recreate the original jpeg just using the data at hand.
The question is different from Reading a .JPG Image and Saving it without file size change, as I don't modify anything in the picture. I really want to restore the original jpeg file based on the data at hand. I assume one could bypass the compression steps (the compression artifacts are already in the data) and just write the file in jpeg format. The question is, if this is possible with OpenCV.
Clarified answer, following comment below:
What you say makes no sense at all; You say that you have the raw, unmodified, RGB data. No you don't. You have the uncompressed data that has been reconstructed from the compressed jpeg file.
The JPEG standards specify how to un-compress an image / video. There is nothing in the standard about how to actually do this compression, so your original image data could have been compressed any one of a zillion different ways. You have no way of knowing the decoding steps that were required to recreate your data, so you cannot reverse them.
Image this.
"I have a number, 44, please tell me how I can get the original
numbers that this came from"
This is, essentially, what you are asking.
The only way you can do what you want (other than just copy the original file) is to read the image into an array before loading into openCV. Then if you want to save it, then just write the raw array to a file, something like this:
fi = 'C:\\Path\\to\\Image.jpg'
fo = 'C:\\Path\\to\\Copy_Image.jpg'
with open(fi,'rb') as myfile:
im_array = np.array(myfile.read())
# Do stuff here
image = cv2.imdecode(im_array)
# Do more stuff here
with open(fo,'wb') as myfile:
myfile.write(im_array)
Of course, it means you will have the data stored twice, effectively, in memory, but this seems to me to be your only option.
Sometimes, no matter how hard you want to do something, you have to accept that it just cannot be done.

digital image read as an array of integers

Using Python's PIL module, we can read an digital image into an array of integers,
from PIL import Image
from numpy import array
img = Image.open('x.jpg')
im = array(img) # im is the array representation of x.jpg
I wonder how does PIL interpret an image as an array? First I tried this
od -tu1 x.jpg
and it indeed gave a sequence of numbers, but how does PIL interpret a color image into a 3D array?
In short, my question is that I want to know how can I get a color image's array representation without using any module like PIL, how could do the job using Python?
Well, it depends on the image format I would say.
For a .jpg, there is a complete description of the format that permits to read the image .
You can read it here
What PIL does is exactly what you did at first. But then it reads the bytes following the specifications, which allow it to transform this into a human readable format (in this case an array).
It may seem complex for JPEG, but if you take png (the version without compression) everything can seem way more simple.
For example this image
If you open it, you will see something like that :
You can see several information on top that corresponds to the header.
Then you see all those zeroes, that are the numerical representation of black pixels of the image (the top left corner).
If you open the image with PIL, you will get an array that is mostly filled with 0.
If you want to know more about the first bytes, look at the png specifications chapter 11.2.2.
You will see that some of the bytes corresponds to the width and height of the image. This is how PIL is able to create the array :).
Hope this helps !
Depends on the color mode. In PIL an image is stored as a list of integers with all channels interleaved on a per-pixel basis.
To illustrate this:
Grayscale image: [pixel1, pixel2, pixel3, ...]
RGB: [pixel1_R, pixel1_G, pixel1_B, pixel2_R, pixel_2_G, ...]
Same goes for RBGA and so on.

Extracting bitmap from a file

given a somewhat complex file of unknown specification that among other things contains an uncompressed bitmap file (.BMP), how would you extract it in Python?
Scan for the "BM" tag and see if the following bytes "resemble" a BMP header?
I'd use the Python Imaging Library PIL and have it a go at the data. If it can parse it, then it's a valid image. When it throws an exception, then it isn't.
You need to search for the begining of the image; if you're lucky, the image reader will ignore garbage after the image data. When it doesn't, use a binary search to locate the end of the image.
Yes, about the only thing you can do is search through the file for the 'BM' marker, pull out the following data into a BITMAPFILEHEADER and corresponding BITMAPINFO, and see if the values in it look valid (i.e. that the dimensions are sensible, colour depth is reasonable, etc).
Once you have found something that looks reasonable, pull that data out and pass it to the library mentioned in another answer.

Categories

Resources