📄 image_io_jpeg.cpp
字号:
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); // further validation: make sure we're actually on the image if (x >= cinfo.output_width || y >= cinfo.output_height) { string msg("CImageIOJpeg::ReadImage(): invalid starting position: "); msg += NStr::IntToString(x); msg += ", "; msg += NStr::IntToString(y); msg += " (image dimensions: "; msg += NStr::IntToString(cinfo.output_width); msg += ", "; msg += NStr::IntToString(cinfo.output_height); msg += ")"; NCBI_THROW(CImageException, eReadError, msg); } // clamp our width and height to the image size if (x + w >= cinfo.output_width) { w = cinfo.output_width - x; LOG_POST(Warning << "CImageIOJpeg::ReadImage(): clamped width to " << w); } if (y + h >= cinfo.output_height) { h = cinfo.output_height - y; LOG_POST(Warning << "CImageIOJpeg::ReadImage(): clamped height to " << h); } // allocate an image to store the subimage's data image.Reset(new CImage(w, h, 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; vector<unsigned char> row(stride); scanline[0] = &row[0]; size_t i; // start by skipping a number of scan lines for (i = 0; i < y; ++i) { jpeg_read_scanlines(&cinfo, scanline, 1); } // now read the actual data unsigned char* data = image->SetData(); switch (cinfo.out_color_components) { case 1: for ( ; i < y + h; ++i) { jpeg_read_scanlines(&cinfo, scanline, 1); for (size_t j = x; j < x + w; ++j) { *data++ = scanline[0][j]; *data++ = scanline[0][j]; *data++ = scanline[0][j]; } } break; case 3: {{ const size_t offs = x * image->GetDepth(); const size_t scan_w = w * image->GetDepth(); const size_t to_stride = image->GetWidth() * image->GetDepth(); for ( ; i < y + h; ++i) { jpeg_read_scanlines(&cinfo, scanline, 1); memcpy(data, scanline[0] + offs, scan_w); data += to_stride; scanline[0] += stride; } }} break; default: NCBI_THROW(CImageException, eReadError, "CImageIOJpeg::ReadImage(): Unhandled color components"); } // standard clean-up jpeg_destroy_decompress(&cinfo); } catch (...) { // clean up our mess jpeg_destroy_decompress(&cinfo); throw; } return image.Release();}//// WriteImage()// write an image to a file in JPEG format// This version writes the entire image//void CImageIOJpeg::WriteImage(const CImage& image, CNcbiOstream& ostr, CImageIO::ECompress compress){ vector<JOCTET> buffer(sc_JpegBufLen); JOCTET* buf_ptr = &buffer[0]; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; try { // standard libjpeg setup cinfo.err = jpeg_std_error(&jerr); cinfo.err->error_exit = s_JpegErrorHandler; cinfo.err->output_message = s_JpegOutputHandler; jpeg_create_compress(&cinfo); //jpeg_stdio_dest(&cinfo, fp); s_JpegWriteSetup(&cinfo, ostr, buf_ptr); cinfo.image_width = image.GetWidth(); cinfo.image_height = image.GetHeight(); cinfo.input_components = image.GetDepth(); cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); // set our compression quality int quality = 70; switch (compress) { case CImageIO::eCompress_None: quality = 100; break; case CImageIO::eCompress_Low: quality = 90; break; case CImageIO::eCompress_Medium: quality = 70; break; case CImageIO::eCompress_High: quality = 40; break; default: LOG_POST(Error << "unknown compression type: " << (int)compress); break; } jpeg_set_quality(&cinfo, quality, TRUE); // begin compression jpeg_start_compress(&cinfo, true); // process our data on a line-by-line basis JSAMPROW data[1]; data[0] = const_cast<JSAMPLE*> (static_cast<const JSAMPLE*> (image.GetData())); for (size_t i = 0; i < image.GetHeight(); ++i) { jpeg_write_scanlines(&cinfo, data, 1); data[0] += image.GetWidth() * image.GetDepth(); } // standard clean-up jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); } catch (...) { jpeg_destroy_compress(&cinfo); throw; }}//// WriteImage()// write an image to a file in JPEG format// This version writes only a subpart of the image//void CImageIOJpeg::WriteImage(const CImage& image, CNcbiOstream& ostr, size_t x, size_t y, size_t w, size_t h, CImageIO::ECompress compress){ // validate our image position as inside the image we've been passed if (x >= image.GetWidth() || y >= image.GetHeight()) { string msg("CImageIOJpeg::WriteImage(): invalid image position: "); msg += NStr::IntToString(x); msg += ", "; msg += NStr::IntToString(y); NCBI_THROW(CImageException, eWriteError, msg); } // clamp our width and height if (x + w >= image.GetWidth()) { w = image.GetWidth() - x; LOG_POST(Warning << "CImageIOJpeg::WriteImage(): clamped width to " << w); } if (y + h >= image.GetHeight()) { h = image.GetHeight() - y; LOG_POST(Warning << "CImageIOJpeg::WriteImage(): clamped height to " << h); } vector<JOCTET> buffer(sc_JpegBufLen); JOCTET* buf_ptr = &buffer[0]; struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; try { // standard libjpeg setup cinfo.err = jpeg_std_error(&jerr); cinfo.err->error_exit = s_JpegErrorHandler; cinfo.err->output_message = s_JpegOutputHandler; jpeg_create_compress(&cinfo); //jpeg_stdio_dest(&cinfo, fp); s_JpegWriteSetup(&cinfo, ostr, buf_ptr); cinfo.image_width = w; cinfo.image_height = h; cinfo.input_components = image.GetDepth(); cinfo.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfo); // set our compression quality int quality = 70; switch (compress) { case CImageIO::eCompress_None: quality = 100; break; case CImageIO::eCompress_Low: quality = 90; break; case CImageIO::eCompress_Medium: quality = 70; break; case CImageIO::eCompress_High: quality = 40; break; default: LOG_POST(Error << "unknown compression type: " << (int)compress); break; } jpeg_set_quality(&cinfo, quality, TRUE); // begin compression jpeg_start_compress(&cinfo, true); // process our data on a line-by-line basis const unsigned char* data_start = image.GetData() + (y * image.GetWidth() + x) * image.GetDepth(); size_t data_stride = image.GetWidth() * image.GetDepth(); JSAMPROW data[1]; data[0] = const_cast<JSAMPLE*> (static_cast<const JSAMPLE*> (data_start)); for (size_t i = 0; i < h; ++i) { jpeg_write_scanlines(&cinfo, data, 1); data[0] += data_stride; } // standard clean-up jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); } catch (...) { jpeg_destroy_compress(&cinfo); throw; }}END_NCBI_SCOPE#else // !HAVE_LIBJPEG//// JPEGLIB functionality not included - we stub out the various needed// functions//BEGIN_NCBI_SCOPECImage* CImageIOJpeg::ReadImage(CNcbiIstream& file){ NCBI_THROW(CImageException, eUnsupported, "CImageIOJpeg::ReadImage(): JPEG format not supported");}CImage* CImageIOJpeg::ReadImage(CNcbiIstream& file, size_t, size_t, size_t, size_t){ NCBI_THROW(CImageException, eUnsupported, "CImageIOJpeg::ReadImage(): JPEG format not supported");}void CImageIOJpeg::WriteImage(const CImage& image, CNcbiOstream& file, CImageIO::ECompress){ NCBI_THROW(CImageException, eUnsupported, "CImageIOJpeg::WriteImage(): JPEG format not supported");}void CImageIOJpeg::WriteImage(const CImage& image, CNcbiOstream& file, size_t, size_t, size_t, size_t, CImageIO::ECompress){ NCBI_THROW(CImageException, eUnsupported, "CImageIOJpeg::WriteImage(): JPEG format not supported");}END_NCBI_SCOPE#endif // HAVE_LIBJPEG/* * =========================================================================== * $Log: image_io_jpeg.cpp,v $ * Revision 1000.3 2004/06/01 19:41:34 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.8 * * Revision 1.8 2004/05/17 21:07:58 gorelenk * Added include of PCH ncbi_pch.hpp * * Revision 1.7 2004/01/31 17:52:10 dicuccio * Added support for black & white JPG images (color components = 1). Fixed * reading of sub-images * * Revision 1.6 2003/12/16 16:12:27 dicuccio * Fixed compilation problems on Linux - return value of read function is not * always unsigned char * * Revision 1.5 2003/12/16 15:49:36 dicuccio * Large re-write of image handling. Added improved error-handling and support * for streams-based i/o (via hooks into each client library). * * Revision 1.4 2003/11/03 15:19:57 dicuccio * Added optional compression parameter * * Revision 1.3 2003/10/02 15:37:33 ivanov * Get rid of compilation warnings * * Revision 1.2 2003/06/16 19:20:02 dicuccio * Added guard for libjpeg on Win32 * * Revision 1.1 2003/06/03 15:17:13 dicuccio * Initial revision of image library * * =========================================================================== */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -