gcgogo
gcgogo

Reputation: 25

How to read .img format image?

I have a image in .img format. The image size is 1920x1200 px. It's a RGB image with 8 bit depth. I am using the following python code to recover this image. However, the error can display the image but the image content isn't correct. I don't where did I do wrong. Anyone can help?

w, h = 1920, 1200   # img image size in px

# read img files and save them to png
with open(file_add, 'rb') as f:
    # Seek backwards from end of file by 3 bytes per pixel
    f.seek(-w*h*3, 2)
    img = np.fromfile(f, dtype=np.uint8).reshape((h, w, 3))

# Save as PNG, and retain 8-bit resolution
PIL.Image.fromarray(img).save('result.png')

I would like to upload the img file, however, it's larger than the 2Mb limitation.

Upvotes: 2

Views: 2654

Answers (3)

ANsofti
ANsofti

Reputation: 1

You can use if you have in case .img with .hdr nibabel or simpleITK and transformed to numpy array important !! simplITK support maximum 5D.

import nibabel as nib 
data_path="sample/path"
array_data=nib.load(data_path).get_fdata() # you get your matrix 
print(array_data.shape)

exemple with SimpleITK

import SimpleITK as sitk 
data_path="/your/path"
imgObj=sitk.Image(data_path) # you will get and Image object it's a complex data format to handle 
array_data = sitk.GetArrayFromImage(imgObj) # you array matrix

Upvotes: 0

Mark Setchell
Mark Setchell

Reputation: 207345

Your file is in some hideous, Microsoft-designed "Compound File Binary Format" which is described here. I don't run Windows so I cannot unpack it. There are apparently tools available, but I cannot vouch for any of them:

https://openrpmsgfile.com/cfbf.html

http://fileformats.archiveteam.org/wiki/Microsoft_Compound_File

There seems to be a Python module called olefile that can read these things. I installed it and was able to test your file and find your image within it as follows:

#!/usr/bin/env python3

import olefile
import numpy as np
from PIL import Image

# Open file
ole = olefile.OleFileIO('image.img')

# Get a directory listing
ole.dumpdirectory()                                                                        

# Open image stream within file and read
stream = ole.openstream('image/__102/DataObject')
data   = stream.read()

# Define image width, height and bytes per pixel
w, h, bpp = 1920, 1200, 3
imsize    = w * h * bpp

# Check data size and image size
print(f'Data size: {len(data)}, Image size: {imsize}')

# There are 192 bytes difference, assume it is a header and take our bytes from the tail of the file
data = data[-imsize:]

# Make into Numpy array
na = np.frombuffer(data, dtype=np.uint8).reshape((h*3,w))

# Convert from interleaved by line to interleaved by plane
R = na[0::3]
G = na[1::3]
B = na[2::3]
na = np.dstack((R,G,B))

# Make into PIL Image and save, but you could equally use OpenCV or scikit-image here
Image.fromarray(na).save('result.jpg')

enter image description here


Sample Output from running script:

'Root Entry' (root) 192 bytes 
  'NonDataObjects' (stream) 26 bytes 
  'Signature' (stream) 12 bytes 
  'image' (storage) 
    '__102' (storage) 
      'DataObject' (stream) 6912192 bytes 
      'DataObjectChilds' (stream) 4 bytes 
      'DataObjectStub' (stream) 6760 bytes 
Data size: 6912192, Image size: 6912000

I worked out it was a CFBF file from the following. Firstly, if you run the Linux/Unix file command to determine the type of the file, you get this:

file image.img
image.img: Composite Document File V2 Document, Cannot read section info

Secondly, if you dump the file with xxd you will see the CFBF signature bytes referred to in the links above:

xxd image.img
00000000: d0cf 11e0 a1b1 1ae1 0000 0000 0000 0000  ................

Keywords: OLE file, CFBF, Composite Document File V2 Document, IMG format, d0cf11e0a1b1

Upvotes: 1

Andrew Combs
Andrew Combs

Reputation: 26

This post seems to be accomplishing what you're looking for. It reads the data with matplotlib instead, but it should still be able to do what you want.

Upvotes: 0

Related Questions