Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
ioTIFF.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #include "ioTIFF.hpp"
35 #include <vlCore/FileSystem.hpp>
36 #include <vlCore/VirtualFile.hpp>
37 #include <vlCore/Image.hpp>
38 #include "tiffio.h"
39 
40 // mic fixme: read and write 16 bits images.
41 
42 using namespace vl;
43 
44 namespace
45 {
46  void tiff_error(const char*, const char*, va_list)
47  {
48  vl::Log::error("ioTIFF unspecified error.\n");
49  }
50  void tiff_warning(const char *, const char *, va_list)
51  {
52  }
53  tsize_t tiff_io_read_func(thandle_t fd, tdata_t buf, tsize_t size)
54  {
55  VirtualFile *fin = (VirtualFile*)fd;
56  long long c = fin->read(buf,size);
57  return (tsize_t)c;
58  }
59  tsize_t tiff_io_write_func(thandle_t fd, tdata_t buf, tsize_t size)
60  {
61  VirtualFile *fin = (VirtualFile*)fd;
62  long long c = fin->write(buf,size);
63  return (tsize_t)c;
64  }
65  toff_t tiff_io_seek_func(thandle_t fd, toff_t off, int i)
66  {
67  VirtualFile*fin = (VirtualFile*)fd;
68 
69  switch(i)
70  {
71  case SEEK_SET:
72  fin->seekSet(off);
73  return (tsize_t)fin->position();
74 
75  case SEEK_CUR:
76  fin->seekCur(off);
77  return (tsize_t)fin->position();
78 
79  case SEEK_END:
80  fin->seekEnd(off);
81  return (tsize_t)fin->position();
82 
83  default:
84  return 0;
85  }
86  }
87  int tiff_io_close_func(thandle_t fd)
88  {
89  VirtualFile*fin = (VirtualFile*)fd;
90  fin->close();
91  return 0;
92  }
93  toff_t tiff_io_size_func(thandle_t fd)
94  {
95  VirtualFile *fin = (VirtualFile*)fd;
96  return (tsize_t)fin->size();
97  }
98  int tiff_io_map_func(thandle_t, tdata_t*, toff_t*)
99  {
100  return 0;
101  }
102  void tiff_io_unmap_func(thandle_t, tdata_t, toff_t)
103  {
104  return;
105  }
106 }
107 
108 //-----------------------------------------------------------------------------
110 {
111  ref<VirtualFile> file = defFileSystem()->locateFile(path);
112  if ( !file )
113  {
114  Log::error( Say("File '%s' not found.\n") << path );
115  return NULL;
116  }
117  else
118  return loadTIFF(file.get());
119 }
120 //-----------------------------------------------------------------------------
122 {
123  file->open(OM_ReadOnly);
124  ref<Image> img = new Image;
125 
126  TIFFSetErrorHandler(tiff_error);
127  TIFFSetWarningHandler(tiff_warning);
128 
129  TIFF* tif = TIFFClientOpen("tiffread", "r", reinterpret_cast<thandle_t>(file),
130  tiff_io_read_func,
131  tiff_io_write_func,
132  tiff_io_seek_func,
133  tiff_io_close_func,
134  tiff_io_size_func,
135  tiff_io_map_func,
136  tiff_io_unmap_func);
137 
138  if (tif)
139  {
140  uint32 w, h;
141  size_t npixels;
142  uint32* raster;
143 
144  TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w);
145  TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h);
146  npixels = w * h;
147  raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
148  if (raster != NULL)
149  {
150  if (TIFFReadRGBAImage(tif, w, h, raster, 0))
151  {
153  memcpy(img->pixels(), raster, img->requiredMemory());
154  }
155  _TIFFfree(raster);
156  }
157  uint16 orientation = ORIENTATION_TOPLEFT; // default
158  TIFFGetField(tif, TIFFTAG_ORIENTATION, &orientation);
159  if (orientation == ORIENTATION_LEFTBOT )
160  img->flipVertically();
161  TIFFClose(tif);
162  }
163 
164  file->close();
165  return img;
166 }
167 //-----------------------------------------------------------------------------
169 {
170  if (!file->open(OM_ReadOnly))
171  return false;
172 
173  unsigned char byteorder[2];
174  file->read(byteorder, 2);
175  bool little_endian = byteorder[0] == 'I'; // 'I' == LE, 'M' == BE
176  unsigned short version = file->readUInt16(little_endian);
177  file->close();
178 
179  if (byteorder[0] != byteorder[1])
180  return false;
181 
182  if (byteorder[0] != 'M' && byteorder[0] != 'I')
183  return false;
184 
185  if (byteorder[1] != 'M' && byteorder[1] != 'I')
186  return false;
187 
188  if (version != 42)
189  return false;
190 
191  return true;
192 }
193 //-----------------------------------------------------------------------------
194 bool vl::saveTIFF(const Image* image, const String& path)
195 {
196  ref<DiskFile> file = new DiskFile(path);
197  return saveTIFF(image, file.get());
198 }
199 //-----------------------------------------------------------------------------
200 bool vl::saveTIFF(const Image* src, VirtualFile* fout)
201 {
202  // mic fixme: handle somehow not supported image type, cubemaps, 3d textures, mimaps etc.
203 
204  int w = src->width();
205  int h = src->height();
206  int d = src->depth();
207  if (h == 0) h=1;
208  if (d == 0) d=1;
209  if (src->isCubemap()) d=6;
210  h = h*d;
211 
212  // convert src to IT_UNSIGNED_BYTE / IF_RGBA
213  ref<Image> cimg;
214  if (src->type() != IT_UNSIGNED_BYTE)
215  {
216  cimg = src->convertType(IT_UNSIGNED_BYTE);
217  src = cimg.get();
218  if (!cimg)
219  {
220  Log::error( Say("saveTIFF('%s'): could not convert src to IT_UNSIGNED_BYTE.\n") << fout->path() );
221  return false;
222  }
223  }
224  if (src->format() != IF_RGBA)
225  {
226  cimg = src->convertFormat(IF_RGBA);
227  src = cimg.get();
228  if (!cimg)
229  {
230  Log::error( Say("saveTIFF('%s'): could not convert src to IF_RGBA.\n") << fout->path() );
231  return false;
232  }
233  }
234 
235  const int SHORT = 3;
236  const int LONG = 4;
237  const int RATIONAL = 5;
238 
239  if (!fout->open(OM_WriteOnly))
240  {
241  Log::error( Say("TIFF: could not open '%s' for writing.\n") << fout->path() );
242  return false;
243  }
244 
245  // little endian
246  unsigned char little_endian[] = { 'I', 'I' };
247  fout->write(little_endian, 2);
248 
249  unsigned short version = 42;
250  fout->writeUInt16(version);
251 
252  unsigned long ifd_offset = 8;
253  fout->writeUInt32(ifd_offset);
254 
255  unsigned short dir_count = 14;
256  fout->writeUInt16(dir_count);
257 
258  unsigned short tag, type;
259  unsigned long count;
260 
261  // WIDTH
262 
263  tag = 256; fout->writeUInt16(tag);
264  type = SHORT; fout->writeUInt16(type);
265  count = 1; fout->writeUInt32(count);
266  fout->writeUInt16((unsigned short)w); fout->writeUInt16(0);
267 
268  // HEIGHT
269 
270  tag = 257; fout->writeUInt16(tag);
271  type = SHORT; fout->writeUInt16(type);
272  count = 1; fout->writeUInt32(count);
273  fout->writeUInt16((unsigned short)h); fout->writeUInt16(0);
274 
275  // BITS PER SAMPLE
276 
277  tag = 258; fout->writeUInt16(tag);
278  type = SHORT; fout->writeUInt16(type);
279  count = 4; fout->writeUInt32(count);
280  fout->writeUInt32(10 + dir_count*12 + 4 + 16);
281 
282  // COMPRESSION
283 
284  tag = 259; fout->writeUInt16(tag);
285  type = SHORT; fout->writeUInt16(type);
286  count = 1; fout->writeUInt32(count);
287  fout->writeUInt16(1); fout->writeUInt16(0);
288 
289  // PHOTOMETRIC INTERPRETATION
290 
291  tag = 262; fout->writeUInt16(tag);
292  type = SHORT; fout->writeUInt16(type);
293  count = 1; fout->writeUInt32(count);
294  fout->writeUInt16(2); fout->writeUInt16(0);
295 
296  // STRIP OFFSET
297 
298  tag = 273; fout->writeUInt16(tag);
299  type = LONG; fout->writeUInt16(type);
300  count = 1; fout->writeUInt32(count);
301  fout->writeUInt32(10 + dir_count*12 + 4 + 16 + 8);
302 
303  // SAMPLES PER PIXEL
304 
305  tag = 277; fout->writeUInt16(tag);
306  type = SHORT; fout->writeUInt16(type);
307  count = 1; fout->writeUInt32(count);
308  fout->writeUInt16(4); fout->writeUInt16(0);
309 
310  // ROWS PER STRIP
311 
312  tag = 278; fout->writeUInt16(tag);
313  type = SHORT; fout->writeUInt16(type);
314  count = 1; fout->writeUInt32(count);
315  fout->writeUInt16((unsigned short)h); fout->writeUInt16(0);
316 
317  // STRIP BYTE COUNT
318 
319  tag = 279; fout->writeUInt16(tag);
320  type = LONG; fout->writeUInt16(type);
321  count = 1; fout->writeUInt32(count);
322  fout->writeUInt32(src->requiredMemory());
323 
324  // X RESOLUTION
325 
326  tag = 282; fout->writeUInt16(tag);
327  type = RATIONAL; fout->writeUInt16(type);
328  count = 1; fout->writeUInt32(count);
329  fout->writeUInt32(10 + dir_count*12 + 4 + 0);
330 
331  // Y RESOLUTION
332 
333  tag = 283; fout->writeUInt16(tag);
334  type = RATIONAL; fout->writeUInt16(type);
335  count = 1; fout->writeUInt32(count);
336  fout->writeUInt32(10 + dir_count*12 + 4 + 8);
337 
338  // PLANAR CONFIGURATION
339 
340  tag = 284; fout->writeUInt16(tag);
341  type = SHORT; fout->writeUInt16(type);
342  count = 1; fout->writeUInt32(count);
343  fout->writeUInt16(1); fout->writeUInt16(0);
344 
345  // RESOLUTION UNIT
346 
347  tag = 296; fout->writeUInt16(tag);
348  type = SHORT; fout->writeUInt16(type);
349  count = 1; fout->writeUInt32(count);
350  fout->writeUInt16(2); fout->writeUInt16(0);
351 
352  // EXTRA SAMPLES
353 
354  tag = 338; fout->writeUInt16(tag);
355  type = SHORT; fout->writeUInt16(type);
356  count = 1; fout->writeUInt32(count);
357  fout->writeUInt16(0); fout->writeUInt16(0);
358 
359  // next ifd offset
360  fout->writeUInt32(0);
361 
362  // rational1
363  fout->writeUInt32(72);
364  fout->writeUInt32(1);
365  // rational2
366  fout->writeUInt32(72);
367  fout->writeUInt32(1);
368 
369  // bits per sample
370  fout->writeUInt16(8);
371  fout->writeUInt16(8);
372  fout->writeUInt16(8);
373  fout->writeUInt16(8);
374 
375  // save the lines in reverse order
376  int y = h;
377  while( y-- )
378  fout->write(src->pixels()+src->pitch()*y, w*src->bitsPerPixel()/8);
379 
380  fout->close();
381  return true;
382 }
383 //-----------------------------------------------------------------------------
long long read(void *buffer, long long byte_count)
Reads byte_count bytes from a file. Returns the number of bytes actually read.
Definition: VirtualFile.cpp:82
VLCORE_EXPORT FileSystem * defFileSystem()
Returns the default FileSystem used by VisualizationLibrary.
Definition: pimpl.cpp:97
int depth() const
Definition: Image.hpp:211
const T * get() const
Definition: Object.hpp:128
An abstract class representing a file.
Definition: VirtualFile.hpp:60
long long writeUInt16(unsigned short data, bool little_endian_data=true)
Writes a single entry. Returns the number of bytes written.
A simple String formatting class.
Definition: Say.hpp:124
const unsigned char * pixels() const
Raw pointer to pixels.
Definition: Image.hpp:170
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
ref< Image > convertType(EImageType new_type) const
Converts the type() of an image.
Definition: Image.cpp:1303
bool seekCur(long long offset)
Changes the current read/write position of a file.
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
virtual ref< VirtualFile > locateFile(const String &full_path, const String &alternate_path=String()) const
Looks for a VirtualFile on the disk and in the currently active FileSystem.
Definition: FileSystem.cpp:61
VLCORE_EXPORT bool saveTIFF(const Image *src, const String &path)
Definition: ioTIFF.cpp:194
int requiredMemory() const
Returns the number of bytes requested to store the image.
Definition: Image.cpp:532
virtual void close()=0
Closes the file.
long long writeUInt32(unsigned int data, bool little_endian_data=true)
Writes a single entry. Returns the number of bytes written.
const String & path() const
Returns the path of the file.
Definition: VirtualFile.hpp:98
VLCORE_EXPORT ref< Image > loadTIFF(VirtualFile *file)
Definition: ioTIFF.cpp:121
Visualization Library main namespace.
int height() const
Definition: Image.hpp:209
int width() const
Definition: Image.hpp:207
long long write(const void *buffer, long long byte_count)
Writes byte_count bytes to a file. Returns the number of bytes actually written.
Definition: VirtualFile.cpp:90
virtual bool open(EOpenMode mode)=0
Opens the file in the specified mode.
int pitch() const
Definition: Image.hpp:213
#define NULL
Definition: OpenGLDefs.hpp:81
bool seekSet(long long offset)
Changes the current read/write position of a file.
virtual long long size() const =0
Returns the size of the file in bytes.
ref< Image > convertFormat(EImageFormat new_format) const
Converts the format() of an image.
Definition: Image.cpp:1719
unsigned short readUInt16(bool little_endian_data=true)
Reads single entry.
A VirtualFile that operates on regular disk files.
Definition: DiskFile.hpp:64
EImageType type() const
Definition: Image.hpp:217
Implements a generic 1d, 2d, 3d and cubemap image that can have mipmaps.
Definition: Image.hpp:54
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
void allocate2D(int x, int y, int bytealign, EImageFormat format, EImageType type)
Definition: Image.cpp:608
bool seekEnd(long long offset)
Changes the current read/write position of a file.
long long position() const
Returns the current position in the file.
Definition: VirtualFile.cpp:98
VLCORE_EXPORT bool isTIFF(VirtualFile *file)
Definition: ioTIFF.cpp:168
void flipVertically()
Definition: Image.cpp:942
static int bitsPerPixel(EImageType type, EImageFormat format)
Returns the number of bits used to represents one pixel.
Definition: Image.cpp:382
EImageFormat format() const
Definition: Image.hpp:215
bool isCubemap() const
Definition: Image.hpp:78