summaryrefslogtreecommitdiff
path: root/src/im_palette.cpp
diff options
context:
space:
mode:
authorscuri <scuri>2008-10-17 06:10:15 +0000
committerscuri <scuri>2008-10-17 06:10:15 +0000
commit5a422aba704c375a307a902bafe658342e209906 (patch)
tree5005011e086bb863d8fb587ad3319bbec59b2447 /src/im_palette.cpp
First commit - moving from LuaForge to SourceForge
Diffstat (limited to 'src/im_palette.cpp')
-rw-r--r--src/im_palette.cpp551
1 files changed, 551 insertions, 0 deletions
diff --git a/src/im_palette.cpp b/src/im_palette.cpp
new file mode 100644
index 0000000..0e6f967
--- /dev/null
+++ b/src/im_palette.cpp
@@ -0,0 +1,551 @@
+/** \file
+ * \brief Palette Generators
+ * Creates several standard palettes
+ *
+ * See Copyright Notice in im_lib.h
+ * $Id: im_palette.cpp,v 1.1 2008/10/17 06:10:16 scuri Exp $
+ */
+
+#include "im.h"
+#include "im_util.h"
+#include "im_palette.h"
+#include "im_colorhsi.h"
+
+#include <stdlib.h>
+#include <memory.h>
+#include <assert.h>
+#include <math.h>
+
+static inline int iSqr(int x)
+{
+ return x*x;
+}
+
+static inline int iAbs(int x)
+{
+ return x < 0? -x: x;
+}
+
+int imPaletteFindNearest(const long* palette, int palette_count, long color)
+{
+ assert(palette);
+ assert(palette_count);
+
+ int lSqrDiff, lBestDiff = (unsigned int)-1;
+ int pIndex = -1;
+
+ imbyte red1, green1, blue1;
+ imColorDecode(&red1, &green1, &blue1, color);
+
+ for (int lIndex = 0; lIndex < palette_count; lIndex++, palette++)
+ {
+ if (color == *palette)
+ return lIndex;
+
+ imbyte red2, green2, blue2;
+ imColorDecode(&red2, &green2, &blue2, *palette);
+
+ lSqrDiff = iSqr(red1 - red2) +
+ iSqr(green1 - green2) +
+ iSqr(blue1 - blue2);
+
+ if (lSqrDiff < lBestDiff)
+ {
+ lBestDiff = lSqrDiff;
+ pIndex = lIndex;
+ }
+ }
+
+ return pIndex;
+}
+
+int imPaletteFindColor(const long* palette, int palette_count, long color, unsigned char tol)
+{
+ assert(palette);
+ assert(palette_count);
+
+ /* Divides in two section for faster results when Tolerance is 0.*/
+ if (tol == 0)
+ {
+ for (int lIndex = 0; lIndex < palette_count; lIndex++, palette++)
+ {
+ if (color == *palette)
+ return lIndex;
+ }
+ }
+ else
+ {
+ imbyte red1, green1, blue1;
+ imColorDecode(&red1, &green1, &blue1, color);
+
+ for (int lIndex = 0; lIndex < palette_count; lIndex++, palette++)
+ {
+ imbyte red2, green2, blue2;
+ imColorDecode(&red2, &green2, &blue2, *palette);
+
+ if (iAbs(red1 - red2) < tol &&
+ iAbs(green1 - green2) < tol &&
+ iAbs(blue1 - blue2) < tol)
+ {
+ return lIndex;
+ }
+ }
+ }
+
+ return -1;
+}
+
+long* imPaletteGray(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+
+ for (int lIndex = 0; lIndex < 256; lIndex++)
+ {
+ /* From (0, 0, 0) to (255, 255, 255)*/
+ /* From Black to White */
+ *(ct++) = imColorEncode((imbyte)lIndex, (imbyte)lIndex, (imbyte)lIndex);
+ }
+
+ return palette;
+}
+
+long* imPaletteRed(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+
+ for (int lIndex = 0; lIndex < 256; lIndex++)
+ {
+ /* From (0, 0, 0) to (255, 0, 0) */
+ /* From Black to Red */
+ *(ct++) = imColorEncode((imbyte)lIndex, 0, 0);
+ }
+
+ return palette;
+}
+
+long* imPaletteGreen(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+
+ for (int lIndex = 0; lIndex < 256; lIndex++)
+ {
+ /* From (0, 0, 0) to (0, 255, 0)*/
+ /* From Black to Green */
+ *(ct++) = imColorEncode(0, (imbyte)lIndex, 0);
+ }
+
+ return palette;
+}
+
+long* imPaletteBlue(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+
+ for (int lIndex = 0; lIndex < 256; lIndex++)
+ {
+ /* From (0, 0, 0) to (0, 0, 255)*/
+ /* From Black to Blue */
+ *(ct++) = imColorEncode(0, 0, (imbyte)lIndex);
+ }
+
+ return palette;
+}
+
+long* imPaletteYellow(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+
+ for (int lIndex = 0; lIndex < 256; lIndex++)
+ {
+ /* From (0, 0, 0) to (255, 255, 0)*/
+ /* From Black to Yellow */
+ *(ct++) = imColorEncode((imbyte)lIndex, (imbyte)lIndex, 0);
+ }
+
+ return palette;
+}
+
+long* imPaletteMagenta(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+
+ for (int lIndex = 0; lIndex < 256; lIndex++)
+ {
+ /* From (0, 0, 0) to (255, 0, 255)*/
+ /* From Black to Magenta */
+ *(ct++) = imColorEncode((imbyte)lIndex, 0, (imbyte)lIndex);
+ }
+
+ return palette;
+}
+
+long* imPaletteCian(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+
+ for (int lIndex = 0; lIndex < 256; lIndex++)
+ {
+ /* From (0, 0, 0) to (0, 255, 255)*/
+ /* From Black to Cian */
+ *(ct++) = imColorEncode(0, (imbyte)lIndex, (imbyte)lIndex);
+ }
+
+ return palette;
+}
+
+long* imPaletteHues(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+ int i;
+ float tone, step1 = 255.0f/41.0f, step2 = 255.0f/42.0f;
+
+ /* 1+42+1+41+1+42+1+41+1+42+1+41+1 = 256 */
+
+ /* red */
+ *(ct++) = imColorEncode((imbyte)255, 0, 0);
+
+ for (tone = step2, i = 0; i < 42; i++, tone += step2)
+ {
+ /* From (255, 0, 0) to (255, 255, 0) */
+ /* From Red to Yellow */
+ *(ct++) = imColorEncode((imbyte)255, (imbyte)tone, 0);
+ }
+
+ /* yellow */
+ *(ct++) = imColorEncode((imbyte)255, (imbyte)255, 0);
+
+ for (tone = step1, i = 0; i < 41; i++, tone += step1)
+ {
+ /* From (255, 255, 0) to (0, 255, 0) */
+ /* From Yellow to Green */
+ *(ct++) = imColorEncode((imbyte)(255.0f-tone), (imbyte)255, 0);
+ }
+
+ /* green */
+ *(ct++) = imColorEncode(0, (imbyte)255, 0);;
+
+ for (tone = step2, i = 0; i < 42; i++, tone += step2)
+ {
+ /* From (0, 255, 0) to (0, 255, 255) */
+ /* From Green to Cian */
+ *(ct++) = imColorEncode(0, (imbyte)255, (imbyte)tone);
+ }
+
+ /* cian */
+ *(ct++) = imColorEncode(0, (imbyte)255, (imbyte)255);
+
+ for (tone = step1, i = 0; i < 41; i++, tone += step1)
+ {
+ /* From (0, 255, 255) to (0, 0, 255) */
+ /* From Cian to Blue */
+ *(ct++) = imColorEncode(0, (imbyte)(255.0f-tone), (imbyte)255);
+ }
+
+ /* blue */
+ *(ct++) = imColorEncode(0, 0, (imbyte)255);
+
+ for (tone = step2, i = 0; i < 42; i++, tone += step2)
+ {
+ /* From (0, 0, 255) to (255, 0, 255) */
+ /* From Blue to Magenta */
+ *(ct++) = imColorEncode((imbyte)tone, 0, (imbyte)255);
+ }
+
+ /* magenta */
+ *(ct++) = imColorEncode((imbyte)255, 0, (imbyte)255);
+
+ for (tone = step1, i = 0; i < 41; i++, tone += step1)
+ {
+ /* From (255, 0, 255) to (255, 0, 0) */
+ /* From Magenta to Red */
+ *(ct++) = imColorEncode((imbyte)255, 0, (imbyte)(255.0f-tone));
+ }
+
+ /* black */
+ *(ct++) = imColorEncode(0, 0, 0);;
+
+ return palette;
+}
+
+long* imPaletteRainbow(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+ int hue;
+ unsigned char r, g, b;
+ float h, s, i, factor, H;
+
+ s = 1.0f;
+ factor = 360.0f / 256.0f;
+
+ for (hue = 0; hue < 256; hue++)
+ {
+ h = hue * factor;
+ h = 300-h;
+ if (h < 0) h += 360;
+ H = h/57.2957795131f;
+
+ i = imColorHSI_ImaxS(H, cos(H), sin(H));
+
+ imColorHSI2RGBbyte(h, s, i, &r, &g, &b);
+
+ *(ct++) = imColorEncode(r, g, b);;
+ }
+
+ return palette;
+}
+
+long* imPaletteBlueIce(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+
+ for (int lIndex = 0; lIndex < 256; lIndex++)
+ {
+ /* From (0, 0, 255) to (255, 255, 255)*/
+ /* From Blue to White */
+ *(ct++) = imColorEncode((imbyte)lIndex, (imbyte)lIndex, 255);
+ }
+
+ return palette;
+}
+
+long* imPaletteHotIron(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+ int lIndex, lSubIndex;
+
+ for (lIndex = 0, lSubIndex = 0; lSubIndex < 128; lSubIndex++, lIndex += 2)
+ {
+ /* From (0, 0, 0) to (254, 0, 0) */
+ /* From Black to ~Red */
+ *(ct++) = imColorEncode((imbyte)lIndex, 0, 0);
+ }
+
+ for (lIndex = 0, lSubIndex = 0; lSubIndex < 64; lSubIndex++, lIndex += 2)
+ {
+ /* From (255, 0, 0) to (255, 126, 0) */
+ /* From Red to ~Orange */
+ *(ct++) = imColorEncode(255, (imbyte)lIndex, 0);
+ }
+
+ for (lIndex = 0, lSubIndex = 0; lSubIndex < 63; lSubIndex++, lIndex += 2)
+ {
+ /* From (255, 128, 0) to (255, 252, 252)*/
+ /* From Orange to ~White */
+ imbyte red = 255;
+ imbyte green = (imbyte)(128 + lIndex);
+ imbyte blue = (imbyte)(lIndex * 2 + 4);
+
+ *(ct++) = imColorEncode(red, green, blue);
+ }
+
+ *(ct++) = imColorEncode(255, 255, 255);
+
+ return palette;
+}
+
+long* imPaletteBlackBody(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+ int lIndex, lSubIndex;
+
+ for (lIndex = 0, lSubIndex = 0; lSubIndex < 85; lSubIndex++, lIndex += 3)
+ {
+ /* From (0, 0, 0) to (252, 0, 0) */
+ /* From Black to ~Red */
+ *(ct++) = imColorEncode((imbyte)lIndex, 0, 0);
+ }
+
+ for (lIndex = 0, lSubIndex = 0; lSubIndex < 85; lSubIndex++, lIndex += 3)
+ {
+ /* From (255, 0, 0) to (255, 252, 0)*/
+ /* From Red to ~Yellow */
+ *(ct++) = imColorEncode(255, (imbyte)lIndex, 0);
+ }
+
+ for (lIndex = 0, lSubIndex = 0; lSubIndex < 86; lSubIndex++, lIndex += 3)
+ {
+ /* From (255, 255, 0) to (255, 255, 255)*/
+ /* From Yellow to White */
+ *(ct++) = imColorEncode(255, 255, (imbyte)lIndex);
+ }
+
+ return palette;
+}
+
+long* imPaletteHighContrast(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+ int lIndex;
+
+ static struct{unsigned char r, g, b;} HighContrastColors[65] = {
+ { 0,0,0 },
+
+ { 255,0,0 }, { 128,0,0 }, { 64,0,0 }, { 192,0,0 },
+ { 0,255,0 }, { 0,128,0 }, { 0,64,0 }, { 0,192,0 },
+ { 0,0,255 }, { 0,0,128 }, { 0,0,64 }, { 0,0,192 },
+ { 255,255,0 }, { 128,128,0 }, { 64,64,0 }, { 192,192,0 },
+ { 255,0,255 }, { 128,0,128 }, { 64,0,64 }, { 192,0,192 },
+ { 0,255,255 }, { 0,128,128 }, { 0,64,64 }, { 0,192,192 },
+ { 255,255,255 }, { 128,128,128 }, { 64,64,64 }, { 192,192,192 },
+
+ { 255,128,128 }, { 64,255,255 }, { 192,255,255 },
+ { 128,255,128 }, { 255,64,255 }, { 255,192,255 },
+ { 128,128,255 }, { 255,255,64 }, { 255,255,192 },
+ { 255,255,128 }, { 64,64,255 }, { 192,192,255 },
+ { 255,128,255 }, { 64,255,64 }, { 192,255,192 },
+ { 128,255,255 }, { 255,64,64 }, { 255,192,192 },
+
+ { 128,64,64 }, { 128,192,192 },
+ { 64,128,64 }, { 192,128,192 },
+ { 64,64,128 }, { 192,192,128 },
+ { 128,128,64 }, { 128,128,192 },
+ { 128,64,128 }, { 128,192,128 },
+ { 64,128,128 }, { 192,128,128 },
+
+ { 192,64,64 },
+ { 64,192,64 },
+ { 64,64,192 },
+ { 192,192,64 },
+ { 192,64,192 },
+ { 64,192,192 },
+ };
+
+ for (lIndex = 0; lIndex < 65; lIndex++)
+ {
+ *(ct++) = imColorEncode(HighContrastColors[lIndex].r,
+ HighContrastColors[lIndex].g,
+ HighContrastColors[lIndex].b);
+ }
+
+ for (; lIndex < 256; lIndex++)
+ {
+ *(ct++) = imColorEncode((imbyte)lIndex, (imbyte)lIndex, (imbyte)lIndex);
+ }
+
+ return palette;
+}
+
+/* 256 divided in 6 steps results in these steps.*/
+static int iSixStepsTable[6] = {0, 51, 102, 153, 204, 255};
+
+long* imPaletteUniform(void)
+{
+ long* palette = (long*)malloc(sizeof(long)*256);
+ long* ct = palette;
+
+ for (int lRedIndex = 0; lRedIndex < 6; lRedIndex++)
+ for (int lGreenIndex = 0; lGreenIndex < 6; lGreenIndex++)
+ for (int lBlueIndex = 0; lBlueIndex < 6; lBlueIndex++)
+ {
+ imbyte red = (imbyte)iSixStepsTable[lRedIndex];
+ imbyte green = (imbyte)iSixStepsTable[lGreenIndex];
+ imbyte blue = (imbyte)iSixStepsTable[lBlueIndex];
+
+ *(ct++) = imColorEncode(red, green, blue);
+ }
+
+ /* We initialize only 216 colors (6x6x6), rest 40 colors.*/
+ /* Fill them with a gray scale palette.*/
+ for (int lIndex = 6; lIndex < 246; lIndex += 6)
+ {
+ *(ct++) = imColorEncode((imbyte)lIndex, (imbyte)lIndex, (imbyte)lIndex);
+ }
+
+ return palette;
+}
+
+/* X divided by 51. Convert to 216 color space. */
+static int iDividedBy51Table[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5
+};
+
+/* X multiplied by 36. Shift to red position.*/
+static int iTimes36Table[6] = {0, 36, 72, 108, 144, 180};
+
+/* X multiplied by 36. Shift to green position.*/
+static int iTimes6Table[6] = {0, 6, 12, 18, 24, 30};
+
+int imPaletteUniformIndex(long color)
+{
+ imbyte red, green, blue;
+ imColorDecode(&red, &green, &blue, color);
+ return iTimes36Table[iDividedBy51Table[red]] + iTimes6Table[iDividedBy51Table[green]] + iDividedBy51Table[blue];
+}
+
+/* Remainder of X divided by 51. Used to position in the halftone*/
+static int iModulo51Table[256] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
+ 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+ 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0
+};
+
+/* Dither matrices for 8 bit to 2.6 bit halftones.*/
+static int iHalftone8x8Table[64] =
+{
+ 0, 38, 9, 47, 2, 40, 11, 50,
+ 25, 12, 35, 22, 27, 15, 37, 24,
+ 6, 44, 3, 41, 8, 47, 5, 43,
+ 31, 19, 28, 15, 34, 21, 31, 18,
+ 1, 39, 11, 49, 0, 39, 10, 48,
+ 27, 14, 36, 23, 26, 13, 35, 23,
+ 7, 46, 4, 43, 7, 45, 3, 42,
+ 33, 20, 30, 17, 32, 19, 29, 16
+};
+
+int imPaletteUniformIndexHalftoned(long color, int x, int y)
+{
+ int lHalf = iHalftone8x8Table[(x % 8) * 8 + y % 8];
+
+ imbyte red, green, blue;
+ imColorDecode(&red, &green, &blue, color);
+
+ /* Now, look up each value in the halftone matrix using an 8x8 ordered dither.*/
+ int lRed = iDividedBy51Table[red] + (iModulo51Table[red] > lHalf? 1: 0);
+ int lGreen = iDividedBy51Table[green] + (iModulo51Table[green] > lHalf? 1: 0);
+ int lBlue = iDividedBy51Table[blue] + (iModulo51Table[blue] > lHalf? 1: 0);
+
+ return iTimes36Table[lRed] + iTimes6Table[lGreen] + lBlue;
+}