|
|
@@ -0,0 +1,123 @@
|
|
|
+#include "JpegImage.h"
|
|
|
+
|
|
|
+
|
|
|
+namespace Image {
|
|
|
+
|
|
|
+const static JOCTET EOI_BUFFER[1] = { JPEG_EOI };
|
|
|
+
|
|
|
+JpegImage::JpegImage()
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+void JpegImage::SetImageData(const std::string& data)
|
|
|
+{
|
|
|
+ DecompressImage(data.c_str(), data.size());
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int JpegImage::Width() const
|
|
|
+{
|
|
|
+ return m_width;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int JpegImage::Height() const
|
|
|
+{
|
|
|
+ return m_height;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int JpegImage::StrideX() const
|
|
|
+{
|
|
|
+ return m_strideX;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned int JpegImage::StrideY() const
|
|
|
+{
|
|
|
+ return m_strideY;
|
|
|
+}
|
|
|
+
|
|
|
+const std::vector<char>& JpegImage::Data() const
|
|
|
+{
|
|
|
+ return m_data;
|
|
|
+}
|
|
|
+
|
|
|
+void JpegImage::InitSource(j_decompress_ptr pCinfo)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+boolean JpegImage::FillInputBuffer(j_decompress_ptr pCinfo)
|
|
|
+{
|
|
|
+ SourceMgrPtr pSrc = reinterpret_cast<SourceMgrPtr>(pCinfo->src);
|
|
|
+ pSrc->pub.next_input_byte = EOI_BUFFER;
|
|
|
+ pSrc->pub.bytes_in_buffer = 1;
|
|
|
+ return TRUE;
|
|
|
+}
|
|
|
+
|
|
|
+void JpegImage::SkipInputData(j_decompress_ptr pCinfo, long numBytes)
|
|
|
+{
|
|
|
+ SourceMgrPtr pSrc = reinterpret_cast<SourceMgrPtr>(pCinfo->src);
|
|
|
+ if (pSrc->pub.bytes_in_buffer < static_cast<size_t>(numBytes))
|
|
|
+ {
|
|
|
+ pSrc->pub.next_input_byte = EOI_BUFFER;
|
|
|
+ pSrc->pub.bytes_in_buffer = 1;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ pSrc->pub.next_input_byte += numBytes;
|
|
|
+ pSrc->pub.bytes_in_buffer -= numBytes;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void JpegImage::TermSource(j_decompress_ptr pCinfo)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+void JpegImage::SetSourceMgr(j_decompress_ptr pCinfo, const char* pData, size_t len) const
|
|
|
+{
|
|
|
+ SourceMgrPtr pSrc;
|
|
|
+ if (pCinfo->src == 0)
|
|
|
+ pCinfo->src = (struct jpeg_source_mgr *)(*pCinfo->mem->alloc_small)(reinterpret_cast<j_common_ptr>(pCinfo), JPOOL_PERMANENT, sizeof(SourceMgr));
|
|
|
+
|
|
|
+ pSrc = reinterpret_cast<SourceMgrPtr>(pCinfo->src);
|
|
|
+ pSrc->pub.init_source = JpegImage::InitSource;
|
|
|
+ pSrc->pub.fill_input_buffer = JpegImage::FillInputBuffer;
|
|
|
+ pSrc->pub.skip_input_data = JpegImage::SkipInputData;
|
|
|
+ pSrc->pub.resync_to_restart = jpeg_resync_to_restart;
|
|
|
+ pSrc->pub.term_source = JpegImage::TermSource;
|
|
|
+
|
|
|
+ pSrc->data = (const JOCTET *)pData;
|
|
|
+ pSrc->len = len;
|
|
|
+ pSrc->pub.bytes_in_buffer = len;
|
|
|
+ pSrc->pub.next_input_byte = pSrc->data;
|
|
|
+}
|
|
|
+
|
|
|
+void JpegImage::DecompressImage(const char* pData, size_t len)
|
|
|
+{
|
|
|
+ struct jpeg_decompress_struct cinfo;
|
|
|
+ struct jpeg_error_mgr jerr;
|
|
|
+
|
|
|
+ jerr.trace_level = 0;
|
|
|
+ cinfo.err = jpeg_std_error(&jerr);
|
|
|
+ jpeg_create_decompress(&cinfo);
|
|
|
+ SetSourceMgr(&cinfo, pData, len);
|
|
|
+
|
|
|
+ jpeg_read_header(&cinfo, TRUE);
|
|
|
+ jpeg_start_decompress(&cinfo);
|
|
|
+
|
|
|
+ m_width = cinfo.image_width;
|
|
|
+ m_height = cinfo.image_height;
|
|
|
+ m_strideX = cinfo.num_components;
|
|
|
+ m_strideY = m_width * cinfo.num_components;
|
|
|
+
|
|
|
+ m_data.resize(m_height * m_strideY);
|
|
|
+
|
|
|
+ JSAMPROW scanlines[1];
|
|
|
+ while (cinfo.output_scanline < cinfo.image_height)
|
|
|
+ {
|
|
|
+ scanlines[0] = reinterpret_cast<JSAMPROW>(&m_data[cinfo.output_scanline * m_strideY]);
|
|
|
+ jpeg_read_scanlines(&cinfo, scanlines, 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ jpeg_finish_decompress(&cinfo);
|
|
|
+ jpeg_destroy_decompress(&cinfo);
|
|
|
+}
|
|
|
+
|
|
|
+} // namespace Image
|