From 6a83d38e7b2502649f652e28834b7823c46db7be Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 9 Sep 2021 23:52:39 -0400 Subject: [PATCH] Add code to load jpegs This lets us avoid gdk-pixbuf for loading textures from the common image formats. As a consequence, we are now linking against libjpeg. --- gdk/loaders/gdkjpeg.c | 127 +++++++++++++++++++++++++++++++++++ gdk/loaders/gdkjpegprivate.h | 29 ++++++++ gdk/meson.build | 3 +- meson.build | 14 ++++ 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 gdk/loaders/gdkjpeg.c create mode 100644 gdk/loaders/gdkjpegprivate.h diff --git a/gdk/loaders/gdkjpeg.c b/gdk/loaders/gdkjpeg.c new file mode 100644 index 0000000000..dc17c7f26e --- /dev/null +++ b/gdk/loaders/gdkjpeg.c @@ -0,0 +1,127 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2021 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#include "config.h" + +#include "gdkjpegprivate.h" + +#include "gdktexture.h" +#include "gdkmemorytextureprivate.h" +#include +#include +#include + +/* {{{ Error handling */ + +/* No sigsetjmp on Windows */ +#ifndef HAVE_SIGSETJMP +#define sigjmp_buf jmp_buf +#define sigsetjmp(jb, x) setjmp(jb) +#define siglongjmp longjmp +#endif + +struct error_handler_data { + struct jpeg_error_mgr pub; + sigjmp_buf setjmp_buffer; + GError **error; +}; + +static void +fatal_error_handler (j_common_ptr cinfo) +{ + struct error_handler_data *errmgr; + + errmgr = (struct error_handler_data *) cinfo->err; + + siglongjmp (errmgr->setjmp_buffer, 1); + + g_assert_not_reached (); +} + +static void +output_message_handler (j_common_ptr cinfo) +{ + /* do nothing */ +} + +/* }}} */ + /* {{{ Public API */ + +GdkTexture * +gdk_load_jpeg (GBytes *input_bytes, + GError **error) +{ + struct jpeg_decompress_struct info; + struct error_handler_data jerr; + struct jpeg_error_mgr err; + int width, height; + int size; + unsigned char *data; + unsigned char *row[1]; + GBytes *bytes; + GdkTexture *texture; + + info.err = jpeg_std_error (&jerr.pub); + jerr.pub.error_exit = fatal_error_handler; + jerr.pub.output_message = output_message_handler; + jerr.error = error; + + if (sigsetjmp (jerr.setjmp_buffer, 1)) + { + jpeg_destroy_decompress (&info); + return NULL; + } + + info.err = jpeg_std_error (&err); + jpeg_create_decompress (&info); + + jpeg_mem_src (&info, + g_bytes_get_data (input_bytes, NULL), + g_bytes_get_size (input_bytes)); + + jpeg_read_header (&info, TRUE); + jpeg_start_decompress (&info); + + width = info.output_width; + height = info.output_height; + + size = width * height * 3; + data = g_malloc (size); + + while (info.output_scanline < info.output_height) + { + row[0] = (unsigned char *)(&data[3 *info.output_width * info.output_scanline]); + jpeg_read_scanlines (&info, row, 1); + } + + jpeg_finish_decompress (&info); + jpeg_destroy_decompress (&info); + + bytes = g_bytes_new_take (data, size); + + texture = gdk_memory_texture_new (width, height, + GDK_MEMORY_R8G8B8, + bytes, width * 3); + + g_bytes_unref (bytes); + + return texture; +} + +/* }}} */ + +/* vim:set foldmethod=marker expandtab: */ diff --git a/gdk/loaders/gdkjpegprivate.h b/gdk/loaders/gdkjpegprivate.h new file mode 100644 index 0000000000..a8e6bd8a82 --- /dev/null +++ b/gdk/loaders/gdkjpegprivate.h @@ -0,0 +1,29 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2021 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + */ + +#ifndef __GDK_JPEG_PRIVATE_H__ +#define __GDK_JPEG_PRIVATE_H__ + +#include "gdkmemorytexture.h" +#include + +#define JPEG_SIGNATURE "\xff\xd8" + +GdkTexture *gdk_load_jpeg (GBytes *bytes, + GError **error); + +#endif diff --git a/gdk/meson.build b/gdk/meson.build index 706053cccf..46a6bd7dd5 100644 --- a/gdk/meson.build +++ b/gdk/meson.build @@ -53,6 +53,7 @@ gdk_public_sources = files([ 'gdkdragsurface.c', 'loaders/gdkpng.c', 'loaders/gdktiff.c', + 'loaders/gdkjpeg.c', ]) gdk_public_headers = files([ @@ -258,7 +259,7 @@ endif libgdk = static_library('gdk', sources: [gdk_sources, gdk_backends_gen_headers, gdkconfig], - dependencies: gdk_deps + [libgtk_css_dep, png_dep, tiff_dep], + dependencies: gdk_deps + [libgtk_css_dep, png_dep, tiff_dep, jpeg_dep], link_with: [libgtk_css], include_directories: [confinc, gdkx11_inc, wlinc], c_args: libgdk_c_args + common_cflags, diff --git a/meson.build b/meson.build index 3904f21ec0..4d6f2740d1 100644 --- a/meson.build +++ b/meson.build @@ -207,6 +207,17 @@ foreach func : check_functions endif endforeach +# We use links() because sigsetjmp() is often a macro hidden behind other macros +cdata.set('HAVE_SIGSETJMP', + cc.links('''#define _POSIX_SOURCE + #include + int main (void) { + sigjmp_buf env; + sigsetjmp (env, 0); + return 0; + }''', name: 'sigsetjmp'), +) + # Check for __uint128_t (gcc) by checking for 128-bit division uint128_t_src = '''int main() { static __uint128_t v1 = 100; @@ -395,6 +406,9 @@ png_dep = dependency('libpng', tiff_dep = dependency('libtiff-4', fallback: ['libtiff', 'libtiff4_dep'], required: true) +jpeg_dep = dependency('libjpeg', + fallback: ['libjpeg-turbo', 'jpeg_dep'], + required: true) epoxy_dep = dependency('epoxy', version: epoxy_req, fallback: ['libepoxy', 'libepoxy_dep'])