2
// Copyright (C) 1997 - 2007, Paul C. Gregory
4
// Contact: pgregory@aqsis.org
6
// This library is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU General Public
8
// License as published by the Free Software Foundation; either
9
// version 2 of the License, or (at your option) any later version.
11
// This library is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
// General Public License for more details.
16
// You should have received a copy of the GNU General Public
17
// License along with this library; if not, write to the Free Software
18
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
* \brief Input interface for tiled images.
24
* \author Chris Foster
27
#ifndef ITILEDTEXINPUTFILE_H_INCLUDED
28
#define ITILEDTEXINPUTFILE_H_INCLUDED
30
#include <aqsis/aqsis.h>
32
#include <boost/shared_ptr.hpp>
34
#include <aqsis/util/file.h>
35
#include <aqsis/tex/io/imagefiletype.h>
36
#include <aqsis/tex/io/texfileheader.h>
40
//------------------------------------------------------------------------------
41
/** \brief Image data input interface for tiled image files.
43
* Tiled images are broken up into a set of rectangular subregions called
44
* "tiles" which are all of the same size. Tile coordinates are such that
45
* (0,0) is in the top left of the image, with (1,0) being the tile to the
46
* immediate right of (0,0), etc.
48
* This interface allows tiles to be read from file one at a time, while also
49
* providing convenient access to various data about the tiling.
51
* Tiled images may contain multiple sub-images stored within the single file.
52
* The interface allows random access to tiles from the various sub-images for
53
* convenience. A useful simplifying assumption is that the tiles for all
54
* subimages are assumed to be of the same size when using this interface.
56
* Efficiency of random tile access depends strongly on the exact image type
57
* being used to store the tile data. Some image formats like TIFF don't model
58
* such random access directly, which means switching between subimages may be
59
* costly. If this becomes an issue, an alternative would be to provide a
60
* clone() function to make a copy of the backend, and use separate copies to
61
* access separate subimages.
63
class AQSIS_TEX_SHARE IqTiledTexInputFile
66
virtual ~IqTiledTexInputFile() {};
68
//--------------------------------------------------
69
/// \name Metadata access
72
virtual boostfs::path fileName() const = 0;
74
virtual EqImageFileType fileType() const = 0;
75
/** Get the file header data
77
* For file types which support multiple sets of header data (eg,
78
* TIFF), index specifies the header data set to consider.
80
* \param index - Header data set to return. Child classes should
81
* return the primary set of header data if index is
82
* larger than the maximum header.
84
virtual const CqTexFileHeader& header(TqInt index = 0) const = 0;
85
/** \brief Get tile dimensions as used by readTile().
87
* Note that this may be different from the tile dimensions as reported
88
* in the file metadata header. The header should report correctly on
89
* the structure of the underlying file, while tileInfo() reports the
90
* effective tile size used by the interface. This is to allow file
91
* formats which aren't tiled at all to share the interface for
92
* convenience. (In these cases, the obvious strategy is to consider
93
* the whole image to be a single tile.)
95
virtual SqTileInfo tileInfo() const = 0;
98
//--------------------------------------------------
99
/// \name Access to information about sub-images.
101
/** Get the number of images in the multi-image file.
103
* \return The number of images
105
virtual TqInt numSubImages() const = 0;
106
/// Get the width of image with the given index
107
virtual TqInt width(TqInt index) const = 0;
108
/// Get the height of image with the given index
109
virtual TqInt height(TqInt index) const = 0;
112
//--------------------------------------------------
113
/** \brief Random read access to tile data.
115
* ArrayT is a type modelling a simple resizeable 2D array
116
* interface. It should provide the following methods:
117
* - void resize(TqInt width, TqInt height, const CqChannelList& channels)
118
* Resizes the buffer. (width, height) is the new dimensions for
119
* the buffer. channels describes the new desired channel
120
* structure for the buffer. If the buffer cannot handle the
121
* given channel structure it should throw.
122
* - TqUint8* rawData()
123
* Gets a raw pointer to the data.
125
* Often the dimensions of an image are not a multiple of the tile
126
* size. In this case, tiles on the right hand side and bottom of the
127
* image are resized to exactly fit the image edges.
129
* \param buffer - buffer to read the tile into
130
* \param tileX - horizontal tile coordinate, starting from 0 in the top left.
131
* \param tileY - vertical tile coordinate, starting from 0 in the top left.
132
* \param subImageIdx - subimage index from which to read the tile.
134
template<typename ArrayT>
135
void readTile(ArrayT& buffer, TqInt tileX, TqInt tileY,
136
TqInt subImageIdx) const;
138
/** \brief Open a tiled input file.
140
* Uses magic numbers to determine the file format of the file given by
141
* fileName. If the format is unknown or the file cannot be opened for
142
* some other reason, throw an exception.
144
* \param fileName - file to open. Can be in any of the formats
145
* understood by aqsistex.
146
* \return The newly opened input file
148
static boost::shared_ptr<IqTiledTexInputFile> open(const boostfs::path& fileName);
149
/** \brief Open any image file using the tiled interface.
151
* Sometimes it may be useful to wrap any image up in a tiled
152
* interface. This function returns a tiled image interface wrapping
153
* any image type which can be read using the IqTexInputFile interface.
155
* \note Using such images as tiled images is not guaranteed to be
158
* \param fileName - file to open. Can be in any of the formats
159
* understood by aqsistex.
160
* \return The newly opened input file
162
static boost::shared_ptr<IqTiledTexInputFile> openAny(const boostfs::path& fileName);
165
/** \brief Low-level readTile() function to be overridden by child classes
167
* The implementation of readTile simply validates the input parameters
168
* against the image dimensions as reported by header(), resizes the
169
* buffer, and calls readPixelsImpl() to do the work.
171
* \param buffer - Pointer to raw data buffer of sufficient size for
173
* \param tileX - x-coordinate for tile
174
* \param tileY - y-coordinate for tile
175
* \param subImageIdx - subimage index
176
* \param tileSize - Size of the tile to be read. (May be truncated at
177
* image bottom or right.)
179
virtual void readTileImpl(TqUint8* buffer, TqInt tileX, TqInt tileY,
180
TqInt subImageIdx, const SqTileInfo tileSize) const = 0;
184
template<typename ArrayT>
185
void IqTiledTexInputFile::readTile(ArrayT& buffer, TqInt tileX, TqInt tileY,
186
TqInt subImageIdx) const
188
SqTileInfo tInfo = tileInfo();
189
TqInt w = width(subImageIdx);
190
TqInt h = height(subImageIdx);
191
// Modify the tile size in the case where a tile of the natural size would
192
// tile fall off the image edge.
193
if((tileX + 1)*tInfo.width > w)
194
tInfo.width = w - tileX*tInfo.width;
195
if((tileY + 1)*tInfo.height > h)
196
tInfo.height = h - tileY*tInfo.height;
197
assert(tInfo.width > 0);
198
assert(tInfo.height > 0);
199
assert(subImageIdx >= 0);
200
assert(subImageIdx < numSubImages());
201
buffer.resize(tInfo.width, tInfo.height, header().channelList());
202
readTileImpl(buffer.rawData(), tileX, tileY, subImageIdx, tInfo);
207
#endif // ITILEDTEXINPUTFILE_H_INCLUDED