#ifndef GIMP_H #define GIMP_H /* -*- c++ -*- * gimp.h: Header for a Qt 3 plug-in for reading GIMP XCF image files * Copyright (C) 2001 lignum Computing, Inc. * Copyright (C) 2004 Melchior FRANZ * * This plug-in is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ typedef unsigned char uchar; /* * These are the constants and functions I extracted from The GIMP source * code. If the reader fails to work, this is probably the place to start * looking for discontinuities. */ // From GIMP "tile.h" v1.2 const uint TILE_WIDTH = 64; //!< Width of a tile in the XCF file. const uint TILE_HEIGHT = 64; //!< Height of a tile in the XCF file. // From GIMP "paint_funcs.c" v1.2 const int RANDOM_TABLE_SIZE = 4096; //!< Size of dissolve random number table. const int RANDOM_SEED = 314159265; //!< Seed for dissolve random number table. const double EPSILON = 0.0001; //!< Roundup in alpha blending. // From GIMP "paint_funcs.h" v1.2 const uchar OPAQUE_OPACITY = 255; //!< Opaque value for 8-bit alpha component. // From GIMP "apptypes.h" v1.2 //! Basic GIMP image type. QImage converter may produce a deeper image //! than is specified here. For example, a grayscale image with an //! alpha channel must (currently) use a 32-bit Qt image. typedef enum { RGB, GRAY, INDEXED } GimpImageBaseType; //! Type of individual layers in an XCF file. typedef enum { RGB_GIMAGE, RGBA_GIMAGE, GRAY_GIMAGE, GRAYA_GIMAGE, INDEXED_GIMAGE, INDEXEDA_GIMAGE } GimpImageType; // From GIMP "libgimp/gimpenums.h" v2.4 //! Effect to apply when layers are merged together. typedef enum { NORMAL_MODE, DISSOLVE_MODE, BEHIND_MODE, MULTIPLY_MODE, SCREEN_MODE, OVERLAY_MODE, DIFFERENCE_MODE, ADDITION_MODE, SUBTRACT_MODE, DARKEN_ONLY_MODE, LIGHTEN_ONLY_MODE, HUE_MODE, SATURATION_MODE, COLOR_MODE, VALUE_MODE, DIVIDE_MODE, DODGE_MODE, BURN_MODE, HARDLIGHT_MODE, SOFTLIGHT_MODE, GRAIN_EXTRACT_MODE, GRAIN_MERGE_MODE } LayerModeEffects; // From GIMP "xcf.c" v1.2 //! Properties which can be stored in an XCF file. typedef enum { PROP_END = 0, PROP_COLORMAP = 1, PROP_ACTIVE_LAYER = 2, PROP_ACTIVE_CHANNEL = 3, PROP_SELECTION = 4, PROP_FLOATING_SELECTION = 5, PROP_OPACITY = 6, PROP_MODE = 7, PROP_VISIBLE = 8, PROP_LINKED = 9, PROP_PRESERVE_TRANSPARENCY = 10, PROP_APPLY_MASK = 11, PROP_EDIT_MASK = 12, PROP_SHOW_MASK = 13, PROP_SHOW_MASKED = 14, PROP_OFFSETS = 15, PROP_COLOR = 16, PROP_COMPRESSION = 17, PROP_GUIDES = 18, PROP_RESOLUTION = 19, PROP_TATTOO = 20, PROP_PARASITES = 21, PROP_UNIT = 22, PROP_PATHS = 23, PROP_USER_UNIT = 24, MAX_SUPPORTED_PROPTYPE // should always be at the end so its value is last + 1 } PropType; // From GIMP "xcf.c" v1.2 //! Compression type used in layer tiles. typedef enum { COMPRESS_NONE = 0, COMPRESS_RLE = 1, COMPRESS_ZLIB = 2, COMPRESS_FRACTAL = 3 /* Unused. */ } CompressionType; // From GIMP "paint_funcs.c" v1.2 /*! * Multiply two color components. Really expects the arguments to be * 8-bit quantities. * \param a first minuend. * \param b second minuend. * \return product of arguments. */ inline int INT_MULT(int a, int b) { int c = a * b + 0x80; return ((c >> 8) + c) >> 8; } /*! * Blend the two color components in the proportion alpha: * * result = alpha a + ( 1 - alpha ) b * * \param a first component. * \param b second component. * \param alpha blend proportion. * \return blended color components. */ inline int INT_BLEND(int a, int b, int alpha) { return INT_MULT(a - b, alpha) + b; } // From GIMP "gimpcolorspace.c" v1.2 /*! * Convert a color in RGB space to HSV space (Hue, Saturation, Value). * \param red the red component (modified in place). * \param green the green component (modified in place). * \param blue the blue component (modified in place). */ static void RGBTOHSV(uchar &red, uchar &green, uchar &blue) { int r, g, b; double h, s, v; int min, max; h = 0.; r = red; g = green; b = blue; if (r > g) { max = qMax(r, b); min = qMin(g, b); } else { max = qMax(g, b); min = qMin(r, b); } v = max; if (max != 0) { s = ((max - min) * 255) / (double)max; } else { s = 0; } if (s == 0) { h = 0; } else { int delta = max - min; if (r == max) { h = (g - b) / (double)delta; } else if (g == max) { h = 2 + (b - r) / (double)delta; } else if (b == max) { h = 4 + (r - g) / (double)delta; } h *= 42.5; if (h < 0) { h += 255; } if (h > 255) { h -= 255; } } red = (uchar)h; green = (uchar)s; blue = (uchar)v; } /*! * Convert a color in HSV space to RGB space. * \param hue the hue component (modified in place). * \param saturation the saturation component (modified in place). * \param value the value component (modified in place). */ static void HSVTORGB(uchar &hue, uchar &saturation, uchar &value) { if (saturation == 0) { hue = value; saturation = value; //value = value; } else { double h = hue * 6. / 255.; double s = saturation / 255.; double v = value / 255.; double f = h - (int)h; double p = v * (1. - s); double q = v * (1. - (s * f)); double t = v * (1. - (s * (1. - f))); // Worth a note here that gcc 2.96 will generate different results // depending on optimization mode on i386. switch ((int)h) { case 0: hue = (uchar)(v * 255); saturation = (uchar)(t * 255); value = (uchar)(p * 255); break; case 1: hue = (uchar)(q * 255); saturation = (uchar)(v * 255); value = (uchar)(p * 255); break; case 2: hue = (uchar)(p * 255); saturation = (uchar)(v * 255); value = (uchar)(t * 255); break; case 3: hue = (uchar)(p * 255); saturation = (uchar)(q * 255); value = (uchar)(v * 255); break; case 4: hue = (uchar)(t * 255); saturation = (uchar)(p * 255); value = (uchar)(v * 255); break; case 5: hue = (uchar)(v * 255); saturation = (uchar)(p * 255); value = (uchar)(q * 255); } } } /*! * Convert a color in RGB space to HLS space (Hue, Lightness, Saturation). * \param red the red component (modified in place). * \param green the green component (modified in place). * \param blue the blue component (modified in place). */ static void RGBTOHLS(uchar &red, uchar &green, uchar &blue) { int r = red; int g = green; int b = blue; int min, max; if (r > g) { max = qMax(r, b); min = qMin(g, b); } else { max = qMax(g, b); min = qMin(r, b); } double h; double l = (max + min) / 2.; double s; if (max == min) { s = 0.; h = 0.; } else { int delta = max - min; if (l < 128) { s = 255 * (double)delta / (double)(max + min); } else { s = 255 * (double)delta / (double)(511 - max - min); } if (r == max) { h = (g - b) / (double)delta; } else if (g == max) { h = 2 + (b - r) / (double)delta; } else { h = 4 + (r - g) / (double)delta; } h *= 42.5; if (h < 0) { h += 255; } else if (h > 255) { h -= 255; } } red = (uchar)h; green = (uchar)l; blue = (uchar)s; } /*! * Implement the HLS "double hex-cone". * \param n1 lightness fraction (?) * \param n2 saturation fraction (?) * \param hue hue "angle". * \return HLS value. */ static int HLSVALUE(double n1, double n2, double hue) { double value; if (hue > 255) { hue -= 255; } else if (hue < 0) { hue += 255; } if (hue < 42.5) { value = n1 + (n2 - n1) * (hue / 42.5); } else if (hue < 127.5) { value = n2; } else if (hue < 170) { value = n1 + (n2 - n1) * ((170 - hue) / 42.5); } else { value = n1; } return (int)(value * 255); } /*! * Convert a color in HLS space to RGB space. * \param hue the hue component (modified in place). * \param lightness the lightness component (modified in place). * \param saturation the saturation component (modified in place). */ static void HLSTORGB(uchar &hue, uchar &lightness, uchar &saturation) { double h = hue; double l = lightness; double s = saturation; if (s == 0) { hue = (uchar)l; lightness = (uchar)l; saturation = (uchar)l; } else { double m1, m2; if (l < 128) { m2 = (l * (255 + s)) / 65025.; } else { m2 = (l + s - (l * s) / 255.) / 255.; } m1 = (l / 127.5) - m2; hue = HLSVALUE(m1, m2, h + 85); lightness = HLSVALUE(m1, m2, h); saturation = HLSVALUE(m1, m2, h - 85); } } #endif