Henrique Gonçal... · Jan 13, 2021

Reading TIF file using ObjectScript


I'm trying to read a TIF file using ObjectScript. 

I know that it is possible to achieve using python or R, but I don't know how to do it using ObjectScript.

If anyone has done it before and has some advice, I really appreciate it. 

Best Regards,

Product version: 
IRIS 2020.4
1 0 10 92


If it's just pure import / export  the .TIF you may access it as %Stream.FileBinary

But if you need some more sophisticated processing and have some working method (eg. in Python)
you may use it in some near future with the promised embedded Python  [@Bob Kuszewski ]

Until then you may take a look to my example in OEX about using Python methods & classes over CPIPE 


Thanks, Robert

I'll take a look for sure! 


TIF is an image format, what do you mean by reading this kind of files using ObjectScript? What do you want to get from reading it? Something like OCR tools does?

I know that is an image format, but I'm trying to read the TIF file's information to create a script to deal with landslide situations.

with landslide situations.

I don't understand what you mean.

You should understand that ObjectScript is not a good way, to deal with such data as pictures, it's not a task for databases to deal with pictures on a low-level. If you need it on ObjectScript level, I would recommend using imagemagick tool, which is external for sure, and available for any platform. But you will get a lot of functionality. and getting image info as well, and you will not be limited by tiff format only. And in addition you will get the ability to do some other stuff with images, scaling, drawing conversion, and so on, it's very powerful.

After a brief look at the tif format, it found to be quite tricky to get ImageSize.

tif(folder, filename) {
#define READWORD $sconvert(fs.Read(2),"U2",endian)
#define READLONG $sconvert(fs.Read(4),"U4",endian)
#define WORD(%val) $sconvert(%val,"U2",endian)
#define LONG(%val) $sconvert(%val,"U4",endian)

  Set fs = ##class(%Stream.FileBinary).%New()
  Set fs.Filename = ##class(%File).NormalizeFilename(filename, folder)
  Set FileSize = fs.Size
  Set Width = 0, Height = 0

  Set Identifier = fs.Read(2)
  If Identifier=$Char(73,73) {
    Set endian = 0
  } ElseIf Identifier=$Char(77,77) {
    Set endian = 1
  } Else {
    Throw "Bad Format"
  Set Version = fs.Read(2)

  Set IFDOffset = $$$READLONG
  Do {
    Do fs.MoveTo(IFDOffset+1)
    Set NumDirEntries = $$$READWORD
    For i=1:1:NumDirEntries {
      Set tag = fs.Read(12)
      Set TagID = $$$WORD($Extract(tag,1,2))
      Set DataType = $$$WORD($Extract(tag,3,4))
      If (TagID=256)||(TagID=257) {
        Set Value = -1
        If DataType=3 Set Value = $$$WORD($Extract(tag,9,12))
        If DataType=4 Set Value = $$$LONG($Extract(tag,9,12))
        Set:TagID=256 Width = Value
        Set:TagID=257 Height = Value
    Set NextIFDOffset = $$$READLONG
    Set IFDOffset = NextIFDOffset
  } While NextIFDOffset>0

  ZWrite Height,Width

I'm not sure, what you want to do, but if you want to read a tiff file by byte-by-byte and the interpret it in some kind, there is a very simple example for the start.
 The method below returns the file type (gif,jpg,png or tif) based on the magic number.

/// Identify an image by its magic number
/// (only for gif,jpg,png and tif)
ClassMethod ImageType(file, ByRef err)
   o file:"ru":0
   i $t {
      s io=$i, err=""
      u file r x#8
      i x?1"GIF8"1(1"7",1"9")1"a" { s typ="gif" }
      elseif $e(x,1,2)=$c(255,216), $$end()=$c(255,217) { s typ="jpg" }
      elseif x=$c(137,80,78,71,13,10,26,10) { s typ="png" }
      elseif $case($e(x,1,4), $c(73,73,42,0):1, $c(77,77,0,42):1, :0) { s typ="tif" }
      else { s typ="", err="File type unknown" }
      c file
      u:io]"" io
   } else { s typ="", err="Can't open "_file }
   q typ

end() s t="" r:$zseek(-2,2) t#2 q t

I have also a method to retrive the image size (pixelsWidth and pixelsHeight) for the same (gif,jpg,png and tif) files. If you are working on similar problem, I could post this method too.

Ok, here I am... sorry for the delay.


Forget it!

I'm unable to copy and paste a program (in this case a method) into this text box!

After paste operation, some lines are joint, others not,  the indention is lost...

Maybe I'm just too dumb to work with the text box...


If you want this class, you can it download from my FTP.
usr: dcmember
psw: member-of-DC