X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?p=CreaPhase.git;a=blobdiff_plain;f=octave_packages%2Fimage-1.0.15%2Ftiff_tag_read.m;fp=octave_packages%2Fimage-1.0.15%2Ftiff_tag_read.m;h=6a4eef32005dc94217398208fbab5fee46f321af;hp=0000000000000000000000000000000000000000;hb=f5f7a74bd8a4900f0b797da6783be80e11a68d86;hpb=1705066eceaaea976f010f669ce8e972f3734b05 diff --git a/octave_packages/image-1.0.15/tiff_tag_read.m b/octave_packages/image-1.0.15/tiff_tag_read.m new file mode 100644 index 0000000..6a4eef3 --- /dev/null +++ b/octave_packages/image-1.0.15/tiff_tag_read.m @@ -0,0 +1,196 @@ +## Copyright (C) 2010 Carnë Draug +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; If not, see . +## +## Based on the documentation at +## * http://en.wikipedia.org/wiki/Tagged_Image_File_Format +## * http://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf +## * http://ibb.gsf.de/homepage/karsten.rodenacker/IDL/Lsmfile.doc +## * http://www.awaresystems.be/imaging/tiff/faq.html +## +## and the function tiff_read by F. Nedelec, EMBL (www.cytosim.org) +## * http://www.cytosim.org/misc/index.html + +## -*- texinfo -*- +## @deftypefn {Function File} [@var{value}, @var{offset}] = tiff_tag_read (@var{file}, @var{tag}, @var{ifd}) +## Reads the values of TIFF file tags. +## +## @var{file} is a TIFF file and @var{tag} is the tag number to read. If +## @var{ifd} is given, only the tag value from that IFD (Image File Directory) +## will be read. By default, reads only the first IFD. +## +## @var{value} is the read value from @var{tag}. @var{offset} will be @code{1} +## if @var{value} is a file offset. +## +## @seealso{imread, imfinfo, readexif} +## @end deftypefn + +## * On the TIFF image file header: +## bytes 00-01 --> byte order used within the file: "II" for little endian +## and "MM" for big endian byte ordering. +## bytes 02-03 --> number 42 that identifies the file as TIFF +## bytes 04-07 --> file offset (in bytes) of the first IFD (Image File Directory) +## +## Note: offset is always from the start of the file ("bof" in fread) and first +## byte has an offset of zero. +## +## * On a TIFF's IFD structure: +## bytes 00-01 --> number of entries (or tags or fields or directories) +## bytes 02-13 --> the entry (the tag is repeated the number of times +## specified at the start of the IFD, but always takes +## 12 bytes of size) +## bytes XX-XX --> file offset for next IFD (last 4 bytes of the IFD) +## +## Note: there must be always one IFD and each IFD must have at least one entry +## +## * On an IFD entry (or TIFF's field) structure: +## bytes 00-01 --> tag that identifies the entry +## bytes 02-03 --> entry type +## 1 --> BYTE (uint8) +## 2 --> ASCII +## 3 --> SHORT (uint16) +## 4 --> LONG (uint32) +## 5 --> RATIONAL (two LONGS) +## 6 --> SBYTE (int8) +## 7 --> UNDEFINED (8 bit) +## 8 --> SSHORT (int16) +## 9 --> SLONG (int32) +## 10 --> FLOAT (single IEEE precision) +## 11 --> DOUBLE (double IEEE precision) +## bytes 04-07 --> number of values (count) +## bytes 08-11 --> file offset to the value or value (only if it fits in 4 bytes) +## +## Note: file offset of the value may point anywhere in the file, even after the image. + +function [value, offset] = tiff_tag_read (file, tag, ifd) + + [FID, msg] = fopen (file, "r", "native"); + if (msg != 0) + error ("Unable to fopen '%s': %s.", file, msg); + endif + + # Read byte order + byte_order = fread(FID, 2, "char=>char"); + if ( strcmp(byte_order', "II") ) + arch = "ieee-le"; # IEEE little endian format + elseif ( strcmp(byte_order',"MM") ) + arch = "ieee-be"; # IEEE big endian format + else + error("First 2 bytes of header returned '%s'. TIFF file expects either 'II' or 'MM'.", byte_order'); + endif + + # Read number 42 + nTIFF = fread(FID, 1, "uint16", arch); + if (nTIFF != 42) + error("This is not a TIFF file (missing 42 on header at offset 2. Instead got '%g').", tiff_id); + endif + + # Read offset and move for the first IFD + offset_IFD = fread(FID, 1, "uint32", arch); + status = fseek(FID, offset_IFD, "bof"); + if (status != 0) + error("Error on fseek when moving to first IFD."); + endif + + # Read number of entries (nTag) and look for the desired tag ID + nTag = fread(FID, 1, "uint16", arch); + iTag = 0; # Tag index + while (1) # Control is made inside the loop + iTag++; + cTag = fread(FID, 1, "uint16", arch); # Tag ID + if (cTag == tag) # Tag ID was found + value = read_value (FID, arch, tag); # Read tag value + break + elseif (iTag == nTag || cTag > tag) # All tags have been read (tags are in ascendent order) + error ("Unable to find tag %g.", tag) + endif + status = fseek(FID, 10, "cof"); # Move to the next tag + if (status != 0) + error("Error on fseek when moving to tag %g of %g. Last tag read had value of %g", rTag, nTag, tag); + endif + endwhile + + fclose (FID); + +endfunction + +##### +function [value, offset] = read_value (FID, arch, tag) + + tiff_type = fread(FID, 1, "uint16", arch); + count = fread(FID, 1, "uint32", arch); + + switch (tiff_type) + case 1 # BYTE = 8-bit unsigned integer + nBytes = 1; + precision = "uint8"; + case 2 # ASCII = 8-bit byte that contains a 7-bit ASCII code; the last byte must be NUL (binary zero) + nBytes = 1; + precision = "uchar"; + case 3 # SHORT = 16-bit (2-byte) unsigned integer + nBytes = 2; + precision = "uint16"; + case 4 # LONG = 32-bit (4-byte) unsigned integer + nBytes = 4; + precision = "uint32"; + case 5 # RATIONAL = Two LONGs: the first represents the numerator of a fraction; the second, the denominator + nBytes = 8; + precision = "uint32"; + case 6 # SBYTE = An 8-bit signed (twos-complement) integer + nBytes = 1; + precision = "int8"; + case 7 # UNDEFINED = An 8-bit byte that may contain anything, depending on the definition of the field + nBytes = 1; + precision = "uchar"; + case 8 # SSHORT = A 16-bit (2-byte) signed (twos-complement) integer + nBytes = 2; + precision = "int16"; + case 9 # SLONG = A 32-bit (4-byte) signed (twos-complement) integer + nBytes = 4; + precision = "int32"; + case 10 # SRATIONAL = Two SLONG’s: the first represents the numerator of a fraction, the second the denominator + nBytes = 8; + precision = "int32"; + case 11 # FLOAT = Single precision (4-byte) IEEE format + nBytes = 4; + precision = "float32"; + case 12 # DOUBLE = Double precision (8-byte) IEEE format + nBytes = 8; + precision = "float64"; + otherwise # Warning (from TIFF file specifications): It is possible that other TIFF field types will be added in the future + error("TIFF type %i not supported", tiff_type) + endswitch + + if ( (nBytes*count) > 4 ) # If it doesn't fit in 4 bytes, it's an offset + offset = 1; + value = fread(FID, 1, "uint32", arch); + ## The file offset must be an even number + if ( rem(value,2) != 0 ) + error("Couldn't find correct value offset for tag %g", tag); + endif + else + offset = 0; + ## read here + switch precision + case { 5, 10 } + value = fread(FID, 2*count, precision, arch); + otherwise + value = fread(FID, count, precision, arch); + endswitch + if (precision == 2) + value = char(value'); + endif + endif + +endfunction