File indexing completed on 2024-04-28 15:25:39

0001 /* -*- c++ -*-
0002     gimp.h: Header for a Qt 3 plug-in for reading GIMP XCF image files
0003     SPDX-FileCopyrightText: 2001 lignum Computing Inc. <allen@lignumcomputing.com>
0004     SPDX-FileCopyrightText: 2004 Melchior FRANZ <mfranz@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-or-later
0007 */
0008 
0009 #ifndef GIMP_H
0010 #define GIMP_H
0011 
0012 typedef unsigned char uchar;
0013 
0014 /*
0015  * These are the constants and functions I extracted from The GIMP source
0016  * code. If the reader fails to work, this is probably the place to start
0017  * looking for discontinuities.
0018  */
0019 
0020 // From GIMP "tile.h" v1.2
0021 
0022 const uint TILE_WIDTH = 64; //!< Width of a tile in the XCF file.
0023 const uint TILE_HEIGHT = 64; //!< Height of a tile in the XCF file.
0024 
0025 // From GIMP "paint_funcs.c" v1.2
0026 
0027 const int RANDOM_TABLE_SIZE = 4096; //!< Size of dissolve random number table.
0028 const int RANDOM_SEED = 314159265; //!< Seed for dissolve random number table.
0029 const double EPSILON = 0.0001; //!< Roundup in alpha blending.
0030 
0031 // From GIMP "paint_funcs.h" v1.2
0032 
0033 const uchar OPAQUE_OPACITY = 255; //!< Opaque value for 8-bit alpha component.
0034 
0035 // From GIMP "apptypes.h" v1.2
0036 
0037 //! Basic GIMP image type. QImage converter may produce a deeper image
0038 //! than is specified here. For example, a grayscale image with an
0039 //! alpha channel must (currently) use a 32-bit Qt image.
0040 
0041 typedef enum {
0042     RGB,
0043     GRAY,
0044     INDEXED,
0045 } GimpImageBaseType;
0046 
0047 // From GIMP "libgimp/gimpenums.h" v2.4
0048 
0049 // From GIMP "paint_funcs.c" v1.2
0050 
0051 /*!
0052  * Multiply two color components. Really expects the arguments to be
0053  * 8-bit quantities.
0054  * \param a first minuend.
0055  * \param b second minuend.
0056  * \return product of arguments.
0057  */
0058 inline int INT_MULT(int a, int b)
0059 {
0060     int c = a * b + 0x80;
0061     return ((c >> 8) + c) >> 8;
0062 }
0063 
0064 /*!
0065  * Blend the two color components in the proportion alpha:
0066  *
0067  * result = alpha a + ( 1 - alpha ) b
0068  *
0069  * \param a first component.
0070  * \param b second component.
0071  * \param alpha blend proportion.
0072  * \return blended color components.
0073  */
0074 
0075 inline int INT_BLEND(int a, int b, int alpha)
0076 {
0077     return INT_MULT(a - b, alpha) + b;
0078 }
0079 
0080 // From GIMP "gimpcolorspace.c" v1.2
0081 
0082 /*!
0083  * Convert a color in RGB space to HSV space (Hue, Saturation, Value).
0084  * \param red the red component (modified in place).
0085  * \param green the green component (modified in place).
0086  * \param blue the blue component (modified in place).
0087  */
0088 static void RGBTOHSV(uchar &red, uchar &green, uchar &blue)
0089 {
0090     int r, g, b;
0091     double h, s, v;
0092     int min, max;
0093 
0094     h = 0.;
0095 
0096     r = red;
0097     g = green;
0098     b = blue;
0099 
0100     if (r > g) {
0101         max = qMax(r, b);
0102         min = qMin(g, b);
0103     } else {
0104         max = qMax(g, b);
0105         min = qMin(r, b);
0106     }
0107 
0108     v = max;
0109 
0110     if (max != 0) {
0111         s = ((max - min) * 255) / (double)max;
0112     } else {
0113         s = 0;
0114     }
0115 
0116     if (s == 0) {
0117         h = 0;
0118     } else {
0119         int delta = max - min;
0120         if (r == max) {
0121             h = (g - b) / (double)delta;
0122         } else if (g == max) {
0123             h = 2 + (b - r) / (double)delta;
0124         } else if (b == max) {
0125             h = 4 + (r - g) / (double)delta;
0126         }
0127         h *= 42.5;
0128 
0129         if (h < 0) {
0130             h += 255;
0131         }
0132         if (h > 255) {
0133             h -= 255;
0134         }
0135     }
0136 
0137     red = (uchar)h;
0138     green = (uchar)s;
0139     blue = (uchar)v;
0140 }
0141 
0142 /*!
0143  * Convert a color in HSV space to RGB space.
0144  * \param hue the hue component (modified in place).
0145  * \param saturation the saturation component (modified in place).
0146  * \param value the value component (modified in place).
0147  */
0148 static void HSVTORGB(uchar &hue, uchar &saturation, uchar &value)
0149 {
0150     if (saturation == 0) {
0151         hue = value;
0152         saturation = value;
0153         // value      = value;
0154     } else {
0155         double h = hue * 6. / 255.;
0156         double s = saturation / 255.;
0157         double v = value / 255.;
0158 
0159         double f = h - (int)h;
0160         double p = v * (1. - s);
0161         double q = v * (1. - (s * f));
0162         double t = v * (1. - (s * (1. - f)));
0163 
0164         // Worth a note here that gcc 2.96 will generate different results
0165         // depending on optimization mode on i386.
0166 
0167         switch ((int)h) {
0168         case 0:
0169             hue = (uchar)(v * 255);
0170             saturation = (uchar)(t * 255);
0171             value = (uchar)(p * 255);
0172             break;
0173         case 1:
0174             hue = (uchar)(q * 255);
0175             saturation = (uchar)(v * 255);
0176             value = (uchar)(p * 255);
0177             break;
0178         case 2:
0179             hue = (uchar)(p * 255);
0180             saturation = (uchar)(v * 255);
0181             value = (uchar)(t * 255);
0182             break;
0183         case 3:
0184             hue = (uchar)(p * 255);
0185             saturation = (uchar)(q * 255);
0186             value = (uchar)(v * 255);
0187             break;
0188         case 4:
0189             hue = (uchar)(t * 255);
0190             saturation = (uchar)(p * 255);
0191             value = (uchar)(v * 255);
0192             break;
0193         case 5:
0194             hue = (uchar)(v * 255);
0195             saturation = (uchar)(p * 255);
0196             value = (uchar)(q * 255);
0197         }
0198     }
0199 }
0200 
0201 /*!
0202  * Convert a color in RGB space to HLS space (Hue, Lightness, Saturation).
0203  * \param red the red component (modified in place).
0204  * \param green the green component (modified in place).
0205  * \param blue the blue component (modified in place).
0206  */
0207 static void RGBTOHLS(uchar &red, uchar &green, uchar &blue)
0208 {
0209     int r = red;
0210     int g = green;
0211     int b = blue;
0212 
0213     int min, max;
0214 
0215     if (r > g) {
0216         max = qMax(r, b);
0217         min = qMin(g, b);
0218     } else {
0219         max = qMax(g, b);
0220         min = qMin(r, b);
0221     }
0222 
0223     double h;
0224     double l = (max + min) / 2.;
0225     double s;
0226 
0227     if (max == min) {
0228         s = 0.;
0229         h = 0.;
0230     } else {
0231         int delta = max - min;
0232 
0233         if (l < 128) {
0234             s = 255 * (double)delta / (double)(max + min);
0235         } else {
0236             s = 255 * (double)delta / (double)(511 - max - min);
0237         }
0238 
0239         if (r == max) {
0240             h = (g - b) / (double)delta;
0241         } else if (g == max) {
0242             h = 2 + (b - r) / (double)delta;
0243         } else {
0244             h = 4 + (r - g) / (double)delta;
0245         }
0246 
0247         h *= 42.5;
0248 
0249         if (h < 0) {
0250             h += 255;
0251         } else if (h > 255) {
0252             h -= 255;
0253         }
0254     }
0255 
0256     red = (uchar)h;
0257     green = (uchar)l;
0258     blue = (uchar)s;
0259 }
0260 
0261 /*!
0262  * Implement the HLS "double hex-cone".
0263  * \param n1 lightness fraction (?)
0264  * \param n2 saturation fraction (?)
0265  * \param hue hue "angle".
0266  * \return HLS value.
0267  */
0268 static int HLSVALUE(double n1, double n2, double hue)
0269 {
0270     double value;
0271 
0272     if (hue > 255) {
0273         hue -= 255;
0274     } else if (hue < 0) {
0275         hue += 255;
0276     }
0277 
0278     if (hue < 42.5) {
0279         value = n1 + (n2 - n1) * (hue / 42.5);
0280     } else if (hue < 127.5) {
0281         value = n2;
0282     } else if (hue < 170) {
0283         value = n1 + (n2 - n1) * ((170 - hue) / 42.5);
0284     } else {
0285         value = n1;
0286     }
0287 
0288     return (int)(value * 255);
0289 }
0290 
0291 /*!
0292  * Convert a color in HLS space to RGB space.
0293  * \param hue the hue component (modified in place).
0294  * \param lightness the lightness component (modified in place).
0295  * \param saturation the saturation component (modified in place).
0296  */
0297 static void HLSTORGB(uchar &hue, uchar &lightness, uchar &saturation)
0298 {
0299     double h = hue;
0300     double l = lightness;
0301     double s = saturation;
0302 
0303     if (s == 0) {
0304         hue = (uchar)l;
0305         lightness = (uchar)l;
0306         saturation = (uchar)l;
0307     } else {
0308         double m1, m2;
0309 
0310         if (l < 128) {
0311             m2 = (l * (255 + s)) / 65025.;
0312         } else {
0313             m2 = (l + s - (l * s) / 255.) / 255.;
0314         }
0315 
0316         m1 = (l / 127.5) - m2;
0317 
0318         hue = HLSVALUE(m1, m2, h + 85);
0319         lightness = HLSVALUE(m1, m2, h);
0320         saturation = HLSVALUE(m1, m2, h - 85);
0321     }
0322 }
0323 #endif