Perform Block Processing on Image Files in Unsupported Formats
In addition to reading TIFF or JPEG2000 files and writing TIFF files, the blockproc
function can read and write other formats. To work with image data
in another file format, you must construct a class that inherits from the ImageAdapter
class. The ImageAdapter
class is an abstract class that is part of the
Image Processing Toolbox™ software. It defines the signature for methods that
blockproc
uses for file I/O with images on disk. You can associate
instances of an Image Adapter class with a file and use them as arguments to
blockproc
for file-based block processing.
This section demonstrates the process of writing an Image Adapter class by discussing an
example class (the LanAdapter
class). The LanAdapter
class is part of the toolbox. Use this simple, read-only class to process arbitrarily large
uint8
LAN files with blockproc
.
Learning More About the LAN File Format
To understand how the LanAdapter
class works, you must first know
about the LAN file format. Landsat thematic mapper imagery is stored in the Erdas LAN
file format. Erdas LAN files contain a 128-byte header followed by one or more spectral
bands of data, band-interleaved-by-line (BIL), in order of increasing band number. The
data is stored in little-endian byte order. The header contains several pieces of
important information about the file, including size, data type, and number of bands of
imagery contained in the file. The LAN file format specification defines the first 24
bytes of the file header as shown in the table.
File Header Content
Bytes | Data Type | Content |
---|---|---|
1–6 | 6 byte array of characters that identify the version of the file format | 'HEADER' or 'HEAD74' (Pre-7.4
files say 'HEADER' .) |
7–8 | 16-bit integer | Pack type of the file (indicating bit depth) |
9–10 | 16-bit integer | Number of bands of data |
11–16 | 6 bytes | Unused |
17–20 | 32-bit integer | Number of columns of data |
21–24 | 32-bit integer | Number of rows of data |
The remaining 104 bytes contain various other properties of the file, which this example does not use.
Parsing the Header
Typically, when working with LAN files, the first step is to learn more about the
file by parsing the header. The following code shows how to parse the header of the
rio.lan
file:
Open the file:
file_name = 'rio.lan'; fid = fopen(file_name,'r');
Read the first six bytes of the header:
headword = fread(fid,6,'uint8=>char')'; fprintf('Version ID: %s\n',headword);
Read the pack type:
pack_type = fread(fid,1,'uint16',0,'ieee-le'); fprintf('Pack Type: %d\n',pack_type);
Read the number of spectral bands:
num_bands = fread(fid,1,'uint16',0,'ieee-le'); fprintf('Number of Bands: %d\n',num_bands);
Read the image width and height:
unused_bytes = fread(fid,6,'uint8',0,'ieee-le'); width = fread(fid,1,'uint32',0,'ieee-le'); height = fread(fid,1,'uint32',0,'ieee-le'); fprintf('Image Size (w x h): %d x %d\n',width,height);
Close the file:
fclose(fid);
The output appears as follows:
Version ID: HEAD74 Pack Type: 0 Number of Bands: 7 Image Size (w x h): 512 x 512
The rio.lan
file is a 512-by-512, 7-band image. The pack type of 0
indicates that each sample is an 8-bit, unsigned integer (uint8
data
type).
Reading the File
In a typical, in-memory workflow, you would read this LAN file using the multibandread
function. The LAN format stores the RGB data from the
visible spectrum in bands 3, 2, and 1, respectively. You could create a truecolor image
for further processing.
truecolor = multibandread('rio.lan', [512, 512, 7],... 'uint8=>uint8', 128,'bil', 'ieee-le', {'Band','Direct',[3 2 1]});
For very large LAN files, however, reading and processing the entire image in memory
using multibandread
can be impractical, depending on your system
capabilities. To avoid memory limitations, use the blockproc
function. With blockproc
, you can process images with a file-based
workflow. You can read, process, and then write the results, one block at a time.
The blockproc
function only supports reading and writing certain
file formats, but it is extensible via the ImageAdapter
class. To
write an Image Adapter class for a particular file format, you must be able to:
Query the size of the file on disk
Read a rectangular block of data from the file
If you meet these two conditions, you can write an Image Adapter class for LAN files.
You can parse the image header to query the file size, and you can modify the call to
multibandread
to read a particular block of data. You can
encapsulate the code for these two objectives in an Image Adapter class structure, and
then operate directly on large LAN files with the blockproc
function.
The LanAdapter
class is an Image Adapter class for LAN files, and is
part of the Image Processing Toolbox software.
Examining the LanAdapter Class
This section describes the constructor, properties, and methods of the
LanAdapter
class. Studying the LanAdapter
class
helps prepare you for writing your own Image Adapter class. If you are new to
object-oriented programming, see Developing Classes—Typical Workflow for general information on writing
classes.
Open LanAdapter.m
and look at the implementation of the
LanAdapter
class.
Classdef
The LanAdapter
class begins with the keyword
classdef
. The classdef
section defines the
class name and indicates that LanAdapter
inherits from the
ImageAdapter
superclass. Inheriting from
ImageAdapter
allows the new class to:
Interact with
blockproc
Define common
ImageAdapter
propertiesDefine the interface that
blockproc
uses to read and write to LAN files
Properties
Following the classdef
section, the
LanAdapter
class contains two blocks of class properties. The
first block contains properties that are publicly visible, but not publicly
modifiable. The second block contains fully public properties. The
LanAdapter
class stores some information from the file header
as class properties. Other classes that also inherit from
ImageAdapter
, but that support different file formats, can have
different properties.
classdef LanAdapter < ImageAdapter properties(GetAccess = public, SetAccess = private) Filename NumBands end properties(Access = public) SelectedBands end
In addition to the properties defined in LanAdapter.m
, the
class inherits the ImageSize
property from the
ImageAdapter
superclass. The new class sets the
ImageSize
property in the constructor.
Methods: Class Constructor
The class constructor initializes the LanAdapter
object. The
LanAdapter
constructor parses the LAN file header information
and sets the class properties. Implement the constructor, a class method, inside a
methods
block.
The constructor contains much of the same code used to parse the LAN file header.
The LanAdapter
class only supports uint8
data
type files, so the constructor validates the pack type of the LAN file, as well as
the headword. The class properties store the remaining information. The method
responsible for reading pixel data uses these properties. The
SelectedBands
property allows you to read a subset of the
bands, with the default set to read all bands.
methods function obj = LanAdapter(fname) % LanAdapter constructor for LanAdapter class. % When creating a new LanAdapter object, read the file % header to validate the file as well as save some image % properties for later use. % Open the file. obj.Filename = fname; fid = fopen(fname,'r'); % Verify that the file begins with the headword 'HEADER' or % 'HEAD74', as per the Erdas LAN file specification. headword = fread(fid,6,'uint8=>char'); if ~(strcmp(headword','HEADER') || strcmp(headword',... 'HEAD74')) error('Invalid LAN file header.'); end % Read the data type from the header. pack_type = fread(fid,1,'uint16',0,'ieee-le'); if ~isequal(pack_type,0) error(['Unsupported pack type. The LanAdapter example ' ... 'only supports reading uint8 data.']); end % Provide band information. obj.NumBands = fread(fid,1,'uint16',0,'ieee-le'); % By default, return all bands of data obj.SelectedBands = 1:obj.NumBands; % Specify image width and height. unused_field = fread(fid,6,'uint8',0,'ieee-le'); width = fread(fid,1,'uint32',0,'ieee-le'); height = fread(fid,1,'uint32',0,'ieee-le'); obj.ImageSize = [height width]; % Close the file handle fclose(fid); end % LanAdapter
Methods: Required
Adapter classes have two required methods defined in the abstract superclass,
ImageAdapter
. All Image Adapter classes must implement these
methods. The blockproc
function uses the first method, readRegion
, to read blocks of data from files on disk. The second
method, close
, performs any necessary cleanup
of the Image Adapter object.
function data = readRegion(obj, region_start, region_size) % readRegion reads a rectangular block of data from the file. % Prepare various arguments to MULTIBANDREAD. header_size = 128; rows = region_start(1):(region_start(1) + region_size(1) - 1); cols = region_start(2):(region_start(2) + region_size(2) - 1); % Call MULTIBANDREAD to get data. full_size = [obj.ImageSize obj.NumBands]; data = multibandread(obj.Filename, full_size,... 'uint8=>uint8', header_size, 'bil', 'ieee-le',... {'Row', 'Direct', rows},... {'Column','Direct', cols},... {'Band', 'Direct', obj.SelectedBands}); end % readRegion
readRegion
has two input arguments,
region_start
and region_size
. The
region_start
argument, a two-element vector in the form
[row col]
, defines the first pixel in the request block of
data. The region_size
argument, a two-element vector in the form
[num_rows num_cols]
, defines the size of the requested block of
data. The readRegion
method uses these input arguments to read and
return the requested block of data from the image.
The readRegion
method is implemented differently for different
file formats, depending on what tools are available for reading the specific files.
The readRegion
method for the LanAdapter
class
uses the input arguments to prepare custom input for
multibandread
. For LAN files, multibandread
provides a convenient way to read specific subsections of an image.
The other required method is close
. The close
method of the
LanAdapter
class appears as follows:
function close(obj) % Close the LanAdapter object. This method is a part % of the ImageAdapter interface and is required. % Since the readRegion method is "atomic", there are % no open file handles to close, so this method is empty. end end % public methods end % LanAdapter
As the comments indicate, the close
method for
LanAdapter
has nothing to do, so close
is
empty. The multibandread
function does not require maintenance of
open file handles, so the close
method has no handles to clean up.
Image Adapter classes for other file formats may have more substantial
close
methods including closing file handles and performing
other class clean-up responsibilities.
Methods (Optional)
As written, the LanAdapter
class can only read LAN files, not
write them. If you want to write output to a LAN format file, or another file with a
format that blockproc
does not support, implement the optional
writeRegion
method. Then, you can
specify your class as a 'Destination'
parameter in
blockproc
and write output to a file of your chosen
format.
The signature of the writeRegion
method is as follows:
function [] = writeRegion(obj, region_start, region_data)
The first argument, region_start
, indicates the first pixel of
the block that the writeRegion
method writes. The second argument,
region_data
, contains the new data that the method writes to
the file.
Classes that implement the writeRegion
method can be more
complex than LanAdapter
. When creating a writable Image Adapter
object, classes often have the additional responsibility of creating new files in the
class constructor. This file creation requires a more complex syntax in the
constructor, where you potentially need to specify the size and data type of a new
file you want to create. Constructors that create new files can also encounter other
issues, such as operating system file permissions or potentially difficult
file-creation code.
Using the LanAdapter Class with blockproc
Now that you understand how the LanAdapter
class works, you can
use it to enhance the visible bands of a LAN file. See the Compute Statistics for Large Images example to see how the
blockproc
function works with the LanAdapter
class.
See Also
blockproc
| ImageAdapter
| multibandread