summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorErkin Bahceci <erkinbah@gmail.com>2009-07-23 19:32:34 -0500
committerErkin Bahceci <erkinbah@gmail.com>2009-07-23 19:32:34 -0500
commit5e69064329054569cf7d56f82d783ad0b565c826 (patch)
treebc53b323e4e6aa726e49d376efbee84262be711c /src
parent97c86a485365a7f7a318b5d189e1d510922c494b (diff)
downloadjpeg-5e69064329054569cf7d56f82d783ad0b565c826.tar.gz
jpeg-5e69064329054569cf7d56f82d783ad0b565c826.tar.bz2
Initial C++ port.
Diffstat (limited to 'src')
-rw-r--r--src/imgjpeg.cpp310
-rw-r--r--src/imgjpeg.h75
2 files changed, 385 insertions, 0 deletions
diff --git a/src/imgjpeg.cpp b/src/imgjpeg.cpp
new file mode 100644
index 0000000..4fcbe6f
--- /dev/null
+++ b/src/imgjpeg.cpp
@@ -0,0 +1,310 @@
+/*
+ * beryl-plugins::jpeg.c - adds JPEG image support to beryl.
+ * Copyright: (C) 2006 Nicholas Thomas
+ * Danny Baumann (JPEG writing, option stuff)
+ *
+ * This program 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 program 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 program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "imgjpeg.h"
+
+COMPIZ_PLUGIN_20090315 (imgjpeg, JpegPluginVTable)
+
+static bool
+rgbToBGRA (const JSAMPLE *source,
+ void *&data,
+ CompSize &size,
+ int alpha)
+{
+ int h, w;
+ char *dest;
+ int height = size.height ();
+ int width = size.width ();
+
+ dest = (char *) malloc (height * width * 4);
+ if (!dest)
+ return false;
+
+ data = dest;
+
+ for (h = 0; h < height; h++)
+ for (w = 0; w < width; w++)
+ {
+ int pos = h * width + w;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ dest[(pos * 4) + 3] = source[(pos * 3) + 2]; /* blue */
+ dest[(pos * 4) + 2] = source[(pos * 3) + 1]; /* green */
+ dest[(pos * 4) + 1] = source[(pos * 3) + 0]; /* red */
+ dest[(pos * 4) + 0] = alpha;
+#else
+ dest[(pos * 4) + 0] = source[(pos * 3) + 2]; /* blue */
+ dest[(pos * 4) + 1] = source[(pos * 3) + 1]; /* green */
+ dest[(pos * 4) + 2] = source[(pos * 3) + 0]; /* red */
+ dest[(pos * 4) + 3] = alpha;
+#endif
+ }
+
+ return true;
+}
+
+static bool
+rgbaToRGB (unsigned char *source,
+ JSAMPLE **dest,
+ CompSize &size,
+ int stride)
+{
+ int h, w;
+ int height = size.height ();
+ int width = size.width ();
+ int ps = stride / width; /* pixel size */
+ JSAMPLE *d;
+
+ d = (JSAMPLE *) malloc (height * width * 3 * sizeof (JSAMPLE));
+ if (!d)
+ return false;
+
+ *dest = d;
+
+ for (h = 0; h < height; h++)
+ for (w = 0; w < width; w++)
+ {
+ int pos = h * width + w;
+#if __BYTE_ORDER == __BIG_ENDIAN
+ d[(pos * 3) + 0] = source[(pos * ps) + 3]; /* red */
+ d[(pos * 3) + 1] = source[(pos * ps) + 2]; /* green */
+ d[(pos * 3) + 2] = source[(pos * ps) + 1]; /* blue */
+#else
+ d[(pos * 3) + 0] = source[(pos * ps) + 0]; /* red */
+ d[(pos * 3) + 1] = source[(pos * ps) + 1]; /* green */
+ d[(pos * 3) + 2] = source[(pos * ps) + 2]; /* blue */
+#endif
+ }
+
+ return true;
+}
+
+static void
+jpegErrorExit (j_common_ptr cinfo)
+{
+ char buffer[JMSG_LENGTH_MAX];
+ struct jpegErrorMgr *err = (struct jpegErrorMgr *) cinfo->err;
+
+ /* Format the message */
+ (*cinfo->err->format_message) (cinfo, buffer);
+
+ printf ("%s\n", buffer);
+
+ /* Return control to the setjmp point */
+ longjmp (err->setjmp_buffer, 1);
+}
+
+bool
+JpegScreen::readJPEG (FILE *file,
+ CompSize &size,
+ void *&data)
+{
+ struct jpeg_decompress_struct cinfo;
+ struct jpegErrorMgr jerr;
+ JSAMPLE *buf;
+ JSAMPROW *rows;
+ bool result;
+
+ if (!file)
+ return false;
+
+ cinfo.err = jpeg_std_error (&jerr.pub);
+ jerr.pub.error_exit = jpegErrorExit;
+
+ if (setjmp (jerr.setjmp_buffer))
+ {
+ /* this is called on decompression errors */
+ jpeg_destroy_decompress (&cinfo);
+ return false;
+ }
+
+ jpeg_create_decompress (&cinfo);
+
+ jpeg_stdio_src (&cinfo, file);
+
+ jpeg_read_header (&cinfo, true);
+
+ cinfo.out_color_space = JCS_RGB;
+
+ jpeg_start_decompress (&cinfo);
+
+ size.setHeight (cinfo.output_height);
+ size.setWidth (cinfo.output_width);
+
+ buf = (JSAMPLE *) calloc (cinfo.output_height * cinfo.output_width *
+ cinfo.output_components, sizeof (JSAMPLE));
+ if (!buf)
+ {
+ jpeg_finish_decompress (&cinfo);
+ jpeg_destroy_decompress (&cinfo);
+ return false;
+ }
+
+ rows = (JSAMPROW *) malloc (cinfo.output_height * sizeof (JSAMPROW));
+ if (!rows)
+ {
+ free (buf);
+ jpeg_finish_decompress (&cinfo);
+ jpeg_destroy_decompress (&cinfo);
+ return false;
+ }
+
+ for (unsigned int i = 0; i < cinfo.output_height; i++)
+ rows[i] = &buf[i * cinfo.output_width * cinfo.output_components];
+
+ while (cinfo.output_scanline < cinfo.output_height)
+ jpeg_read_scanlines (&cinfo, &rows[cinfo.output_scanline],
+ cinfo.output_height - cinfo.output_scanline);
+
+ jpeg_finish_decompress (&cinfo);
+ jpeg_destroy_decompress (&cinfo);
+
+ /* convert the rgb data into BGRA format */
+ result = rgbToBGRA (buf, data, size, 255);
+
+ free (rows);
+ free (buf);
+ return result;
+}
+
+bool
+JpegScreen::writeJPEG (unsigned char *buffer,
+ FILE *file,
+ CompSize &size,
+ int stride)
+{
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JSAMPROW row_pointer[1];
+ JSAMPLE *data;
+
+ /* convert the rgb data into BGRA format */
+ if (!rgbaToRGB (buffer, &data, size, stride))
+ return false;
+
+ cinfo.err = jpeg_std_error (&jerr);
+ jpeg_create_compress (&cinfo);
+
+ jpeg_stdio_dest (&cinfo, file);
+
+ cinfo.image_width = size.width ();
+ cinfo.image_height = size.height ();
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_RGB;
+
+ jpeg_set_defaults (&cinfo);
+ jpeg_set_quality (&cinfo, optionGetQuality (), true);
+ jpeg_start_compress (&cinfo, true);
+
+ while (cinfo.next_scanline < cinfo.image_height)
+ {
+ row_pointer[0] =
+ &data[(cinfo.image_height - cinfo.next_scanline - 1) *
+ size.width () * 3];
+ jpeg_write_scanlines (&cinfo, row_pointer, 1);
+ }
+
+ jpeg_finish_compress (&cinfo);
+ jpeg_destroy_compress (&cinfo);
+
+ free (data);
+
+ return true;
+}
+
+CompString
+JpegScreen::fileNameWithExtension (CompString &path)
+{
+ unsigned int len = path.length ();
+
+ if ((len > 5 && path.substr (len - 5, 5) == ".jpeg") ||
+ (len > 4 && path.substr (len - 4, 4) == ".jpg"))
+ return path;
+
+ return path + ".jpeg";
+}
+
+bool
+JpegScreen::imageToFile (CompString &path,
+ CompString &format,
+ CompSize &size,
+ int stride,
+ void *data)
+{
+ bool status = false;
+ FILE *file;
+ CompString fileName = fileNameWithExtension (path);
+
+ if (format == "jpeg" || format == "jpg" ||
+ !(status = screen->imageToFile (path, format, size, stride, data)))
+ {
+ file = fopen (fileName.c_str (), "wb");
+ if (file)
+ {
+ status = writeJPEG ((unsigned char *) data, file, size, stride);
+ fclose (file);
+ }
+ }
+
+ return status;
+}
+
+bool
+JpegScreen::fileToImage (CompString &name,
+ CompSize &size,
+ int &stride,
+ void *&data)
+{
+ bool status = false;
+ FILE *file;
+ CompString fileName = fileNameWithExtension (name);
+
+ file = fopen (fileName.c_str (), "rb");
+ if (file)
+ {
+ status = readJPEG (file, size, data);
+ fclose (file);
+ }
+
+ if (status)
+ {
+ stride = size.width () * 4;
+ return true;
+ }
+
+ /* Isn't a JPEG - pass to the next in the chain. */
+ return screen->fileToImage (name, size, stride, data);
+}
+
+JpegScreen::JpegScreen (CompScreen *screen) :
+ PluginClassHandler<JpegScreen, CompScreen> (screen)
+{
+ ScreenInterface::setHandler (screen, true);
+}
+
+bool
+JpegPluginVTable::init ()
+{
+ if (!CompPlugin::checkPluginABI ("core", CORE_ABIVERSION))
+ return false;
+
+ return true;
+}
+
diff --git a/src/imgjpeg.h b/src/imgjpeg.h
new file mode 100644
index 0000000..65d2cfd
--- /dev/null
+++ b/src/imgjpeg.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright © 2006 Novell, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Novell, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * Novell, Inc. makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+
+#include <core/core.h>
+#include <core/pluginclasshandler.h>
+
+#include <X11/Xarch.h>
+#include <jpeglib.h>
+
+#include "imgjpeg_options.h"
+
+
+
+struct jpegErrorMgr
+{
+ struct jpeg_error_mgr pub; /* "public" fields */
+ jmp_buf setjmp_buffer; /* for return to caller */
+};
+
+class JpegScreen :
+ public ScreenInterface,
+ public PluginClassHandler<JpegScreen, CompScreen>,
+ public ImgjpegOptions
+{
+ public:
+ JpegScreen (CompScreen *screen);
+
+ bool fileToImage (CompString &path, CompSize &size,
+ int &stride, void *&data);
+ bool imageToFile (CompString &path, CompString &format,
+ CompSize &size, int stride, void *data);
+
+ private:
+ CompString fileNameWithExtension (CompString &path);
+
+ bool readJPEG (FILE *file, CompSize &size, void *&data);
+ bool writeJPEG (unsigned char *buffer, FILE *file,
+ CompSize &size, int stride);
+};
+
+class JpegPluginVTable :
+ public CompPlugin::VTableForScreen<JpegScreen>
+{
+ public:
+ bool init ();
+};
+