2 * Copyright (C) 20019 - The Geeqie Team
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "image-load.h"
24 #include "image_load_j2k.h"
30 #include <sys/sysinfo.h>
33 typedef struct _ImageLoaderJ2K ImageLoaderJ2K;
34 struct _ImageLoaderJ2K {
35 ImageLoaderBackendCbAreaUpdated area_updated_cb;
36 ImageLoaderBackendCbSize size_cb;
37 ImageLoaderBackendCbAreaPrepared area_prepared_cb;
40 guint requested_width;
41 guint requested_height;
45 static void free_buffer(guchar *pixels, gpointer data)
50 typedef struct opj_buffer_info {
56 static OPJ_SIZE_T opj_read_from_buffer (void* pdst, OPJ_SIZE_T len, opj_buffer_info_t* psrc)
58 OPJ_SIZE_T n = psrc->buf + psrc->len - psrc->cur;
64 memcpy (pdst, psrc->cur, n);
73 static OPJ_SIZE_T opj_write_to_buffer (void* p_buffer, OPJ_SIZE_T p_nb_bytes,
74 opj_buffer_info_t* p_source_buffer)
76 void* pbuf = p_source_buffer->buf;
77 void* pcur = p_source_buffer->cur;
79 OPJ_SIZE_T len = p_source_buffer->len;
84 OPJ_SIZE_T dist = pcur - pbuf, n = len - dist;
85 g_assert (dist <= len);
87 while (n < p_nb_bytes) {
92 if (len != p_source_buffer->len) {
96 return (OPJ_SIZE_T)-1;
98 if (p_source_buffer->buf) {
99 memcpy (pbuf, p_source_buffer->buf, dist);
100 free (p_source_buffer->buf);
103 p_source_buffer->buf = pbuf;
104 p_source_buffer->cur = pbuf + dist;
105 p_source_buffer->len = len;
108 memcpy (p_source_buffer->cur, p_buffer, p_nb_bytes);
109 p_source_buffer->cur += p_nb_bytes;
114 static OPJ_SIZE_T opj_skip_from_buffer (OPJ_SIZE_T len, opj_buffer_info_t* psrc)
116 OPJ_SIZE_T n = psrc->buf + psrc->len - psrc->cur;
130 static OPJ_BOOL opj_seek_from_buffer (OPJ_OFF_T len, opj_buffer_info_t* psrc)
132 OPJ_SIZE_T n = psrc->len;
137 psrc->cur = psrc->buf + n;
142 opj_stream_t* OPJ_CALLCONV opj_stream_create_buffer_stream (opj_buffer_info_t* psrc, OPJ_BOOL input)
147 opj_stream_t* ps = opj_stream_default_create (input);
152 opj_stream_set_user_data (ps, psrc, 0);
153 opj_stream_set_user_data_length (ps, psrc->len);
156 opj_stream_set_read_function (
157 ps, (opj_stream_read_fn)opj_read_from_buffer);
159 opj_stream_set_write_function(
160 ps,(opj_stream_write_fn) opj_write_to_buffer);
162 opj_stream_set_skip_function (
163 ps, (opj_stream_skip_fn)opj_skip_from_buffer);
165 opj_stream_set_seek_function (
166 ps, (opj_stream_seek_fn)opj_seek_from_buffer);
171 static gboolean image_loader_j2k_load(gpointer loader, const guchar *buf, gsize count, GError **error)
173 ImageLoaderJ2K *ld = (ImageLoaderJ2K *) loader;
174 ImageLoader *il = ld->data;
175 opj_stream_t *stream;
177 opj_dparameters_t parameters;
184 gint bytes_per_pixel;
185 opj_buffer_info_t *decode_buffer;
192 buf_copy = (guchar *) g_malloc(count);
193 memcpy(buf_copy, buf, count);
195 decode_buffer = g_new0(opj_buffer_info_t, 1);
196 decode_buffer->buf = buf_copy;
197 decode_buffer->len = count;
198 decode_buffer->cur = buf_copy;
200 stream = opj_stream_create_buffer_stream(decode_buffer, OPJ_TRUE);
204 log_printf(_("Could not open file for reading"));
208 if (memcmp(buf_copy + 20, "jp2", 3) == 0)
210 codec = opj_create_decompress(OPJ_CODEC_JP2);
214 log_printf(_("Unknown jpeg2000 decoder type"));
218 opj_set_default_decoder_parameters(¶meters);
219 if (opj_setup_decoder (codec, ¶meters) != OPJ_TRUE)
221 log_printf(_("Couldn't set parameters on decoder for file."));
225 opj_codec_set_threads(codec, get_cpu_cores());
227 if (opj_read_header(stream, codec, &image) != OPJ_TRUE)
229 log_printf(_("Couldn't read JP2 header from file"));
233 if (opj_decode(codec, stream, image) != OPJ_TRUE)
235 log_printf(_("Couldn't decode JP2 image in file"));
239 if (opj_end_decompress(codec, stream) != OPJ_TRUE)
241 log_printf(_("Couldn't decompress JP2 image in file"));
245 num_components = image->numcomps;
246 if (num_components != 3)
248 log_printf(_("JP2 image not rgb"));
252 width = image->comps[0].w;
253 height = image->comps[0].h;
257 pixels = g_new0(guchar, width * bytes_per_pixel * height);
258 for (i = 0; i < height; i++)
260 for (j = 0; j < num_components; j++)
262 for (k = 0; k < width; k++)
264 pixels[(k * bytes_per_pixel + j) + (i * width * bytes_per_pixel)] = image->comps[j].data[i * width + k];
269 ld->pixbuf = gdk_pixbuf_new_from_data(pixels, GDK_COLORSPACE_RGB, FALSE , 8, width, height, width * bytes_per_pixel, free_buffer, NULL);
271 ld->area_updated_cb(loader, 0, 0, width, height, ld->data);
273 g_free(decode_buffer);
276 opj_image_destroy (image);
278 opj_destroy_codec (codec);
280 opj_stream_destroy (stream);
285 static gpointer image_loader_j2k_new(ImageLoaderBackendCbAreaUpdated area_updated_cb, ImageLoaderBackendCbSize size_cb, ImageLoaderBackendCbAreaPrepared area_prepared_cb, gpointer data)
287 ImageLoaderJ2K *loader = g_new0(ImageLoaderJ2K, 1);
288 loader->area_updated_cb = area_updated_cb;
289 loader->size_cb = size_cb;
290 loader->area_prepared_cb = area_prepared_cb;
292 return (gpointer) loader;
295 static void image_loader_j2k_set_size(gpointer loader, int width, int height)
297 ImageLoaderJ2K *ld = (ImageLoaderJ2K *) loader;
298 ld->requested_width = width;
299 ld->requested_height = height;
302 static GdkPixbuf* image_loader_j2k_get_pixbuf(gpointer loader)
304 ImageLoaderJ2K *ld = (ImageLoaderJ2K *) loader;
308 static gchar* image_loader_j2k_get_format_name(gpointer loader)
310 return g_strdup("j2k");
313 static gchar** image_loader_j2k_get_format_mime_types(gpointer loader)
315 static gchar *mime[] = {"image/jp2", NULL};
316 return g_strdupv(mime);
319 static gboolean image_loader_j2k_close(gpointer loader, GError **error)
324 static void image_loader_j2k_abort(gpointer loader)
326 ImageLoaderJ2K *ld = (ImageLoaderJ2K *) loader;
330 static void image_loader_j2k_free(gpointer loader)
332 ImageLoaderJ2K *ld = (ImageLoaderJ2K *) loader;
333 if (ld->pixbuf) g_object_unref(ld->pixbuf);
337 void image_loader_backend_set_j2k(ImageLoaderBackend *funcs)
339 funcs->loader_new = image_loader_j2k_new;
340 funcs->set_size = image_loader_j2k_set_size;
341 funcs->load = image_loader_j2k_load;
343 funcs->get_pixbuf = image_loader_j2k_get_pixbuf;
344 funcs->close = image_loader_j2k_close;
345 funcs->abort = image_loader_j2k_abort;
346 funcs->free = image_loader_j2k_free;
347 funcs->get_format_name = image_loader_j2k_get_format_name;
348 funcs->get_format_mime_types = image_loader_j2k_get_format_mime_types;
352 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */