mirror of
https://invent.kde.org/frameworks/kimageformats.git
synced 2025-06-03 17:08:08 -04:00
418 lines
10 KiB
C++
418 lines
10 KiB
C++
#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. <allen@lignumcomputing.com>
|
|
* Copyright (C) 2004 Melchior FRANZ <mfranz@kde.org>
|
|
*
|
|
* 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
|