Merge lp:~ballogy/gloobus-preview/drop-loaders into lp:gloobus-preview

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
Reviewer Review Type Date Requested Status
Gloobus Developers Pending
Review via email: mp+245375@code.launchpad.net

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

Subscribers

People subscribed via source and target branches