summaryrefslogtreecommitdiffstats
path: root/common/rfb
diff options
context:
space:
mode:
authorDRC <dcommander@users.sourceforge.net>2011-11-03 18:51:00 +0000
committerDRC <dcommander@users.sourceforge.net>2011-11-03 18:51:00 +0000
commit7c2a39cd1384bb48ef108a324c53ed1149930f75 (patch)
treee819e081be5f7a1c142cc584e4ea87f658133f25 /common/rfb
parent33c15e3a3a1db376feae90ef7521a107dd957752 (diff)
downloadtigervnc-7c2a39cd1384bb48ef108a324c53ed1149930f75.tar.gz
tigervnc-7c2a39cd1384bb48ef108a324c53ed1149930f75.zip
Move JPEG decoding into a standalone class (these should have been checked in with r4757. Oops.)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4758 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'common/rfb')
-rw-r--r--common/rfb/JpegDecompressor.cxx233
-rw-r--r--common/rfb/JpegDecompressor.h60
2 files changed, 293 insertions, 0 deletions
diff --git a/common/rfb/JpegDecompressor.cxx b/common/rfb/JpegDecompressor.cxx
new file mode 100644
index 00000000..9cd891a5
--- /dev/null
+++ b/common/rfb/JpegDecompressor.cxx
@@ -0,0 +1,233 @@
+/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright (C) 2004-2005 Cendio AB. All rights reserved.
+ * Copyright (C) 2011 D. R. Commander. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <rfb/JpegDecompressor.h>
+#include <rdr/Exception.h>
+#include <rfb/Rect.h>
+#include <rfb/PixelFormat.h>
+
+#include <stdio.h>
+extern "C" {
+#include <jpeglib.h>
+}
+#include <jerror.h>
+#include <setjmp.h>
+
+using namespace rfb;
+
+
+//
+// Error manager implmentation for the JPEG library
+//
+
+struct JPEG_ERROR_MGR {
+ struct jpeg_error_mgr pub;
+ jmp_buf jmpBuffer;
+ char lastError[JMSG_LENGTH_MAX];
+};
+
+static void
+JpegErrorExit(j_common_ptr dinfo)
+{
+ JPEG_ERROR_MGR *err = (JPEG_ERROR_MGR *)dinfo->err;
+
+ (*dinfo->err->output_message)(dinfo);
+ longjmp(err->jmpBuffer, 1);
+}
+
+static void
+JpegOutputMessage(j_common_ptr dinfo)
+{
+ JPEG_ERROR_MGR *err = (JPEG_ERROR_MGR *)dinfo->err;
+
+ (*dinfo->err->format_message)(dinfo, err->lastError);
+}
+
+
+//
+// Source manager implementation for the JPEG library.
+//
+
+struct JPEG_SRC_MGR {
+ struct jpeg_source_mgr pub;
+ JpegDecompressor *instance;
+};
+
+static void
+JpegNoOp(j_decompress_ptr dinfo)
+{
+}
+
+static boolean
+JpegFillInputBuffer(j_decompress_ptr dinfo)
+{
+ ERREXIT(dinfo, JERR_BUFFER_SIZE);
+ return TRUE;
+}
+
+static void
+JpegSkipInputData(j_decompress_ptr dinfo, long num_bytes)
+{
+ JPEG_SRC_MGR *src = (JPEG_SRC_MGR *)dinfo->src;
+
+ if (num_bytes < 0 || (size_t)num_bytes > src->pub.bytes_in_buffer) {
+ ERREXIT(dinfo, JERR_BUFFER_SIZE);
+ } else {
+ src->pub.next_input_byte += (size_t) num_bytes;
+ src->pub.bytes_in_buffer -= (size_t) num_bytes;
+ }
+}
+
+JpegDecompressor::JpegDecompressor(void)
+{
+ dinfo = new jpeg_decompress_struct;
+
+ err = new struct JPEG_ERROR_MGR;
+ dinfo->err = jpeg_std_error(&err->pub);
+ snprintf(err->lastError, JMSG_LENGTH_MAX, "No error");
+ err->pub.error_exit = JpegErrorExit;
+ err->pub.output_message = JpegOutputMessage;
+
+ if(setjmp(err->jmpBuffer)) {
+ // this will execute if libjpeg has an error
+ throw rdr::Exception(err->lastError);
+ }
+
+ jpeg_create_decompress(dinfo);
+
+ src = new struct JPEG_SRC_MGR;
+ src->pub.init_source = JpegNoOp;
+ src->pub.fill_input_buffer = JpegFillInputBuffer;
+ src->pub.skip_input_data = JpegSkipInputData;
+ src->pub.resync_to_restart = jpeg_resync_to_restart;
+ src->pub.term_source = JpegNoOp;
+ src->instance = this;
+ dinfo->src = (struct jpeg_source_mgr *)src;
+}
+
+JpegDecompressor::~JpegDecompressor(void)
+{
+ if(setjmp(err->jmpBuffer)) {
+ // this will execute if libjpeg has an error
+ return;
+ }
+
+ jpeg_destroy_decompress(dinfo);
+
+ delete err;
+ delete src;
+
+ delete dinfo;
+}
+
+void JpegDecompressor::decompress(const rdr::U8 *jpegBuf, int jpegBufLen,
+ rdr::U8 *buf, int pitch, const Rect& r, const PixelFormat& pf)
+{
+ int w = r.width();
+ int h = r.height();
+ int pixelsize;
+ int dstBufPitch;
+ rdr::U8 *dstBuf = NULL;
+ bool dstBufIsTemp = false;
+ JSAMPROW *rowPointer = NULL;
+
+ if(setjmp(err->jmpBuffer)) {
+ // this will execute if libjpeg has an error
+ jpeg_abort_decompress(dinfo);
+ if (dstBufIsTemp && dstBuf) delete[] dstBuf;
+ if (rowPointer) delete[] rowPointer;
+ throw rdr::Exception(err->lastError);
+ }
+
+ src->pub.next_input_byte = jpegBuf;
+ src->pub.bytes_in_buffer = jpegBufLen;
+
+ jpeg_read_header(dinfo, TRUE);
+ dinfo->out_color_space = JCS_RGB;
+ pixelsize = 3;
+ if (pitch == 0) pitch = w * pf.bpp / 8;
+ dstBufPitch = pitch;
+
+#ifdef JCS_EXTENSIONS
+ // Try to have libjpeg output directly to our native format
+ if (pf.is888()) {
+ int redShift, greenShift, blueShift;
+
+ if(pf.bigEndian) {
+ redShift = 24 - pf.redShift;
+ greenShift = 24 - pf.greenShift;
+ blueShift = 24 - pf.blueShift;
+ } else {
+ redShift = pf.redShift;
+ greenShift = pf.greenShift;
+ blueShift = pf.blueShift;
+ }
+
+ // libjpeg can only handle some "standard" formats
+ if(redShift == 0 && greenShift == 8 && blueShift == 16)
+ dinfo->out_color_space = JCS_EXT_RGBX;
+ if(redShift == 16 && greenShift == 8 && blueShift == 0)
+ dinfo->out_color_space = JCS_EXT_BGRX;
+ if(redShift == 24 && greenShift == 16 && blueShift == 8)
+ dinfo->out_color_space = JCS_EXT_XBGR;
+ if(redShift == 8 && greenShift == 16 && blueShift == 24)
+ dinfo->out_color_space = JCS_EXT_XRGB;
+
+ if (dinfo->out_color_space != JCS_RGB) {
+ dstBuf = (rdr::U8 *)buf;
+ pixelsize = 4;
+ }
+ }
+#endif
+
+ if (dinfo->out_color_space == JCS_RGB) {
+ dstBuf = new rdr::U8[w * h * pixelsize];
+ dstBufIsTemp = true;
+ dstBufPitch = w * pixelsize;
+ }
+
+ rowPointer = new JSAMPROW[h];
+ for (int dy = 0; dy < h; dy++)
+ rowPointer[dy] = (JSAMPROW)(&dstBuf[dy * dstBufPitch]);
+
+ jpeg_start_decompress(dinfo);
+
+ if (dinfo->output_width != (unsigned)r.width()
+ || dinfo->output_height != (unsigned)r.height()
+ || dinfo->output_components != pixelsize) {
+ jpeg_abort_decompress(dinfo);
+ if (dstBufIsTemp && dstBuf) delete[] dstBuf;
+ if (rowPointer) delete[] rowPointer;
+ throw rdr::Exception("Tight Decoding: Wrong JPEG data received.\n");
+ }
+
+ while (dinfo->output_scanline < dinfo->output_height) {
+ jpeg_read_scanlines(dinfo, &rowPointer[dinfo->output_scanline],
+ dinfo->output_height - dinfo->output_scanline);
+ }
+
+ if (dinfo->out_color_space == JCS_RGB)
+ pf.bufferFromRGB((rdr::U8*)buf, dstBuf, w, pitch, h);
+
+ jpeg_finish_decompress(dinfo);
+
+ if (dstBufIsTemp) delete [] dstBuf;
+ delete[] rowPointer;
+}
diff --git a/common/rfb/JpegDecompressor.h b/common/rfb/JpegDecompressor.h
new file mode 100644
index 00000000..ed367786
--- /dev/null
+++ b/common/rfb/JpegDecompressor.h
@@ -0,0 +1,60 @@
+/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright (C) 2004-2005 Cendio AB. All rights reserved.
+ * Copyright (C) 2011 D. R. Commander. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+//
+// JpegDecompressor decompresses a JPEG image into RGB output
+// an underlying MemOutStream
+//
+
+#ifndef __RFB_JPEGDECOMPRESSOR_H__
+#define __RFB_JPEGDECOMPRESSOR_H__
+
+#include <rfb/PixelFormat.h>
+#include <rfb/Rect.h>
+
+struct jpeg_decompress_struct;
+
+struct JPEG_ERROR_MGR;
+struct JPEG_SRC_MGR;
+
+namespace rfb {
+
+ class JpegDecompressor {
+
+ public:
+
+ JpegDecompressor(void);
+ virtual ~JpegDecompressor();
+
+ void decompress(const rdr::U8 *, int, rdr::U8 *, int, const Rect&,
+ const PixelFormat&);
+
+ private:
+
+ struct jpeg_decompress_struct *dinfo;
+
+ struct JPEG_ERROR_MGR *err;
+ struct JPEG_SRC_MGR *src;
+
+ };
+
+} // end of namespace rfb
+
+#endif