Merge lp:~ballogy/gloobus-preview/drop-loaders into lp:gloobus-preview
- drop-loaders
- Merge into last_working_branch
Proposed by
Balló György
Status: | Merged |
---|---|
Merged at revision: | 307 |
Proposed branch: | lp:~ballogy/gloobus-preview/drop-loaders |
Merge into: | lp:gloobus-preview |
Diff against target: |
2351 lines (+0/-2281) 7 files modified
configure.ac (+0/-9) src/Makefile.am (+0/-2) src/loaders/PSD/Makefile.am (+0/-12) src/loaders/PSD/io-psd.c (+0/-598) src/loaders/XCF/Makefile.am (+0/-13) src/loaders/XCF/io-xcf.c (+0/-1641) src/plugin-pixbuf/plugin-pixbuf.h (+0/-6) |
To merge this branch: | bzr merge lp:~ballogy/gloobus-preview/drop-loaders |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gloobus Developers | Pending | ||
Review via email: mp+245375@code.launchpad.net |
Commit message
Description of the change
Remove custom gdk-pixbuf loaders
These are buggy and not needed anymore, since PSD and XCF formats are supported by the new imagemagick plugin.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'configure.ac' |
2 | --- configure.ac 2014-12-25 16:27:26 +0000 |
3 | +++ configure.ac 2014-12-26 04:45:12 +0000 |
4 | @@ -32,12 +32,8 @@ |
5 | AC_CHECK_LIB(gthread, g_thread_init) |
6 | AC_CHECK_LIB(pthread, pthread_create) |
7 | |
8 | -# To compile XCF loader ==> sudo apt-get install libtool libbz2-dev |
9 | -AC_CHECK_LIB(bz2,BZ2_bzDecompressInit,,AC_MSG_ERROR(Can not find libbz2)) |
10 | - |
11 | # *** checks for headers ***************************************************** # |
12 | AC_CHECK_HEADERS([stdlib.h string.h pthread.h]) |
13 | -AC_CHECK_HEADER(bzlib.h,,AC_MSG_ERROR(Can not find bzlib header)) # To compile XCF loader |
14 | |
15 | # *** checks for modules ***************************************************** # |
16 | PKG_CHECK_MODULES(ATK, atk) |
17 | @@ -57,9 +53,6 @@ |
18 | PKG_CHECK_MODULES(DBUS, dbus-glib-1) |
19 | PKG_CHECK_MODULES(X11, x11) |
20 | |
21 | -PKG_CHECK_MODULES(GMODULE, gmodule-2.0) # To compile XCF loader |
22 | -PKG_CHECK_MODULES(GDKPIXBUF, gdk-pixbuf-2.0) # To compile XCF loader |
23 | - |
24 | # Checks for typedefs, structures, and compiler characteristics. |
25 | AC_HEADER_STDBOOL |
26 | |
27 | @@ -90,8 +83,6 @@ |
28 | src/plugin-text/Makefile |
29 | src/plugin-ttf/Makefile |
30 | src/plugin-xps/Makefile |
31 | - src/loaders/PSD/Makefile |
32 | - src/loaders/XCF/Makefile |
33 | src/gloobus-sushi/Makefile |
34 | data/Makefile |
35 | data/images/Makefile |
36 | |
37 | === modified file 'src/Makefile.am' |
38 | --- src/Makefile.am 2014-12-25 16:27:26 +0000 |
39 | +++ src/Makefile.am 2014-12-26 04:45:12 +0000 |
40 | @@ -1,7 +1,5 @@ |
41 | SUBDIRS = \ |
42 | gloobus-sushi \ |
43 | - loaders/PSD \ |
44 | - loaders/XCF \ |
45 | plugin-comic \ |
46 | plugin-folder \ |
47 | plugin-compressed \ |
48 | |
49 | === removed directory 'src/loaders' |
50 | === removed directory 'src/loaders/PSD' |
51 | === removed file 'src/loaders/PSD/Makefile.am' |
52 | --- src/loaders/PSD/Makefile.am 2010-08-21 18:06:49 +0000 |
53 | +++ src/loaders/PSD/Makefile.am 1970-01-01 00:00:00 +0000 |
54 | @@ -1,12 +0,0 @@ |
55 | -#pluginexecdir = $(prefix)/lib/gtk-2.0/2.10.0/loaders/ |
56 | -pluginexecdir = $(prefix)/lib/gdk-pixbuf-2.0/2.10.0/loaders/ |
57 | - |
58 | -AM_CPPFLAGS += $(GTK_CFLAGS) -shared -fpic -std=c99 -DGDK_PIXBUF_ENABLE_BACKEND |
59 | -AM_LDFLAGS = $(GTK_LIBS) |
60 | - |
61 | -pluginexec_LTLIBRARIES = libpixbufloader-psd.la |
62 | -libpixbufloader_psd_la_SOURCES = io-psd.c |
63 | -libpixbufloader_psd_la_LDFLAGS = -module -export-dynamic $(AM_LDFLAGS) |
64 | - |
65 | -#install-exec-hook: |
66 | -# install -d $(prefix)/lib/gdk-pixbuf-2.0/2.10.0/loaders/ |
67 | |
68 | === removed file 'src/loaders/PSD/io-psd.c' |
69 | --- src/loaders/PSD/io-psd.c 2009-12-23 17:50:28 +0000 |
70 | +++ src/loaders/PSD/io-psd.c 1970-01-01 00:00:00 +0000 |
71 | @@ -1,598 +0,0 @@ |
72 | -/* -*- mode: C; c-file-style: "linux" -*- */ |
73 | -/* GdkPixbuf library - PSD image loader |
74 | - * |
75 | - * Copyright (C) 2008 Jan Dudek |
76 | - * |
77 | - * Authors: Jan Dudek <jd@jandudek.com> |
78 | - * |
79 | - * This library is free software; you can redistribute it and/or |
80 | - * modify it under the terms of the GNU Lesser General Public |
81 | - * License as published by the Free Software Foundation; either |
82 | - * version 2 of the License, or (at your option) any later version. |
83 | - * |
84 | - * This library is distributed in the hope that it will be useful, |
85 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
86 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
87 | - * Lesser General Public License for more |
88 | - * You should have received a copy of the GNU Lesser General Public |
89 | - * License along with this library; if not, write to the |
90 | - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
91 | - * Boston, MA 02111-1307, USA. |
92 | - */ |
93 | - |
94 | -/* |
95 | - * TODO |
96 | - * - use http://library.gnome.org/devel/glib/unstable/glib-Byte-Order-Macros.html |
97 | - * - report errors from parse_psd_header |
98 | - * - other color modes (CMYK at least) |
99 | - * - i18n |
100 | - */ |
101 | - |
102 | -#include <stdlib.h> |
103 | -#include <stdio.h> |
104 | -#include <string.h> |
105 | -#include <gdk-pixbuf/gdk-pixbuf-io.h> |
106 | -#include <glib/gstdio.h> |
107 | - |
108 | - |
109 | -typedef struct |
110 | -{ |
111 | - guchar signature[4]; /* file ID, always "8BPS" */ |
112 | - guint16 version; /* version number, always 1 */ |
113 | - guchar resetved[6]; |
114 | - guint16 channels; /* number of color channels (1-24) */ |
115 | - guint32 rows; /* height of image in pixels (1-30000) */ |
116 | - guint32 columns; /* width of image in pixels (1-30000) */ |
117 | - guint16 depth; /* number of bits per channel (1, 8, and 16) */ |
118 | - guint16 color_mode; /* color mode as defined below */ |
119 | -} PsdHeader; |
120 | - |
121 | -#define PSD_HEADER_SIZE 26 |
122 | - |
123 | -typedef enum |
124 | -{ |
125 | - PSD_MODE_MONO = 0, |
126 | - PSD_MODE_GRAYSCALE = 1, |
127 | - PSD_MODE_INDEXED = 2, |
128 | - PSD_MODE_RGB = 3, |
129 | - PSD_MODE_CMYK = 4, |
130 | - PSD_MODE_MULTICHANNEL = 7, |
131 | - PSD_MODE_DUOTONE = 8, |
132 | - PSD_MODE_LAB = 9, |
133 | -} PsdColorMode; |
134 | - |
135 | -typedef enum |
136 | -{ |
137 | - PSD_COMPRESSION_NONE = 0, |
138 | - PSD_COMPRESSION_RLE = 1 |
139 | -} PsdCompressionType; |
140 | - |
141 | -typedef enum |
142 | -{ |
143 | - PSD_STATE_HEADER, |
144 | - PSD_STATE_COLOR_MODE_BLOCK, |
145 | - PSD_STATE_RESOURCES_BLOCK, |
146 | - PSD_STATE_LAYERS_BLOCK, |
147 | - PSD_STATE_COMPRESSION, |
148 | - PSD_STATE_LINES_LENGTHS, |
149 | - PSD_STATE_CHANNEL_DATA, |
150 | - PSD_STATE_DONE |
151 | -} PsdReadState; |
152 | - |
153 | -typedef struct |
154 | -{ |
155 | - PsdReadState state; |
156 | - |
157 | - GdkPixbuf* pixbuf; |
158 | - |
159 | - GdkPixbufModuleSizeFunc size_func; |
160 | - GdkPixbufModuleUpdatedFunc updated_func; |
161 | - GdkPixbufModulePreparedFunc prepared_func; |
162 | - gpointer user_data; |
163 | - |
164 | - guchar* buffer; |
165 | - guint bytes_read; |
166 | - guint32 bytes_to_skip; |
167 | - gboolean bytes_to_skip_known; |
168 | - |
169 | - guint32 width; /* width of image in pixels (1-30000) */ |
170 | - guint32 height; /* height of image in pixels (1-30000) */ |
171 | - guint16 channels; /* number of color channels (1-24) */ |
172 | - guint16 depth; /* number of bits per channel (1/8/16) */ |
173 | - PsdColorMode color_mode; |
174 | - PsdCompressionType compression; |
175 | - |
176 | - guchar** ch_bufs; /* channels buffers */ |
177 | - guint curr_ch; /* current channel */ |
178 | - guint curr_row; |
179 | - guint pos; // redundant? |
180 | - guint16* lines_lengths; |
181 | - gboolean finalized; |
182 | - gboolean use_alpha; |
183 | -} PsdContext; |
184 | - |
185 | - |
186 | -static guint16 |
187 | -read_uint16 (guchar* buf) |
188 | -{ |
189 | - return (buf[0] << 8) | buf[1]; |
190 | -} |
191 | - |
192 | -static guint32 |
193 | -read_uint32 (guchar* buf) |
194 | -{ |
195 | - return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; |
196 | -} |
197 | - |
198 | - |
199 | -/* |
200 | - * Parse Psdheader from buffer |
201 | - * |
202 | - * str is expected to be at least PSD_HEADER_SIZE long |
203 | - */ |
204 | -static PsdHeader |
205 | -psd_parse_header (guchar* str) |
206 | -{ |
207 | - PsdHeader hd; |
208 | - |
209 | - memcpy(hd.signature, str, 4); |
210 | - hd.version = read_uint16(str + 4); |
211 | - hd.channels = read_uint16(str + 12); |
212 | - hd.rows = read_uint32(str + 14); |
213 | - hd.columns = read_uint32(str + 18); |
214 | - hd.depth = read_uint16(str + 22); |
215 | - hd.color_mode = read_uint16(str + 24); |
216 | - |
217 | - return hd; |
218 | -} |
219 | - |
220 | -/* |
221 | - * Attempts to read bytes_needed bytes from data and stores them in buffer. |
222 | - * |
223 | - * Returns true if there were enough bytes and false otherwise |
224 | - * (which means we need to call feed_buffer again) |
225 | - */ |
226 | -static gboolean |
227 | -feed_buffer (guchar* buffer, |
228 | - guint* bytes_read, |
229 | - const guchar** data, |
230 | - guint* size, |
231 | - guint bytes_needed) |
232 | -{ |
233 | - gint how_many = bytes_needed - *bytes_read; |
234 | - if (how_many > *size) { |
235 | - how_many = *size; |
236 | - } |
237 | - memcpy(buffer + *bytes_read, *data, how_many); |
238 | - *bytes_read += how_many; |
239 | - *data += how_many; |
240 | - *size -= how_many; |
241 | - return (*bytes_read == bytes_needed); |
242 | -} |
243 | - |
244 | -/* |
245 | - * Attempts to read size of the block and then skip this block. |
246 | - * |
247 | - * Returns true when finishes consuming block data, otherwise false |
248 | - * (false means we need to call skip_block again) |
249 | - */ |
250 | -static gboolean |
251 | -skip_block (PsdContext* context, const guchar** data, guint* size) |
252 | -{ |
253 | - static guint counter; |
254 | - |
255 | - if (!context->bytes_to_skip_known) { |
256 | - context->bytes_read = 0; |
257 | - if (feed_buffer(context->buffer, &context->bytes_read, data, size, 4)) { |
258 | - context->bytes_to_skip = read_uint32(context->buffer); |
259 | - context->bytes_to_skip_known = TRUE; |
260 | - counter = 0; |
261 | - } else { |
262 | - return FALSE; |
263 | - } |
264 | - } |
265 | - if (*size < context->bytes_to_skip) { |
266 | - *data += *size; |
267 | - context->bytes_to_skip -= *size; |
268 | - counter += *size; |
269 | - *size = 0; |
270 | - return FALSE; |
271 | - } else { |
272 | - counter += context->bytes_to_skip; |
273 | - *size -= context->bytes_to_skip; |
274 | - *data += context->bytes_to_skip; |
275 | - return TRUE; |
276 | - } |
277 | -} |
278 | - |
279 | -/* |
280 | - * Decodes RLE-compressed data |
281 | - */ |
282 | -static void |
283 | -decompress_line(const guchar* src, guint line_length, guchar* dest) |
284 | -{ |
285 | - guint16 bytes_read = 0; |
286 | - while (bytes_read < line_length) { |
287 | - gchar byte = src[bytes_read]; |
288 | - ++bytes_read; |
289 | - |
290 | - if (byte == -128) { |
291 | - continue; |
292 | - } else if (byte > -1) { |
293 | - gint count = byte + 1; |
294 | - |
295 | - // copy next count bytes |
296 | - for (int k = 0; k < count; ++k) { |
297 | - *dest = src[bytes_read]; |
298 | - ++dest; |
299 | - ++bytes_read; |
300 | - } |
301 | - } else { |
302 | - gint count = -byte + 1; |
303 | - |
304 | - // copy next byte count times |
305 | - guchar next_byte = src[bytes_read]; |
306 | - ++bytes_read; |
307 | - for (int k = 0; k < count; ++k) { |
308 | - *dest = next_byte; |
309 | - ++dest; |
310 | - } |
311 | - } |
312 | - } |
313 | -} |
314 | - |
315 | -static void |
316 | -reset_context_buffer(PsdContext* ctx) |
317 | -{ |
318 | - ctx->bytes_read = 0; |
319 | - ctx->bytes_to_skip = 0; |
320 | - ctx->bytes_to_skip_known = FALSE; |
321 | -} |
322 | - |
323 | -static gpointer |
324 | -gdk_pixbuf__psd_image_begin_load (GdkPixbufModuleSizeFunc size_func, |
325 | - GdkPixbufModulePreparedFunc prepared_func, |
326 | - GdkPixbufModuleUpdatedFunc updated_func, |
327 | - gpointer user_data, |
328 | - GError **error) |
329 | -{ |
330 | - PsdContext* context = g_malloc(sizeof(PsdContext)); |
331 | - if (context == NULL) { |
332 | - g_set_error ( |
333 | - error, |
334 | - GDK_PIXBUF_ERROR, |
335 | - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, |
336 | - ("Not enough memory")); |
337 | - return NULL; |
338 | - } |
339 | - context->size_func = size_func; |
340 | - context->prepared_func = prepared_func; |
341 | - context->updated_func = updated_func; |
342 | - context->user_data = user_data; |
343 | - |
344 | - context->state = PSD_STATE_HEADER; |
345 | - |
346 | - // we'll allocate larger buffer once we know image size |
347 | - context->buffer = g_malloc(PSD_HEADER_SIZE); |
348 | - reset_context_buffer(context); |
349 | - |
350 | - context->ch_bufs = NULL; |
351 | - context->curr_ch = 0; |
352 | - context->curr_row = 0; |
353 | - context->pos = 0; |
354 | - context->lines_lengths = NULL; |
355 | - context->finalized = FALSE; |
356 | - context->use_alpha = FALSE; |
357 | - |
358 | - return (gpointer) context; |
359 | -} |
360 | - |
361 | -static gboolean |
362 | -gdk_pixbuf__psd_image_stop_load (gpointer context_ptr, GError **error) |
363 | -{ |
364 | - PsdContext *ctx = (PsdContext *) context_ptr; |
365 | - gboolean retval = TRUE; |
366 | - |
367 | - if (ctx->state != PSD_STATE_DONE) { |
368 | - g_set_error ( |
369 | - error, |
370 | - GDK_PIXBUF_ERROR, |
371 | - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, |
372 | - ("PSD file was corrupted or incomplete.")); |
373 | - retval = FALSE; |
374 | - } |
375 | - |
376 | - g_free(ctx->buffer); |
377 | - g_free(ctx->lines_lengths); |
378 | - if (ctx->ch_bufs) { |
379 | - for (int i = 0; i < ctx->channels; i++) { |
380 | - g_free(ctx->ch_bufs[i]); |
381 | - } |
382 | - } |
383 | - g_free(ctx); |
384 | - |
385 | - return retval; |
386 | -} |
387 | - |
388 | - |
389 | -static gboolean |
390 | -gdk_pixbuf__psd_image_load_increment (gpointer context_ptr, |
391 | - const guchar *data, |
392 | - guint size, |
393 | - GError **error) |
394 | -{ |
395 | - PsdContext* ctx = (PsdContext*) context_ptr; |
396 | - |
397 | - while (size > 0) { |
398 | - switch (ctx->state) { |
399 | - case PSD_STATE_HEADER: |
400 | - if (feed_buffer( |
401 | - ctx->buffer, &ctx->bytes_read, |
402 | - &data, &size, PSD_HEADER_SIZE)) |
403 | - { |
404 | - PsdHeader hd = psd_parse_header(ctx->buffer); |
405 | - |
406 | - ctx->width = hd.columns; |
407 | - ctx->height = hd.rows; |
408 | - ctx->channels = hd.channels; |
409 | - ctx->depth = hd.depth; |
410 | - ctx->color_mode = hd.color_mode; |
411 | - |
412 | - /* |
413 | - if (ctx->color_mode == PSD_MODE_RGB && ctx->channels == 4) { |
414 | - ctx->use_alpha = TRUE; |
415 | - }*/ |
416 | - |
417 | - //g_message("color_mode=%d, channels=%d, depth=%d", |
418 | - // ctx->color_mode, ctx->channels, ctx->depth); |
419 | - |
420 | - if (ctx->color_mode != PSD_MODE_RGB |
421 | - //&& ctx->color_mode != PSD_MODE_CMYK |
422 | - ) { |
423 | - g_set_error (error, GDK_PIXBUF_ERROR, |
424 | - GDK_PIXBUF_ERROR_UNKNOWN_TYPE, |
425 | - ("Unsupported color mode")); |
426 | - return FALSE; |
427 | - } |
428 | - |
429 | - if (ctx->depth != 8) { |
430 | - g_set_error (error, GDK_PIXBUF_ERROR, |
431 | - GDK_PIXBUF_ERROR_UNKNOWN_TYPE, |
432 | - ("Unsupported color depth")); |
433 | - return FALSE; |
434 | - } |
435 | - |
436 | - if (ctx->size_func) { |
437 | - gint w = ctx->width; |
438 | - gint h = ctx->height; |
439 | - ctx->size_func(&w, &h, ctx->user_data); |
440 | - if (w == 0 || h == 0) { |
441 | - return FALSE; |
442 | - } |
443 | - } |
444 | - |
445 | - // we need buffer that can contain one channel data of one |
446 | - // row in RLE compressed format. 2*width should be enough |
447 | - g_free(ctx->buffer); |
448 | - ctx->buffer = g_malloc(ctx->width * 2); |
449 | - |
450 | - // this will be needed for RLE decompression |
451 | - ctx->lines_lengths = |
452 | - g_malloc(2 * ctx->channels * ctx->height); |
453 | - |
454 | - ctx->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, |
455 | - ctx->use_alpha, 8, ctx->width, ctx->height); |
456 | - |
457 | - if (ctx->lines_lengths == NULL || ctx->buffer == NULL || |
458 | - ctx->pixbuf == NULL) |
459 | - { |
460 | - g_set_error (error, GDK_PIXBUF_ERROR, |
461 | - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, |
462 | - ("Insufficient memory to load PSD image file")); |
463 | - return FALSE; |
464 | - } |
465 | - |
466 | - // create separate buffers for each channel |
467 | - ctx->ch_bufs = g_malloc(sizeof(guchar*) * ctx->channels); |
468 | - for (int i = 0; i < ctx->channels; i++) { |
469 | - ctx->ch_bufs[i] = |
470 | - g_malloc(ctx->width * ctx->height); |
471 | - |
472 | - if (ctx->ch_bufs[i] == NULL) { |
473 | - g_set_error (error, GDK_PIXBUF_ERROR, |
474 | - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, |
475 | - ("Insufficient memory to load PSD image file")); |
476 | - return FALSE; |
477 | - } |
478 | - } |
479 | - |
480 | - ctx->prepared_func(ctx->pixbuf, NULL, ctx->user_data); |
481 | - |
482 | - ctx->state = PSD_STATE_COLOR_MODE_BLOCK; |
483 | - reset_context_buffer(ctx); |
484 | - } |
485 | - break; |
486 | - case PSD_STATE_COLOR_MODE_BLOCK: |
487 | - if (skip_block(ctx, &data, &size)) { |
488 | - ctx->state = PSD_STATE_RESOURCES_BLOCK; |
489 | - reset_context_buffer(ctx); |
490 | - } |
491 | - break; |
492 | - case PSD_STATE_RESOURCES_BLOCK: |
493 | - if (skip_block(ctx, &data, &size)) { |
494 | - ctx->state = PSD_STATE_LAYERS_BLOCK; |
495 | - reset_context_buffer(ctx); |
496 | - } |
497 | - break; |
498 | - case PSD_STATE_LAYERS_BLOCK: |
499 | - if (skip_block(ctx, &data, &size)) { |
500 | - ctx->state = PSD_STATE_COMPRESSION; |
501 | - reset_context_buffer(ctx); |
502 | - } |
503 | - break; |
504 | - case PSD_STATE_COMPRESSION: |
505 | - if (feed_buffer(ctx->buffer, &ctx->bytes_read, &data, &size, 2)) |
506 | - { |
507 | - ctx->compression = read_uint16(ctx->buffer); |
508 | - |
509 | - if (ctx->compression == PSD_COMPRESSION_RLE) { |
510 | - ctx->state = PSD_STATE_LINES_LENGTHS; |
511 | - reset_context_buffer(ctx); |
512 | - } else if (ctx->compression == PSD_COMPRESSION_NONE) { |
513 | - ctx->state = PSD_STATE_CHANNEL_DATA; |
514 | - } else { |
515 | - g_set_error (error, GDK_PIXBUF_ERROR, |
516 | - GDK_PIXBUF_ERROR_UNKNOWN_TYPE, |
517 | - ("Unsupported compression type")); |
518 | - return FALSE; |
519 | - } |
520 | - } |
521 | - break; |
522 | - case PSD_STATE_LINES_LENGTHS: |
523 | - if (feed_buffer( |
524 | - (guchar*) ctx->lines_lengths, &ctx->bytes_read, &data, |
525 | - &size, 2 * ctx->height * ctx->channels)) |
526 | - { |
527 | - // convert from different endianness |
528 | - for (int i = 0; i < ctx->height * ctx->channels; i++) { |
529 | - ctx->lines_lengths[i] = read_uint16( |
530 | - (guchar*) &ctx->lines_lengths[i]); |
531 | - } |
532 | - ctx->state = PSD_STATE_CHANNEL_DATA; |
533 | - reset_context_buffer(ctx); |
534 | - } |
535 | - break; |
536 | - case PSD_STATE_CHANNEL_DATA: |
537 | - { |
538 | - guint line_length = ctx->width; |
539 | - if (ctx->compression == PSD_COMPRESSION_RLE) { |
540 | - line_length = ctx->lines_lengths[ |
541 | - ctx->curr_ch * ctx->height + ctx->curr_row]; |
542 | - } |
543 | - |
544 | - if (feed_buffer(ctx->buffer, &ctx->bytes_read, &data, &size, |
545 | - line_length)) |
546 | - { |
547 | - reset_context_buffer(ctx); |
548 | - |
549 | - if (ctx->compression == PSD_COMPRESSION_RLE) { |
550 | - decompress_line(ctx->buffer, line_length, |
551 | - ctx->ch_bufs[ctx->curr_ch] + ctx->pos |
552 | - ); |
553 | - } else { |
554 | - memcpy(ctx->ch_bufs[ctx->curr_ch] + ctx->pos, |
555 | - ctx->buffer, ctx->width); |
556 | - } |
557 | - |
558 | - ctx->pos += ctx->width; |
559 | - ++ctx->curr_row; |
560 | - |
561 | - if (ctx->curr_row >= ctx->height) { |
562 | - ++ctx->curr_ch; |
563 | - ctx->curr_row = 0; |
564 | - ctx->pos = 0; |
565 | - if (ctx->curr_ch >= ctx->channels) { |
566 | - ctx->state = PSD_STATE_DONE; |
567 | - } |
568 | - } |
569 | - } |
570 | - } |
571 | - break; |
572 | - case PSD_STATE_DONE: |
573 | - default: |
574 | - size = 0; |
575 | - break; |
576 | - } |
577 | - } |
578 | - |
579 | - if (ctx->state == PSD_STATE_DONE && !ctx->finalized) { |
580 | - // convert or copy channel buffers to our GdkPixbuf |
581 | - if (ctx->color_mode == PSD_MODE_RGB && !ctx->use_alpha) { |
582 | - guchar* pixels = gdk_pixbuf_get_pixels(ctx->pixbuf); |
583 | - for (int i = 0; i < ctx->height; i++) { |
584 | - for (int j = 0; j < ctx->width; j++) { |
585 | - pixels[3*j+0] = ctx->ch_bufs[0][ctx->width*i + j]; |
586 | - pixels[3*j+1] = ctx->ch_bufs[1][ctx->width*i + j]; |
587 | - pixels[3*j+2] = ctx->ch_bufs[2][ctx->width*i + j]; |
588 | - } |
589 | - pixels += gdk_pixbuf_get_rowstride(ctx->pixbuf); |
590 | - } |
591 | - } else if (ctx->color_mode == PSD_MODE_RGB && ctx->use_alpha) { |
592 | - guchar* pixels = gdk_pixbuf_get_pixels(ctx->pixbuf); |
593 | - for (int i = 0; i < ctx->height; i++) { |
594 | - for (int j = 0; j < ctx->width; j++) { |
595 | - pixels[4*j+0] = ctx->ch_bufs[0][ctx->width*i + j]; |
596 | - pixels[4*j+1] = ctx->ch_bufs[1][ctx->width*i + j]; |
597 | - pixels[4*j+2] = ctx->ch_bufs[2][ctx->width*i + j]; |
598 | - pixels[4*j+3] = ctx->ch_bufs[3][ctx->width*i + j]; |
599 | - } |
600 | - pixels += gdk_pixbuf_get_rowstride(ctx->pixbuf); |
601 | - } |
602 | - } else if (ctx->color_mode == PSD_MODE_CMYK) { |
603 | - // unfortunately, this doesn't seem to work correctly... |
604 | - |
605 | - guchar* pixels = gdk_pixbuf_get_pixels(ctx->pixbuf); |
606 | - for (int i = 0; i < ctx->height; i++) { |
607 | - for (int j = 0; j < ctx->width; j++) { |
608 | - double c = 1.0 - |
609 | - (double) ctx->ch_bufs[0][ctx->width*i + j] / 255.0; |
610 | - double m = 1.0 - |
611 | - (double) ctx->ch_bufs[1][ctx->width*i + j] / 255.0; |
612 | - double y = 1.0 - |
613 | - (double) ctx->ch_bufs[2][ctx->width*i + j] / 255.0; |
614 | - double k = 1.0 - |
615 | - (double) ctx->ch_bufs[3][ctx->width*i + j] / 255.0; |
616 | - |
617 | - pixels[3*j+0] = (1.0 - (c * (1.0 - k) + k)) * 255.0; |
618 | - pixels[3*j+1] = (1.0 - (m * (1.0 - k) + k)) * 255.0; |
619 | - pixels[3*j+2] = (1.0 - (y * (1.0 - k) + k)) * 255.0; |
620 | - } |
621 | - pixels += gdk_pixbuf_get_rowstride(ctx->pixbuf); |
622 | - } |
623 | - } |
624 | - ctx->finalized = TRUE; |
625 | - } |
626 | - |
627 | - return TRUE; |
628 | -} |
629 | - |
630 | - |
631 | -#ifndef INCLUDE_psd |
632 | -#define MODULE_ENTRY(function) G_MODULE_EXPORT void function |
633 | -#else |
634 | -#define MODULE_ENTRY(function) void _gdk_pixbuf__psd_ ## function |
635 | -#endif |
636 | - |
637 | -MODULE_ENTRY (fill_vtable) (GdkPixbufModule* module) |
638 | -{ |
639 | - module->begin_load = gdk_pixbuf__psd_image_begin_load; |
640 | - module->stop_load = gdk_pixbuf__psd_image_stop_load; |
641 | - module->load_increment = gdk_pixbuf__psd_image_load_increment; |
642 | -} |
643 | - |
644 | -MODULE_ENTRY (fill_info) (GdkPixbufFormat *info) |
645 | -{ |
646 | - static GdkPixbufModulePattern signature[] = { |
647 | - { "8BPS", NULL, 100 }, |
648 | - { NULL, NULL, 0 } |
649 | - }; |
650 | - static gchar * mime_types[] = { |
651 | - "image/x-psd", |
652 | - NULL |
653 | - }; |
654 | - static gchar * extensions[] = { |
655 | - "psd", |
656 | - NULL |
657 | - }; |
658 | - |
659 | - info->name = "psd"; |
660 | - info->signature = signature; |
661 | - //info->description = N_("Adobe Photoshop format"); |
662 | - info->description = "Adobe Photoshop format"; |
663 | - info->mime_types = mime_types; |
664 | - info->extensions = extensions; |
665 | - info->flags = GDK_PIXBUF_FORMAT_THREADSAFE; |
666 | - info->flags = 0; |
667 | - info->license = "LGPL"; |
668 | -} |
669 | - |
670 | |
671 | === removed directory 'src/loaders/XCF' |
672 | === removed file 'src/loaders/XCF/Makefile.am' |
673 | --- src/loaders/XCF/Makefile.am 2010-08-21 18:06:49 +0000 |
674 | +++ src/loaders/XCF/Makefile.am 1970-01-01 00:00:00 +0000 |
675 | @@ -1,13 +0,0 @@ |
676 | -#pluginexecdir = $(prefix)/lib/gtk-2.0/2.10.0/loaders/ |
677 | -pluginexecdir = $(prefix)/lib/gdk-pixbuf-2.0/2.10.0/loaders/ |
678 | - |
679 | -AM_CPPFLAGS += $(GTK_CFLAGS) $(GDKPIXBUF_CFLAGS) $(GLIB_CFLAGS) -shared -fpic -g -std=c99 -DGDK_PIXBUF_ENABLE_BACKEND |
680 | -AM_LDFLAGS = $(GTK_LIBS) $(GDKPIXBUF_LIBS) $(GLIB_LIBS) |
681 | - |
682 | - |
683 | -pluginexec_LTLIBRARIES = libpixbufloader-xcf.la |
684 | -libpixbufloader_xcf_la_SOURCES = io-xcf.c |
685 | -libpixbufloader_xcf_la_LDFLAGS = -module -export-dynamic $(AM_LDFLAGS) |
686 | - |
687 | -#install-exec-hook: |
688 | -# install -d $(prefix)/lib/gdk-pixbuf-2.0/2.10.0/loaders/ |
689 | |
690 | === removed file 'src/loaders/XCF/io-xcf.c' |
691 | --- src/loaders/XCF/io-xcf.c 2010-05-24 09:46:52 +0000 |
692 | +++ src/loaders/XCF/io-xcf.c 1970-01-01 00:00:00 +0000 |
693 | @@ -1,1641 +0,0 @@ |
694 | -/* |
695 | - * Pixbuf loader for xcf |
696 | - * |
697 | - * Author(s): |
698 | - * Stephane Delcroix <stephane@delcroix.org> |
699 | - * |
700 | - * Copyright (C) 2009 Novell, Inc |
701 | - * |
702 | - * This is a clean room implementation, based solely on |
703 | - * http://henning.makholm.net/xcftools/xcfspec.txt and hexdumps |
704 | - * of existing .xcf files. |
705 | - * |
706 | - * This library is free software; you can redistribute it and/or |
707 | - * modify it under the terms of the GNU Lesser General Public |
708 | - * License as published by the Free Software Foundation; either |
709 | - * version 2 of the License, or (at your option) any later version. |
710 | - * |
711 | - * This library is distributed in the hope that it will be useful, |
712 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
713 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
714 | - * Lesser General Public License for more details. |
715 | - * |
716 | - * You should have received a copy of the GNU Lesser General Public |
717 | - * License along with this library; if not, write to the |
718 | - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
719 | - * Boston, MA 02111-1307, USA. |
720 | - */ |
721 | - |
722 | -/* |
723 | - * TODO: |
724 | - * - fix the spots/stains (where are they coming from) ? |
725 | - * - indexed mode |
726 | - * - if the bg layer mode is not Normal or Dissolve, change it to Normal |
727 | - * - file an enhancement request to gdk-pixbuf |
728 | - */ |
729 | - |
730 | -//#define GDK_PIXBUF_ENABLE_BACKEND |
731 | - |
732 | -#include <gmodule.h> |
733 | -#include <gdk-pixbuf/gdk-pixbuf.h> |
734 | -#include <gio/gio.h> |
735 | -#if GIO_2_23 |
736 | -#include <gio/gzlibcompressor.h> |
737 | -#include <gio/gunixinputstream.h> |
738 | -#include <gio/gunixoutputstream.h> |
739 | -#endif |
740 | -#include <stdio.h> |
741 | -#include <math.h> |
742 | -#include <string.h> |
743 | -#include <stdlib.h> |
744 | -#include <errno.h> |
745 | -#include <bzlib.h> |
746 | -#include <glib.h> |
747 | -#include <glib/gstdio.h> |
748 | - |
749 | -//#define LOG(...) printf (__VA_ARGS__); |
750 | -#define LOG(...) |
751 | - |
752 | -#define _GNU_SOURCE 1 |
753 | -#define POSIX_SOURCE 1 |
754 | - |
755 | -#define PROP_END 0 |
756 | -#define PROP_COLORMAP 1 |
757 | -#define PROP_FLOATING_SELECTION 5 |
758 | -#define PROP_OPACITY 6 |
759 | -#define PROP_MODE 7 |
760 | -#define PROP_VISIBLE 8 |
761 | -#define PROP_LINKED 9 |
762 | -#define PROP_APPLY_MASK 11 |
763 | -#define PROP_OFFSETS 15 |
764 | -#define PROP_COMPRESSION 17 |
765 | -#define PROP_GUIDES 18 |
766 | -#define PROP_RESOLUTION 19 |
767 | -#define PROP_TATOO 20 |
768 | -#define PROP_PARASITES 21 |
769 | -#define PROP_UNIT 22 |
770 | -#define PROP_PATHS 23 |
771 | -#define PROP_USER_UNIT 24 |
772 | -#define PROP_VECTORS 25 |
773 | - |
774 | -#define COMPRESSION_NONE 0 |
775 | -#define COMPRESSION_RLE 1 |
776 | - |
777 | -#define LAYERTYPE_RGB 0 |
778 | -#define LAYERTYPE_RGBA 1 |
779 | -#define LAYERTYPE_GRAYSCALE 2 |
780 | -#define LAYERTYPE_GRAYSCALEA 3 |
781 | -#define LAYERTYPE_INDEXED 4 |
782 | -#define LAYERTYPE_INDEXEDA 5 |
783 | - |
784 | -#define LAYERMODE_NORMAL 0 |
785 | -#define LAYERMODE_DISSOLVE 1 |
786 | -#define LAYERMODE_BEHIND 2 |
787 | -#define LAYERMODE_MULTIPLY 3 |
788 | -#define LAYERMODE_SCREEN 4 |
789 | -#define LAYERMODE_OVERLAY 5 |
790 | -#define LAYERMODE_DIFFERENCE 6 |
791 | -#define LAYERMODE_ADDITION 7 |
792 | -#define LAYERMODE_SUBTRACT 8 |
793 | -#define LAYERMODE_DARKENONLY 9 |
794 | -#define LAYERMODE_LIGHTENONLY 10 |
795 | -#define LAYERMODE_HUE 11 |
796 | -#define LAYERMODE_SATURATION 12 |
797 | -#define LAYERMODE_COLOR 13 |
798 | -#define LAYERMODE_VALUE 14 |
799 | -#define LAYERMODE_DIVIDE 15 |
800 | -#define LAYERMODE_DODGE 16 |
801 | -#define LAYERMODE_BURN 17 |
802 | -#define LAYERMODE_HARDLIGHT 18 |
803 | -#define LAYERMODE_SOFTLIGHT 19 |
804 | -#define LAYERMODE_GRAINEXTRACT 20 |
805 | -#define LAYERMODE_GRAINMERGE 21 |
806 | - |
807 | -#define FILETYPE_STREAMCLOSED -1 |
808 | -#define FILETYPE_UNKNOWN 0 |
809 | -#define FILETYPE_XCF 1 |
810 | -#define FILETYPE_XCF_BZ2 2 |
811 | -#if GIO_2_23 |
812 | -#define FILETYPE_XCF_GZ 3 |
813 | -#endif |
814 | - |
815 | -extern FILE *fdopen (int __fd, __const char *__modes) __THROW __wur; |
816 | - |
817 | -typedef struct _XcfContext XcfContext; |
818 | -struct _XcfContext { |
819 | - GdkPixbufModuleSizeFunc size_func; |
820 | - GdkPixbufModulePreparedFunc prepare_func; |
821 | - GdkPixbufModuleUpdatedFunc update_func; |
822 | - gpointer user_data; |
823 | - gint type; |
824 | - bz_stream *bz_stream; |
825 | - |
826 | -#if GIO_2_23 |
827 | - GInputStream *input, *stream; |
828 | -#endif |
829 | - |
830 | - gchar *tempname; |
831 | - FILE *file; |
832 | -}; |
833 | - |
834 | -typedef struct _XcfChannel XcfChannel; |
835 | -struct _XcfChannel { |
836 | - guint32 width; |
837 | - guint32 height; |
838 | - gboolean visible; |
839 | - guint32 opacity; |
840 | - guint32 lptr; |
841 | -}; |
842 | - |
843 | -typedef struct _XcfLayer XcfLayer; |
844 | -struct _XcfLayer { |
845 | - guint32 width; |
846 | - guint32 height; |
847 | - guint32 type; |
848 | - guint32 mode; |
849 | - gboolean apply_mask; |
850 | - gboolean visible; |
851 | - guint32 opacity; |
852 | - gint32 dx; |
853 | - gint32 dy; |
854 | - XcfChannel* layer_mask; |
855 | - guint32 lptr;; |
856 | -}; |
857 | - |
858 | -void |
859 | -rle_decode (FILE *f, gchar *ptr, int count, int type) |
860 | -{ |
861 | - int channels; |
862 | - switch (type) { |
863 | - case LAYERTYPE_RGB : channels = 3; break; |
864 | - case LAYERTYPE_RGBA: channels = 4; break; |
865 | - case LAYERTYPE_GRAYSCALE: channels = 1; break; |
866 | - case LAYERTYPE_GRAYSCALEA: channels = 2; break; |
867 | - case LAYERTYPE_INDEXED: channels = 1; break; |
868 | - case LAYERTYPE_INDEXEDA: channels = 2; break; |
869 | - } |
870 | - |
871 | - guchar opcode; |
872 | - guchar buffer[3]; |
873 | - guchar ch[channels][count]; |
874 | - int channel; |
875 | - size_t lfr; |
876 | - |
877 | - //un-rle |
878 | - for (channel = 0; channel < channels; channel++) { |
879 | - int pixels_count = 0; |
880 | - while (pixels_count < count) { |
881 | - lfr = fread (&opcode, sizeof(guchar), 1, f); |
882 | - if (opcode <= 126) { |
883 | - lfr = fread (buffer, 1, 1, f); |
884 | - opcode ++; |
885 | - while (opcode --) |
886 | - memcpy (ch[channel] + (pixels_count++), buffer, 1); |
887 | - } else if (opcode == 127) { |
888 | - lfr = fread (buffer, 3, 1, f); |
889 | - int p = buffer[0]; |
890 | - int q = buffer[1]; |
891 | - int count = p*256+q; |
892 | - while (count --) |
893 | - memcpy (ch[channel] + (pixels_count++), buffer+2, 1); |
894 | - } else if (opcode == 128) { |
895 | - lfr = fread (buffer, 2, 1, f); |
896 | - int p = buffer[0]; |
897 | - int q = buffer[1]; |
898 | - lfr = fread (ch[channel] + pixels_count, p*256+q, 1, f); |
899 | - pixels_count += p*256+q; |
900 | - } else if (opcode >= 129) { |
901 | - lfr = fread (ch[channel] + pixels_count, 256 - opcode, 1, f); |
902 | - pixels_count += 256 - opcode; |
903 | - } |
904 | - } |
905 | - } |
906 | - |
907 | - //reinterlace the channels |
908 | - int i, j; |
909 | - for (i=0; i <count; i++) |
910 | - for (j=0; j<channels; j++) |
911 | - memcpy (ptr + i * channels + j, ch[j] + i, 1); |
912 | -} |
913 | - |
914 | -void |
915 | -to_rgba (gchar *ptr, int count, int type) |
916 | -{ |
917 | - //pad to rgba |
918 | - int i; |
919 | - |
920 | - for (i=count-1; i>=0;i--) |
921 | - switch (type) { |
922 | - case LAYERTYPE_RGB: |
923 | - memcpy (ptr + 4*i, ptr + 3*i, 3); |
924 | - ptr[4*i + 3] = 0xff; |
925 | - break; |
926 | - case LAYERTYPE_RGBA: |
927 | - ///nothing to do |
928 | - break; |
929 | - case LAYERTYPE_GRAYSCALE: |
930 | - memcpy (ptr + 4*i, ptr + i, 1); |
931 | - memcpy (ptr + 4*i + 1, ptr + i, 1); |
932 | - memcpy (ptr + 4*i + 2, ptr + i, 1); |
933 | - ptr[4*i + 3] = 0xff; |
934 | - break; |
935 | - case LAYERTYPE_GRAYSCALEA: |
936 | - memcpy (ptr + 4*i, ptr + i, 1); |
937 | - memcpy (ptr + 4*i + 1, ptr + i, 1); |
938 | - memcpy (ptr + 4*i + 2, ptr + i, 1); |
939 | - memcpy (ptr + 4+i + 3, ptr + i + 1, 1); |
940 | - break; |
941 | - } |
942 | -} |
943 | - |
944 | -void |
945 | -apply_opacity (guchar* ptr, int size, guint32 opacity) |
946 | -{ |
947 | - int i; |
948 | - for (i=0; i<size; i++) |
949 | - ptr[4*i + 3] = (guchar)((ptr[4*i+3] * opacity) / 0xff); |
950 | -} |
951 | - |
952 | -void |
953 | -apply_mask (FILE *f, gchar compression, guchar *ptr, int size, XcfChannel *mask, int tile_id) |
954 | -{ |
955 | - //save file position |
956 | - long pos = ftell (f); |
957 | - size_t lfr; |
958 | - |
959 | - guint32 tptr = mask->lptr + (2 + tile_id) * sizeof(guint32); //skip width and height |
960 | - fseek (f, tptr, SEEK_SET); |
961 | - lfr = fread (&tptr, sizeof(guint32), 1, f); |
962 | - fseek (f, GUINT32_FROM_BE(tptr), SEEK_SET); |
963 | - |
964 | - gchar pixels[4096]; |
965 | - if (compression == COMPRESSION_RLE) |
966 | - rle_decode (f, pixels, size, LAYERTYPE_GRAYSCALE); |
967 | - else //COMPRESSION_NONE |
968 | - lfr = fread (pixels, sizeof(gchar), size, f); |
969 | - |
970 | - int i; |
971 | - for (i = 0; i<size; i++) |
972 | - ptr[4*i + 3] = ptr[4 * i + 3] * pixels[i] / 0xff; |
973 | - |
974 | - //rewind |
975 | - fseek (f, pos, SEEK_SET); |
976 | -} |
977 | - |
978 | - |
979 | -void |
980 | -intersect_tile (guchar* ptr, int im_width, int im_height, int *ox, int *oy, int *tw, int *th) |
981 | -{ |
982 | - int i; |
983 | - if (*ox < 0) { |
984 | - for (i=0; i<*th; i++) { |
985 | - memmove (ptr + 4 * i * (*tw + *ox), ptr + 4 * i * (*tw), 4 * (*tw + *ox)); |
986 | - } |
987 | - *tw = *tw + *ox; |
988 | - *ox = 0; |
989 | - } |
990 | - if (*oy < 0) { |
991 | - memmove (ptr, ptr + 4 * *tw * -*oy, 4 * *tw * (*th + *oy)); |
992 | - *th = *th + *oy; |
993 | - *oy = 0; |
994 | - } |
995 | - if (*ox + *tw > im_width) { |
996 | - for (i=0; i<*th; i++) { |
997 | - memmove (ptr + 4 * i * (im_width - *ox), ptr + 4 * i * (*tw), 4 * (im_width - *ox)); |
998 | - } |
999 | - *tw = im_width - *ox; |
1000 | - } |
1001 | - if (*oy + *th > im_height) { |
1002 | - *th = im_height - *oy; |
1003 | - } |
1004 | -} |
1005 | - |
1006 | -void blend (guchar* rgba0, guchar* rgba1) |
1007 | -{ |
1008 | - if (rgba0[3] == 0 && rgba1[3] == 0) |
1009 | - return; |
1010 | - |
1011 | - guchar k = 0xff * rgba1[3] / (0xff - (0xff-rgba0[3])*(0xff-rgba1[3])/0xff); |
1012 | - rgba0[0] = ((0xff - k) * rgba0[0] + k * rgba1[0]) / 0xff; |
1013 | - rgba0[1] = ((0xff - k) * rgba0[1] + k * rgba1[1]) / 0xff; |
1014 | - rgba0[2] = ((0xff - k) * rgba0[2] + k * rgba1[2]) / 0xff; |
1015 | -} |
1016 | - |
1017 | -typedef void (*composite_func) (guchar* rgb0, guchar* rgb1); |
1018 | - |
1019 | -void |
1020 | -multiply (guchar *rgb0, guchar *rgb1) |
1021 | -{ |
1022 | - rgb1[0] = (rgb0[0] * rgb1[0] ) / 0xff; |
1023 | - rgb1[1] = (rgb0[1] * rgb1[1] ) / 0xff; |
1024 | - rgb1[2] = (rgb0[2] * rgb1[2] ) / 0xff; |
1025 | -} |
1026 | - |
1027 | -void |
1028 | -screen (guchar *rgb0, guchar *rgb1) |
1029 | -{ |
1030 | - rgb1[0] = 0xff - (0xff - rgb0[0]) * (0xff - rgb1[0]) / 0xff; |
1031 | - rgb1[1] = 0xff - (0xff - rgb0[1]) * (0xff - rgb1[1]) / 0xff; |
1032 | - rgb1[2] = 0xff - (0xff - rgb0[2]) * (0xff - rgb1[2]) / 0xff; |
1033 | -} |
1034 | - |
1035 | -void |
1036 | -overlay (guchar *rgb0, guchar *rgb1) |
1037 | -{ |
1038 | - //FIXME |
1039 | - //LOG ("Overlay (%d %d %d) (%d %d %d) : ", rgb0[0], rgb0[1], rgb0[2], rgb1[0], rgb1[1], rgb1[2]); |
1040 | - rgb1[0] = MIN (0xff, ((0xff - rgb1[0]) * rgb0[0] * rgb0[0] / 0xff + rgb0[0] * (0xff - (0xff - rgb1[0]) * (0xff - rgb1[0]) / 0xff)) / 0xff); |
1041 | - rgb1[1] = MIN (0xff, ((0xff - rgb1[1]) * rgb0[1] * rgb0[1] / 0xff + rgb0[1] * (0xff - (0xff - rgb1[1]) * (0xff - rgb1[1]) / 0xff)) / 0xff); |
1042 | - rgb1[2] = MIN (0xff, ((0xff - rgb1[2]) * rgb0[2] * rgb0[2] / 0xff + rgb0[2] * (0xff - (0xff - rgb1[2]) * (0xff - rgb1[2]) / 0xff)) / 0xff); |
1043 | - //LOG ("(%d %d %d)\n", rgb1[0], rgb1[1], rgb1[2]); |
1044 | -} |
1045 | - |
1046 | -void |
1047 | -difference (guchar *rgb0, guchar *rgb1) |
1048 | -{ |
1049 | - rgb1[0] = (rgb0[0] > rgb1[0]) ? rgb0[0] - rgb1[0] : rgb1[0] - rgb0[0]; |
1050 | - rgb1[1] = (rgb0[1] > rgb1[1]) ? rgb0[1] - rgb1[1] : rgb1[1] - rgb0[1]; |
1051 | - rgb1[2] = (rgb0[2] > rgb1[2]) ? rgb0[2] - rgb1[2] : rgb1[2] - rgb0[2]; |
1052 | -} |
1053 | - |
1054 | -void |
1055 | -addition (guchar *rgb0, guchar *rgb1) |
1056 | -{ |
1057 | -// LOG ("addition (%d %d %d) (%d %d %d):", rgb0[0], rgb0[1], rgb0[2], rgb1[0], rgb1[1], rgb1[2]); |
1058 | - rgb1[0] = (rgb0[0] + rgb1[0]) > 0xff ? 0xff : rgb0[0] + rgb1[0]; |
1059 | - rgb1[1] = (rgb0[1] + rgb1[1]) > 0xff ? 0xff : rgb0[1] + rgb1[1]; |
1060 | - rgb1[2] = (rgb0[2] + rgb1[2]) > 0xff ? 0xff : rgb0[2] + rgb1[2]; |
1061 | -// LOG ("(%d %d %d)\n", rgb1[0], rgb1[1], rgb1[2]); |
1062 | -} |
1063 | - |
1064 | -void |
1065 | -subtract (guchar *rgb0, guchar *rgb1) |
1066 | -{ |
1067 | - rgb1[0] = (rgb0[0] - rgb1[0]) < 0 ? 0 : rgb0[0] - rgb1[0]; |
1068 | - rgb1[1] = (rgb0[1] - rgb1[1]) < 0 ? 0 : rgb0[1] - rgb1[1]; |
1069 | - rgb1[2] = (rgb0[2] - rgb1[2]) < 0 ? 0 : rgb0[2] - rgb1[2]; |
1070 | -} |
1071 | - |
1072 | -void |
1073 | -min (guchar *rgb0, guchar *rgb1) |
1074 | -{ |
1075 | - rgb1[0] = MIN (rgb0[0], rgb1[0]); |
1076 | - rgb1[1] = MIN (rgb0[1], rgb1[1]); |
1077 | - rgb1[2] = MIN (rgb0[2], rgb1[2]); |
1078 | -} |
1079 | - |
1080 | -void |
1081 | -max (guchar *rgb0, guchar *rgb1) |
1082 | -{ |
1083 | - rgb1[0] = MAX (rgb0[0], rgb1[0]); |
1084 | - rgb1[1] = MAX (rgb0[1], rgb1[1]); |
1085 | - rgb1[2] = MAX (rgb0[2], rgb1[2]); |
1086 | -} |
1087 | - |
1088 | -void |
1089 | -divide (guchar *rgb0, guchar *rgb1) |
1090 | -{ |
1091 | - rgb1[0] = rgb1[0] == 0 ? (rgb0[0] == 0 ? 0 : 0xff) : MIN (0xff, 0xff * rgb0[0] / rgb1[0]); |
1092 | - rgb1[1] = rgb1[1] == 0 ? (rgb0[1] == 0 ? 0 : 0xff) : MIN (0xff, 0xff * rgb0[1] / rgb1[1]); |
1093 | - rgb1[2] = rgb1[2] == 0 ? (rgb0[2] == 0 ? 0 : 0xff) : MIN (0xff, 0xff * rgb0[2] / rgb1[2]); |
1094 | -} |
1095 | - |
1096 | -void |
1097 | -dodge (guchar *rgb0, guchar *rgb1) |
1098 | -{ |
1099 | - rgb1[0] = rgb1[0] == 0xff ? (rgb0[0] == 0 ? 0 : 0xff) : MIN (0xff, 0xff * rgb0[0] / (0xff - rgb1[0])); |
1100 | - rgb1[1] = rgb1[1] == 0xff ? (rgb0[1] == 0 ? 0 : 0xff) : MIN (0xff, 0xff * rgb0[1] / (0xff - rgb1[1])); |
1101 | - rgb1[2] = rgb1[2] == 0xff ? (rgb0[2] == 0 ? 0 : 0xff) : MIN (0xff, 0xff * rgb0[2] / (0xff - rgb1[2])); |
1102 | -} |
1103 | - |
1104 | -void |
1105 | -burn (guchar *rgb0, guchar *rgb1) // 1-(1-x1)/x2 |
1106 | -{ |
1107 | - rgb1[0] = rgb1[0] == 0 ? (rgb0[0] == 0xff ? 0xff : 0) : 0xff - MIN (0xff, 0xff * (0xff - rgb0[0]) / rgb1[0]); |
1108 | - rgb1[1] = rgb1[1] == 0 ? (rgb0[1] == 0xff ? 0xff : 0) : 0xff - MIN (0xff, 0xff * (0xff - rgb0[1]) / rgb1[1]); |
1109 | - rgb1[2] = rgb1[2] == 0 ? (rgb0[2] == 0xff ? 0xff : 0) : 0xff - MIN (0xff, 0xff * (0xff - rgb0[2]) / rgb1[2]); |
1110 | -} |
1111 | - |
1112 | -void |
1113 | -hardlight (guchar *rgb0, guchar *rgb1) //if x2 < 0.5 then 2*x1*x2 else 1-2*(1-x1)(1-x2) |
1114 | -{ |
1115 | - rgb1[0] = rgb1[0] < 0x80 ? 2 * rgb0[0] * rgb1[0] / 0xff : 0xff - 2 * (0xff - rgb0[0]) * (0xff - rgb1[0])/ 0xff; |
1116 | - rgb1[1] = rgb1[1] < 0x80 ? 2 * rgb0[1] * rgb1[1] / 0xff : 0xff - 2 * (0xff - rgb0[1]) * (0xff - rgb1[1])/ 0xff; |
1117 | - rgb1[2] = rgb1[2] < 0x80 ? 2 * rgb0[2] * rgb1[2] / 0xff : 0xff - 2 * (0xff - rgb0[2]) * (0xff - rgb1[2])/ 0xff; |
1118 | -} |
1119 | - |
1120 | -void |
1121 | -softlight(guchar *rgb0, guchar *rgb1) |
1122 | -{ |
1123 | - //FIXME |
1124 | - //LOG ("Softlight (%d %d %d) (%d %d %d) : ", rgb0[0], rgb0[1], rgb0[2], rgb1[0], rgb1[1], rgb1[2]); |
1125 | - rgb1[0] = ((0xff - rgb0[0]) * rgb0[0] * rgb1[0] / 0xff + rgb0[0] * (0xff - (0xff - rgb1[0]) * (0xff - rgb0[0]) / 0x100)) / 0x100; |
1126 | - rgb1[1] = ((0xff - rgb0[1]) * rgb0[1] * rgb1[1] / 0xff + rgb0[1] * (0xff - (0xff - rgb1[1]) * (0xff - rgb0[1]) / 0x100)) / 0x100; |
1127 | - rgb1[2] = ((0xff - rgb0[2]) * rgb0[2] * rgb1[2] / 0xff + rgb0[2] * (0xff - (0xff - rgb1[2]) * (0xff - rgb0[2]) / 0x100)) / 0x100; |
1128 | - //LOG ("(%d %d %d)\n", rgb1[0], rgb1[1], rgb1[2]); |
1129 | -} |
1130 | - |
1131 | -void |
1132 | -grainextract (guchar *rgb0, guchar *rgb1) //x1-x2+.5 |
1133 | -{ |
1134 | - rgb1[0] = MAX (0, MIN (0xff, rgb0[0] - rgb1[0] + 0x80)); |
1135 | - rgb1[1] = MAX (0, MIN (0xff, rgb0[1] - rgb1[1] + 0x80)); |
1136 | - rgb1[2] = MAX (0, MIN (0xff, rgb0[2] - rgb1[2] + 0x80)); |
1137 | -} |
1138 | - |
1139 | -void |
1140 | -grainmerge (guchar *rgb0, guchar *rgb1) |
1141 | -{ |
1142 | - rgb1[0] = MAX (0, MIN (0xff, rgb0[0] + rgb1[0] - 0x80)); |
1143 | - rgb1[1] = MAX (0, MIN (0xff, rgb0[1] + rgb1[1] - 0x80)); |
1144 | - rgb1[2] = MAX (0, MIN (0xff, rgb0[2] + rgb1[2] - 0x80)); |
1145 | -} |
1146 | - |
1147 | - |
1148 | -//FIXME: any way to do the following 4 ones in integer arithmetic ? |
1149 | -void |
1150 | -hue (guchar *rgb0, guchar *rgb1) |
1151 | -{ |
1152 | - if (rgb1[0] == rgb1[1] == rgb1[2]) { |
1153 | - rgb1[0] = rgb0[0]; |
1154 | - rgb1[1] = rgb0[1]; |
1155 | - rgb1[2] = rgb0[2]; |
1156 | - return; |
1157 | - } |
1158 | - //hue of rgb1, value and saturation of rgb0 |
1159 | - guchar min0 = MIN (MIN (rgb0[0], rgb0[1]), rgb0[2]); |
1160 | - guchar max0 = MAX (MAX (rgb0[0], rgb0[1]), rgb0[2]); |
1161 | - guchar min1 = MIN (MIN (rgb1[0], rgb1[1]), rgb1[2]); |
1162 | - guchar max1 = MAX (MAX (rgb1[0], rgb1[1]), rgb1[2]); |
1163 | - if (max0 == 0) { |
1164 | - rgb1[0] = 0x00; |
1165 | - rgb1[1] = 0x00; |
1166 | - rgb1[2] = 0x00; |
1167 | - return; |
1168 | - } |
1169 | - double p = max0 * (max0 - min0) / (max1*(max0-min0) - min1*max0 + max1*min0); |
1170 | - double q = - max0 * (min1*max0 - max1*min0) / (max1*(max0-min0) - min1*max0 + max1*min0); |
1171 | - rgb1[0] = (guchar)(rgb1[0] * p + q); |
1172 | - rgb1[1] = (guchar)(rgb1[1] * p + q); |
1173 | - rgb1[2] = (guchar)(rgb1[2] * p + q); |
1174 | -} |
1175 | - |
1176 | -void |
1177 | -saturation (guchar *rgb0, guchar *rgb1) |
1178 | -{ |
1179 | - //hue and value of rgb0, saturation of rgb1 |
1180 | - guchar min0 = MIN (MIN (rgb0[0], rgb0[1]), rgb0[2]); |
1181 | - guchar max0 = MAX (MAX (rgb0[0], rgb0[1]), rgb0[2]); |
1182 | - guchar min1 = MIN (MIN (rgb1[0], rgb1[1]), rgb1[2]); |
1183 | - guchar max1 = MAX (MAX (rgb1[0], rgb1[1]), rgb1[2]); |
1184 | - if (max0 == 0) { |
1185 | - rgb1[0] = 0x00; |
1186 | - rgb1[1] = 0x00; |
1187 | - rgb1[2] = 0x00; |
1188 | - return; |
1189 | - } |
1190 | - if (max0 == min0) { |
1191 | - rgb1[0] = max0; |
1192 | - rgb1[1] = min1*max0 / max0; |
1193 | - rgb1[2] = rgb1[1]; |
1194 | - return; |
1195 | - } |
1196 | - double p = max0 * (min1 - max1) / (max0*(min1-max1) - min1*max0 + max1*min0); |
1197 | - double q = - max0 * (min1*max0 - max1*min0) / (max0*(min1-max1) - min1*max0 + max1*min0); |
1198 | - rgb1[0] = (guchar)(rgb0[0] * p + q); |
1199 | - rgb1[1] = (guchar)(rgb0[1] * p + q); |
1200 | - rgb1[2] = (guchar)(rgb0[2] * p + q); |
1201 | - |
1202 | -} |
1203 | - |
1204 | -void |
1205 | -value (guchar *rgb0, guchar *rgb1) |
1206 | -{ |
1207 | - //hue and saturation ov rgb0, value of rgb1 |
1208 | - guchar min0 = MIN (MIN (rgb0[0], rgb0[1]), rgb0[2]); |
1209 | - guchar max0 = MAX (MAX (rgb0[0], rgb0[1]), rgb0[2]); |
1210 | - guchar min1 = MIN (MIN (rgb1[0], rgb1[1]), rgb1[2]); |
1211 | - guchar max1 = MAX (MAX (rgb1[0], rgb1[1]), rgb1[2]); |
1212 | - if (max0 == 0) { |
1213 | - rgb1[0] = 0x00; |
1214 | - rgb1[1] = 0x00; |
1215 | - rgb1[2] = 0x00; |
1216 | - return; |
1217 | - } |
1218 | - if (max0 == min0) { |
1219 | - rgb1[0] = max1; |
1220 | - rgb1[1] = max1; |
1221 | - rgb1[2] = max1; |
1222 | - return; |
1223 | - } |
1224 | - |
1225 | - double p = max1 / max0; |
1226 | - |
1227 | - rgb1[0] = (guchar)(rgb0[0] * p); |
1228 | - rgb1[1] = (guchar)(rgb0[1] * p); |
1229 | - rgb1[2] = (guchar)(rgb0[2] * p); |
1230 | -} |
1231 | - |
1232 | -void |
1233 | -color (guchar *rgb0, guchar *rgb1) |
1234 | -{ |
1235 | - //hue and hsl-saturation or rgb1, luminosity of rgb0 |
1236 | - guchar min0 = MIN (MIN (rgb0[0], rgb0[1]), rgb0[2]); |
1237 | - guchar max0 = MAX (MAX (rgb0[0], rgb0[1]), rgb0[2]); |
1238 | - guchar min1 = MIN (MIN (rgb1[0], rgb1[1]), rgb1[2]); |
1239 | - guchar max1 = MAX (MAX (rgb1[0], rgb1[1]), rgb1[2]); |
1240 | - |
1241 | - double p = MIN ((min0+max0)/2, 0xff - (min0+max0)/2) / MIN ((min1+max1)/2, 0xff - (min1+max1)/2); |
1242 | - double q = (min0 + max0 - (min1 + max1) * p) / 2.0; |
1243 | - |
1244 | - rgb1[0] = (guchar)(rgb1[0] * p + q); |
1245 | - rgb1[1] = (guchar)(rgb1[1] * p + q); |
1246 | - rgb1[2] = (guchar)(rgb1[2] * p + q); |
1247 | -} |
1248 | - |
1249 | -void |
1250 | -composite (gchar *pixbuf_pixels, int rowstride, gchar *tile_pixels, int ox, int oy, int tw, int th, guint32 layer_mode) |
1251 | -{ |
1252 | - composite_func f = NULL; |
1253 | - int origin = 4 * ox + rowstride * oy; |
1254 | - int i, j; |
1255 | - |
1256 | - switch (layer_mode) { |
1257 | - case LAYERMODE_NORMAL: |
1258 | - for (j=0;j<th;j++) |
1259 | - for (i=0;i<tw;i++) { |
1260 | - //a0 = 1 - (1-a0)*(a-a1) |
1261 | - //rgb0 = BLEND (rgba0, rgba1) |
1262 | - gchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1263 | - gchar *src = tile_pixels + j*tw*4 + i*4; |
1264 | - guchar alpha = 0xff - (0xff - dest[3]) * (0xff - src [3]); |
1265 | - blend (dest, src); |
1266 | - dest[3] = alpha; |
1267 | - } |
1268 | - break; |
1269 | - case LAYERMODE_DISSOLVE: |
1270 | - srand(time(0)); |
1271 | - for (j=0;j<th;j++) |
1272 | - for (i=0;i<tw;i++) { |
1273 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1274 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1275 | - guchar d = rand () % 0x100; |
1276 | - dest [0] = d <= src[3] ? src[0] : dest[0]; |
1277 | - dest [1] = d <= src[3] ? src[1] : dest[1]; |
1278 | - dest [2] = d <= src[3] ? src[2] : dest[2]; |
1279 | - dest [3] = d <= src[3] ? 0xff : dest[3]; |
1280 | - } |
1281 | - break; |
1282 | - case LAYERMODE_BEHIND: //ignore |
1283 | - break; |
1284 | - // 3<=mode<=10 || 15<=mode<=21 |
1285 | - // a0 = a0 |
1286 | - // rgba0 = blend (rgba0, F(rgb0, rgb1), MIN(a0, a1) |
1287 | - case LAYERMODE_MULTIPLY: |
1288 | - f = multiply; |
1289 | - for (j=0;j<th;j++) |
1290 | - for (i=0;i<tw;i++) { |
1291 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1292 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1293 | - f (dest, src); |
1294 | - src[3] = MIN (dest[3], src[3]); |
1295 | - blend (dest, src); |
1296 | - } |
1297 | - break; |
1298 | - case LAYERMODE_SCREEN: |
1299 | - f = screen; |
1300 | - for (j=0;j<th;j++) |
1301 | - for (i=0;i<tw;i++) { |
1302 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1303 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1304 | - f (dest, src); |
1305 | - src[3] = MIN (dest[3], src[3]); |
1306 | - blend (dest, src); |
1307 | - } |
1308 | - break; |
1309 | - case LAYERMODE_OVERLAY: |
1310 | - f = overlay; |
1311 | - for (j=0;j<th;j++) |
1312 | - for (i=0;i<tw;i++) { |
1313 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1314 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1315 | - f (dest, src); |
1316 | - src[3] = MIN (dest[3], src[3]); |
1317 | - blend (dest, src); |
1318 | - } |
1319 | - break; |
1320 | - case LAYERMODE_SOFTLIGHT: |
1321 | - f = softlight; |
1322 | - for (j=0;j<th;j++) |
1323 | - for (i=0;i<tw;i++) { |
1324 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1325 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1326 | - f (dest, src); |
1327 | - src[3] = MIN (dest[3], src[3]); |
1328 | - blend (dest, src); |
1329 | - } |
1330 | - break; |
1331 | - case LAYERMODE_DIFFERENCE: |
1332 | - f = difference; |
1333 | - for (j=0;j<th;j++) |
1334 | - for (i=0;i<tw;i++) { |
1335 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1336 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1337 | - f (dest, src); |
1338 | - src[3] = MIN (dest[3], src[3]); |
1339 | - blend (dest, src); |
1340 | - } |
1341 | - break; |
1342 | - case LAYERMODE_ADDITION: |
1343 | - f = addition; |
1344 | - for (j=0;j<th;j++) |
1345 | - for (i=0;i<tw;i++) { |
1346 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1347 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1348 | - f (dest, src); |
1349 | - src[3] = MIN (dest[3], src[3]); |
1350 | - blend (dest, src); |
1351 | - } |
1352 | - break; |
1353 | - case LAYERMODE_SUBTRACT: |
1354 | - f = subtract; |
1355 | - for (j=0;j<th;j++) |
1356 | - for (i=0;i<tw;i++) { |
1357 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1358 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1359 | - f (dest, src); |
1360 | - src[3] = MIN (dest[3], src[3]); |
1361 | - blend (dest, src); |
1362 | - } |
1363 | - break; |
1364 | - case LAYERMODE_DARKENONLY: |
1365 | - f = min; |
1366 | - for (j=0;j<th;j++) |
1367 | - for (i=0;i<tw;i++) { |
1368 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1369 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1370 | - f (dest, src); |
1371 | - src[3] = MIN (dest[3], src[3]); |
1372 | - blend (dest, src); |
1373 | - } |
1374 | - break; |
1375 | - case LAYERMODE_LIGHTENONLY: |
1376 | - f = max; |
1377 | - for (j=0;j<th;j++) |
1378 | - for (i=0;i<tw;i++) { |
1379 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1380 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1381 | - f (dest, src); |
1382 | - src[3] = MIN (dest[3], src[3]); |
1383 | - blend (dest, src); |
1384 | - } |
1385 | - break; |
1386 | - case LAYERMODE_DIVIDE: |
1387 | - f = divide; |
1388 | - for (j=0;j<th;j++) |
1389 | - for (i=0;i<tw;i++) { |
1390 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1391 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1392 | - f (dest, src); |
1393 | - src[3] = MIN (dest[3], src[3]); |
1394 | - blend (dest, src); |
1395 | - } |
1396 | - break; |
1397 | - case LAYERMODE_DODGE: |
1398 | - f = dodge; |
1399 | - for (j=0;j<th;j++) |
1400 | - for (i=0;i<tw;i++) { |
1401 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1402 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1403 | - f (dest, src); |
1404 | - src[3] = MIN (dest[3], src[3]); |
1405 | - blend (dest, src); |
1406 | - } |
1407 | - break; |
1408 | - case LAYERMODE_BURN: |
1409 | - f = burn; |
1410 | - for (j=0;j<th;j++) |
1411 | - for (i=0;i<tw;i++) { |
1412 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1413 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1414 | - f (dest, src); |
1415 | - src[3] = MIN (dest[3], src[3]); |
1416 | - blend (dest, src); |
1417 | - } |
1418 | - break; |
1419 | - case LAYERMODE_HARDLIGHT: |
1420 | - f = hardlight; |
1421 | - for (j=0;j<th;j++) |
1422 | - for (i=0;i<tw;i++) { |
1423 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1424 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1425 | - f (dest, src); |
1426 | - src[3] = MIN (dest[3], src[3]); |
1427 | - blend (dest, src); |
1428 | - } |
1429 | - break; |
1430 | - case LAYERMODE_GRAINEXTRACT: |
1431 | - f = grainextract; |
1432 | - for (j=0;j<th;j++) |
1433 | - for (i=0;i<tw;i++) { |
1434 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1435 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1436 | - f (dest, src); |
1437 | - src[3] = MIN (dest[3], src[3]); |
1438 | - blend (dest, src); |
1439 | - } |
1440 | - break; |
1441 | - case LAYERMODE_GRAINMERGE: |
1442 | - f = grainmerge; |
1443 | - for (j=0;j<th;j++) |
1444 | - for (i=0;i<tw;i++) { |
1445 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1446 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1447 | - f (dest, src); |
1448 | - src[3] = MIN (dest[3], src[3]); |
1449 | - blend (dest, src); |
1450 | - } |
1451 | - break; |
1452 | - case LAYERMODE_HUE: |
1453 | - f = hue; |
1454 | - for (j=0;j<th;j++) |
1455 | - for (i=0;i<tw;i++) { |
1456 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1457 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1458 | - f (dest, src); |
1459 | - src[3] = MIN (dest[3], src[3]); |
1460 | - blend (dest, src); |
1461 | - } |
1462 | - break; |
1463 | - case LAYERMODE_SATURATION: |
1464 | - f = saturation; |
1465 | - for (j=0;j<th;j++) |
1466 | - for (i=0;i<tw;i++) { |
1467 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1468 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1469 | - f (dest, src); |
1470 | - src[3] = MIN (dest[3], src[3]); |
1471 | - blend (dest, src); |
1472 | - } |
1473 | - break; |
1474 | - case LAYERMODE_VALUE: |
1475 | - f = value; |
1476 | - for (j=0;j<th;j++) |
1477 | - for (i=0;i<tw;i++) { |
1478 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1479 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1480 | - f (dest, src); |
1481 | - src[3] = MIN (dest[3], src[3]); |
1482 | - blend (dest, src); |
1483 | - } |
1484 | - break; |
1485 | - case LAYERMODE_COLOR: |
1486 | - f = color; |
1487 | - for (j=0;j<th;j++) |
1488 | - for (i=0;i<tw;i++) { |
1489 | - guchar *dest = pixbuf_pixels + origin + j * rowstride + 4 * i; |
1490 | - guchar *src = tile_pixels + j*tw*4 + i*4; |
1491 | - f (dest, src); |
1492 | - src[3] = MIN (dest[3], src[3]); |
1493 | - blend (dest, src); |
1494 | - } |
1495 | - break; |
1496 | - |
1497 | - default: //Pack layer on top of each other, without any blending at all |
1498 | - for (j=0; j<th;j++) { |
1499 | - memcpy (pixbuf_pixels + origin + j * rowstride, tile_pixels + j*tw*4 , tw*4); |
1500 | - } |
1501 | - break; |
1502 | - } |
1503 | - |
1504 | -} |
1505 | - |
1506 | -static GdkPixbuf* |
1507 | -xcf_image_load_real (FILE *f, XcfContext *context, GError **error) |
1508 | -{ |
1509 | - guint32 width; |
1510 | - guint32 height; |
1511 | - guint32 color_mode; |
1512 | - gchar compression = 0; |
1513 | - GList *layers = NULL; |
1514 | - GdkPixbuf *pixbuf = NULL; |
1515 | - |
1516 | - guchar buffer[32]; |
1517 | - guint32 data[3]; |
1518 | - guint32 property[2]; |
1519 | - size_t lfr; |
1520 | - |
1521 | - //Magic and version |
1522 | - lfr = fread (buffer, sizeof(guchar), 9, f); |
1523 | - //LOG ("%s\n", buffer); |
1524 | - if (strncmp (buffer, "gimp xcf ", 9)) { |
1525 | - g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, "Wrong magic"); |
1526 | - return NULL; |
1527 | - } |
1528 | - |
1529 | - lfr = fread (buffer, sizeof(guchar), 4, f); |
1530 | - if (strncmp (buffer, "file", 4) && strncmp (buffer, "v001", 4) && strncmp (buffer, "v002", 4)) { |
1531 | - g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_UNKNOWN_TYPE, "Unsupported version"); |
1532 | - return NULL; |
1533 | - } |
1534 | - lfr = fread (buffer, sizeof(guchar), 1, f); |
1535 | - |
1536 | - //Canvas size and Color mode |
1537 | - lfr = fread (data, sizeof(guint32), 3, f); |
1538 | - |
1539 | - width = GUINT32_FROM_BE(data[0]); |
1540 | - height = GUINT32_FROM_BE(data[1]); |
1541 | - color_mode = GUINT32_FROM_BE(data[2]); |
1542 | - if (color_mode == 2) { //Indexed, not supported for now |
1543 | - g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_UNKNOWN_TYPE, "Indexed color mode unsupported"); |
1544 | - return NULL; |
1545 | - } |
1546 | - |
1547 | - |
1548 | - LOG ("W: %d, H: %d, mode: %d\n", width, height, color_mode); |
1549 | - |
1550 | - //Image Properties |
1551 | - while (1) { |
1552 | - lfr = fread (property, sizeof(guint32), 2, f); //read property and payload |
1553 | - if (!property[0]) |
1554 | - break; |
1555 | - property[0] = GUINT32_FROM_BE(property[0]); |
1556 | - property[1] = GUINT32_FROM_BE(property[1]); |
1557 | - //LOG ("property %d, payload %d\n", property[0], property[1]); |
1558 | - switch (property[0]) { |
1559 | - case PROP_COMPRESSION: |
1560 | - lfr = fread (&compression, sizeof(gchar), 1, f); |
1561 | - LOG ("compression: %d\n", compression); |
1562 | - break; |
1563 | - case PROP_COLORMAP: //essential, need to parse this |
1564 | - case PROP_END: |
1565 | - default: |
1566 | - //skip the payload |
1567 | - fseek (f, property[1], SEEK_CUR); |
1568 | - break; |
1569 | - } |
1570 | - } |
1571 | - |
1572 | - //Layer Pointer |
1573 | - guint32 layer_ptr; |
1574 | - while (1) { |
1575 | - lfr = fread (&layer_ptr, sizeof(guint32), 1, f); |
1576 | - layer_ptr = GUINT32_FROM_BE (layer_ptr); |
1577 | - if (!layer_ptr) |
1578 | - break;; |
1579 | - |
1580 | - XcfLayer *layer = g_try_new (XcfLayer, 1); |
1581 | - if (!layer) { |
1582 | - g_set_error (error, |
1583 | - GDK_PIXBUF_ERROR, |
1584 | - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, |
1585 | - "Cannot allocate memory for loading XCF image"); |
1586 | - return NULL; |
1587 | - } |
1588 | - |
1589 | - gboolean ignore_layer = FALSE; |
1590 | - |
1591 | - layer->mode = 0; |
1592 | - layer->apply_mask = FALSE; |
1593 | - layer->layer_mask = NULL; |
1594 | - layer->dx = layer->dy = 0; |
1595 | - layer->visible = TRUE; |
1596 | - layer->opacity = 0xff; |
1597 | - |
1598 | - //LOG ("layer_ptr: %d\n", layer_ptr); |
1599 | - long pos = ftell (f); |
1600 | - //jump to the layer |
1601 | - fseek(f, layer_ptr, SEEK_SET); |
1602 | - |
1603 | - //layer width, height, type |
1604 | - lfr = fread (data, sizeof(guint32), 3, f); |
1605 | - layer->width = GUINT32_FROM_BE(data[0]); |
1606 | - layer->height = GUINT32_FROM_BE(data[1]); |
1607 | - layer->type = GUINT32_FROM_BE(data[2]); |
1608 | - LOG("\tLayer w:%d h:%d type:%d\n", layer->width, layer->height, layer->type); |
1609 | - |
1610 | - //Layer name, ignore |
1611 | - guint32 string_size; |
1612 | - lfr = fread (&string_size, sizeof(guint32), 1, f); |
1613 | - fseek (f, GUINT32_FROM_BE(string_size), SEEK_CUR); |
1614 | - |
1615 | - //Layer properties |
1616 | - while (1) { |
1617 | - lfr = fread (property, sizeof(guint32), 2, f); //property and payload |
1618 | - if (!property[0]) |
1619 | - break; //break on PROP_END |
1620 | - property[0] = GUINT32_FROM_BE (property[0]); |
1621 | - property[1] = GUINT32_FROM_BE (property[1]); |
1622 | - //LOG ("\tproperty %d, payload %d\n", property[0], property[1]); |
1623 | - switch (property[0]) { |
1624 | - case PROP_OPACITY: |
1625 | - lfr = fread (data, sizeof(guint32), 1, f); |
1626 | - layer->opacity = GUINT32_FROM_BE(data[0]); |
1627 | - break; |
1628 | - case PROP_MODE: |
1629 | - lfr = fread (data, sizeof(guint32), 1, f); |
1630 | - layer->mode = GUINT32_FROM_BE (data[0]); |
1631 | - break; |
1632 | - case PROP_VISIBLE: |
1633 | - lfr = fread (data, sizeof(guint32), 1, f); |
1634 | - if (GUINT32_FROM_BE(data[0]) == 0) { |
1635 | - layer->visible = FALSE; |
1636 | - ignore_layer = TRUE; |
1637 | - } |
1638 | - break; |
1639 | - case PROP_APPLY_MASK: |
1640 | - lfr = fread (data, sizeof(guint32), 1, f); |
1641 | - if (GUINT32_FROM_BE(data[0]) == 1) |
1642 | - layer->apply_mask = TRUE; |
1643 | - break; |
1644 | - case PROP_OFFSETS: |
1645 | - lfr = fread(data, sizeof(gint32), 2, f); |
1646 | - layer->dx = GUINT32_FROM_BE(data[0]); |
1647 | - layer->dy = GUINT32_FROM_BE(data[1]); |
1648 | - break; |
1649 | - case PROP_FLOATING_SELECTION: |
1650 | - ignore_layer = TRUE; |
1651 | - default: |
1652 | - //skip the payload |
1653 | - fseek (f, property[1], SEEK_CUR); |
1654 | - break; |
1655 | - } |
1656 | - } |
1657 | - |
1658 | - //Hierararchy Pointer |
1659 | - guint32 hptr; |
1660 | - lfr = fread (&hptr, sizeof(guint32), 1, f); |
1661 | - hptr = GUINT32_FROM_BE (hptr); |
1662 | - long pos1 = ftell (f); |
1663 | - //jump to hierarchy |
1664 | - fseek (f, hptr, SEEK_SET); |
1665 | - |
1666 | - //Hierarchy w, h, bpp |
1667 | - lfr = fread (data, sizeof(guint32), 3, f); |
1668 | - data[0] = GUINT32_FROM_BE(data[0]); |
1669 | - data[1] = GUINT32_FROM_BE(data[1]); |
1670 | - data[2] = GUINT32_FROM_BE(data[2]); |
1671 | - //LOG ("\tHierarchy w:%d, h:%d, bpp:%d\n", data[0], data[1], data[2]); |
1672 | - |
1673 | - guint32 lptr; |
1674 | - lfr = fread (&lptr, sizeof(guint32), 1, f); |
1675 | - layer->lptr = GUINT32_FROM_BE (lptr); |
1676 | - //Layer parsing is done at rendering time |
1677 | - |
1678 | - //Here I could iterate over the unused dlevels and skip them |
1679 | - |
1680 | - //rewind to the layer position |
1681 | - fseek (f, pos1, SEEK_SET); |
1682 | - |
1683 | - //Mask Pointer |
1684 | - guint32 mptr; |
1685 | - lfr = fread (&mptr, sizeof(guint32), 1, f); |
1686 | - if (mptr) |
1687 | - mptr = GUINT32_FROM_BE(mptr); |
1688 | - |
1689 | - //rewind to the previous position |
1690 | - fseek (f, pos, SEEK_SET); |
1691 | - |
1692 | - |
1693 | - if (!ignore_layer) |
1694 | - layers = g_list_prepend (layers, layer); //prepend so the layers are in a bottom-up order in the list |
1695 | - else { |
1696 | - g_free (layer); |
1697 | - continue; |
1698 | - } |
1699 | - |
1700 | - if (!layer->apply_mask || !mptr) |
1701 | - continue; |
1702 | - |
1703 | - LOG ("\t\tthis layer has a mask\n"); |
1704 | - XcfChannel *mask = g_try_new (XcfChannel, 1); |
1705 | - if (!mask) { |
1706 | - g_set_error (error, |
1707 | - GDK_PIXBUF_ERROR, |
1708 | - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, |
1709 | - "Cannot allocate memory for loading XCF image"); |
1710 | - return NULL; |
1711 | - } |
1712 | - |
1713 | - mask->opacity = 0xff; |
1714 | - mask->visible = TRUE; |
1715 | - |
1716 | - //LOG ("\t\tchannel_ptr: %d\n", mptr); |
1717 | - long mpos = ftell (f); |
1718 | - //jump to the channel |
1719 | - fseek(f, mptr, SEEK_SET); |
1720 | - |
1721 | - //Channel w, h |
1722 | - lfr = fread (data, sizeof(guint32), 2, f); |
1723 | - data[0] = GUINT32_FROM_BE(data[0]); |
1724 | - data[1] = GUINT32_FROM_BE(data[1]); |
1725 | - LOG ("\t\tChannel w:%d, h:%d\n", data[0], data[1]); |
1726 | - |
1727 | - //Channel name, ignore |
1728 | - lfr = fread (&string_size, sizeof(guint32), 1, f); |
1729 | - fseek (f, GUINT32_FROM_BE(string_size), SEEK_CUR); |
1730 | - |
1731 | - //Channel properties |
1732 | - while (1) { |
1733 | - lfr = fread (property, sizeof(guint32), 2, f); //property and payload |
1734 | - if (!property[0]) |
1735 | - break; //break on PROP_END |
1736 | - property[0] = GUINT32_FROM_BE (property[0]); |
1737 | - property[1] = GUINT32_FROM_BE (property[1]); |
1738 | - //LOG ("\tproperty %d, payload %d\n", property[0], property[1]); |
1739 | - switch (property[0]) { |
1740 | - case PROP_OPACITY: |
1741 | - lfr = fread (data, sizeof(guint32), 1, f); |
1742 | - mask->opacity = GUINT32_FROM_BE(data[0]); |
1743 | - break; |
1744 | - case PROP_VISIBLE: |
1745 | - lfr = fread (data, sizeof(guint32), 1, f); |
1746 | - if (GUINT32_FROM_BE(data[0]) == 0) |
1747 | - mask->visible = FALSE; |
1748 | - break; |
1749 | - default: |
1750 | - //skip the payload |
1751 | - fseek (f, property[1], SEEK_CUR); |
1752 | - break; |
1753 | - } |
1754 | - } |
1755 | - |
1756 | - //Hierararchy Pointer |
1757 | - lfr = fread (&hptr, sizeof(guint32), 1, f); |
1758 | - hptr = GUINT32_FROM_BE (hptr); |
1759 | - long mpos1 = ftell (f); |
1760 | - //jump to hierarchy |
1761 | - fseek (f, hptr, SEEK_SET); |
1762 | - |
1763 | - //Hierarchy w, h, bpp |
1764 | - lfr = fread (data, sizeof(guint32), 3, f); |
1765 | - data[0] = GUINT32_FROM_BE(data[0]); |
1766 | - data[1] = GUINT32_FROM_BE(data[1]); |
1767 | - data[2] = GUINT32_FROM_BE(data[2]); |
1768 | - //LOG ("\tHierarchy w:%d, h:%d, bpp:%d\n", data[0], data[1], data[2]); |
1769 | - |
1770 | - lfr = fread (&lptr, sizeof(guint32), 1, f); |
1771 | - mask->lptr = GUINT32_FROM_BE (lptr); |
1772 | - //level parsing is done at render time |
1773 | - |
1774 | - if (mask->visible) |
1775 | - layer->layer_mask = mask; |
1776 | - else |
1777 | - g_free (mask); |
1778 | - |
1779 | - //rewind... |
1780 | - fseek (f, mpos1, SEEK_SET); |
1781 | - |
1782 | - //rewind to the previous position |
1783 | - fseek (f, mpos, SEEK_SET); |
1784 | - } |
1785 | - |
1786 | - //Channels goes here, don't read |
1787 | - |
1788 | - LOG("Done parsing\n"); |
1789 | - |
1790 | - //Compose the pixbuf |
1791 | - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height); |
1792 | - LOG ("pixbuf %d %d\n", gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf)); |
1793 | - LOG ("PrepareFunc\n"); |
1794 | - if (context && context->prepare_func) |
1795 | - (* context->prepare_func) (pixbuf, NULL, context->user_data); |
1796 | - |
1797 | - if (!pixbuf) |
1798 | - g_set_error (error, |
1799 | - GDK_PIXBUF_ERROR, |
1800 | - GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, |
1801 | - "Cannot allocate memory for loading XCF image"); |
1802 | - |
1803 | - gdk_pixbuf_fill (pixbuf, 0x00000000); |
1804 | - |
1805 | - GList *current; |
1806 | - gchar pixels[16384]; |
1807 | - for (current = g_list_first (layers); current; current = g_list_next(current)) { |
1808 | - XcfLayer *layer = current->data; |
1809 | - if (!layer->visible) |
1810 | - continue; |
1811 | - |
1812 | - fseek (f, layer->lptr, SEEK_SET); |
1813 | - //Ignore Level w and h (same as hierarchy) |
1814 | - fseek (f, 2 * sizeof(guint32), SEEK_CUR); |
1815 | - |
1816 | - |
1817 | - //Iterate on the tiles |
1818 | - guint32 tptr; |
1819 | - int tile_id = 0; |
1820 | - guchar *pixs = gdk_pixbuf_get_pixels (pixbuf); |
1821 | - int rowstride = gdk_pixbuf_get_rowstride (pixbuf); |
1822 | - int line_width = ceil ((layer->width) / 64.0); |
1823 | - |
1824 | - while (1) { |
1825 | - lfr = fread (&tptr, sizeof(guint32), 1, f); |
1826 | - if (!tptr) |
1827 | - break; |
1828 | - tptr = GUINT32_FROM_BE(tptr); |
1829 | - long lpos = ftell (f); |
1830 | - fseek (f, tptr, SEEK_SET); |
1831 | - |
1832 | - int ox = 64 * (tile_id % line_width); |
1833 | - int oy = 64 * (tile_id / line_width); |
1834 | - int tw = MIN (64, layer->width - ox); |
1835 | - int th = MIN (64, layer->height - oy); |
1836 | - ox += layer->dx; |
1837 | - oy += layer->dy; |
1838 | - //LOG("\tTile %d %d (%d %d) (%d %d)\n", tile_id, tptr, ox, oy, tw, th); |
1839 | - |
1840 | - //if the tile doesn't intersect with the canvas, ignore |
1841 | - if (ox + tw < 0 || oy + th < 0 || ox > (int)width || oy > (int)height ) { |
1842 | - fseek (f, lpos, SEEK_SET); |
1843 | - tile_id++; |
1844 | - continue; |
1845 | - } |
1846 | - |
1847 | - //decompress |
1848 | - if (compression == COMPRESSION_RLE) |
1849 | - rle_decode (f, pixels, tw*th, layer->type); |
1850 | - else {//COMPRESSION_NONE |
1851 | - int channels; |
1852 | - switch (layer->type) { |
1853 | - case LAYERTYPE_RGB : channels = 3; break; |
1854 | - case LAYERTYPE_RGBA: channels = 4; break; |
1855 | - case LAYERTYPE_GRAYSCALE: channels = 1; break; |
1856 | - case LAYERTYPE_GRAYSCALEA: channels = 2; break; |
1857 | - case LAYERTYPE_INDEXED: channels = 1; break; |
1858 | - case LAYERTYPE_INDEXEDA: channels = 2; break; |
1859 | - } |
1860 | - lfr = fread (pixels, sizeof(gchar), tw*th*channels, f); |
1861 | - } |
1862 | - |
1863 | - //pad to rgba |
1864 | - to_rgba (pixels, tw*th, layer->type); |
1865 | - |
1866 | - //apply mask |
1867 | - if (layer->layer_mask) |
1868 | - apply_mask (f, compression, pixels, tw*th, layer->layer_mask, tile_id); |
1869 | - |
1870 | - //reduce the tile to its intersection with the canvas |
1871 | - intersect_tile (pixels, width, height, &ox, &oy, &tw, &th); |
1872 | - |
1873 | - //apply layer opacity |
1874 | - apply_opacity (pixels, tw*th, layer->opacity); |
1875 | - |
1876 | - //composite |
1877 | - composite (pixs, rowstride, pixels, ox, oy, tw, th, layer->mode); |
1878 | - |
1879 | - //notify |
1880 | - if (context && context->update_func) |
1881 | - (* context->update_func) (pixbuf, ox, oy, tw, th, context->user_data); |
1882 | - |
1883 | - |
1884 | - fseek (f, lpos, SEEK_SET); |
1885 | - tile_id++; |
1886 | - } |
1887 | - } |
1888 | - |
1889 | - //free the layers and masks |
1890 | - for (current = g_list_first (layers); current; current = g_list_next(current)) { |
1891 | - XcfLayer *layer = current->data; |
1892 | - if (layer->layer_mask) |
1893 | - g_free (layer->layer_mask); |
1894 | - } |
1895 | - g_list_free (layers); |
1896 | - |
1897 | - return pixbuf; |
1898 | -} |
1899 | - |
1900 | -/* Static Loader */ |
1901 | - |
1902 | -static GdkPixbuf* |
1903 | -xcf_image_load (FILE *f, GError **error) |
1904 | -{ |
1905 | - size_t lfr; |
1906 | - guchar buffer[4]; |
1907 | - lfr = fread (buffer, sizeof(guchar), 4, f); |
1908 | - rewind (f); |
1909 | - if (!strncmp (buffer, "BZh", 3)) { //Decompress the xcf.bz2 file to a temp file |
1910 | - gchar *tempname; |
1911 | - gint fd = g_file_open_tmp ("gdkpixbuf-xcf-tmp.XXXXXX", &tempname, NULL); |
1912 | - if (fd < 0) { |
1913 | - gint save_errno = errno; |
1914 | - g_set_error (error, |
1915 | - G_FILE_ERROR, |
1916 | - g_file_error_from_errno (save_errno), |
1917 | - "Failed to create temporary file when loading Xcf image"); |
1918 | - return NULL; |
1919 | - } |
1920 | - |
1921 | - FILE *file = fdopen (fd, "w+"); |
1922 | - if (!file) { |
1923 | - gint save_errno = errno; |
1924 | - g_set_error (error, |
1925 | - G_FILE_ERROR, |
1926 | - g_file_error_from_errno (save_errno), |
1927 | - "Failed to open temporary file when loading Xcf image"); |
1928 | - g_free (tempname); |
1929 | - return NULL; |
1930 | - } |
1931 | - |
1932 | - int bzerror; |
1933 | - BZFILE *b = BZ2_bzReadOpen (&bzerror, f, 0, 0, NULL, 0); |
1934 | - if (bzerror != BZ_OK) { |
1935 | - BZ2_bzReadClose (&bzerror, b); |
1936 | - fclose (file); |
1937 | - g_unlink (tempname); |
1938 | - g_free (tempname); |
1939 | - g_set_error (error, |
1940 | - GDK_PIXBUF_ERROR, |
1941 | - GDK_PIXBUF_ERROR_FAILED, |
1942 | - "Failed to initialize bz2 decompressor"); |
1943 | - return NULL; |
1944 | - } |
1945 | - |
1946 | - bzerror = BZ_OK; |
1947 | - gchar buf [65536]; |
1948 | - gint nBuf; |
1949 | - while (bzerror == BZ_OK) { |
1950 | - nBuf = BZ2_bzRead (&bzerror, b, buf, 65536); |
1951 | - if (bzerror == BZ_OK || bzerror == BZ_STREAM_END) |
1952 | - if (fwrite (buf, sizeof (guchar), nBuf, file) != nBuf) { |
1953 | - gint save_errno = errno; |
1954 | - g_set_error (error, |
1955 | - G_FILE_ERROR, |
1956 | - g_file_error_from_errno (save_errno), |
1957 | - "Failed to write to temporary file when loading Xcf image"); |
1958 | - BZ2_bzReadClose (&bzerror, b); |
1959 | - fclose (file); |
1960 | - g_unlink (tempname); |
1961 | - g_free (tempname); |
1962 | - return NULL; |
1963 | - } |
1964 | - } |
1965 | - |
1966 | - if (bzerror != BZ_STREAM_END) { |
1967 | - LOG ("bzerror = %d\n", bzerror); |
1968 | - BZ2_bzReadClose (&bzerror, b); |
1969 | - fclose (file); |
1970 | - g_unlink (tempname); |
1971 | - g_free (tempname); |
1972 | - g_set_error (error, |
1973 | - GDK_PIXBUF_ERROR, |
1974 | - GDK_PIXBUF_ERROR_FAILED, |
1975 | - "Decompression error while loading Xcf.bz2 file"); |
1976 | - return NULL; |
1977 | - } else { |
1978 | - LOG ("bzerror = %d\n", bzerror); |
1979 | - BZ2_bzReadClose (&bzerror, b); |
1980 | - } |
1981 | - |
1982 | - fflush (file); |
1983 | - rewind (file); |
1984 | - g_unlink (tempname); |
1985 | - g_free (tempname); |
1986 | - |
1987 | - GdkPixbuf *pixbuf = xcf_image_load_real (file, NULL, error); |
1988 | - fclose (file); |
1989 | - return pixbuf; |
1990 | -#if GIO_2_23 |
1991 | - } else if (!strncmp (buffer, "\x1f\x8b", 2)) { //Decompress the .gz to a temp file |
1992 | - GZlibDecompressor *compressor; |
1993 | - GInputStream *input, *stream; |
1994 | - |
1995 | - compressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP); |
1996 | - input = g_unix_input_stream_new (fileno (f), FALSE); |
1997 | - stream = (GInputStream *) g_converter_input_stream_new (input, (GConverter *) (compressor)); |
1998 | - g_object_unref (compressor); |
1999 | - g_object_unref (input); |
2000 | - |
2001 | - gchar *tempname; |
2002 | - gint fd = g_file_open_tmp ("gdkpixbuf-xcf-tmp.XXXXXX", &tempname, NULL); |
2003 | - if (fd < 0) { |
2004 | - gint save_errno = errno; |
2005 | - g_set_error (error, |
2006 | - G_FILE_ERROR, |
2007 | - g_file_error_from_errno (save_errno), |
2008 | - "Failed to create temporary file when loading Xcf image"); |
2009 | - return NULL; |
2010 | - } |
2011 | - GOutputStream *output; |
2012 | - output = g_unix_output_stream_new (fd, TRUE); |
2013 | - if (!g_output_stream_splice (G_OUTPUT_STREAM (output), stream, |
2014 | - G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, |
2015 | - NULL, NULL)) { |
2016 | - LOG ("splicing failed\n"); |
2017 | - g_set_error (error, |
2018 | - GDK_PIXBUF_ERROR, |
2019 | - GDK_PIXBUF_ERROR_FAILED, |
2020 | - "Decompression error while loading Xcf.gz file"); |
2021 | - return NULL; |
2022 | - } |
2023 | - |
2024 | - FILE *file; |
2025 | - file = fopen (tempname, "r"); |
2026 | - g_unlink (tempname); |
2027 | - g_free (tempname); |
2028 | - |
2029 | - GdkPixbuf *pixbuf = xcf_image_load_real (file, NULL, error); |
2030 | - fclose (file); |
2031 | - |
2032 | - return pixbuf; |
2033 | -#endif |
2034 | - } else |
2035 | - return xcf_image_load_real (f, NULL, error); |
2036 | -} |
2037 | - |
2038 | - |
2039 | -/* Progressive loader */ |
2040 | - |
2041 | -/* |
2042 | - * as the layers are packed top down in the xcf format, and we have to render them bottom-up, |
2043 | - * we need the full file loaded to start rendering |
2044 | - */ |
2045 | - |
2046 | -static gpointer |
2047 | -xcf_image_begin_load (GdkPixbufModuleSizeFunc size_func, |
2048 | - GdkPixbufModulePreparedFunc prepare_func, |
2049 | - GdkPixbufModuleUpdatedFunc update_func, |
2050 | - gpointer user_data, |
2051 | - GError **error) |
2052 | -{ |
2053 | - LOG ("Begin\n"); |
2054 | - XcfContext *context; |
2055 | - gint fd; |
2056 | - |
2057 | - context = g_new (XcfContext, 1); |
2058 | - context->size_func = size_func; |
2059 | - context->prepare_func = prepare_func; |
2060 | - context->update_func = update_func; |
2061 | - context->user_data = user_data; |
2062 | - context->type = FILETYPE_UNKNOWN; |
2063 | - context->bz_stream = NULL; |
2064 | -#if GIO_2_23 |
2065 | - context->stream = NULL; |
2066 | - context->input = NULL; |
2067 | -#endif |
2068 | - |
2069 | - fd = g_file_open_tmp ("gdkpixbuf-xcf-tmp.XXXXXX", &context->tempname, NULL); |
2070 | - |
2071 | - if (fd < 0) { |
2072 | - g_free (context); |
2073 | - return NULL; |
2074 | - } |
2075 | - |
2076 | - context->file = fdopen (fd, "w+"); |
2077 | - if (!context->file) { |
2078 | - g_free (context->tempname); |
2079 | - g_free (context); |
2080 | - return NULL; |
2081 | - } |
2082 | - |
2083 | - return context; |
2084 | -} |
2085 | - |
2086 | -static gboolean |
2087 | -xcf_image_stop_load (gpointer data, GError **error) |
2088 | -{ |
2089 | - LOG ("Stop\n"); |
2090 | - XcfContext *context = (XcfContext*) data; |
2091 | - gboolean retval = TRUE; |
2092 | - |
2093 | - g_return_val_if_fail (data, TRUE); |
2094 | - |
2095 | - if (context->type == FILETYPE_XCF || |
2096 | - context->type == FILETYPE_XCF_BZ2) { |
2097 | - fflush (context->file); |
2098 | - rewind (context->file); |
2099 | - if (context->tempname) { |
2100 | - g_unlink (context->tempname); |
2101 | - g_free (context->tempname); |
2102 | - context->tempname = NULL; |
2103 | - } |
2104 | - GdkPixbuf *pixbuf = xcf_image_load_real (context->file, context, error); |
2105 | - if (!pixbuf) |
2106 | - retval = FALSE; |
2107 | - else |
2108 | - g_object_unref (pixbuf); |
2109 | -#if GIO_2_23 |
2110 | - } else if (context->type == FILETYPE_XCF_GZ) { |
2111 | - g_object_unref (context->input); |
2112 | - context->input = NULL; |
2113 | - |
2114 | - gchar buf [65536]; |
2115 | - gsize count; |
2116 | - GError *err = NULL; |
2117 | - while ((count = g_input_stream_read (G_INPUT_STREAM (context->stream), |
2118 | - &buf, sizeof (buf), NULL, error)) > 0) { |
2119 | - if (fwrite (buf, sizeof (gchar), count, context->file) != count) { |
2120 | - gint save_errno = errno; |
2121 | - g_set_error (error, |
2122 | - G_FILE_ERROR, |
2123 | - g_file_error_from_errno (save_errno), |
2124 | - "Failed to write to temporary file when loading Xcf image"); |
2125 | - retval = FALSE; |
2126 | - goto bail; |
2127 | - } |
2128 | - } |
2129 | - if (count == -1) { |
2130 | - /* error is already set */ |
2131 | - retval = FALSE; |
2132 | - goto bail; |
2133 | - } |
2134 | -#endif |
2135 | - } else { |
2136 | - g_assert_not_reached (); |
2137 | - } |
2138 | - |
2139 | - fflush (context->file); |
2140 | - rewind (context->file); |
2141 | - if (context->tempname) { |
2142 | - g_unlink (context->tempname); |
2143 | - g_free (context->tempname); |
2144 | - context->tempname = NULL; |
2145 | - } |
2146 | - GdkPixbuf *pixbuf = xcf_image_load_real (context->file, context, error); |
2147 | - if (!pixbuf) |
2148 | - retval = FALSE; |
2149 | - else |
2150 | - g_object_unref (pixbuf); |
2151 | - |
2152 | -bail: |
2153 | -#if GIO_2_23 |
2154 | - if (context->stream) |
2155 | - g_object_unref (context->stream); |
2156 | -#endif |
2157 | - fclose (context->file); |
2158 | - if (context->tempname) { |
2159 | - g_unlink (context->tempname); |
2160 | - g_free (context->tempname); |
2161 | - } |
2162 | - g_free (context); |
2163 | - |
2164 | - return retval; |
2165 | -} |
2166 | - |
2167 | -static gboolean |
2168 | -xcf_image_load_increment (gpointer data, |
2169 | - const guchar *buf, |
2170 | - guint size, |
2171 | - GError **error) |
2172 | -{ |
2173 | - LOG ("Increment %d\n", size); |
2174 | - g_return_val_if_fail (data, FALSE); |
2175 | - XcfContext *context = (XcfContext*) data; |
2176 | - |
2177 | - if (context->type == FILETYPE_STREAMCLOSED) { //end of compressed stream reached |
2178 | - g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, "end of compressed stream reached before the end of the file"); |
2179 | - return FALSE; |
2180 | - } |
2181 | - |
2182 | - if (context->type == FILETYPE_UNKNOWN) { // first chunk |
2183 | - if (!strncmp (buf, "gimp xcf ", 9)) |
2184 | - context->type = FILETYPE_XCF; |
2185 | - else if (!strncmp (buf, "BZh", 3)) { |
2186 | - context->type = FILETYPE_XCF_BZ2; |
2187 | - |
2188 | - //Initialize bzlib |
2189 | - context->bz_stream = g_new (bz_stream, 1); |
2190 | - context->bz_stream->bzalloc = NULL; |
2191 | - context->bz_stream->bzfree = NULL; |
2192 | - context->bz_stream->opaque = NULL; |
2193 | - |
2194 | - int ret = BZ2_bzDecompressInit (context->bz_stream, 0, 0); //Verbosity = 0, don't optimize for memory usage |
2195 | - if (ret != BZ_OK) { |
2196 | - g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, "Failed to initialize bz2 decompressor"); |
2197 | - g_free(context->bz_stream); |
2198 | - context->bz_stream = NULL; |
2199 | - return FALSE; |
2200 | - } |
2201 | -#if GIO_2_23 |
2202 | - } else if (!strncmp (buf, "\x1f\x8b", 2)) { |
2203 | - GZlibDecompressor *compressor; |
2204 | - |
2205 | - context->type = FILETYPE_XCF_GZ; |
2206 | - compressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP); |
2207 | - |
2208 | - context->input = g_memory_input_stream_new (); |
2209 | - context->stream = (GInputStream *) g_converter_input_stream_new (context->input, (GConverter *) (compressor)); |
2210 | - g_object_unref (compressor); |
2211 | -#endif |
2212 | - } |
2213 | - LOG ("File type %d\n", context->type); |
2214 | - } |
2215 | - |
2216 | - gchar *outbuf; |
2217 | - switch (context->type) { |
2218 | - case FILETYPE_XCF_BZ2: |
2219 | - outbuf = g_new (gchar, 65536); |
2220 | - context->bz_stream->next_in = (gchar*)buf; |
2221 | - context->bz_stream->avail_in = size; |
2222 | - while (context->bz_stream->avail_in > 0) { |
2223 | - context->bz_stream->next_out = outbuf; |
2224 | - context->bz_stream->avail_out = 65536; |
2225 | - int ret = BZ2_bzDecompress (context->bz_stream); |
2226 | - switch (ret) { |
2227 | - case BZ_OK: |
2228 | - break; |
2229 | - case BZ_STREAM_END: |
2230 | - LOG ("End of bz stream\n"); |
2231 | - BZ2_bzDecompressEnd (context->bz_stream); |
2232 | - context->type = FILETYPE_STREAMCLOSED; |
2233 | - break; |
2234 | - default: |
2235 | - BZ2_bzDecompressEnd (context->bz_stream); |
2236 | - context->type = FILETYPE_STREAMCLOSED; |
2237 | - g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, "Failed to decompress"); |
2238 | - g_free(outbuf); |
2239 | - context->bz_stream->next_out = NULL; |
2240 | - outbuf = NULL; |
2241 | - g_free(context->bz_stream); |
2242 | - context->bz_stream = NULL; |
2243 | - return FALSE; |
2244 | - } |
2245 | - |
2246 | - int total_out = 65536 - context->bz_stream->avail_out; |
2247 | - LOG ("Wrote %d to file %s\n", total_out, context->tempname); |
2248 | - if (fwrite (outbuf, sizeof (guchar), total_out, context->file) != total_out) { |
2249 | - gint save_errno = errno; |
2250 | - g_set_error (error, |
2251 | - G_FILE_ERROR, |
2252 | - g_file_error_from_errno (save_errno), |
2253 | - "Failed to write to temporary file when loading Xcf image"); |
2254 | - g_free(outbuf); |
2255 | - context->bz_stream->next_out = NULL; |
2256 | - outbuf = NULL; |
2257 | - g_free(context->bz_stream); |
2258 | - context->bz_stream = NULL; |
2259 | - return FALSE; |
2260 | - } |
2261 | - } |
2262 | - g_free(outbuf); |
2263 | - context->bz_stream->next_out = NULL; |
2264 | - outbuf = NULL; |
2265 | - if (context->type == FILETYPE_STREAMCLOSED) |
2266 | - { |
2267 | - g_free(context->bz_stream); |
2268 | - context->bz_stream = NULL; |
2269 | - } |
2270 | - break; |
2271 | -#if GIO_2_23 |
2272 | - case FILETYPE_XCF_GZ: |
2273 | - g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (context->input), |
2274 | - buf, size, NULL); |
2275 | - break; |
2276 | -#endif |
2277 | - case FILETYPE_XCF: |
2278 | - default: |
2279 | - if (fwrite (buf, sizeof (guchar), size, context->file) != size) { |
2280 | - gint save_errno = errno; |
2281 | - g_set_error (error, |
2282 | - G_FILE_ERROR, |
2283 | - g_file_error_from_errno (save_errno), |
2284 | - "Failed to write to temporary file when loading Xcf image"); |
2285 | - return FALSE; |
2286 | - } |
2287 | - break; |
2288 | - } |
2289 | - |
2290 | - return TRUE; |
2291 | -} |
2292 | - |
2293 | - |
2294 | -#define MODULE_ENTRY(function) G_MODULE_EXPORT void function |
2295 | -MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module) |
2296 | -{ |
2297 | - module->load = xcf_image_load; |
2298 | - module->begin_load = xcf_image_begin_load; |
2299 | - module->stop_load = xcf_image_stop_load; |
2300 | - module->load_increment = xcf_image_load_increment; |
2301 | -} |
2302 | - |
2303 | -MODULE_ENTRY (fill_info) (GdkPixbufFormat *info) |
2304 | -{ |
2305 | - static GdkPixbufModulePattern signature[] = { |
2306 | - { "gimp xcf", NULL, 100 }, |
2307 | - { "BZh", NULL, 80 }, |
2308 | -#if GIO_2_23 |
2309 | - { "\x1f\x8b", NULL, 80 }, |
2310 | -#endif |
2311 | - { NULL, NULL, 0 } |
2312 | - }; |
2313 | - static gchar * mime_types[] = { |
2314 | - "image/x-xcf", |
2315 | - "image/x-compressed-xcf", |
2316 | - NULL |
2317 | - }; |
2318 | - static gchar * extensions[] = { |
2319 | - "xcf", |
2320 | - "xcf.bz2", |
2321 | -#if GIO_2_23 |
2322 | - "xcf.gz", |
2323 | -#endif |
2324 | - NULL |
2325 | - }; |
2326 | - |
2327 | - info->name = "xcf"; |
2328 | - info->signature = signature; |
2329 | - info->description = "The XCF (The Gimp) image format"; |
2330 | - info->mime_types = mime_types; |
2331 | - info->extensions = extensions; |
2332 | - info->flags = 0; |
2333 | - info->license = "LGPL"; |
2334 | -} |
2335 | |
2336 | === modified file 'src/plugin-pixbuf/plugin-pixbuf.h' |
2337 | --- src/plugin-pixbuf/plugin-pixbuf.h 2010-05-31 14:57:37 +0000 |
2338 | +++ src/plugin-pixbuf/plugin-pixbuf.h 2014-12-26 04:45:12 +0000 |
2339 | @@ -48,12 +48,6 @@ |
2340 | } |
2341 | g_slist_free(suportedFormats); |
2342 | |
2343 | -PluginManager::register_filetype("image/vnd.adobe.photoshop", 1); |
2344 | -PluginManager::register_filetype("image/x-xcf", 1); |
2345 | -PluginManager::register_filetype("image/x-compressed-xcf", 1); |
2346 | -//PluginManager::register_filetype("image/x-icns", 2); |
2347 | -//PluginManager::register_filetype("image/jpeg", 1); //TODO: do we need this? |
2348 | - |
2349 | #endif |
2350 | |
2351 | #endif |