[Image-SIG] 16-bit unsigned short: PIL tile descriptor?

Robert Klimek klimek@grc.nasa.gov
Mon, 24 Feb 2003 15:53:15 +0000


--------------Boundary-00=_RGLT2QNRVQT8EJAQI8OY
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

On Friday February 21 2003 12:37 am, K.Arun wrote:
> Hello,
>
>         I'm trying to write a PIL plug-in for a in-house image
> format. It's a very simple format with a 1024-byte header followed by
> unsigned shorts in big-endian byte order. I tried using both the 'raw'
> and 'bit' decoders without much success - while 'L' works with 'raw',
> in that I don't get any errors, my images look weird when
> processed. Using "F;16B" in the parameters tuple for 'raw' mode (what
> should self.mode be in this case ?), results in a 'ValueError :
> unrecognized mode' exception being thrown. Could someone throw light
> on what self.mode needs to be set to and the correct tile descriptor
> values to use ? Thanks,

Sorry I'm a bit late with this reply but just got back from vacation. A f=
ew=20
months ago I've played around with reading 16-bit and 12-bit TIFF files u=
sing=20
PIL and I've attached a small crude test program. Note that you need wxPy=
thon=20
to run this program but maybe you can get some ideas there. Also, it may =
not=20
work with any 16-bit tif files but is customized for only one particular=20
type.

Bob
--------------Boundary-00=_RGLT2QNRVQT8EJAQI8OY
Content-Type: text/x-python;
  charset="iso-8859-1";
  name="Read12-bitTiffData.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="Read12-bitTiffData.py"

# Program wxReadData

import os
from wxPython.wx import *
import Image

ID_FILE_OPEN = 101
ID_FILE_EXIT  = 103


class mtImagePanel(wxPanel):
    def __init__(self, parent, id):
        wxPanel.__init__(self, parent, id)
        self.image = None
        EVT_PAINT(self, self.OnPaint)

    def display(self, pilimage):
        self.image = self.PILToWX(pilimage)
        self.Refresh(true)
            
    def OnPaint(self, evt):
        dc = wxPaintDC(self)
        if self.image:
            dc.DrawBitmap(self.image.ConvertToBitmap(), 0,0)

    def PILToWX(self, image):
        "convert a PIL image to a wxImage"
        if image.mode != 'RGB': # SetData() requires an RGB image
            image = image.convert('RGB')
        imageData = image.tostring('raw', 'RGB')
        imageWx = wxEmptyImage(image.size[0], image.size[1])
        imageWx.SetData(imageData)
        return imageWx

class mtFrame(wxFrame):
    def __init__(self, parent, ID, title):
        wxFrame.__init__(self, parent, ID, title, wxDefaultPosition, wxSize(500, 400))

        self.iPanel = mtImagePanel(self, -1)
        self.im = None

        # Construct "File" menu
        self.menuBar = wxMenuBar()
        self.menuFile = wxMenu()
        self.menuFile.Append(ID_FILE_OPEN, "&Open image","")
        EVT_MENU(self, ID_FILE_OPEN, self.OnOpen)
        self.menuFile.AppendSeparator()
        self.menuFile.Append(ID_FILE_EXIT, "E&xit", "")
        EVT_MENU(self, ID_FILE_EXIT,  self.OnExit)
        self.menuBar.Append(self.menuFile, "&File");

        # Construct "Process" menu
        self.menuProcess = wxMenu()
        self.menuProcess.Append(1200, "Read 12-bit image", "")
        EVT_MENU(self, 1200,  self.OnRead1)
        self.menuProcess.Append(1201, "Read 16-bit image", "")
        EVT_MENU(self, 1201,  self.OnRead2)
        self.menuProcess.Append(1203, "View tiff tags", "")
        EVT_MENU(self, 1203,  self.OnRead3)

        self.menuBar.Append(self.menuProcess, "&Process")

        self.SetMenuBar(self.menuBar)

    def OnOpen(self, event):
        fileTypes = self.getImageFileFilter('wxOPEN')
        fd = wxFileDialog(self, "Open Image", "", "", fileTypes, wxOPEN)

        if fd.ShowModal() == wxID_OK:
            self.LoadImage(fd.GetPath())
        fd.Destroy()

    def getImageFileFilter(self, type):
        f2 = '|TIFF file (*.tif)|*.tif;*.TIF'
        f3 = '|BMP file (*.bmp)|*.bmp;*.BMP'
        f4 = '|JPG file (*.jpg)|*.jpg;*.JPG'
        f5 = '|PNG file (*.png)|*.png;*.PNG'
        f6 = '|GIF file (*.gif)|*.gif;*.GIF'
        if type == 'wxOPEN':
            # OPEN can read tga,  but not save
            label = 'All supported image files|'
            ext = '*.tif;*.TIF;*.jpg;*.JPG;*.bmp;*.BMP;*.png;*.PNG;*.gif;*.GIF;*.tga;*.TGA'
            f1 = label + ext
            f7 = '|TGA file (*.tga)|*.tga;*.TGA'
            fileTypes = f1 + f2 + f3 + f4 + f5 + f6 + f7
        else:
            label = 'All supported image files|'
            ext = '*.tif;*.TIF;*.jpg;*.JPG;*.bmp;*.BMP;*.png;*.PNG;*.gif;*.GIF'
            f1 = label + ext
            fileTypes = f1 + f2 + f3 + f4 + f5 + f6
        return fileTypes

    def LoadImage(self, path):
        try:
            self.im = Image.open(path)
            self.iPanel.display(self.im)
        except IOError:
            print "can't open the file"

    def OnRead1(self, event):
        '''Read a 12 bit image - no padding '''
        imgDir = '/home/klimek/Images/16-bit'
        inFile = os.path.abspath(os.path.join(imgDir, '12-bit-IMAP.tif'))
        f = open(inFile, 'rb')
        allData = f.read()
        f.close()
        offset = 8 # this was determined from "StripOffsets" tag by reading an 8-bit IMAP image
        data = allData[offset : 1024*1024*12/8+offset] # 12-bit saved by IMAP

        bits = 12 # number of bits per pixel
        pad = 0  # 0=no padding, 8=lines are padded to full bytes
        fill = 0
        sign = 0 # 0=bit fields are unsigned, non-zero= bit fields are sign extended
        orientation = 1  # 1=1st line is on top of image, -1=1st line on bottom
        im = Image.fromstring("F", (1024,1024), data, "bit", bits, pad, fill, sign, orientation)
        pix1 = im.getpixel((50,50))
        pix2 = im.getpixel((500,300))
        print pix1, pix2

    def OnRead2(self, event):
        '''Read a 16 bit image - originally 12-bit padded to 16 bit '''
        imgDir = '/home/klimek/Images/16-bit'
        inFile = os.path.abspath(os.path.join(imgDir, '16-bit-IMAP.tif'))
        f = open(inFile, 'rb')
        allData = f.read()
        f.close()
        offset = 8 # this was determined from "StripOffsets" tag by reading an 8-bit IMAP image
        data = allData[offset : 1024*1024*16/8+offset] # 16-bit saved by IMAP

        im = Image.fromstring("F", (1024,1024), data, "raw", "F;16", 0,1)

        pix1 = im.getpixel((50,50))
        pix2 = im.getpixel((500,300))
        print pix1, pix2

    def getTag(self, im, n):
        t = -1
        if im.tag.tags.has_key(n):
            t = im.tag.tags[n]
        return t

    def OnRead3(self, event):
        '''Read tiff tags from on already opened (loaded) image. Must be read before
        any other operations are done on the image, otherwise the tag info is lost.'''
        imgDir = '/home/klimek/Images/16-bit'
        inFile = os.path.abspath(os.path.join(imgDir, '8-bit-IMAP.tif'))  # saved by IMAP
        im = Image.open(inFile)
        ## inFile = os.path.abspath(os.path.join(imgDir, '8-bit-PIL.tif')) # saved by PIL
        ## im = Image.open(inFile)
        w = self.getTag(im, 256) #ImageWidth
        h = self.getTag(im, 257) #ImageLength
        so = self.getTag(im, 273) #StripOffsets
        print w, h, so

    def OnCloseWindow(self, event):
        self.Destroy()

    def OnExit(self, event):
        self.Close(true)

#---------------------------------------------------------------------------

class mtApp(wxApp):
    def OnInit(self):
        frame = mtFrame(NULL, -1, "ReadTiffData") # can set frame title here
        frame.Show(true)
        self.SetTopWindow(frame)
        return true

app = mtApp(0)
app.MainLoop() 

--------------Boundary-00=_RGLT2QNRVQT8EJAQI8OY--