Tinter now 2x to 4x faster
This commit is contained in:
parent
c8d07b8fd7
commit
db7e2935cb
2 changed files with 516 additions and 312 deletions
823
src/tuxpaint.c
823
src/tuxpaint.c
|
|
@ -353,6 +353,42 @@ static void win32_perror(const char * const str)
|
|||
#define clamp(lo,value,hi) (min(max(value,lo),hi))
|
||||
|
||||
|
||||
// since gcc-2.5
|
||||
#ifdef __GNUC__
|
||||
#define NORETURN __attribute__((__noreturn__))
|
||||
#define FUNCTION __attribute__((__const__)) // no access to global mem, even via ptr, and no side effect
|
||||
#else
|
||||
#define NORETURN
|
||||
#define FUNCTION
|
||||
#endif
|
||||
|
||||
#if !defined(restrict) && __STDC_VERSION__ < 199901
|
||||
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 92
|
||||
#define restrict __restrict__
|
||||
#else
|
||||
#warning No restrict keyword?
|
||||
#define restrict
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 96
|
||||
// won't alias anything, and aligned enough for anything
|
||||
#define MALLOC __attribute__ ((__malloc__))
|
||||
// no side effect, may read globals
|
||||
#define PURE __attribute__ ((__pure__))
|
||||
// tell gcc what to expect: if(unlikely(err)) die(err);
|
||||
#define likely(x) __builtin_expect(!!(x),1)
|
||||
#define unlikely(x) __builtin_expect(!!(x),0)
|
||||
#define expected(x,y) __builtin_expect((x),(y))
|
||||
#else
|
||||
#define MALLOC
|
||||
#define PURE
|
||||
#define likely(x) (x)
|
||||
#define unlikely(x) (x)
|
||||
#define expected(x,y) (x)
|
||||
#endif
|
||||
|
||||
|
||||
/* Unfortunately, there is a bug in SDL_ttf-2.0.6, the current version
|
||||
that causes a segmentation fault if an attempt is made to call
|
||||
TTF_OpenFont() with the filename of a font that doesn't exist. This
|
||||
|
|
@ -3028,13 +3064,300 @@ static void blit_brush(int x, int y)
|
|||
#define TINTER_NORMAL 2 // normal
|
||||
#define TINTER_VECTOR 3 // map black->white to black->destination
|
||||
|
||||
// This goes from 8-bit sRGB (range 0 to 255) to linear (range 0 to 1).
|
||||
// The math to produce a table entry:
|
||||
// tmp = oldvalue / 255.0;
|
||||
// result = (tmp<=0.03928) ? tmp/12.92 : pow((tmp+0.055)/1.055,2.4);
|
||||
static const float sRGB_to_linear_table[256] = {
|
||||
0.000000, 0.000304, 0.000607, 0.000911, 0.001214, 0.001518, 0.001821,
|
||||
0.002125, 0.002428, 0.002732, 0.003035, 0.003347, 0.003677, 0.004025,
|
||||
0.004391, 0.004777, 0.005182, 0.005605, 0.006049, 0.006512, 0.006995,
|
||||
0.007499, 0.008023, 0.008568, 0.009134, 0.009721, 0.010330, 0.010960,
|
||||
0.011612, 0.012286, 0.012983, 0.013702, 0.014444, 0.015209, 0.015996,
|
||||
0.016807, 0.017642, 0.018500, 0.019382, 0.020289, 0.021219, 0.022174,
|
||||
0.023153, 0.024158, 0.025187, 0.026241, 0.027321, 0.028426, 0.029557,
|
||||
0.030713, 0.031896, 0.033105, 0.034340, 0.035601, 0.036889, 0.038204,
|
||||
0.039546, 0.040915, 0.042311, 0.043735, 0.045186, 0.046665, 0.048172,
|
||||
0.049707, 0.051269, 0.052861, 0.054480, 0.056128, 0.057805, 0.059511,
|
||||
0.061246, 0.063010, 0.064803, 0.066626, 0.068478, 0.070360, 0.072272,
|
||||
0.074214, 0.076185, 0.078187, 0.080220, 0.082283, 0.084376, 0.086500,
|
||||
0.088656, 0.090842, 0.093059, 0.095307, 0.097587, 0.099899, 0.102242,
|
||||
0.104616, 0.107023, 0.109462, 0.111932, 0.114435, 0.116971, 0.119538,
|
||||
0.122139, 0.124772, 0.127438, 0.130136, 0.132868, 0.135633, 0.138432,
|
||||
0.141263, 0.144128, 0.147027, 0.149960, 0.152926, 0.155926, 0.158961,
|
||||
0.162029, 0.165132, 0.168269, 0.171441, 0.174647, 0.177888, 0.181164,
|
||||
0.184475, 0.187821, 0.191202, 0.194618, 0.198069, 0.201556, 0.205079,
|
||||
0.208637, 0.212231, 0.215861, 0.219526, 0.223228, 0.226966, 0.230740,
|
||||
0.234551, 0.238398, 0.242281, 0.246201, 0.250158, 0.254152, 0.258183,
|
||||
0.262251, 0.266356, 0.270498, 0.274677, 0.278894, 0.283149, 0.287441,
|
||||
0.291771, 0.296138, 0.300544, 0.304987, 0.309469, 0.313989, 0.318547,
|
||||
0.323143, 0.327778, 0.332452, 0.337164, 0.341914, 0.346704, 0.351533,
|
||||
0.356400, 0.361307, 0.366253, 0.371238, 0.376262, 0.381326, 0.386429,
|
||||
0.391572, 0.396755, 0.401978, 0.407240, 0.412543, 0.417885, 0.423268,
|
||||
0.428690, 0.434154, 0.439657, 0.445201, 0.450786, 0.456411, 0.462077,
|
||||
0.467784, 0.473531, 0.479320, 0.485150, 0.491021, 0.496933, 0.502886,
|
||||
0.508881, 0.514918, 0.520996, 0.527115, 0.533276, 0.539479, 0.545724,
|
||||
0.552011, 0.558340, 0.564712, 0.571125, 0.577580, 0.584078, 0.590619,
|
||||
0.597202, 0.603827, 0.610496, 0.617207, 0.623960, 0.630757, 0.637597,
|
||||
0.644480, 0.651406, 0.658375, 0.665387, 0.672443, 0.679542, 0.686685,
|
||||
0.693872, 0.701102, 0.708376, 0.715694, 0.723055, 0.730461, 0.737910,
|
||||
0.745404, 0.752942, 0.760525, 0.768151, 0.775822, 0.783538, 0.791298,
|
||||
0.799103, 0.806952, 0.814847, 0.822786, 0.830770, 0.838799, 0.846873,
|
||||
0.854993, 0.863157, 0.871367, 0.879622, 0.887923, 0.896269, 0.904661,
|
||||
0.913099, 0.921582, 0.930111, 0.938686, 0.947307, 0.955973, 0.964686,
|
||||
0.973445, 0.982251, 0.991102, 1.000000,
|
||||
};
|
||||
|
||||
// this goes the other way; range checking will be required
|
||||
static const unsigned char linear_to_sRGB_table[4096] =
|
||||
"\x00\x01\x02\x03\x03\x04\x05\x06\x07\x08\x08\x09\x0a\x0b\x0b\x0c\x0d\x0d"
|
||||
"\x0e\x0f\x10\x10\x11\x11\x12\x12\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17"
|
||||
"\x18\x18\x18\x19\x19\x1a\x1a\x1a\x1b\x1b\x1c\x1c\x1c\x1d\x1d\x1d\x1e\x1e"
|
||||
"\x1e\x1f\x1f\x1f\x20\x20\x20\x21\x21\x21\x22\x22\x22\x23\x23\x23\x23\x24"
|
||||
"\x24\x24\x25\x25\x25\x25\x26\x26\x26\x26\x27\x27\x27\x28\x28\x28\x28\x29"
|
||||
"\x29\x29\x29\x2a\x2a\x2a\x2a\x2b\x2b\x2b\x2b\x2c\x2c\x2c\x2c\x2c\x2d\x2d"
|
||||
"\x2d\x2d\x2e\x2e\x2e\x2e\x2f\x2f\x2f\x2f\x2f\x30\x30\x30\x30\x30\x31\x31"
|
||||
"\x31\x31\x31\x32\x32\x32\x32\x33\x33\x33\x33\x33\x34\x34\x34\x34\x34\x35"
|
||||
"\x35\x35\x35\x35\x35\x36\x36\x36\x36\x36\x37\x37\x37\x37\x37\x38\x38\x38"
|
||||
"\x38\x38\x38\x39\x39\x39\x39\x39\x39\x3a\x3a\x3a\x3a\x3a\x3a\x3b\x3b\x3b"
|
||||
"\x3b\x3b\x3c\x3c\x3c\x3c\x3c\x3c\x3d\x3d\x3d\x3d\x3d\x3d\x3d\x3e\x3e\x3e"
|
||||
"\x3e\x3e\x3e\x3f\x3f\x3f\x3f\x3f\x3f\x40\x40\x40\x40\x40\x40\x41\x41\x41"
|
||||
"\x41\x41\x41\x41\x42\x42\x42\x42\x42\x42\x42\x43\x43\x43\x43\x43\x43\x44"
|
||||
"\x44\x44\x44\x44\x44\x44\x45\x45\x45\x45\x45\x45\x45\x46\x46\x46\x46\x46"
|
||||
"\x46\x46\x46\x47\x47\x47\x47\x47\x47\x47\x48\x48\x48\x48\x48\x48\x48\x48"
|
||||
"\x49\x49\x49\x49\x49\x49\x49\x4a\x4a\x4a\x4a\x4a\x4a\x4a\x4a\x4b\x4b\x4b"
|
||||
"\x4b\x4b\x4b\x4b\x4c\x4c\x4c\x4c\x4c\x4c\x4c\x4c\x4d\x4d\x4d\x4d\x4d\x4d"
|
||||
"\x4d\x4d\x4e\x4e\x4e\x4e\x4e\x4e\x4e\x4e\x4f\x4f\x4f\x4f\x4f\x4f\x4f\x4f"
|
||||
"\x50\x50\x50\x50\x50\x50\x50\x50\x50\x51\x51\x51\x51\x51\x51\x51\x51\x51"
|
||||
"\x52\x52\x52\x52\x52\x52\x52\x52\x53\x53\x53\x53\x53\x53\x53\x53\x53\x54"
|
||||
"\x54\x54\x54\x54\x54\x54\x54\x54\x55\x55\x55\x55\x55\x55\x55\x55\x55\x56"
|
||||
"\x56\x56\x56\x56\x56\x56\x56\x56\x57\x57\x57\x57\x57\x57\x57\x57\x57\x58"
|
||||
"\x58\x58\x58\x58\x58\x58\x58\x58\x58\x59\x59\x59\x59\x59\x59\x59\x59\x59"
|
||||
"\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5a\x5b\x5b\x5b\x5b\x5b\x5b\x5b\x5b"
|
||||
"\x5b\x5b\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5c\x5d\x5d\x5d\x5d\x5d\x5d"
|
||||
"\x5d\x5d\x5d\x5e\x5e\x5e\x5e\x5e\x5e\x5e\x5e\x5e\x5e\x5e\x5f\x5f\x5f\x5f"
|
||||
"\x5f\x5f\x5f\x5f\x5f\x5f\x60\x60\x60\x60\x60\x60\x60\x60\x60\x60\x60\x61"
|
||||
"\x61\x61\x61\x61\x61\x61\x61\x61\x61\x62\x62\x62\x62\x62\x62\x62\x62\x62"
|
||||
"\x62\x62\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x64\x64\x64\x64\x64"
|
||||
"\x64\x64\x64\x64\x64\x64\x65\x65\x65\x65\x65\x65\x65\x65\x65\x65\x65\x66"
|
||||
"\x66\x66\x66\x66\x66\x66\x66\x66\x66\x66\x67\x67\x67\x67\x67\x67\x67\x67"
|
||||
"\x67\x67\x67\x67\x68\x68\x68\x68\x68\x68\x68\x68\x68\x68\x68\x69\x69\x69"
|
||||
"\x69\x69\x69\x69\x69\x69\x69\x69\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a\x6a"
|
||||
"\x6a\x6a\x6b\x6b\x6b\x6b\x6b\x6b\x6b\x6b\x6b\x6b\x6b\x6b\x6c\x6c\x6c\x6c"
|
||||
"\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x6c\x6d\x6d\x6d\x6d\x6d\x6d\x6d\x6d\x6d"
|
||||
"\x6d\x6d\x6d\x6e\x6e\x6e\x6e\x6e\x6e\x6e\x6e\x6e\x6e\x6e\x6e\x6f\x6f\x6f"
|
||||
"\x6f\x6f\x6f\x6f\x6f\x6f\x6f\x6f\x6f\x70\x70\x70\x70\x70\x70\x70\x70\x70"
|
||||
"\x70\x70\x70\x70\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x71\x72"
|
||||
"\x72\x72\x72\x72\x72\x72\x72\x72\x72\x72\x72\x72\x73\x73\x73\x73\x73\x73"
|
||||
"\x73\x73\x73\x73\x73\x73\x73\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74\x74"
|
||||
"\x74\x74\x75\x75\x75\x75\x75\x75\x75\x75\x75\x75\x75\x75\x75\x75\x76\x76"
|
||||
"\x76\x76\x76\x76\x76\x76\x76\x76\x76\x76\x76\x77\x77\x77\x77\x77\x77\x77"
|
||||
"\x77\x77\x77\x77\x77\x77\x77\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78\x78"
|
||||
"\x78\x78\x78\x79\x79\x79\x79\x79\x79\x79\x79\x79\x79\x79\x79\x79\x79\x7a"
|
||||
"\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7a\x7b\x7b\x7b\x7b\x7b\x7b"
|
||||
"\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7b\x7c\x7c\x7c\x7c\x7c\x7c\x7c\x7c\x7c"
|
||||
"\x7c\x7c\x7c\x7c\x7c\x7d\x7d\x7d\x7d\x7d\x7d\x7d\x7d\x7d\x7d\x7d\x7d\x7d"
|
||||
"\x7d\x7e\x7e\x7e\x7e\x7e\x7e\x7e\x7e\x7e\x7e\x7e\x7e\x7e\x7e\x7e\x7f\x7f"
|
||||
"\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x80\x80\x80\x80\x80"
|
||||
"\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x81\x81\x81\x81\x81\x81\x81\x81"
|
||||
"\x81\x81\x81\x81\x81\x81\x81\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82\x82"
|
||||
"\x82\x82\x82\x82\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83\x83"
|
||||
"\x83\x83\x84\x84\x84\x84\x84\x84\x84\x84\x84\x84\x84\x84\x84\x84\x84\x85"
|
||||
"\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x85\x86\x86\x86"
|
||||
"\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x86\x87\x87\x87\x87\x87"
|
||||
"\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x87\x88\x88\x88\x88\x88\x88\x88"
|
||||
"\x88\x88\x88\x88\x88\x88\x88\x88\x88\x89\x89\x89\x89\x89\x89\x89\x89\x89"
|
||||
"\x89\x89\x89\x89\x89\x89\x89\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a\x8a"
|
||||
"\x8a\x8a\x8a\x8a\x8a\x8b\x8b\x8b\x8b\x8b\x8b\x8b\x8b\x8b\x8b\x8b\x8b\x8b"
|
||||
"\x8b\x8b\x8b\x8b\x8c\x8c\x8c\x8c\x8c\x8c\x8c\x8c\x8c\x8c\x8c\x8c\x8c\x8c"
|
||||
"\x8c\x8c\x8c\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d\x8d"
|
||||
"\x8d\x8d\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e\x8e"
|
||||
"\x8e\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f\x8f"
|
||||
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x91"
|
||||
"\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x92"
|
||||
"\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x92\x93"
|
||||
"\x93\x93\x93\x93\x93\x93\x93\x93\x93\x93\x93\x93\x93\x93\x93\x93\x94\x94"
|
||||
"\x94\x94\x94\x94\x94\x94\x94\x94\x94\x94\x94\x94\x94\x94\x94\x94\x95\x95"
|
||||
"\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x95\x96\x96"
|
||||
"\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x96\x97"
|
||||
"\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x98"
|
||||
"\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98\x98"
|
||||
"\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99"
|
||||
"\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a"
|
||||
"\x9a\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b\x9b"
|
||||
"\x9b\x9b\x9c\x9c\x9c\x9c\x9c\x9c\x9c\x9c\x9c\x9c\x9c\x9c\x9c\x9c\x9c\x9c"
|
||||
"\x9c\x9c\x9c\x9c\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d\x9d"
|
||||
"\x9d\x9d\x9d\x9d\x9d\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e"
|
||||
"\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f"
|
||||
"\x9f\x9f\x9f\x9f\x9f\x9f\x9f\x9f\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0"
|
||||
"\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1"
|
||||
"\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa1\xa2\xa2\xa2\xa2\xa2\xa2"
|
||||
"\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa3\xa3\xa3\xa3"
|
||||
"\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa3\xa4"
|
||||
"\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4"
|
||||
"\xa4\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5\xa5"
|
||||
"\xa5\xa5\xa5\xa5\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6"
|
||||
"\xa6\xa6\xa6\xa6\xa6\xa6\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7"
|
||||
"\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa7\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8"
|
||||
"\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa9\xa9\xa9\xa9\xa9"
|
||||
"\xa9\xa9\xa9\xa9\xa9\xa9\xa9\xa9\xa9\xa9\xa9\xa9\xa9\xa9\xa9\xa9\xaa\xaa"
|
||||
"\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
|
||||
"\xaa\xaa\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab"
|
||||
"\xab\xab\xab\xab\xab\xac\xac\xac\xac\xac\xac\xac\xac\xac\xac\xac\xac\xac"
|
||||
"\xac\xac\xac\xac\xac\xac\xac\xac\xac\xad\xad\xad\xad\xad\xad\xad\xad\xad"
|
||||
"\xad\xad\xad\xad\xad\xad\xad\xad\xad\xad\xad\xad\xad\xae\xae\xae\xae\xae"
|
||||
"\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xae\xaf"
|
||||
"\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf\xaf"
|
||||
"\xaf\xaf\xaf\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0"
|
||||
"\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb0\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
|
||||
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb2\xb2\xb2\xb2\xb2\xb2"
|
||||
"\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb2\xb3"
|
||||
"\xb3\xb3\xb3\xb3\xb3\xb3\xb3\xb3\xb3\xb3\xb3\xb3\xb3\xb3\xb3\xb3\xb3\xb3"
|
||||
"\xb3\xb3\xb3\xb3\xb4\xb4\xb4\xb4\xb4\xb4\xb4\xb4\xb4\xb4\xb4\xb4\xb4\xb4"
|
||||
"\xb4\xb4\xb4\xb4\xb4\xb4\xb4\xb4\xb4\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xb5"
|
||||
"\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xb5\xb6\xb6\xb6"
|
||||
"\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6"
|
||||
"\xb6\xb6\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7"
|
||||
"\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8"
|
||||
"\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb8\xb9\xb9\xb9\xb9"
|
||||
"\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9"
|
||||
"\xb9\xba\xba\xba\xba\xba\xba\xba\xba\xba\xba\xba\xba\xba\xba\xba\xba\xba"
|
||||
"\xba\xba\xba\xba\xba\xba\xba\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb"
|
||||
"\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbc\xbc\xbc\xbc"
|
||||
"\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc"
|
||||
"\xbc\xbc\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd"
|
||||
"\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbd\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe"
|
||||
"\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbe\xbf\xbf"
|
||||
"\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf\xbf"
|
||||
"\xbf\xbf\xbf\xbf\xbf\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0"
|
||||
"\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc0\xc1\xc1\xc1\xc1\xc1\xc1"
|
||||
"\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1\xc1"
|
||||
"\xc1\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc2"
|
||||
"\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc2\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3"
|
||||
"\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc3\xc4\xc4"
|
||||
"\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4"
|
||||
"\xc4\xc4\xc4\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5"
|
||||
"\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc6\xc6\xc6\xc6"
|
||||
"\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6\xc6"
|
||||
"\xc6\xc6\xc6\xc6\xc6\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7"
|
||||
"\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc7\xc8\xc8\xc8\xc8\xc8"
|
||||
"\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8\xc8"
|
||||
"\xc8\xc8\xc8\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9"
|
||||
"\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xc9\xca\xca\xca\xca\xca\xca"
|
||||
"\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca"
|
||||
"\xca\xca\xca\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb"
|
||||
"\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcb\xcc\xcc\xcc\xcc\xcc\xcc"
|
||||
"\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc"
|
||||
"\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd"
|
||||
"\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xce\xce\xce\xce\xce"
|
||||
"\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce"
|
||||
"\xce\xce\xce\xce\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf"
|
||||
"\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xd0\xd0\xd0\xd0"
|
||||
"\xd0\xd0\xd0\xd0\xd0\xd0\xd0\xd0\xd0\xd0\xd0\xd0\xd0\xd0\xd0\xd0\xd0\xd0"
|
||||
"\xd0\xd0\xd0\xd0\xd0\xd0\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1"
|
||||
"\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd1\xd2\xd2"
|
||||
"\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2"
|
||||
"\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3"
|
||||
"\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3\xd3"
|
||||
"\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4"
|
||||
"\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
|
||||
"\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5"
|
||||
"\xd5\xd5\xd5\xd5\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6"
|
||||
"\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd7\xd7\xd7"
|
||||
"\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7"
|
||||
"\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8"
|
||||
"\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8\xd8"
|
||||
"\xd8\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9"
|
||||
"\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xd9\xda\xda\xda\xda\xda"
|
||||
"\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda"
|
||||
"\xda\xda\xda\xda\xda\xda\xda\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb"
|
||||
"\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb\xdb"
|
||||
"\xdb\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc"
|
||||
"\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdd\xdd\xdd\xdd\xdd"
|
||||
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd"
|
||||
"\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xde\xde\xde\xde\xde\xde\xde\xde\xde\xde\xde"
|
||||
"\xde\xde\xde\xde\xde\xde\xde\xde\xde\xde\xde\xde\xde\xde\xde\xde\xde\xde"
|
||||
"\xde\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf"
|
||||
"\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xdf\xe0\xe0\xe0\xe0"
|
||||
"\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0"
|
||||
"\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe0\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1"
|
||||
"\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1"
|
||||
"\xe1\xe1\xe1\xe1\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2"
|
||||
"\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe2\xe3"
|
||||
"\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3"
|
||||
"\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe3\xe4\xe4\xe4\xe4\xe4\xe4"
|
||||
"\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4"
|
||||
"\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe4\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5"
|
||||
"\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5\xe5"
|
||||
"\xe5\xe5\xe5\xe5\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6"
|
||||
"\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe6\xe7"
|
||||
"\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7"
|
||||
"\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe7\xe8\xe8\xe8\xe8\xe8"
|
||||
"\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8"
|
||||
"\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe8\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9"
|
||||
"\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9\xe9"
|
||||
"\xe9\xe9\xe9\xe9\xe9\xe9\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea"
|
||||
"\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea\xea"
|
||||
"\xea\xea\xea\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb"
|
||||
"\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xeb\xec"
|
||||
"\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec"
|
||||
"\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xec\xed\xed\xed"
|
||||
"\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed"
|
||||
"\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xed\xee\xee\xee\xee\xee\xee"
|
||||
"\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee\xee"
|
||||
"\xee\xee\xee\xee\xee\xee\xee\xee\xee\xef\xef\xef\xef\xef\xef\xef\xef\xef"
|
||||
"\xef\xef\xef\xef\xef\xef\xef\xef\xef\xef\xef\xef\xef\xef\xef\xef\xef\xef"
|
||||
"\xef\xef\xef\xef\xef\xef\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0"
|
||||
"\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0\xf0"
|
||||
"\xf0\xf0\xf0\xf0\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1"
|
||||
"\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1\xf1"
|
||||
"\xf1\xf1\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2"
|
||||
"\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2\xf2"
|
||||
"\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3"
|
||||
"\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf3\xf4\xf4"
|
||||
"\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4"
|
||||
"\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf4\xf5\xf5\xf5"
|
||||
"\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5"
|
||||
"\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf5\xf6\xf6\xf6\xf6"
|
||||
"\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6"
|
||||
"\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf6\xf7\xf7\xf7\xf7\xf7\xf7"
|
||||
"\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7"
|
||||
"\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf7\xf8\xf8\xf8\xf8\xf8\xf8\xf8"
|
||||
"\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8"
|
||||
"\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf9\xf9\xf9\xf9\xf9\xf9\xf9"
|
||||
"\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9"
|
||||
"\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xf9\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa"
|
||||
"\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa"
|
||||
"\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfa\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb"
|
||||
"\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb"
|
||||
"\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfb\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc"
|
||||
"\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc"
|
||||
"\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfc\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd"
|
||||
"\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd"
|
||||
"\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfd\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
|
||||
"\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe"
|
||||
"\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
;
|
||||
|
||||
static unsigned char linear_to_sRGB (float linear) FUNCTION;
|
||||
static unsigned char linear_to_sRGB (float linear)
|
||||
{
|
||||
unsigned slot;
|
||||
slot = linear*4096.0 + 0.5;
|
||||
if(slot>4095)
|
||||
{
|
||||
if(linear>0.5)
|
||||
slot = 4095;
|
||||
else
|
||||
slot = 0;
|
||||
}
|
||||
return linear_to_sRGB_table[slot];
|
||||
}
|
||||
|
||||
typedef struct multichan {
|
||||
double r,g,b; // linear
|
||||
double L,u,v; // L,a,b would be better -- 2-way formula unknown
|
||||
double hue,sat;
|
||||
unsigned char or,og,ob; // old 8-bit sRGB values
|
||||
unsigned char nr,ng,nb; // new 8-bit sRGB values
|
||||
unsigned char alpha; // 8-bit alpha value
|
||||
double L,hue,sat; // L,a,b would be better -- 2-way formula unknown
|
||||
unsigned char or,og,ob,alpha; // old 8-bit values
|
||||
} multichan;
|
||||
|
||||
#define X0 ((double)0.9505)
|
||||
|
|
@ -3043,24 +3366,21 @@ typedef struct multichan {
|
|||
#define u0_prime ( (4.0 * X0) / (X0 + 15.0*Y0 + 3.0*Z0) )
|
||||
#define v0_prime ( (9.0 * Y0) / (X0 + 15.0*Y0 + 3.0*Z0) )
|
||||
|
||||
static void fill_multichan(multichan *mc)
|
||||
|
||||
static void fill_multichan(multichan *mc, double *up, double *vp)
|
||||
{
|
||||
double tmp,X,Y,Z;
|
||||
double X,Y,Z,u,v;
|
||||
double u_prime, v_prime; /* temp, part of official formula */
|
||||
double Y_norm, fract; /* severely temp */
|
||||
|
||||
// from 8-bit sRGB to linear RGB
|
||||
tmp = mc->or / 255.0;
|
||||
mc->r = (tmp<=0.03928) ? tmp/12.92 : pow((tmp+0.055)/1.055,2.4);
|
||||
tmp = mc->og / 255.0;
|
||||
mc->g = (tmp<=0.03928) ? tmp/12.92 : pow((tmp+0.055)/1.055,2.4);
|
||||
tmp = mc->ob / 255.0;
|
||||
mc->b = (tmp<=0.03928) ? tmp/12.92 : pow((tmp+0.055)/1.055,2.4);
|
||||
double r = sRGB_to_linear_table[mc->or];
|
||||
double g = sRGB_to_linear_table[mc->og];
|
||||
double b = sRGB_to_linear_table[mc->ob];
|
||||
|
||||
// coordinate change, RGB --> XYZ
|
||||
X = 0.4124*mc->r + 0.3576*mc->g + 0.1805*mc->b;
|
||||
Y = 0.2126*mc->r + 0.7152*mc->g + 0.0722*mc->b;
|
||||
Z = 0.0193*mc->r + 0.1192*mc->g + 0.9505*mc->b;
|
||||
X = 0.4124*r + 0.3576*g + 0.1805*b;
|
||||
Y = 0.2126*r + 0.7152*g + 0.0722*b;
|
||||
Z = 0.0193*r + 0.1192*g + 0.9505*b;
|
||||
|
||||
// XYZ --> Luv
|
||||
Y_norm = Y/Y0;
|
||||
|
|
@ -3068,59 +3388,140 @@ static void fill_multichan(multichan *mc)
|
|||
u_prime = 4.0*X*fract;
|
||||
v_prime = 9.0*Y*fract;
|
||||
mc->L = (Y_norm>0.008856) ? 116.0*pow(Y_norm,1.0/3.0)-16.0 : 903.3*Y_norm;
|
||||
mc->u = 13.0*mc->L*(u_prime - u0_prime);
|
||||
mc->v = 13.0*mc->L*(v_prime - v0_prime);
|
||||
u = 13.0*mc->L*(u_prime - u0_prime);
|
||||
v = 13.0*mc->L*(v_prime - v0_prime);
|
||||
|
||||
mc->sat = sqrt(mc->u*mc->u + mc->v*mc->v);
|
||||
mc->hue = atan2(mc->u,mc->v);
|
||||
mc->sat = sqrt(u*u + v*v);
|
||||
mc->hue = atan2(u,v);
|
||||
if(up) *up = u;
|
||||
if(vp) *vp = v;
|
||||
}
|
||||
|
||||
static void tint_surface(SDL_Surface * tmp_surf, SDL_Surface * surf_ptr)
|
||||
|
||||
static double tint_part_1(multichan *work, SDL_Surface *in)
|
||||
{
|
||||
unsigned i;
|
||||
int xx, yy;
|
||||
|
||||
unsigned width = surf_ptr->w;
|
||||
unsigned height = surf_ptr->h;
|
||||
|
||||
multichan *work = malloc(sizeof *work * width * height);
|
||||
|
||||
// put pixels into a more tolerable form
|
||||
SDL_LockSurface(surf_ptr);
|
||||
for (yy = 0; yy < surf_ptr->h; yy++)
|
||||
{
|
||||
for (xx = 0; xx < surf_ptr->w; xx++)
|
||||
{
|
||||
multichan *mc = work+yy*width+xx;
|
||||
SDL_GetRGBA(getpixel(surf_ptr, xx, yy),
|
||||
surf_ptr->format,
|
||||
&mc->or, &mc->og, &mc->ob, &mc->alpha);
|
||||
}
|
||||
}
|
||||
SDL_UnlockSurface(surf_ptr);
|
||||
|
||||
i = width * height;
|
||||
while (i--)
|
||||
{
|
||||
multichan *mc = work+i;
|
||||
fill_multichan(mc);
|
||||
}
|
||||
|
||||
// initial hue guess
|
||||
double alpha_total = 0;
|
||||
int xx,yy;
|
||||
double u_total = 0;
|
||||
double v_total = 0;
|
||||
i = width * height;
|
||||
while (i--)
|
||||
{
|
||||
multichan *mc = work+i;
|
||||
alpha_total += mc->alpha;
|
||||
// more weight to opaque high-saturation pixels
|
||||
u_total += mc->alpha * mc->u * mc->sat;
|
||||
v_total += mc->alpha * mc->v * mc->sat;
|
||||
}
|
||||
double initial_hue = atan2(u_total,v_total);
|
||||
|
||||
SDL_LockSurface(in);
|
||||
for (yy = 0; yy < in->h; yy++)
|
||||
{
|
||||
for (xx = 0; xx < in->w; xx++)
|
||||
{
|
||||
multichan *mc = work+yy*in->w+xx;
|
||||
// put pixels into a more tolerable form
|
||||
SDL_GetRGBA(getpixel(in, xx, yy),
|
||||
in->format,
|
||||
&mc->or, &mc->og, &mc->ob, &mc->alpha);
|
||||
double u,v;
|
||||
fill_multichan(mc,&u,&v);
|
||||
// average out u and v, giving more weight to opaque high-saturation pixels
|
||||
// (this is to take an initial guess at the primary hue)
|
||||
u_total += mc->alpha * u * mc->sat;
|
||||
v_total += mc->alpha * v * mc->sat;
|
||||
}
|
||||
}
|
||||
SDL_UnlockSurface(in);
|
||||
|
||||
return atan2(u_total,v_total);
|
||||
}
|
||||
|
||||
|
||||
static void change_colors(SDL_Surface *out, multichan *work, double hue_range, multichan *key_color_ptr)
|
||||
{
|
||||
double lower_hue_1,upper_hue_1,lower_hue_2,upper_hue_2;
|
||||
int xx,yy;
|
||||
|
||||
// prepare source and destination color info
|
||||
// should reset hue_range or not? won't bother for now
|
||||
multichan key_color = *key_color_ptr; // want to work from a copy, for safety
|
||||
lower_hue_1 = key_color.hue - hue_range;
|
||||
upper_hue_1 = key_color.hue + hue_range;
|
||||
if (lower_hue_1 < -M_PI)
|
||||
{
|
||||
lower_hue_2 = lower_hue_1 + 2 * M_PI;
|
||||
upper_hue_2 = upper_hue_1 + 2 * M_PI;
|
||||
}
|
||||
else
|
||||
{
|
||||
lower_hue_2 = lower_hue_1 - 2 * M_PI;
|
||||
upper_hue_2 = upper_hue_1 - 2 * M_PI;
|
||||
}
|
||||
|
||||
// get the destination color set up
|
||||
multichan dst;
|
||||
dst.or = color_hexes[cur_color][0];
|
||||
dst.og = color_hexes[cur_color][1];
|
||||
dst.ob = color_hexes[cur_color][2];
|
||||
fill_multichan(&dst,NULL,NULL);
|
||||
double satratio = dst.sat / key_color.sat;
|
||||
double slope = (dst.L-key_color.L)/dst.sat;
|
||||
|
||||
SDL_LockSurface(out);
|
||||
for (yy = 0; yy < out->h; yy++)
|
||||
{
|
||||
for (xx = 0; xx < out->w; xx++)
|
||||
{
|
||||
multichan *mc = work+yy*out->w+xx;
|
||||
|
||||
double oldhue = mc->hue;
|
||||
|
||||
// if not in the first range, and not in the second range, skip this one
|
||||
// (really should alpha-blend as a function of hue angle difference)
|
||||
if( (oldhue<lower_hue_1 || oldhue>upper_hue_1) && (oldhue<lower_hue_2 || oldhue>upper_hue_2) )
|
||||
{
|
||||
putpixel(out, xx, yy, SDL_MapRGBA(out->format, mc->or, mc->og, mc->ob, mc->alpha));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Modify the pixel
|
||||
double old_sat = mc->sat;
|
||||
double newsat = old_sat * satratio;
|
||||
double L = mc->L;
|
||||
if(dst.sat>0)
|
||||
L += newsat * slope; // not greyscale destination
|
||||
else
|
||||
L += old_sat*(dst.L-key_color.L)/key_color.sat;
|
||||
|
||||
// convert from L,u,v all the way back to sRGB with 8-bit channels
|
||||
double X,Y,Z;
|
||||
double u_prime, v_prime; /* temp, part of official formula */
|
||||
unsigned tries = 3;
|
||||
trysat:;
|
||||
double u = newsat * sin(dst.hue);
|
||||
double v = newsat * cos(dst.hue);
|
||||
|
||||
// Luv to XYZ
|
||||
u_prime = u/(13.0*L)+u0_prime;
|
||||
v_prime = v/(13.0*L)+v0_prime;
|
||||
Y = (L>7.99959199307) ? Y0*pow((L+16.0)/116.0,3.0) : Y0*L/903.3;
|
||||
X = 2.25*Y*u_prime/v_prime;
|
||||
Z = (3.0*Y - 0.75*Y*u_prime)/v_prime - 5.0*Y;
|
||||
|
||||
// coordinate change: XYZ to RGB
|
||||
double r = 3.2410*X + -1.5374*Y + -0.4986*Z;
|
||||
double g = -0.9692*X + 1.8760*Y + 0.0416*Z;
|
||||
double b = 0.0556*X + -0.2040*Y + 1.0570*Z;
|
||||
|
||||
// If it is out of gamut, try to de-saturate it a few times before truncating.
|
||||
// (the linear_to_sRGB function will truncate)
|
||||
if((r<=-0.5 || g<=-0.5 || b<=-0.5 || r>=255.5 || g>=255.5 || b>=255.5) && tries--)
|
||||
{
|
||||
newsat *= 0.8;
|
||||
goto trysat;
|
||||
}
|
||||
|
||||
putpixel(out, xx, yy,
|
||||
SDL_MapRGBA(out->format, linear_to_sRGB(r), linear_to_sRGB(g), linear_to_sRGB(b), mc->alpha));
|
||||
}
|
||||
}
|
||||
SDL_UnlockSurface(out);
|
||||
}
|
||||
|
||||
|
||||
static multichan *find_most_saturated(double initial_hue, multichan *work, unsigned i, double *hue_range_ptr)
|
||||
{
|
||||
// find the most saturated pixel near the initial hue guess
|
||||
multichan *key_color_ptr = NULL;
|
||||
double hue_range;
|
||||
|
|
@ -3153,7 +3554,6 @@ hue_range_retry:;
|
|||
lower_hue_2 = lower_hue_1 - 2 * M_PI;
|
||||
upper_hue_2 = upper_hue_1 - 2 * M_PI;
|
||||
}
|
||||
i = width * height;
|
||||
while (i--)
|
||||
{
|
||||
multichan *mc = work+i;
|
||||
|
|
@ -3170,268 +3570,69 @@ hue_range_retry:;
|
|||
hue_range *= 1.5;
|
||||
if (hue_range < M_PI)
|
||||
goto hue_range_retry;
|
||||
goto give_up;
|
||||
}
|
||||
|
||||
// wider for processing than for searching
|
||||
hue_range *= 1.5;
|
||||
|
||||
// prepare source and destination color info
|
||||
// should reset hue_range or not? won't bother for now
|
||||
multichan key_color = *key_color_ptr; // want to work from a copy, for safety
|
||||
lower_hue_1 = key_color.hue - hue_range;
|
||||
upper_hue_1 = key_color.hue + hue_range;
|
||||
if (lower_hue_1 < -M_PI)
|
||||
{
|
||||
lower_hue_2 = lower_hue_1 + 2 * M_PI;
|
||||
upper_hue_2 = upper_hue_1 + 2 * M_PI;
|
||||
}
|
||||
else
|
||||
{
|
||||
lower_hue_2 = lower_hue_1 - 2 * M_PI;
|
||||
upper_hue_2 = upper_hue_1 - 2 * M_PI;
|
||||
}
|
||||
|
||||
// get the destination color set up
|
||||
multichan dst;
|
||||
dst.or = color_hexes[cur_color][0];
|
||||
dst.og = color_hexes[cur_color][1];
|
||||
dst.ob = color_hexes[cur_color][2];
|
||||
fill_multichan(&dst);
|
||||
double satratio = dst.sat / key_color.sat;
|
||||
double slope = (dst.L-key_color.L)/dst.sat;
|
||||
|
||||
// change the colors!
|
||||
i = width * height;
|
||||
while (i--)
|
||||
{
|
||||
multichan *mc = work+i;
|
||||
// if not in the first range, and not in the second range, skip this one
|
||||
// (really should alpha-blend as a function of hue angle difference)
|
||||
if( (mc->hue<lower_hue_1 || mc->hue>upper_hue_1) && (mc->hue<lower_hue_2 || mc->hue>upper_hue_2) )
|
||||
continue;
|
||||
// this one will now be modified
|
||||
double old_sat = mc->sat;
|
||||
mc->hue = dst.hue;
|
||||
mc->sat = mc->sat * satratio;
|
||||
if(dst.sat>0)
|
||||
mc->L += mc->sat * slope; // not greyscale destination
|
||||
else
|
||||
mc->L += old_sat*(dst.L-key_color.L)/key_color.sat;
|
||||
}
|
||||
|
||||
give_up:
|
||||
|
||||
i = width * height;
|
||||
while (i--)
|
||||
{
|
||||
multichan *mc = work+i;
|
||||
double X,Y,Z;
|
||||
double u_prime, v_prime; /* temp, part of official formula */
|
||||
int r,g,b;
|
||||
unsigned tries = 3;
|
||||
double sat = mc->sat;
|
||||
trysat:;
|
||||
double u = sat * sin(mc->hue);
|
||||
double v = sat * cos(mc->hue);
|
||||
double L = mc->L;
|
||||
|
||||
// Luv to XYZ
|
||||
u_prime = u/(13.0*L)+u0_prime;
|
||||
v_prime = v/(13.0*L)+v0_prime;
|
||||
Y = (L>7.99959199307) ? Y0*pow((L+16.0)/116.0,3.0) : Y0*L/903.3;
|
||||
X = 2.25*Y*u_prime/v_prime;
|
||||
Z = (3.0*Y - 0.75*Y*u_prime)/v_prime - 5.0*Y;
|
||||
|
||||
// coordinate change: XYZ to RGB
|
||||
mc->r = 3.2410*X + -1.5374*Y + -0.4986*Z;
|
||||
mc->g = -0.9692*X + 1.8760*Y + 0.0416*Z;
|
||||
mc->b = 0.0556*X + -0.2040*Y + 1.0570*Z;
|
||||
|
||||
// gamma: linear to sRGB
|
||||
r = ( (mc->r<=0.00304) ? 12.92*mc->r : 1.055*pow(mc->r,1.0/2.4)-0.055 ) * 255.9999;
|
||||
g = ( (mc->g<=0.00304) ? 12.92*mc->g : 1.055*pow(mc->g,1.0/2.4)-0.055 ) * 255.9999;
|
||||
b = ( (mc->b<=0.00304) ? 12.92*mc->b : 1.055*pow(mc->b,1.0/2.4)-0.055 ) * 255.9999;
|
||||
|
||||
if((r|g|b)>>8){
|
||||
static int cnt = 42;
|
||||
if(cnt){
|
||||
cnt--;
|
||||
// printf("%d %d %d\n",r,g,b);
|
||||
}
|
||||
sat *= 0.8;
|
||||
if(tries--)
|
||||
goto trysat; // maybe it'll work if we de-saturate a bit
|
||||
else
|
||||
{ // bummer, this is out of gamut and fighting
|
||||
if (r>255)
|
||||
r = 255;
|
||||
if (g>255)
|
||||
g = 255;
|
||||
if (b>255)
|
||||
b = 255;
|
||||
if (r<0)
|
||||
r = 0;
|
||||
if (g<0)
|
||||
g = 0;
|
||||
if (b<0)
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
|
||||
mc->nr = r;
|
||||
mc->ng = g;
|
||||
mc->nb = b;
|
||||
}
|
||||
|
||||
// put data back into SDL form
|
||||
SDL_LockSurface(tmp_surf);
|
||||
for (yy = 0; yy < tmp_surf->h; yy++)
|
||||
{
|
||||
for (xx = 0; xx < tmp_surf->w; xx++)
|
||||
{
|
||||
multichan *mc = work+yy*width+xx;
|
||||
putpixel(tmp_surf, xx, yy,
|
||||
SDL_MapRGBA(tmp_surf->format, mc->nr, mc->ng, mc->nb, mc->alpha));
|
||||
}
|
||||
}
|
||||
SDL_UnlockSurface(tmp_surf);
|
||||
free(work);
|
||||
*hue_range_ptr = hue_range;
|
||||
return key_color_ptr;
|
||||
}
|
||||
|
||||
// This tints a greyscale stamp. Hopefully such stamps remain rare.
|
||||
// If they were common, a more efficient way to do this is to simply
|
||||
// scale the linear RGB values of the destination color by the linear
|
||||
// brightness of the stamp colors.
|
||||
static void vector_tint_surface(SDL_Surface * tmp_surf, SDL_Surface * surf_ptr)
|
||||
{
|
||||
unsigned i;
|
||||
int xx, yy;
|
||||
|
||||
static void vector_tint_surface(SDL_Surface * out, SDL_Surface * in)
|
||||
{
|
||||
int xx,yy;
|
||||
|
||||
double r = sRGB_to_linear_table[color_hexes[cur_color][0]];
|
||||
double g = sRGB_to_linear_table[color_hexes[cur_color][1]];
|
||||
double b = sRGB_to_linear_table[color_hexes[cur_color][2]];
|
||||
|
||||
SDL_LockSurface(in);
|
||||
for (yy = 0; yy < in->h; yy++)
|
||||
{
|
||||
for (xx = 0; xx < in->w; xx++)
|
||||
{
|
||||
unsigned char r8, g8, b8, a8;
|
||||
SDL_GetRGBA(getpixel(in, xx, yy),
|
||||
in->format,
|
||||
&r8, &g8, &b8, &a8);
|
||||
// get the linear greyscale value
|
||||
double old = sRGB_to_linear_table[r8]*0.2126 + sRGB_to_linear_table[g8]*0.7152 + sRGB_to_linear_table[b8]*0.0722;
|
||||
|
||||
putpixel(out, xx, yy,
|
||||
SDL_MapRGBA(out->format, linear_to_sRGB(r*old), linear_to_sRGB(g*old), linear_to_sRGB(b*old), a8));
|
||||
}
|
||||
}
|
||||
SDL_UnlockSurface(in);
|
||||
}
|
||||
|
||||
|
||||
static void tint_surface(SDL_Surface * tmp_surf, SDL_Surface * surf_ptr)
|
||||
{
|
||||
unsigned width = surf_ptr->w;
|
||||
unsigned height = surf_ptr->h;
|
||||
|
||||
multichan *work = malloc(sizeof *work * width * height);
|
||||
|
||||
// put pixels into a more tolerable form
|
||||
SDL_LockSurface(surf_ptr);
|
||||
for (yy = 0; yy < surf_ptr->h; yy++)
|
||||
{
|
||||
for (xx = 0; xx < surf_ptr->w; xx++)
|
||||
{
|
||||
multichan *mc = work+yy*width+xx;
|
||||
SDL_GetRGBA(getpixel(surf_ptr, xx, yy),
|
||||
surf_ptr->format,
|
||||
&mc->or, &mc->og, &mc->ob, &mc->alpha);
|
||||
}
|
||||
}
|
||||
SDL_UnlockSurface(surf_ptr);
|
||||
double initial_hue = tint_part_1(work, surf_ptr);
|
||||
|
||||
i = width * height;
|
||||
while (i--)
|
||||
double hue_range;
|
||||
multichan *key_color_ptr = find_most_saturated(initial_hue, work, width*height, &hue_range);
|
||||
|
||||
if (key_color_ptr)
|
||||
{
|
||||
multichan *mc = work+i;
|
||||
fill_multichan(mc);
|
||||
// wider for processing than for searching
|
||||
hue_range *= 1.5;
|
||||
|
||||
change_colors(tmp_surf, work, hue_range, key_color_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "fallback to tinter=vector, this should be in the *.dat file\n");
|
||||
vector_tint_surface(tmp_surf, surf_ptr);
|
||||
}
|
||||
|
||||
// get the destination color set up
|
||||
multichan dst;
|
||||
dst.or = color_hexes[cur_color][0];
|
||||
dst.og = color_hexes[cur_color][1];
|
||||
dst.ob = color_hexes[cur_color][2];
|
||||
fill_multichan(&dst);
|
||||
|
||||
if (dst.L > 0.0) // if not black (else this is a SLOW memcpy!)
|
||||
{
|
||||
// change the colors!
|
||||
i = width * height;
|
||||
while (i--)
|
||||
{
|
||||
multichan *mc = work+i;
|
||||
// this one will now be modified
|
||||
mc->hue = dst.hue;
|
||||
mc->sat = dst.sat * mc->L / 100.0;
|
||||
mc->L = mc->L * mc->L / 100.0;
|
||||
}
|
||||
}
|
||||
|
||||
i = width * height;
|
||||
while (i--)
|
||||
{
|
||||
multichan *mc = work+i;
|
||||
double X,Y,Z;
|
||||
double u_prime, v_prime; /* temp, part of official formula */
|
||||
int r,g,b;
|
||||
unsigned tries = 3;
|
||||
double sat = mc->sat;
|
||||
trysat:;
|
||||
double u = sat * sin(mc->hue);
|
||||
double v = sat * cos(mc->hue);
|
||||
double L = mc->L;
|
||||
|
||||
// Luv to XYZ
|
||||
u_prime = u/(13.0*L)+u0_prime;
|
||||
v_prime = v/(13.0*L)+v0_prime;
|
||||
Y = (L>7.99959199307) ? Y0*pow((L+16.0)/116.0,3.0) : Y0*L/903.3;
|
||||
X = 2.25*Y*u_prime/v_prime;
|
||||
Z = (3.0*Y - 0.75*Y*u_prime)/v_prime - 5.0*Y;
|
||||
|
||||
// coordinate change: XYZ to RGB
|
||||
mc->r = 3.2410*X + -1.5374*Y + -0.4986*Z;
|
||||
mc->g = -0.9692*X + 1.8760*Y + 0.0416*Z;
|
||||
mc->b = 0.0556*X + -0.2040*Y + 1.0570*Z;
|
||||
|
||||
// gamma: linear to sRGB
|
||||
r = ( (mc->r<=0.00304) ? 12.92*mc->r : 1.055*pow(mc->r,1.0/2.4)-0.055 ) * 255.9999;
|
||||
g = ( (mc->g<=0.00304) ? 12.92*mc->g : 1.055*pow(mc->g,1.0/2.4)-0.055 ) * 255.9999;
|
||||
b = ( (mc->b<=0.00304) ? 12.92*mc->b : 1.055*pow(mc->b,1.0/2.4)-0.055 ) * 255.9999;
|
||||
|
||||
if((r|g|b)>>8){
|
||||
static int cnt = 42;
|
||||
if(cnt){
|
||||
cnt--;
|
||||
// printf("%d %d %d\n",r,g,b);
|
||||
}
|
||||
sat *= 0.8;
|
||||
if(tries--)
|
||||
goto trysat; // maybe it'll work if we de-saturate a bit
|
||||
else
|
||||
{ // bummer, this is out of gamut and fighting
|
||||
if (r>255)
|
||||
r = 255;
|
||||
if (g>255)
|
||||
g = 255;
|
||||
if (b>255)
|
||||
b = 255;
|
||||
if (r<0)
|
||||
r = 0;
|
||||
if (g<0)
|
||||
g = 0;
|
||||
if (b<0)
|
||||
b = 0;
|
||||
}
|
||||
}
|
||||
|
||||
mc->nr = r;
|
||||
mc->ng = g;
|
||||
mc->nb = b;
|
||||
}
|
||||
|
||||
// put data back into SDL form
|
||||
SDL_LockSurface(tmp_surf);
|
||||
for (yy = 0; yy < tmp_surf->h; yy++)
|
||||
{
|
||||
for (xx = 0; xx < tmp_surf->w; xx++)
|
||||
{
|
||||
multichan *mc = work+yy*width+xx;
|
||||
putpixel(tmp_surf, xx, yy,
|
||||
SDL_MapRGBA(tmp_surf->format, mc->nr, mc->ng, mc->nb, mc->alpha));
|
||||
}
|
||||
}
|
||||
SDL_UnlockSurface(tmp_surf);
|
||||
free(work);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
/* Draw using the current stamp: */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue