📄 image_io_jpeg.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: image_io_jpeg.cpp,v $ * PRODUCTION Revision 1000.3 2004/06/01 19:41:34 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8 * PRODUCTION * =========================================================================== *//* $Id: image_io_jpeg.cpp,v 1000.3 2004/06/01 19:41:34 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: * CImageIOJpeg -- interface class for reading/writing JPEG files */#include <ncbi_pch.hpp>#include "image_io_jpeg.hpp"#include <util/image/image.hpp>#include <util/image/image_exception.hpp>#ifdef HAVE_LIBJPEG////// JPEG SUPPORT////#include <stdio.h>// hack to get around duplicate definition of INT32#ifdef NCBI_OS_MSWIN#define XMD_H#endif// jpeglib include (not extern'ed already (!))extern "C" {#include <jpeglib.h>}BEGIN_NCBI_SCOPEstatic const int sc_JpegBufLen = 4096;static void s_JpegErrorHandler(j_common_ptr ptr){ string msg("Error processing JPEG image: "); msg += ptr->err->jpeg_message_table[ptr->err->msg_code]; if (ptr->is_decompressor) { NCBI_THROW(CImageException, eReadError, msg); } else { NCBI_THROW(CImageException, eWriteError, msg); }}static void s_JpegOutputHandler(j_common_ptr ptr){ string msg("JPEG message: "); msg += ptr->err->jpeg_message_table[ptr->err->msg_code]; LOG_POST(Warning << msg);}//// specialized internal structs used for reading/writing from streams//struct SJpegInput { // the input data elements struct jpeg_source_mgr pub; // our buffer and stream CNcbiIstream* stream; JOCTET* buffer;};struct SJpegOutput { // the input data elements struct jpeg_destination_mgr pub; // our buffer and stream CNcbiOstream* stream; JOCTET* buffer;};//// JPEG stream i/o handlers handlers//// initialize reading on the streamstatic void s_JpegReadInit(j_decompress_ptr cinfo){ struct SJpegInput* sptr = (SJpegInput*)cinfo->src; // set up our buffer for the first read sptr->pub.bytes_in_buffer = 0; sptr->pub.next_input_byte = sptr->buffer;}// grab data from the streamstatic boolean s_JpegReadBuffer(j_decompress_ptr cinfo){ struct SJpegInput* sptr = (SJpegInput*)cinfo->src; // read data from the stream sptr->stream->read(reinterpret_cast<char*>(sptr->buffer), sc_JpegBufLen); // reset our counts sptr->pub.bytes_in_buffer = sptr->stream->gcount(); sptr->pub.next_input_byte = sptr->buffer; return TRUE;}// skip over some data in an input stream (rare operation)static void s_JpegReadSkipData(j_decompress_ptr cinfo, long bytes){ struct SJpegInput* sptr = (SJpegInput*)cinfo->src; if (bytes > 0) { while (bytes > sptr->pub.bytes_in_buffer) { bytes -= sptr->pub.bytes_in_buffer; s_JpegReadBuffer(cinfo); } sptr->pub.next_input_byte += (size_t) bytes; sptr->pub.bytes_in_buffer -= (size_t) bytes; }}// finalize reading in a stream (no-op)static void s_JpegReadTerminate(j_decompress_ptr){ // don't need to do anything here}// initialize writing to a streamstatic void s_JpegWriteInit(j_compress_ptr cinfo){ struct SJpegOutput* sptr = (SJpegOutput*)cinfo->dest; // set up our buffer for the first read sptr->pub.next_output_byte = sptr->buffer; sptr->pub.free_in_buffer = sc_JpegBufLen;}// fill the input bufferstatic boolean s_JpegWriteBuffer(j_compress_ptr cinfo){ struct SJpegOutput* sptr = (SJpegOutput*)cinfo->dest; // read data from the stream sptr->stream->write(reinterpret_cast<const char*>(sptr->buffer), sc_JpegBufLen); // reset our counts sptr->pub.next_output_byte = sptr->buffer; sptr->pub.free_in_buffer = sc_JpegBufLen; return TRUE;}// finalize our JPEG outputstatic void s_JpegWriteTerminate(j_compress_ptr cinfo){ // don't need to do anything here struct SJpegOutput* sptr = (SJpegOutput*)cinfo->dest; size_t datacount = sc_JpegBufLen - sptr->pub.free_in_buffer; // read data from the stream if (datacount > 0) { sptr->stream->write(reinterpret_cast<const char*>(sptr->buffer), datacount); } sptr->stream->flush(); if ( !*(sptr->stream) ) { NCBI_THROW(CImageException, eWriteError, "Error writing to JPEG stream"); }}//// set up our read structure to handle stream sources// this is provided in place of jpeg_stdio_src()//static void s_JpegReadSetup(j_decompress_ptr cinfo, CNcbiIstream& istr, JOCTET* buffer){ struct SJpegInput* sptr = NULL; if (cinfo->src == NULL) { cinfo->src = (struct jpeg_source_mgr*)malloc(sizeof(SJpegInput)); sptr = (SJpegInput*)cinfo->src; } // allocate buffer and save our stream sptr->stream = &istr; sptr->buffer = buffer; // set our callbacks sptr->pub.init_source = s_JpegReadInit; sptr->pub.fill_input_buffer = s_JpegReadBuffer; sptr->pub.skip_input_data = s_JpegReadSkipData; sptr->pub.resync_to_restart = jpeg_resync_to_restart; sptr->pub.term_source = s_JpegReadTerminate; // make sure the structure knows we're just starting now sptr->pub.bytes_in_buffer = 0; sptr->pub.next_input_byte = buffer;}//// set up our read structure to handle stream sources// this is provided in place of jpeg_stdio_src()//static void s_JpegWriteSetup(j_compress_ptr cinfo, CNcbiOstream& ostr, JOCTET* buffer){ struct SJpegOutput* sptr = NULL; if (cinfo->dest == NULL) { cinfo->dest = (struct jpeg_destination_mgr*)malloc(sizeof(SJpegOutput)); sptr = (SJpegOutput*)cinfo->dest; } // allocate buffer and save our stream sptr->stream = &ostr; sptr->buffer = buffer; // set our callbacks sptr->pub.init_destination = s_JpegWriteInit; sptr->pub.empty_output_buffer = s_JpegWriteBuffer; sptr->pub.term_destination = s_JpegWriteTerminate; // make sure the structure knows we're just starting now sptr->pub.free_in_buffer = sc_JpegBufLen; sptr->pub.next_output_byte = buffer;}//// ReadImage()// read a JPEG format image into memory, returning the image itself// This version reads the entire image//CImage* CImageIOJpeg::ReadImage(CNcbiIstream& istr){ vector<JOCTET> buffer(sc_JpegBufLen); JOCTET* buf_ptr = &buffer[0]; CRef<CImage> image; // standard libjpeg stuff struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; try { // open our file for reading // set up the standard error handler cinfo.err = jpeg_std_error(&jerr); cinfo.err->error_exit = s_JpegErrorHandler; cinfo.err->output_message = s_JpegOutputHandler; jpeg_create_decompress(&cinfo); // set up our standard stream processor s_JpegReadSetup(&cinfo, istr, buf_ptr); //jpeg_stdio_src(&cinfo, fp); jpeg_read_header(&cinfo, TRUE); // decompression parameters cinfo.dct_method = JDCT_FLOAT; jpeg_start_decompress(&cinfo); // allocate an image to hold our data image.Reset(new CImage(cinfo.output_width, cinfo.output_height, 3)); // we process the image 1 scanline at a time unsigned char *scanline[1]; const size_t stride = cinfo.output_width * cinfo.out_color_components; switch (cinfo.out_color_components) { case 1: {{ unsigned char* data = image->SetData(); vector<unsigned char> scan_buf(stride); scanline[0] = &scan_buf[0]; for (size_t i = 0; i < image->GetHeight(); ++i) { jpeg_read_scanlines(&cinfo, scanline, 1); for (size_t j = 0; j < stride; ++j) { *data++ = scanline[0][j]; *data++ = scanline[0][j]; *data++ = scanline[0][j]; } } }} break; case 3: scanline[0] = image->SetData(); for (size_t i = 0; i < image->GetHeight(); ++i) { jpeg_read_scanlines(&cinfo, scanline, 1); scanline[0] += stride; } break; default: NCBI_THROW(CImageException, eReadError, "CImageIOJpeg::ReadImage(): Unhandled color components"); } // standard clean-up jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); } catch (...) { // clean up our mess jpeg_destroy_decompress(&cinfo); throw; } return image.Release();}//// ReadImage()// read a JPEG format image into memory, returning the image itself// This version reads only a subset of the image//CImage* CImageIOJpeg::ReadImage(CNcbiIstream& istr, size_t x, size_t y, size_t w, size_t h){ vector<JOCTET> buffer(sc_JpegBufLen); JOCTET* buf_ptr = &buffer[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -