Finished working on the new color lookup system.

There is room for optimization and maybe bugfixing.
The cluster table size is now:
511*15 = 7665bytes, this is 1094 times better than the color table.

Please test and report your results !


git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1874 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Adrien Destugues 2011-11-22 21:38:03 +00:00
parent 91e7d459a3
commit d3a107bb7c
6 changed files with 178 additions and 262 deletions

View File

@ -391,7 +391,7 @@ endif
.PHONY : all debug release clean depend zip version force install uninstall .PHONY : all debug release clean depend zip version force install uninstall
# This is the list of the objects we want to build. Dependancies are built by "make depend" automatically. # This is the list of the objects we want to build. Dependancies are built by "make depend" automatically.
OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o $(OBJDIR)/libraw2crtc.o $(OBJDIR)/brush_ops.o $(OBJDIR)/buttons_effects.o $(OBJDIR)/layers.o $(OBJDIR)/oldies.o $(OBJDIR)/tiles.o OBJ = $(OBJDIR)/main.o $(OBJDIR)/init.o $(OBJDIR)/graph.o $(OBJDIR)/sdlscreen.o $(OBJDIR)/misc.o $(OBJDIR)/special.o $(OBJDIR)/buttons.o $(OBJDIR)/palette.o $(OBJDIR)/help.o $(OBJDIR)/operatio.o $(OBJDIR)/pages.o $(OBJDIR)/loadsave.o $(OBJDIR)/readline.o $(OBJDIR)/engine.o $(OBJDIR)/filesel.o $(OBJDIR)/op_c.o $(OBJDIR)/readini.o $(OBJDIR)/saveini.o $(OBJDIR)/shade.o $(OBJDIR)/keyboard.o $(OBJDIR)/io.o $(OBJDIR)/version.o $(OBJDIR)/text.o $(OBJDIR)/SFont.o $(OBJDIR)/setup.o $(OBJDIR)/pxsimple.o $(OBJDIR)/pxtall.o $(OBJDIR)/pxwide.o $(OBJDIR)/pxdouble.o $(OBJDIR)/pxtriple.o $(OBJDIR)/pxtall2.o $(OBJDIR)/pxwide2.o $(OBJDIR)/pxquad.o $(OBJDIR)/windows.o $(OBJDIR)/brush.o $(OBJDIR)/realpath.o $(OBJDIR)/mountlist.o $(OBJDIR)/input.o $(OBJDIR)/hotkeys.o $(OBJDIR)/transform.o $(OBJDIR)/pversion.o $(OBJDIR)/factory.o $(PLATFORMOBJ) $(OBJDIR)/fileformats.o $(OBJDIR)/miscfileformats.o $(OBJDIR)/libraw2crtc.o $(OBJDIR)/brush_ops.o $(OBJDIR)/buttons_effects.o $(OBJDIR)/layers.o $(OBJDIR)/oldies.o $(OBJDIR)/tiles.o $(OBJDIR)/colorred.o
SKIN_FILES = ../share/grafx2/skins/skin_classic.png ../share/grafx2/skins/skin_modern.png ../share/grafx2/skins/skin_DPaint.png ../share/grafx2/skins/font_Classic.png ../share/grafx2/skins/font_Fun.png ../share/grafx2/skins/font_Fairlight.png ../share/grafx2/skins/font_Melon.png ../share/grafx2/skins/font_DPaint.png ../share/grafx2/skins/skin_scenish.png ../share/grafx2/skins/font_Seen.png ../share/grafx2/skins/skin_Aurora.png SKIN_FILES = ../share/grafx2/skins/skin_classic.png ../share/grafx2/skins/skin_modern.png ../share/grafx2/skins/skin_DPaint.png ../share/grafx2/skins/font_Classic.png ../share/grafx2/skins/font_Fun.png ../share/grafx2/skins/font_Fairlight.png ../share/grafx2/skins/font_Melon.png ../share/grafx2/skins/font_DPaint.png ../share/grafx2/skins/skin_scenish.png ../share/grafx2/skins/font_Seen.png ../share/grafx2/skins/skin_Aurora.png

View File

@ -1,33 +1,34 @@
$(OBJDIR)/SFont.o: SFont.c SFont.h
$(OBJDIR)/brush.o: brush.c global.h struct.h const.h graph.h misc.h errors.h \
windows.h sdlscreen.h brush.h
$(OBJDIR)/brush_ops.o: brush_ops.c brush.h struct.h const.h buttons.h engine.h \ $(OBJDIR)/brush_ops.o: brush_ops.c brush.h struct.h const.h buttons.h engine.h \
global.h graph.h misc.h operatio.h pages.h sdlscreen.h windows.h global.h graph.h misc.h operatio.h pages.h sdlscreen.h windows.h
$(OBJDIR)/brush.o: brush.c global.h struct.h const.h graph.h misc.h errors.h \
windows.h sdlscreen.h brush.h tiles.h
$(OBJDIR)/buttons_effects.o: buttons_effects.c brush.h struct.h const.h \
buttons.h engine.h global.h graph.h help.h input.h misc.h pages.h \
readline.h sdlscreen.h windows.h tiles.h
$(OBJDIR)/buttons.o: buttons.c const.h struct.h global.h misc.h graph.h engine.h \ $(OBJDIR)/buttons.o: buttons.c const.h struct.h global.h misc.h graph.h engine.h \
readline.h filesel.h loadsave.h init.h buttons.h operatio.h pages.h \ readline.h filesel.h loadsave.h init.h buttons.h operatio.h pages.h \
palette.h errors.h readini.h saveini.h shade.h io.h help.h text.h \ palette.h errors.h readini.h saveini.h shade.h io.h help.h text.h \
sdlscreen.h windows.h brush.h input.h special.h setup.h sdlscreen.h windows.h brush.h input.h special.h tiles.h setup.h
$(OBJDIR)/buttons_effects.o: buttons_effects.c buttons.h struct.h const.h engine.h \ $(OBJDIR)/colorred.o: colorred.c
global.h graph.h help.h input.h misc.h readline.h sdlscreen.h windows.h \
brush.h
$(OBJDIR)/engine.o: engine.c const.h struct.h global.h graph.h misc.h special.h \ $(OBJDIR)/engine.o: engine.c const.h struct.h global.h graph.h misc.h special.h \
buttons.h operatio.h shade.h errors.h sdlscreen.h windows.h brush.h \ buttons.h operatio.h shade.h errors.h sdlscreen.h windows.h brush.h \
input.h engine.h pages.h layers.h factory.h loadsave.h io.h input.h engine.h pages.h layers.h factory.h loadsave.h io.h
$(OBJDIR)/factory.o: factory.c brush.h struct.h const.h buttons.h engine.h errors.h \ $(OBJDIR)/factory.o: factory.c brush.h struct.h const.h buttons.h engine.h \
filesel.h loadsave.h global.h graph.h io.h misc.h pages.h readline.h \ errors.h filesel.h loadsave.h global.h graph.h io.h misc.h pages.h \
sdlscreen.h windows.h palette.h input.h help.h realpath.h readline.h sdlscreen.h windows.h palette.h input.h help.h realpath.h \
setup.h
$(OBJDIR)/fileformats.o: fileformats.c errors.h global.h struct.h const.h \ $(OBJDIR)/fileformats.o: fileformats.c errors.h global.h struct.h const.h \
loadsave.h misc.h io.h windows.h pages.h loadsave.h misc.h io.h windows.h pages.h
$(OBJDIR)/filesel.o: filesel.c const.h struct.h global.h misc.h errors.h io.h \ $(OBJDIR)/filesel.o: filesel.c const.h struct.h global.h misc.h errors.h io.h \
windows.h sdlscreen.h loadsave.h mountlist.h engine.h readline.h input.h \ windows.h sdlscreen.h loadsave.h mountlist.h engine.h readline.h \
help.h filesel.h input.h help.h filesel.h
$(OBJDIR)/graph.o: graph.c global.h struct.h const.h engine.h buttons.h pages.h \ $(OBJDIR)/graph.o: graph.c global.h struct.h const.h engine.h buttons.h pages.h \
errors.h sdlscreen.h graph.h misc.h pxsimple.h pxtall.h pxwide.h \ errors.h sdlscreen.h graph.h misc.h pxsimple.h pxtall.h pxwide.h \
pxdouble.h pxtriple.h pxwide2.h pxtall2.h pxquad.h windows.h input.h \ pxdouble.h pxtriple.h pxwide2.h pxtall2.h pxquad.h windows.h input.h \
brush.h brush.h tiles.h
$(OBJDIR)/help.o: help.c const.h struct.h global.h misc.h engine.h helpfile.h \ $(OBJDIR)/help.o: help.c haiku.h struct.h const.h global.h misc.h engine.h \
help.h sdlscreen.h text.h keyboard.h windows.h input.h hotkeys.h \ helpfile.h help.h sdlscreen.h text.h keyboard.h windows.h input.h \
errors.h pages.h hotkeys.h errors.h pages.h
$(OBJDIR)/hotkeys.o: hotkeys.c struct.h const.h global.h hotkeys.h $(OBJDIR)/hotkeys.o: hotkeys.c struct.h const.h global.h hotkeys.h
$(OBJDIR)/init.o: init.c buttons.h struct.h const.h errors.h global.h graph.h \ $(OBJDIR)/init.o: init.c buttons.h struct.h const.h errors.h global.h graph.h \
init.h io.h factory.h help.h hotkeys.h keyboard.h loadsave.h misc.h \ init.h io.h factory.h help.h hotkeys.h keyboard.h loadsave.h misc.h \
@ -37,70 +38,76 @@ $(OBJDIR)/input.o: input.c global.h struct.h const.h keyboard.h sdlscreen.h \
windows.h errors.h misc.h buttons.h input.h loadsave.h windows.h errors.h misc.h buttons.h input.h loadsave.h
$(OBJDIR)/io.o: io.c struct.h const.h io.h realpath.h $(OBJDIR)/io.o: io.c struct.h const.h io.h realpath.h
$(OBJDIR)/keyboard.o: keyboard.c global.h struct.h const.h keyboard.h $(OBJDIR)/keyboard.o: keyboard.c global.h struct.h const.h keyboard.h
$(OBJDIR)/layers.o: layers.c const.h struct.h global.h windows.h engine.h pages.h \ $(OBJDIR)/layers.o: layers.c const.h struct.h global.h windows.h engine.h \
sdlscreen.h input.h help.h misc.h pages.h sdlscreen.h input.h help.h misc.h readline.h
$(OBJDIR)/libraw2crtc.o: libraw2crtc.c const.h global.h struct.h loadsave.h $(OBJDIR)/libraw2crtc.o: libraw2crtc.c const.h global.h struct.h loadsave.h
$(OBJDIR)/loadsave.o: loadsave.c buttons.h struct.h const.h errors.h global.h io.h \ $(OBJDIR)/loadsave.o: loadsave.c buttons.h struct.h const.h errors.h global.h \
loadsave.h misc.h graph.h op_c.h pages.h palette.h sdlscreen.h windows.h \ io.h loadsave.h misc.h graph.h op_c.h pages.h palette.h sdlscreen.h \
engine.h brush.h setup.h windows.h engine.h brush.h setup.h
$(OBJDIR)/main.o: main.c const.h struct.h global.h graph.h misc.h init.h buttons.h \ $(OBJDIR)/main.o: main.c const.h struct.h global.h graph.h misc.h init.h \
engine.h pages.h loadsave.h sdlscreen.h errors.h readini.h saveini.h \ buttons.h engine.h pages.h loadsave.h sdlscreen.h errors.h readini.h \
io.h text.h setup.h windows.h brush.h palette.h realpath.h input.h \ saveini.h io.h text.h setup.h windows.h brush.h palette.h realpath.h \
help.h input.h help.h
$(OBJDIR)/misc.o: misc.c struct.h const.h sdlscreen.h global.h errors.h buttons.h \ $(OBJDIR)/misc.o: misc.c struct.h const.h sdlscreen.h global.h errors.h \
engine.h misc.h keyboard.h windows.h palette.h input.h graph.h pages.h buttons.h engine.h misc.h keyboard.h windows.h palette.h input.h \
$(OBJDIR)/miscfileformats.o: miscfileformats.c engine.h struct.h const.h errors.h \ graph.h pages.h
global.h io.h libraw2crtc.h loadsave.h misc.h sdlscreen.h windows.h $(OBJDIR)/miscfileformats.o: miscfileformats.c engine.h struct.h const.h \
$(OBJDIR)/mountlist.o: mountlist.c errors.h global.h io.h libraw2crtc.h \
$(OBJDIR)/op_c.o: op_c.c op_c.h struct.h const.h errors.h global.h engine.h \ /boot/develop/abi/x86/gcc2/tools/gcc-2.95.3-haiku-100818/lib/gcc-lib/i586-pc-haiku/2.95.3-haiku-100818/include/limits.h \
windows.h loadsave.h misc.h sdlscreen.h windows.h oldies.h
$(OBJDIR)/operatio.o: operatio.c const.h struct.h global.h misc.h engine.h graph.h \ $(OBJDIR)/mountlist.o: mountlist.c mountlist.h
operatio.h buttons.h pages.h errors.h sdlscreen.h brush.h windows.h \ $(OBJDIR)/oldies.o: oldies.c struct.h const.h global.h errors.h misc.h palette.h
input.h $(OBJDIR)/op_c.o: op_c.c op_c.h struct.h const.h errors.h global.h \
/boot/develop/abi/x86/gcc2/tools/gcc-2.95.3-haiku-100818/lib/gcc-lib/i586-pc-haiku/2.95.3-haiku-100818/include/limits.h \
engine.h windows.h
$(OBJDIR)/operatio.o: operatio.c const.h struct.h global.h misc.h engine.h \
graph.h operatio.h buttons.h pages.h errors.h sdlscreen.h brush.h \
windows.h input.h
$(OBJDIR)/pages.o: pages.c global.h struct.h const.h pages.h errors.h loadsave.h \ $(OBJDIR)/pages.o: pages.c global.h struct.h const.h pages.h errors.h loadsave.h \
misc.h windows.h misc.h windows.h
$(OBJDIR)/palette.o: palette.c const.h struct.h global.h misc.h engine.h readline.h \ $(OBJDIR)/palette.o: palette.c const.h struct.h global.h misc.h engine.h \
buttons.h pages.h help.h sdlscreen.h errors.h op_c.h windows.h input.h \
palette.h shade.h
$(OBJDIR)/palette_test.o: palette_test.c const.h struct.h global.h misc.h engine.h \
readline.h buttons.h pages.h help.h sdlscreen.h errors.h op_c.h \ readline.h buttons.h pages.h help.h sdlscreen.h errors.h op_c.h \
windows.h input.h palette.h shade.h windows.h input.h palette.h shade.h
$(OBJDIR)/pversion.o: pversion.c $(OBJDIR)/pversion.o: pversion.c
$(OBJDIR)/pxdouble.o: pxdouble.c global.h struct.h const.h sdlscreen.h misc.h \ $(OBJDIR)/pxdouble.o: pxdouble.c global.h struct.h const.h sdlscreen.h misc.h \
graph.h pxdouble.h pxwide.h graph.h pxdouble.h pxwide.h
$(OBJDIR)/pxquad.o: pxquad.c global.h struct.h const.h sdlscreen.h misc.h graph.h \ $(OBJDIR)/pxquad.o: pxquad.c global.h struct.h const.h sdlscreen.h misc.h \
pxquad.h graph.h pxquad.h
$(OBJDIR)/pxsimple.o: pxsimple.c global.h struct.h const.h sdlscreen.h misc.h \ $(OBJDIR)/pxsimple.o: pxsimple.c global.h struct.h const.h sdlscreen.h misc.h \
graph.h pxsimple.h graph.h pxsimple.h
$(OBJDIR)/pxtall.o: pxtall.c global.h struct.h const.h sdlscreen.h misc.h graph.h \ $(OBJDIR)/pxtall.o: pxtall.c global.h struct.h const.h sdlscreen.h misc.h \
pxtall.h pxsimple.h graph.h pxtall.h pxsimple.h
$(OBJDIR)/pxtall2.o: pxtall2.c global.h struct.h const.h sdlscreen.h misc.h graph.h \ $(OBJDIR)/pxtall2.o: pxtall2.c global.h struct.h const.h sdlscreen.h misc.h \
pxtall2.h graph.h pxtall2.h
$(OBJDIR)/pxtriple.o: pxtriple.c global.h struct.h const.h sdlscreen.h misc.h \ $(OBJDIR)/pxtriple.o: pxtriple.c global.h struct.h const.h sdlscreen.h misc.h \
graph.h pxtriple.h graph.h pxtriple.h
$(OBJDIR)/pxwide.o: pxwide.c global.h struct.h const.h sdlscreen.h misc.h graph.h \ $(OBJDIR)/pxwide.o: pxwide.c global.h struct.h const.h sdlscreen.h misc.h \
pxwide.h graph.h pxwide.h
$(OBJDIR)/pxwide2.o: pxwide2.c global.h struct.h const.h sdlscreen.h misc.h graph.h \ $(OBJDIR)/pxwide2.o: pxwide2.c global.h struct.h const.h sdlscreen.h misc.h \
pxwide2.h graph.h pxwide2.h
$(OBJDIR)/readini.o: readini.c const.h errors.h global.h struct.h misc.h readini.h \ $(OBJDIR)/readini.o: readini.c const.h errors.h global.h struct.h misc.h \
setup.h realpath.h io.h readini.h setup.h realpath.h io.h
$(OBJDIR)/readline.o: readline.c const.h struct.h global.h misc.h errors.h \ $(OBJDIR)/readline.o: readline.c const.h struct.h global.h misc.h errors.h \
sdlscreen.h readline.h windows.h input.h engine.h sdlscreen.h readline.h windows.h input.h engine.h
$(OBJDIR)/realpath.o: realpath.c $(OBJDIR)/realpath.o: realpath.c
$(OBJDIR)/saveini.o: saveini.c const.h global.h struct.h readini.h io.h errors.h \ $(OBJDIR)/saveini.o: saveini.c const.h global.h struct.h readini.h io.h errors.h \
misc.h saveini.h setup.h misc.h saveini.h setup.h
$(OBJDIR)/sdlscreen.o: sdlscreen.c global.h struct.h const.h sdlscreen.h errors.h \ $(OBJDIR)/sdlscreen.o: sdlscreen.c global.h struct.h const.h sdlscreen.h \
misc.h errors.h misc.h
$(OBJDIR)/setup.o: setup.c struct.h const.h io.h setup.h $(OBJDIR)/setup.o: setup.c struct.h const.h io.h setup.h
$(OBJDIR)/SFont.o: SFont.c SFont.h
$(OBJDIR)/shade.o: shade.c global.h struct.h const.h graph.h engine.h errors.h \ $(OBJDIR)/shade.o: shade.c global.h struct.h const.h graph.h engine.h errors.h \
misc.h readline.h help.h sdlscreen.h windows.h input.h shade.h misc.h readline.h help.h sdlscreen.h windows.h input.h shade.h
$(OBJDIR)/special.o: special.c const.h struct.h global.h graph.h engine.h windows.h \ $(OBJDIR)/special.o: special.c const.h struct.h global.h graph.h engine.h \
special.h pages.h misc.h buttons.h windows.h special.h pages.h misc.h buttons.h
$(OBJDIR)/text.o: text.c SFont.h struct.h const.h global.h sdlscreen.h io.h \ $(OBJDIR)/text.o: text.c SFont.h struct.h const.h global.h sdlscreen.h io.h \
errors.h windows.h misc.h setup.h errors.h windows.h misc.h setup.h
$(OBJDIR)/tiles.o: tiles.c $(OBJDIR)/tiles.o: tiles.c struct.h const.h global.h graph.h sdlscreen.h \
$(OBJDIR)/transform.o: transform.c global.h struct.h const.h transform.h engine.h \ engine.h windows.h input.h misc.h tiles.h
sdlscreen.h windows.h input.h help.h misc.h readline.h buttons.h pages.h $(OBJDIR)/transform.o: transform.c global.h struct.h const.h transform.h \
engine.h sdlscreen.h windows.h input.h help.h misc.h readline.h \
buttons.h pages.h tiles.h
$(OBJDIR)/version.o: version.c $(OBJDIR)/version.o: version.c
$(OBJDIR)/windows.o: windows.c windows.h struct.h const.h engine.h errors.h \ $(OBJDIR)/windows.o: windows.c windows.h struct.h const.h engine.h errors.h \
global.h graph.h input.h misc.h op_c.h readline.h sdlscreen.h palette.h global.h graph.h input.h misc.h op_c.h readline.h sdlscreen.h \
palette.h

View File

@ -23,6 +23,7 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include "colorred.h" #include "colorred.h"
@ -35,11 +36,19 @@ but :
CT_Node* CT_new() {return NULL;} CT_Node* CT_new() {return NULL;}
void CT_set(CT_Node* colorTree, byte Rmin, byte Gmin, byte Bmin, // debug helper
void CT_Print(CT_Node* node)
{
printf("R %d %d\tG %d %d\tB %d %d\ti %d\n",
node->Rmin, node->Rmax, node->Gmin, node->Gmax,
node->Bmin, node->Bmax, node->index);
}
void CT_set(CT_Node** colorTree, byte Rmin, byte Gmin, byte Bmin,
byte Rmax, byte Gmax, byte Bmax, byte index) byte Rmax, byte Gmax, byte Bmax, byte index)
{ {
int i; int i;
CT_Node* parent = colorTree; CT_Node* parent;
// Create and setup node // Create and setup node
CT_Node* node = malloc(sizeof(CT_Node)); CT_Node* node = malloc(sizeof(CT_Node));
@ -51,65 +60,77 @@ void CT_set(CT_Node* colorTree, byte Rmin, byte Gmin, byte Bmin,
node->Bmax = Bmax; node->Bmax = Bmax;
node->index = index; node->index = index;
for(i = 0; i < 7; i++) printf("Add node:");
CT_Print(node);
for(i = 0; i < 2; i++)
node->children[i] = NULL; node->children[i] = NULL;
// Now insert it in tree // Now insert it in tree
parent = *colorTree;
if (parent == NULL) { if (parent == NULL) {
// This is our first node. // This is our first node.
colorTree = node; *colorTree = node;
} else for(;;) { } else for(;;) {
// Find where to insert ourselves // Find where to insert ourselves
// (clusters are non-intersecting, so there is no need to check for that)
int where = 0;
if (parent->Rmin < node->Rmin)
where += 4;
if (parent->Gmin < node->Gmin)
where += 2;
if (parent->Bmin < node->Bmin)
where += 1;
// TODO - we always insert downwards, maybe we should try to keep // pre-condition: the parent we're looking at is a superset of the node we're inserting
// the tree balanced... // it may have 0, 1, or 2 child
if (parent->children[where] == NULL) // 0 child: insert as child 0
// 1 child: either we're included in the child, and recurse, or we''re not, and insert at child 1
// 2 child: one of them has to be a superset of the node.
if (parent->children[0] == NULL)
{ {
// insert! parent->children[0] = node;
parent->children[where] = node;
break; break;
} else { } else {
// recurse CT_Node* child0 = parent->children[0];
parent = parent->children[where]; if (child0->Rmin <= node->Rmin
&& child0->Gmin <= node->Gmin
&& child0->Bmin <= node->Bmin
&& child0->Rmax >= node->Rmax
&& child0->Gmax >= node->Gmax
&& child0->Bmax >= node->Bmax
) {
parent = child0;
} else if(parent->children[1] == NULL)
{
parent->children[1] = node;
break;
} else {
parent = parent->children[1];
}
} }
} }
} }
byte CT_get(CT_Node* node, byte r, byte g, byte b) byte CT_get(CT_Node* node, byte r, byte g, byte b)
{ {
int wheremin = 0; // pre condition: node contains (rgb)
int wheremax = 0; // find the leaf that also contains (rgb)
if (node->Rmin < r) for(;;) {
wheremin += 4; if(node->children[0] == NULL)
if (node->Gmin < g) return node->index;
wheremin += 2; else {
if (node->Bmin < b) // Left or right ?
wheremin += 1; CT_Node* child0 = node->children[0];
if (child0->Rmin <= r
if (node->Rmax < r) && child0->Gmin <= g
wheremin += 4; && child0->Bmin <= b
if (node->Gmax < g) && child0->Rmax >= r
wheremin += 2; && child0->Gmax >= g
if (node->Bmax < b) && child0->Bmax >= b
wheremin += 1; ) {
// left
if (wheremin == 7 && wheremax == 0) node = child0;
{ } else {
// Found it! // right
return node->index; node = node->children[1];
} else { }
return CT_get(node->children[wheremin], r, g, b); }
} }
} }
@ -118,7 +139,7 @@ void CT_delete(CT_Node* tree)
int i; int i;
if (tree == NULL) if (tree == NULL)
return; return;
for (i = 0; i < 8; i++) for (i = 0; i < 2; i++)
{ {
CT_delete(tree->children[i]); CT_delete(tree->children[i]);
} }

View File

@ -46,18 +46,26 @@ typedef struct CT_Node_s
byte Gmax; byte Gmax;
byte Bmax; byte Bmax;
// possible optimization: a cluster has either two childs or a color index.
// if the first child is NULL, then the other can be used to store the index
// when the tree is being built, a node may have child0 set and not child1, but not the reverse)
// possible optimization: there can't be more than 511 clusters in the tree
// for a 256 color picture, so use int16 as pointers and store everything in a table :
// * makes them smaller
// * helps with cache locality
// palette index (valid iff any child is NULL) // palette index (valid iff any child is NULL)
byte index; byte index;
// child nodes // child nodes
struct CT_Node_s* children[8]; struct CT_Node_s* children[2];
//rgb rgB rGb rGB Rgb RgB RGb RGB
} CT_Node; } CT_Node;
CT_Node* CT_new(); CT_Node* CT_new();
void CT_delete(CT_Node* t); void CT_delete(CT_Node* t);
byte CT_get(CT_Node* t,byte r,byte g,byte b); byte CT_get(CT_Node* t,byte r,byte g,byte b);
void CT_set(CT_Node* colorTree, byte Rmin, byte Gmin, byte Bmin, void CT_set(CT_Node** colorTree, byte Rmin, byte Gmin, byte Bmin,
byte Rmax, byte Gmax, byte Bmax, byte index); byte Rmax, byte Gmax, byte Bmax, byte index);
#endif #endif

View File

@ -30,6 +30,7 @@
#include "op_c.h" #include "op_c.h"
#include "errors.h" #include "errors.h"
#include "colorred.h"
int Convert_24b_bitmap_to_256_fast(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette); int Convert_24b_bitmap_to_256_fast(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette);
@ -178,95 +179,6 @@ long Perceptual_lightness(T_Components *color)
19*color->B*19*color->B; 19*color->B*19*color->B;
} }
// Conversion table handlers
// The conversion table is built after a run of the median cut algorithm and is
// used to find the best color index for a given (RGB) color. GIMP avoids
// creating the whole table and only create parts of it when they are actually
// needed. This may or may not be faster
/// Creates a new conversion table
/// params: bumber of bits for R, G, B (precision)
T_Conversion_table * CT_new(int nbb_r,int nbb_g,int nbb_b)
{
T_Conversion_table * n;
int size;
n=(T_Conversion_table *)malloc(sizeof(T_Conversion_table));
if (n!=NULL)
{
// Copy the passed parameters
n->nbb_r=nbb_r;
n->nbb_g=nbb_g;
n->nbb_b=nbb_b;
// Calculate the others
// Value ranges (max value actually)
n->rng_r=(1<<nbb_r);
n->rng_g=(1<<nbb_g);
n->rng_b=(1<<nbb_b);
// Shifts
n->dec_r=nbb_g+nbb_b;
n->dec_g=nbb_b;
n->dec_b=0;
// Reductions (how many bits are lost)
n->red_r=8-nbb_r;
n->red_g=8-nbb_g;
n->red_b=8-nbb_b;
// Allocate the table
size=(n->rng_r)*(n->rng_g)*(n->rng_b);
n->table=(byte *)calloc(size, 1);
if (n->table == NULL)
{
// Not enough memory
free(n);
n=NULL;
}
}
return n;
}
/// Delete a conversion table and release its memory
void CT_delete(T_Conversion_table * t)
{
free(t->table);
free(t);
t = NULL;
}
/// Get the best palette index for an (R, G, B) color
byte CT_get(T_Conversion_table * t,int r,int g,int b)
{
int index;
// Reduce the number of bits to the table precision
r=(r>>t->red_r);
g=(g>>t->red_g);
b=(b>>t->red_b);
// Find the nearest color
index=(r<<t->dec_r) | (g<<t->dec_g) | (b<<t->dec_b);
return t->table[index];
}
/// Set an entry of the table, index (RGB), value i
void CT_set(T_Conversion_table * t,int r,int g,int b,byte i)
{
int index;
index=(r<<t->dec_r) | (g<<t->dec_g) | (b<<t->dec_b);
t->table[index]=i;
}
// Handlers for the occurences tables // Handlers for the occurences tables
// This table is used to count the occurence of an (RGB) pixel value in the // This table is used to count the occurence of an (RGB) pixel value in the
// source 24bit image. These count are then used by the median cut algorithm to // source 24bit image. These count are then used by the median cut algorithm to
@ -883,7 +795,8 @@ void CS_Set(T_Cluster_set * cs,T_Cluster * c)
// 4) We pack the 2 resulting boxes again to leave no empty space between the box border and the first pixel // 4) We pack the 2 resulting boxes again to leave no empty space between the box border and the first pixel
// 5) We take the box with the biggest number of pixels inside and we split it again // 5) We take the box with the biggest number of pixels inside and we split it again
// 6) Iterate until there are 256 boxes. Associate each of them to its middle color // 6) Iterate until there are 256 boxes. Associate each of them to its middle color
void CS_Generate(T_Cluster_set * cs, T_Occurrence_table * to) // At the same time, put the split clusters in the color tree for later palette lookup
void CS_Generate(T_Cluster_set * cs, T_Occurrence_table * to, CT_Node** colorTree)
{ {
T_Cluster current; T_Cluster current;
T_Cluster Nouveau1; T_Cluster Nouveau1;
@ -895,6 +808,10 @@ void CS_Generate(T_Cluster_set * cs, T_Occurrence_table * to)
// Get the biggest one // Get the biggest one
CS_Get(cs,&current); CS_Get(cs,&current);
// We're going to split, so add the cluster to the colortree
CT_set(colorTree,current.Rmin, current.Gmin, current.Bmin,
current.Rmax, current.Vmax, current.Bmax, 0);
// Split it // Split it
Cluster_split(&current, &Nouveau1, &Nouveau2, current.plus_large, to); Cluster_split(&current, &Nouveau1, &Nouveau2, current.plus_large, to);
@ -994,10 +911,9 @@ void CS_Sort_by_luminance(T_Cluster_set * cs)
/// Generates the palette from the clusters, then the conversion table to map (RGB) to a palette index /// Generates the palette from the clusters, then the conversion table to map (RGB) to a palette index
void CS_Generate_color_table_and_palette(T_Cluster_set * cs,T_Conversion_table * tc,T_Components * palette) void CS_Generate_color_table_and_palette(T_Cluster_set * cs,CT_Node** tc,T_Components * palette)
{ {
int index; int index;
int r,g,b;
T_Cluster* current = cs->clusters; T_Cluster* current = cs->clusters;
for (index=0;index<cs->nb;index++) for (index=0;index<cs->nb;index++)
@ -1006,10 +922,8 @@ void CS_Generate_color_table_and_palette(T_Cluster_set * cs,T_Conversion_table *
palette[index].G=current->g; palette[index].G=current->g;
palette[index].B=current->b; palette[index].B=current->b;
for (r=current->Rmin; r<=current->Rmax; r++) CT_set(tc,current->Rmin, current->Gmin, current->Bmin,
for (g=current->Gmin;g<=current->Vmax;g++) current->Rmax, current->Vmax, current->Bmax, index);
for (b=current->Bmin;b<=current->Bmax;b++)
CT_set(tc,r,g,b,index);
current = current->next; current = current->next;
} }
} }
@ -1120,11 +1034,11 @@ void GS_Generate(T_Gradient_set * ds,T_Cluster_set * cs)
/// Compute best palette for given picture. /// Compute best palette for given picture.
T_Conversion_table * Optimize_palette(T_Bitmap24B image, int size, CT_Node* Optimize_palette(T_Bitmap24B image, int size,
T_Components * palette, int r, int g, int b) T_Components * palette, int r, int g, int b)
{ {
T_Occurrence_table * to; T_Occurrence_table * to;
T_Conversion_table * tc; CT_Node* tc;
T_Cluster_set * cs; T_Cluster_set * cs;
T_Gradient_set * ds; T_Gradient_set * ds;
@ -1135,13 +1049,14 @@ T_Conversion_table * Optimize_palette(T_Bitmap24B image, int size,
if (to == NULL) if (to == NULL)
return 0; return 0;
tc = CT_new(r, g, b); tc = CT_new();
/*
if (tc == NULL) if (tc == NULL)
{ {
OT_delete(to); OT_delete(to);
return 0; return NULL;
} }
*/
// Count pixels for each color // Count pixels for each color
OT_count_occurrences(to, image, size); OT_count_occurrences(to, image, size);
@ -1156,7 +1071,7 @@ T_Conversion_table * Optimize_palette(T_Bitmap24B image, int size,
// Ok, everything was allocated // Ok, everything was allocated
// Generate the cluster set with median cut algorithm // Generate the cluster set with median cut algorithm
CS_Generate(cs, to); CS_Generate(cs, to, &tc);
//CS_Check(cs); //CS_Check(cs);
// Compute the color data for each cluster (palette entry + HL) // Compute the color data for each cluster (palette entry + HL)
@ -1176,7 +1091,7 @@ T_Conversion_table * Optimize_palette(T_Bitmap24B image, int size,
//CS_Check(cs); //CS_Check(cs);
// And finally generate the conversion table to map RGB > pal. index // And finally generate the conversion table to map RGB > pal. index
CS_Generate_color_table_and_palette(cs, tc, palette); CS_Generate_color_table_and_palette(cs, &tc, palette);
//CS_Check(cs); //CS_Check(cs);
CS_Delete(cs); CS_Delete(cs);
@ -1204,7 +1119,7 @@ int Modified_value(int value,int modif)
/// Convert a 24b image to 256 colors (with a given palette and conversion table) /// Convert a 24b image to 256 colors (with a given palette and conversion table)
/// This destroys the 24b picture ! /// This destroys the 24b picture !
/// Uses floyd steinberg dithering. /// Uses floyd steinberg dithering.
void Convert_24b_bitmap_to_256_Floyd_Steinberg(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette,T_Conversion_table * tc) void Convert_24b_bitmap_to_256_Floyd_Steinberg(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette,CT_Node* tc)
{ {
T_Bitmap24B current; T_Bitmap24B current;
T_Bitmap24B c_plus1; T_Bitmap24B c_plus1;
@ -1300,7 +1215,7 @@ void Convert_24b_bitmap_to_256_Floyd_Steinberg(T_Bitmap256 dest,T_Bitmap24B sour
/// Converts from 24b to 256c without dithering, using given conversion table /// Converts from 24b to 256c without dithering, using given conversion table
void Convert_24b_bitmap_to_256_nearest_neighbor(T_Bitmap256 dest, void Convert_24b_bitmap_to_256_nearest_neighbor(T_Bitmap256 dest,
T_Bitmap24B source, int width, int height, __attribute__((unused)) T_Components * palette, T_Bitmap24B source, int width, int height, __attribute__((unused)) T_Components * palette,
T_Conversion_table * tc) CT_Node* tc)
{ {
T_Bitmap24B current; T_Bitmap24B current;
T_Bitmap256 d; T_Bitmap256 d;
@ -1359,19 +1274,20 @@ int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int
return Convert_24b_bitmap_to_256_fast(dest, source, width, height, palette); return Convert_24b_bitmap_to_256_fast(dest, source, width, height, palette);
#else #else
T_Conversion_table * table; // table de conversion CT_Node* table; // table de conversion
int ip; // index de précision pour la conversion int ip; // index de précision pour la conversion
// On essaye d'obtenir une table de conversion qui loge en mémoire, avec la // On essaye d'obtenir une table de conversion qui loge en mémoire, avec la
// meilleure précision possible // meilleure précision possible
for (ip=0;ip<(10*3);ip+=3) for (ip=0;ip<(10*3);ip+=3)
{ {
table=Optimize_palette(source,width*height,palette,precision_24b[ip+0], table = Optimize_palette(source,width*height,palette,
precision_24b[ip+1],precision_24b[ip+2]); precision_24b[ip], precision_24b[ip+1], precision_24b[ip+2]);
if (table!=0) if (table != NULL)
break; break;
} }
if (table!=0)
if (table!=NULL)
{ {
//Convert_24b_bitmap_to_256_Floyd_Steinberg(dest,source,width,height,palette,table); //Convert_24b_bitmap_to_256_Floyd_Steinberg(dest,source,width,height,palette,table);
Convert_24b_bitmap_to_256_nearest_neighbor(dest,source,width,height,palette,table); Convert_24b_bitmap_to_256_nearest_neighbor(dest,source,width,height,palette,table);

View File

@ -30,6 +30,7 @@
#define _OP_C_H_ #define _OP_C_H_
#include "struct.h" #include "struct.h"
#include "colorred.h"
//////////////////////////////////////////////// Définition des types de base //////////////////////////////////////////////// Définition des types de base
@ -37,32 +38,6 @@ typedef T_Components * T_Bitmap24B;
typedef byte * T_Bitmap256; typedef byte * T_Bitmap256;
//////////////////////////////////////// Définition d'une table de conversion
typedef struct
{
int nbb_r; // Nb de bits de précision sur les rouges
int nbb_g; // Nb de bits de précision sur les verts
int nbb_b; // Nb de bits de précision sur les bleu
int rng_r; // Nb de valeurs sur les rouges (= 1<<nbb_r)
int rng_g; // Nb de valeurs sur les verts (= 1<<nbb_g)
int rng_b; // Nb de valeurs sur les bleus (= 1<<nbb_b)
int dec_r; // Coefficient multiplicateur d'accès dans la table (= nbb_g+nbb_b)
int dec_g; // Coefficient multiplicateur d'accès dans la table (= nbb_b)
int dec_b; // Coefficient multiplicateur d'accès dans la table (= 0)
int red_r; // Coefficient réducteur de traduction d'une couleur rouge (= 8-nbb_r)
int red_g; // Coefficient réducteur de traduction d'une couleur verte (= 8-nbb_g)
int red_b; // Coefficient réducteur de traduction d'une couleur bleue (= 8-nbb_b)
byte * table;
} T_Conversion_table;
///////////////////////////////////////// Définition d'une table d'occurences ///////////////////////////////////////// Définition d'une table d'occurences
typedef struct typedef struct
@ -146,17 +121,6 @@ typedef struct
T_Gradient * gradients; // Les dégradés T_Gradient * gradients; // Les dégradés
} T_Gradient_set; } T_Gradient_set;
/////////////////////////////////////////////////////////////////////////////
///////////////////////////// Méthodes de gestion des tables de conversion //
/////////////////////////////////////////////////////////////////////////////
T_Conversion_table * CT_new(int nbb_r,int nbb_g,int nbb_b);
void CT_delete(T_Conversion_table * t);
byte CT_get(T_Conversion_table * t,int r,int g,int b);
void CT_set(T_Conversion_table * t,int r,int g,int b,byte i);
void RGB_to_HSL(int r, int g,int b, byte* h, byte*s, byte* l); void RGB_to_HSL(int r, int g,int b, byte* h, byte*s, byte* l);
void HSL_to_RGB(byte h, byte s, byte l, byte* r, byte* g, byte* b); void HSL_to_RGB(byte h, byte s, byte l, byte* r, byte* g, byte* b);
@ -194,9 +158,9 @@ T_Cluster_set * CS_New(int nbmax,T_Occurrence_table * to);
void CS_Delete(T_Cluster_set * cs); void CS_Delete(T_Cluster_set * cs);
void CS_Get(T_Cluster_set * cs,T_Cluster * c); void CS_Get(T_Cluster_set * cs,T_Cluster * c);
void CS_Set(T_Cluster_set * cs,T_Cluster * c); void CS_Set(T_Cluster_set * cs,T_Cluster * c);
void CS_Generate(T_Cluster_set * cs,T_Occurrence_table * to); void CS_Generate(T_Cluster_set * cs,T_Occurrence_table * to, CT_Node** colorTree);
void CS_Compute_colors(T_Cluster_set * cs,T_Occurrence_table * to); void CS_Compute_colors(T_Cluster_set * cs,T_Occurrence_table * to);
void CS_Generate_color_table_and_palette(T_Cluster_set * cs,T_Conversion_table * tc,T_Components * palette); void CS_Generate_color_table_and_palette(T_Cluster_set * cs,CT_Node** tc,T_Components * palette);
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
//////////////////////////// Méthodes de gestion des ensembles de dégradés // //////////////////////////// Méthodes de gestion des ensembles de dégradés //