📄 image_io_gif.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: image_io_gif.cpp,v $ * PRODUCTION Revision 1000.3 2004/06/01 19:41:27 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.6 * PRODUCTION * =========================================================================== *//* $Id: image_io_gif.cpp,v 1000.3 2004/06/01 19:41:27 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Authors: Mike DiCuccio * * File Description: * CImageIOGif -- interface class for reading/writing CompuServ GIF files *///// we include gif_lib.h first because of a conflict with windows.h// (DrawText() is both a giflib function and a Win32 GDI function)//#include <ncbi_pch.hpp>#include <ncbiconf.h>#ifdef HAVE_LIBGIF// alas, poor giflib... it isn't extern'edextern "C" {# include <gif_lib.h> /// !@#$%^ libunfig mis-spelled the prototype in their header, /// so we must add it here GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc);};#endif#include "image_io_gif.hpp"#include <util/image/image.hpp>#include <util/image/image_exception.hpp>#ifdef HAVE_LIBGIF////// LIBGIF support////BEGIN_NCBI_SCOPEstatic int s_GifRead(GifFileType* file, GifByteType* data, int len){ CNcbiIstream* istr = reinterpret_cast<CNcbiIstream*>(file->UserData); if (istr) { istr->read(reinterpret_cast<char*>(data), len); return istr->gcount(); } return -1;}static int s_GifWrite(GifFileType* file, const GifByteType* data, int len){ CNcbiOstream* ostr = reinterpret_cast<CNcbiOstream*>(file->UserData); if (ostr) { ostr->write(reinterpret_cast<const char*>(data), len); if ( *ostr ) { return len; } } return -1;}//// ReadImage()// read an entire GIF image into memory. This will read only the first image// in an image set.//CImage* CImageIOGif::ReadImage(CNcbiIstream& istr){ GifFileType* fp = NULL; CRef<CImage> image; try { // open our file for reading fp = DGifOpen(&istr, s_GifRead); if ( !fp ) { NCBI_THROW(CImageException, eReadError, "CImageIOGif::ReadImage(): " "cannot open file for reading"); } // allocate an image image.Reset(new CImage(fp->SWidth, fp->SHeight, 3)); memset(image->SetData(), fp->SBackGroundColor, image->GetWidth() * image->GetHeight() * image->GetDepth()); // we also allocate a single row // this row is a color indexed row, and will be decoded row-by-row into the // image vector<unsigned char> row_data(image->GetWidth()); unsigned char* row_ptr = &row_data[0]; bool done = false; while ( !done ) { // determine what sort of record type we have // these can be image, extension, or termination GifRecordType type; if (DGifGetRecordType(fp, &type) == GIF_ERROR) { NCBI_THROW(CImageException, eReadError, "CImageIOGif::ReadImage(): error reading file"); } switch (type) { case IMAGE_DESC_RECORD_TYPE: // // we only support the first image in a gif // if (DGifGetImageDesc(fp) == GIF_ERROR) { NCBI_THROW(CImageException, eReadError, "CImageIOGif::ReadImage(): error reading file"); } if (fp->Image.Interlace) { // interlaced images are a bit more complex size_t row = fp->Image.Top; size_t col = fp->Image.Left; size_t wid = fp->Image.Width; size_t ht = fp->Image.Height; static int interlaced_offs[4] = { 0, 4, 2, 1 }; static int interlaced_jump[4] = { 8, 8, 4, 2 }; for (size_t i = 0; i < 4; ++i) { for (size_t j = row + interlaced_offs[i]; j < row + ht; j += interlaced_jump[i]) { x_ReadLine(fp, row_ptr); x_UnpackData(fp, row_ptr, image->SetData() + (j * wid + col) * image->GetDepth()); } } } else { size_t col = fp->Image.Left; size_t wid = fp->Image.Width; size_t ht = fp->Image.Height; for (size_t i = 0; i < ht; ++i) { x_ReadLine(fp, row_ptr); x_UnpackData(fp, row_ptr, image->SetData() + (i * wid + col) * image->GetDepth()); } } break; case EXTENSION_RECORD_TYPE: {{ int ext_code; GifByteType* extension; // we ignore extension blocks if (DGifGetExtension(fp, &ext_code, &extension) == GIF_ERROR) { NCBI_THROW(CImageException, eReadError, "CImageIOGif::ReadImage(): " "error reading file"); } while (extension != NULL) { if (DGifGetExtensionNext(fp, &extension) == GIF_OK) { continue; } NCBI_THROW(CImageException, eReadError, "CImageIOGif::ReadImage(): " "error reading file"); } }} break; default: // terminate record - break our of our while() done = true; break; } } // close up and exit DGifCloseFile(fp); } catch (...) { DGifCloseFile(fp); fp = NULL; throw; } return image.Release();}//// ReadImage// this version returns a sub-image from the desired image.//CImage* CImageIOGif::ReadImage(CNcbiIstream& istr, size_t x, size_t y, size_t w, size_t h){ // we use a brain-dead implementation here - this can be done in a more // memory-efficient manner... CRef<CImage> image(ReadImage(istr)); return image->GetSubImage(x, y, w, h);}//// WriteImage()// this writes out a GIF image.//void CImageIOGif::WriteImage(const CImage& image, CNcbiOstream& ostr, CImageIO::ECompress){ if ( !image.GetData() ) { NCBI_THROW(CImageException, eWriteError, "CImageIOGif::WriteImage(): " "cannot write empty image to file"); } ColorMapObject* cmap = NULL; GifFileType* fp = NULL; try { // first, we need to split our image into red/green/blue channels // we do this to get proper GIF quantization size_t size = image.GetWidth() * image.GetHeight(); vector<unsigned char> red (size); vector<unsigned char> green(size); vector<unsigned char> blue (size);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -