NCBI C++ ToolKit
image_io.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: image_io.cpp 91363 2020-10-19 14:54:50Z grichenk $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Mike DiCuccio
27  *
28  * File Description:
29  * CImageIO -- framework for reading/writing images
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <util/image/image_io.hpp>
35 #include <corelib/stream_utils.hpp>
36 #include <util/error_codes.hpp>
37 
38 #include "image_io_raw.hpp"
39 #include "image_io_bmp.hpp"
40 #include "image_io_gif.hpp"
41 #include "image_io_jpeg.hpp"
42 #include "image_io_png.hpp"
43 #include "image_io_sgi.hpp"
44 #include "image_io_tiff.hpp"
45 
46 
47 #define NCBI_USE_ERRCODE_X Util_Image
48 
49 
51 
52 //
53 // file magic signatures for various formats
54 //
55 
56 // we read at most 16 bytes
57 static const int kMaxMagic = 16;
58 
59 struct SMagicInfo
60 {
62  unsigned int m_Length;
63  unsigned char m_Signature[kMaxMagic];
64 };
65 static const struct SMagicInfo kMagicTable[] = {
66  { CImageIO::eBmp, 2, "BM" },
67  { CImageIO::eGif, 4, "GIF8" },
68  { CImageIO::eJpeg, 2, "\xff\xd8" },
69  { CImageIO::ePng, 4, "\x89PNG" },
70  { CImageIO::eSgi, 2, "\x1\xda" },
71  { CImageIO::eTiff, 4, "II*\0" },
72  { CImageIO::eTiff, 4, "MM\0*" }, // this one might need to be { 'M', 'M', 0, '*' }
73  { CImageIO::eXpm, 7, "/* XPM */" },
74  { CImageIO::eRaw, 4, "RAW\0" },
75 
76  // must be last
77  { CImageIO::eUnknown, 0, "" }
78 };
79 
80 // extract an image's type from its magic number
82 {
83  CNcbiIfstream i_file (file.c_str());
84  if (!i_file) {
85  return eUnknown;
86  }
87 
88  return GetTypeFromMagic(i_file);
89 }
90 
92 {
93  // magic numbers live in the first few bytes
94  unsigned char magic[kMaxMagic];
95  memset(magic, 0x00, kMaxMagic);
96 
97  istr.read((char *)magic, kMaxMagic);
98  istr.seekg(-istr.gcount(), ios::cur);
99  //CStreamUtils::Pushback(istr, (CT_CHAR_TYPE*)magic, istr.gcount());
100 
101  EType type = eUnknown;
102 
103  // we just compare against our (small) table of known image magic values
104  for (const SMagicInfo* i = kMagicTable; i->m_Length; ++i) {
105  if (memcmp(magic, i->m_Signature, i->m_Length) == 0) {
106  type = i->m_Type;
107  break;
108  }
109  }
110 
111  return type;
112 }
113 
114 
115 //
116 // magic from extension info
117 //
119 {
121  const char* m_Ext;
122 };
123 
125  { CImageIO::eBmp, "bmp" },
126  { CImageIO::eGif, "gif" },
127  { CImageIO::eJpeg, "jpeg" },
128  { CImageIO::eJpeg, "jpg" },
129  { CImageIO::ePng, "png" },
130  { CImageIO::eSgi, "sgi" },
131  { CImageIO::eTiff, "tif" },
132  { CImageIO::eTiff, "tiff" },
133  { CImageIO::eXpm, "xpm" },
134  { CImageIO::eRaw, "raw" },
135 
136  // must be last
138 };
139 
140 //
141 // GetTypeFromFileName()
142 // This function will determine a file's expected type from a given file name
143 //
145 {
146  string::size_type pos = fname.find_last_of(".");
147  if (pos == string::npos) {
148  return eUnknown;
149  }
150 
151  string ext(fname.substr(pos + 1, fname.length() - pos - 1));
152  ext = NStr::ToLower(ext);
153 
154  // compare the extension against our table
155  for (const SExtMagicInfo* i = kExtensionMagicTable; i->m_Ext; ++i) {
156  if (ext == i->m_Ext) {
157  return i->m_Type;
158  }
159  }
160  return eUnknown;
161 }
162 
163 /// read just the image information
164 bool CImageIO::ReadImageInfo(const string& file,
165  size_t* width, size_t* height, size_t* depth,
166  EType* type)
167 {
168  CNcbiIfstream istr(file.c_str(), ios::in|ios::binary);
169  return ReadImageInfo(istr, width, height, depth, type);
170 }
171 
172 
174  size_t* width, size_t* height, size_t* depth,
175  EType* type)
176 {
177  try {
178  /// first, set up a simple buffer - we hold the first 16k
179  /// or so of the image. this will allow us to manage things like TIFF
180  /// image directories
181 
182  EType image_type = GetTypeFromMagic(istr);
183  if (type) {
184  *type = image_type;
185  }
187 
188  size_t pos = istr.tellg();
189  bool res = handler->ReadImageInfo(istr, width, height, depth);
190  istr.seekg(pos, ios::beg);
191  return res;
192  }
193  catch (CImageException& e) {
194  ERR_POST_X(3, Error << "Error reading image: " << e.what());
195  }
196  return false;
197 }
198 
199 
200 
201 //
202 // ReadImage()
203 // read an image from disk, returning its contents
204 //
206 {
207  CNcbiIfstream istr(file.c_str(), ios::in|ios::binary);
208  return ReadImage(istr, type);
209 }
210 
211 
213 {
214  try {
215  if (type == eUnknown) {
216  type = GetTypeFromMagic(istr);
217  }
219  return handler->ReadImage(istr);
220  }
221  catch (CImageException& e) {
222  ERR_POST_X(4, Error << "Error reading image: " << e.what());
223  return NULL;
224  }
225  // all other exceptions are explicitly not caught - handler in user code
226 }
227 
228 
229 //
230 // ReadSubImage()
231 // read part of an image from disk, returning its contents
232 //
234  size_t x, size_t y, size_t w, size_t h,
235  EType type)
236 {
237  CNcbiIfstream istr(file.c_str(), ios::in|ios::binary);
238  return ReadSubImage(istr, x, y, w, h, type);
239 }
240 
241 
243  size_t x, size_t y, size_t w, size_t h,
244  EType type)
245 {
246  try {
247  if (type == eUnknown) {
248  type = GetTypeFromMagic(istr);
249  }
251  return handler->ReadImage(istr, x, y, w, h);
252  }
253  catch (CImageException& e) {
254  ERR_POST_X(5, Error << "Error reading subimage: " << e.what());
255  return NULL;
256  }
257  // all other exceptions are explicitly not caught - handler in user code
258 }
259 
260 
261 //
262 // WriteImage()
263 // write an image to disk
264 //
265 bool CImageIO::WriteImage(const CImage& image, const string& file,
267 {
268  try {
269  if (type == eUnknown) {
271  }
272  }
273  catch (CImageException& e) {
274  ERR_POST_X(6, Error << "Error writing image: " << e.what());
275  return false;
276  }
277 
278  CNcbiOfstream ostr(file.c_str(), ios::out|ios::binary);
279  if (ostr.good()) {
280  return WriteImage(image, ostr, type, compress);
281  }
282 
283  return false;
284 }
285 
286 
287 bool CImageIO::WriteImage(const CImage& image, CNcbiOstream& ostr,
289 {
290  try {
292  handler->WriteImage(image, ostr, compress);
293  return true;
294  }
295  catch (CImageException& e) {
296  ERR_POST_X(7, Error << "Error writing image: " << e.what());
297  return false;
298  }
299  // all other exceptions are explicitly not caught - handler in user code
300 }
301 
302 
303 //
304 // WriteSubImage()
305 // write part of an image to disk
306 //
307 bool CImageIO::WriteSubImage(const CImage& image,
308  const string& file,
309  size_t x, size_t y, size_t w, size_t h,
311 {
312  try {
313  if (type == eUnknown) {
315  }
316  }
317  catch (CImageException& e) {
318  ERR_POST_X(8, Error << "Error writing image: " << e.what());
319  return false;
320  }
321 
322  CNcbiOfstream ostr(file.c_str(), ios::out|ios::binary);
323  if (ostr.good()) {
324  return WriteSubImage(image, ostr, x, y, w, h, type, compress);
325  }
326 
327  return false;
328 }
329 
330 
331 bool CImageIO::WriteSubImage(const CImage& image,
332  CNcbiOstream& ostr,
333  size_t x, size_t y, size_t w, size_t h,
335 {
336  try {
338  handler->WriteImage(image, ostr, x, y, w, h, compress);
339  return true;
340  }
341  catch (CImageException& e) {
342  ERR_POST_X(9, Error << "Error writing image: " << e.what());
343  return false;
344  }
345  // all other exceptions are explicitly not caught - handler in user code
346 }
347 
348 
349 //
350 // x_GetImageHandler()
351 // Retrieve a CImageIOHandler-derived class to handle reading and writing for a
352 // given image formag
353 //
355 {
356  switch (type) {
357  default:
358  case eUnknown:
359  NCBI_THROW(CImageException, eInvalidImage,
360  "Image format not supported");
361 
362  case eJpeg:
363  return new CImageIOJpeg();
364 
365  case eBmp:
366  return new CImageIOBmp();
367 
368  case ePng:
369  return new CImageIOPng();
370 
371  case eSgi:
372  return new CImageIOSgi();
373 
374  case eGif:
375  return new CImageIOGif();
376 
377  case eRaw:
378  return new CImageIORaw();
379 
380  case eTiff:
381  return new CImageIOTiff();
382  }
383 }
384 
385 
class CImageIOHandler This is the base class for all image I/O handlers, and defines the standard int...
static EType GetTypeFromMagic(CNcbiIstream &istr)
Definition: image_io.cpp:91
static bool WriteSubImage(const CImage &image, CNcbiOstream &ostr, size_t x, size_t y, size_t w, size_t h, EType type, ECompress compress=eCompress_Default)
Definition: image_io.cpp:331
static bool ReadImageInfo(const string &file, size_t *width, size_t *height, size_t *depth, EType *type)
read just the image information
Definition: image_io.cpp:164
static CImage * ReadSubImage(CNcbiIstream &istr, size_t x, size_t y, size_t w, size_t h, EType type=CImageIO::eUnknown)
Definition: image_io.cpp:242
@ eUnknown
Definition: image_io.hpp:61
static CImageIOHandler * x_GetHandler(EType type)
Definition: image_io.cpp:354
static bool WriteImage(const CImage &image, CNcbiOstream &ostr, EType type, ECompress compress=eCompress_Default)
Definition: image_io.cpp:287
static EType GetTypeFromFileName(const string &file)
Definition: image_io.cpp:144
static CImage * ReadImage(const string &file, EType type=CImageIO::eUnknown)
Definition: image_io.cpp:205
CImage –.
Definition: Image.hpp:66
CRef –.
Definition: ncbiobj.hpp:618
void(*)(CSeq_entry_Handle seh, IWorkbench *wb, const CSerialObject &obj) handler
static unsigned char depth[2 *(256+1+29)+1]
std::ofstream out("events_result.xml")
main entry point for tests
static int type
Definition: getdata.c:31
#define NULL
Definition: ncbistd.hpp:225
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
Definition: ncbidiag.hpp:550
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
IO_PREFIX::ofstream CNcbiOfstream
Portable alias for ofstream.
Definition: ncbistre.hpp:500
IO_PREFIX::ostream CNcbiOstream
Portable alias for ostream.
Definition: ncbistre.hpp:149
IO_PREFIX::istream CNcbiIstream
Portable alias for istream.
Definition: ncbistre.hpp:146
IO_PREFIX::ifstream CNcbiIfstream
Portable alias for ifstream.
Definition: ncbistre.hpp:439
static string & ToLower(string &str)
Convert string to lower case – string& version.
Definition: ncbistr.cpp:405
static const SExtMagicInfo kExtensionMagicTable[]
Definition: image_io.cpp:124
static const int kMaxMagic
Definition: image_io.cpp:57
static const struct SMagicInfo kMagicTable[]
Definition: image_io.cpp:65
Definition of all error codes used in util (xutil.lib).
FILE * file
int i
std::istream & in(std::istream &in_, double &x_)
CImageIO::EType m_Type
Definition: image_io.cpp:120
const char * m_Ext
Definition: image_io.cpp:121
unsigned char m_Signature[kMaxMagic]
Definition: image_io.cpp:63
unsigned int m_Length
Definition: image_io.cpp:62
CImageIO::EType m_Type
Definition: image_io.cpp:61
Definition: type.c:6
#define compress
Definition: zconf.h:37
Modified on Sat Dec 09 04:44:17 2023 by modify_doxy.py rev. 669887