image_io.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:10k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: image_io.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:41:21  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.4
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: image_io.cpp,v 1000.3 2004/06/01 19:41:21 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Mike DiCuccio
  35.  *
  36.  * File Description:
  37.  *    CImageIO -- framework for reading/writing images
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <util/image/image_io.hpp>
  41. #include <util/image/image_exception.hpp>
  42. #include "image_io_raw.hpp"
  43. #include "image_io_bmp.hpp"
  44. #include "image_io_gif.hpp"
  45. #include "image_io_jpeg.hpp"
  46. #include "image_io_png.hpp"
  47. #include "image_io_sgi.hpp"
  48. #include "image_io_tiff.hpp"
  49. BEGIN_NCBI_SCOPE
  50. //
  51. // file magic signatures for various formats
  52. //
  53. // we read at most 16 bytes
  54. static const int kMaxMagic = 16;
  55. struct SMagicInfo
  56. {
  57.     CImageIO::EType m_Type;
  58.     unsigned int    m_Length;
  59.     unsigned char   m_Signature[kMaxMagic];
  60. };
  61. static const struct SMagicInfo kMagicTable[] = {
  62.     { CImageIO::eBmp,     2, "BM" },
  63.     { CImageIO::eGif,     4, "GIF8" },
  64.     { CImageIO::eJpeg,    2, "xffxd8" },
  65.     { CImageIO::ePng,     4, "x89PNG" },
  66.     { CImageIO::eSgi,     2, "x1xda" },
  67.     { CImageIO::eTiff,    4, "II*" },
  68.     { CImageIO::eTiff,    4, "MM*" }, // this one might need to be { 'M', 'M', 0, '*' }
  69.     { CImageIO::eXpm,     7, "/* XPM */" },
  70.     { CImageIO::eRaw,     4, "RAW" },
  71.     // must be last
  72.     { CImageIO::eUnknown, 0, "" }
  73. };
  74. // extract an image's type from its magic number
  75. CImageIO::EType CImageIO::GetTypeFromMagic(const string& file)
  76. {
  77.     CNcbiIfstream i_file (file.c_str());
  78.     if (!i_file) {
  79.         return eUnknown;
  80.     }
  81.     return GetTypeFromMagic(i_file);
  82. }
  83. CImageIO::EType CImageIO::GetTypeFromMagic(CNcbiIstream& istr)
  84. {
  85.     // magic numbers live in the first few bytes
  86.     unsigned char magic[kMaxMagic];
  87.     memset(magic, 0x00, kMaxMagic);
  88.     istr.read((char *)magic, kMaxMagic);
  89.     istr.seekg(-istr.gcount(), ios::cur);
  90.     // we just compare against our (small) table of known image magic values
  91.     for (const SMagicInfo* i = kMagicTable;  i->m_Length;  ++i) {
  92.         if (memcmp(magic, i->m_Signature, i->m_Length) == 0) {
  93.             return i->m_Type;
  94.         }
  95.     }
  96.     return eUnknown;
  97. }
  98. //
  99. // magic from extension info
  100. //
  101. struct SExtMagicInfo
  102. {
  103.     CImageIO::EType m_Type;
  104.     const char* m_Ext;
  105. };
  106. static const SExtMagicInfo kExtensionMagicTable[] = {
  107.     { CImageIO::eBmp,  "bmp" },
  108.     { CImageIO::eGif,  "gif" },
  109.     { CImageIO::eJpeg, "jpeg" },
  110.     { CImageIO::eJpeg, "jpg" },
  111.     { CImageIO::ePng,  "png" },
  112.     { CImageIO::eSgi,  "sgi" },
  113.     { CImageIO::eTiff, "tif" },
  114.     { CImageIO::eTiff, "tiff" },
  115.     { CImageIO::eXpm,  "xpm" },
  116.     { CImageIO::eRaw,  "raw" },
  117.     // must be last
  118.     { CImageIO::eUnknown, NULL }
  119. };
  120. //
  121. // GetTypeFromFileName()
  122. // This function will determine a file's expected type from a given file name
  123. //
  124. CImageIO::EType CImageIO::GetTypeFromFileName(const string& fname)
  125. {
  126.     string::size_type pos = fname.find_last_of(".");
  127.     if (pos == string::npos) {
  128.         return eUnknown;
  129.     }
  130.     string ext(fname.substr(pos + 1, fname.length() - pos - 1));
  131.     ext = NStr::ToLower(ext);
  132.     // compare the extension against our table
  133.     for (const SExtMagicInfo* i = kExtensionMagicTable;  i->m_Ext;  ++i) {
  134.         if (ext == i->m_Ext) {
  135.             return i->m_Type;
  136.         }
  137.     }
  138.     return eUnknown;
  139. }
  140. //
  141. // ReadImage()
  142. // read an image from disk, returning its contents
  143. //
  144. CImage* CImageIO::ReadImage(const string& file)
  145. {
  146.     CNcbiIfstream istr(file.c_str(), ios::in|ios::binary);
  147.     return ReadImage(istr);
  148. }
  149. CImage* CImageIO::ReadImage(CNcbiIstream& istr)
  150. {
  151.     try {
  152.         CRef<CImageIOHandler> handler(x_GetHandler(GetTypeFromMagic(istr)));
  153.         return handler->ReadImage(istr);
  154.     }
  155.     catch (CImageException& e) {
  156.         LOG_POST(Error << "Error reading image: " << e.what());
  157.         return NULL;
  158.     }
  159.     // all other exceptions are explicitly not caught - handler in user code
  160. }
  161. //
  162. // ReadSubImage()
  163. // read part of an image from disk, returning its contents
  164. //
  165. CImage* CImageIO::ReadSubImage(const string& file,
  166.                                size_t x, size_t y, size_t w, size_t h)
  167. {
  168.     CNcbiIfstream istr(file.c_str(), ios::in|ios::binary);
  169.     return ReadSubImage(istr, x, y, w, h);
  170. }
  171. CImage* CImageIO::ReadSubImage(CNcbiIstream& istr,
  172.                                size_t x, size_t y, size_t w, size_t h)
  173. {
  174.     try {
  175.         CRef<CImageIOHandler> handler(x_GetHandler(GetTypeFromMagic(istr)));
  176.         return handler->ReadImage(istr, x, y, w, h);
  177.     }
  178.     catch (CImageException& e) {
  179.         LOG_POST(Error << "Error reading subimage: " << e.what());
  180.         return NULL;
  181.     }
  182.     // all other exceptions are explicitly not caught - handler in user code
  183. }
  184. //
  185. // WriteImage()
  186. // write an image to disk
  187. //
  188. bool CImageIO::WriteImage(const CImage& image, const string& file,
  189.                           EType type, ECompress compress)
  190. {
  191.     try {
  192.         if (type == eUnknown) {
  193.             type = GetTypeFromFileName(file);
  194.         }
  195.     }
  196.     catch (CImageException& e) {
  197.         LOG_POST(Error << "Error writing image: " << e.what());
  198.         return false;
  199.     }
  200.     CNcbiOfstream ostr(file.c_str(), ios::out|ios::binary);
  201.     return WriteImage(image, ostr, type, compress);
  202. }
  203. bool CImageIO::WriteImage(const CImage& image, CNcbiOstream& ostr,
  204.                           EType type, ECompress compress)
  205. {
  206.     try {
  207.         CRef<CImageIOHandler> handler(x_GetHandler(type));
  208.         handler->WriteImage(image, ostr, compress);
  209.         return true;
  210.     }
  211.     catch (CImageException& e) {
  212.         LOG_POST(Error << "Error writing image: " << e.what());
  213.         return false;
  214.     }
  215.     // all other exceptions are explicitly not caught - handler in user code
  216. }
  217. //
  218. // WriteSubImage()
  219. // write part of an image to disk
  220. //
  221. bool CImageIO::WriteSubImage(const CImage& image,
  222.                              const string& file,
  223.                              size_t x, size_t y, size_t w, size_t h,
  224.                              EType type, ECompress compress)
  225. {
  226.     try {
  227.         if (type == eUnknown) {
  228.             type = GetTypeFromFileName(file);
  229.         }
  230.     }
  231.     catch (CImageException& e) {
  232.         LOG_POST(Error << "Error writing image: " << e.what());
  233.         return false;
  234.     }
  235.     CNcbiOfstream ostr(file.c_str(), ios::out|ios::binary);
  236.     return WriteSubImage(image, ostr, x, y, w, h, type, compress);
  237. }
  238. bool CImageIO::WriteSubImage(const CImage& image,
  239.                              CNcbiOstream& ostr,
  240.                              size_t x, size_t y, size_t w, size_t h,
  241.                              EType type, ECompress compress)
  242. {
  243.     try {
  244.         CRef<CImageIOHandler> handler(x_GetHandler(type));
  245.         handler->WriteImage(image, ostr, x, y, w, h, compress);
  246.         return true;
  247.     }
  248.     catch (CImageException& e) {
  249.         LOG_POST(Error << "Error writing image: " << e.what());
  250.         return false;
  251.     }
  252.     // all other exceptions are explicitly not caught - handler in user code
  253. }
  254. //
  255. // x_GetImageHandler()
  256. // Retrieve a CImageIOHandler-derived class to handle reading and writing for a
  257. // given image formag
  258. //
  259. CImageIOHandler* CImageIO::x_GetHandler(EType type)
  260. {
  261.     switch (type) {
  262.     default:
  263.     case eUnknown:
  264.         NCBI_THROW(CImageException, eInvalidImage,
  265.                    "Image format not supported");
  266.     case eJpeg:
  267.         return new CImageIOJpeg();
  268.     case eBmp:
  269.         return new CImageIOBmp();
  270.     case ePng:
  271.         return new CImageIOPng();
  272.     case eSgi:
  273.         return new CImageIOSgi();
  274.     case eGif:
  275.         return new CImageIOGif();
  276.     case eRaw:
  277.         return new CImageIORaw();
  278.     case eTiff:
  279.         return new CImageIOTiff();
  280.     }
  281. }
  282. END_NCBI_SCOPE
  283. /*
  284.  * ===========================================================================
  285.  * $Log: image_io.cpp,v $
  286.  * Revision 1000.3  2004/06/01 19:41:21  gouriano
  287.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.4
  288.  *
  289.  * Revision 1.4  2004/05/17 21:07:58  gorelenk
  290.  * Added include of PCH ncbi_pch.hpp
  291.  *
  292.  * Revision 1.3  2003/12/16 15:49:35  dicuccio
  293.  * Large re-write of image handling.  Added improved error-handling and support
  294.  * for streams-based i/o (via hooks into each client library).
  295.  *
  296.  * Revision 1.2  2003/11/03 15:19:57  dicuccio
  297.  * Added optional compression parameter
  298.  *
  299.  * Revision 1.1  2003/06/03 15:17:13  dicuccio
  300.  * Initial revision of image library
  301.  *
  302.  * ===========================================================================
  303.  */