[layers] merged in the recent changes from trunk

git-svn-id: svn://pulkomandy.tk/GrafX2/branches/layers@1162 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Yves Rizoud 2009-11-10 20:35:09 +00:00
commit c150be2664
91 changed files with 828 additions and 193 deletions

View File

@ -229,7 +229,7 @@ else
# Compiles a regular linux exectutable for the native platform # Compiles a regular linux exectutable for the native platform
BIN = grafx2 BIN = grafx2
COPT = -W -Wall -Wdeclaration-after-statement -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT) $(LUACOPT) COPT = -W -Wall -Wdeclaration-after-statement -std=c99 -c -g `sdl-config --cflags` $(TTFCOPT) $(LUACOPT)
LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng $(LUALOPT) LOPT = `sdl-config --libs` -lSDL_image $(TTFLOPT) -lpng $(LUALOPT) -lm
# Use gcc for compiling. Use ncc to build a callgraph and analyze the code. # Use gcc for compiling. Use ncc to build a callgraph and analyze the code.
CC = gcc CC = gcc
#CC = nccgen -ncgcc -ncld -ncfabs #CC = nccgen -ncgcc -ncld -ncfabs
@ -287,7 +287,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 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
SKIN_FILES = skins/skin_classic.png skins/skin_modern.png skins/font_Classic.png skins/font_Fun.png SKIN_FILES = skins/skin_classic.png skins/skin_modern.png skins/font_Classic.png skins/font_Fun.png

View File

@ -30,16 +30,17 @@ $(OBJDIR)/input.o: input.c global.h struct.h const.h keyboard.h sdlscreen.h \
windows.h errors.h misc.h input.h windows.h errors.h misc.h input.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)/libraw2crtc.o: libraw2crtc.c global.h struct.h const.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 io.h \
loadsave.h misc.h op_c.h pages.h palette.h sdlscreen.h windows.h \ loadsave.h misc.h graph.h op_c.h pages.h palette.h sdlscreen.h \
engine.h windows.h engine.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 buttons.h \
engine.h pages.h loadsave.h sdlscreen.h errors.h readini.h saveini.h \ engine.h pages.h loadsave.h sdlscreen.h errors.h readini.h saveini.h \
io.h text.h setup.h windows.h brush.h palette.h realpath.h io.h text.h setup.h windows.h brush.h palette.h realpath.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 buttons.h \
engine.h misc.h keyboard.h windows.h palette.h input.h engine.h misc.h keyboard.h windows.h palette.h input.h graph.h
$(OBJDIR)/miscfileformats.o: miscfileformats.c global.h struct.h const.h loadsave.h \ $(OBJDIR)/miscfileformats.o: miscfileformats.c engine.h struct.h const.h errors.h \
windows.h global.h io.h libraw2crtc.h loadsave.h misc.h sdlscreen.h windows.h
$(OBJDIR)/mountlist.o: mountlist.c $(OBJDIR)/mountlist.o: mountlist.c
$(OBJDIR)/op_c.o: op_c.c op_c.h struct.h const.h errors.h $(OBJDIR)/op_c.o: op_c.c op_c.h struct.h const.h errors.h
$(OBJDIR)/operatio.o: operatio.c const.h struct.h global.h misc.h engine.h graph.h \ $(OBJDIR)/operatio.o: operatio.c const.h struct.h global.h misc.h engine.h graph.h \

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* SFont: a simple font-library that uses special .pngs as fonts /* SFont: a simple font-library that uses special .pngs as fonts
Copyright (C) 2003 Karl Bartel Copyright (C) 2003 Karl Bartel

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* SFont: a simple font-library that uses special bitmaps as fonts /* SFont: a simple font-library that uses special bitmaps as fonts
Copyright (C) 2003 Karl Bartel Copyright (C) 2003 Karl Bartel

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007-2008 Adrien Destugues Copyright 2007-2008 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
@ -3453,6 +3455,11 @@ void Button_Grid_menu(void)
short dx_selected=Snap_offset_X; short dx_selected=Snap_offset_X;
short dy_selected=Snap_offset_Y; short dy_selected=Snap_offset_Y;
char showgrid = Show_grid;
// if grid is shown check if we snap
// if not snap by default (so the window work like before we introduced the "show" option)
char snapgrid = Show_grid?Snap_mode:1;
T_Special_button * input_x_button; T_Special_button * input_x_button;
T_Special_button * input_y_button; T_Special_button * input_y_button;
T_Special_button * input_dx_button; T_Special_button * input_dx_button;
@ -3461,10 +3468,10 @@ void Button_Grid_menu(void)
char str[3]; char str[3];
Open_window(133,98,"Grid"); Open_window(133,118,"Grid");
Window_set_normal_button(12,72,51,14,"Cancel",0,1,KEY_ESC); // 1 Window_set_normal_button(12,92,51,14,"Cancel",0,1,KEY_ESC); // 1
Window_set_normal_button(70,72,51,14,"OK" ,0,1,SDLK_RETURN); // 2 Window_set_normal_button(70,92,51,14,"OK" ,0,1,SDLK_RETURN); // 2
Print_in_window(19,26, "X:",MC_Dark,MC_Light); Print_in_window(19,26, "X:",MC_Dark,MC_Light);
input_x_button = Window_set_input_button(37,24,2); // 3 input_x_button = Window_set_input_button(37,24,2); // 3
@ -3484,6 +3491,16 @@ void Button_Grid_menu(void)
Print_in_window(69,47,"dY:",MC_Dark,MC_Light); Print_in_window(69,47,"dY:",MC_Dark,MC_Light);
input_dy_button = Window_set_input_button(95,45,2); // 6 input_dy_button = Window_set_input_button(95,45,2); // 6
Num2str(dy_selected,str,2); Num2str(dy_selected,str,2);
Window_set_normal_button(12, 62, 14, 14, " ", 0, 1, 0); // 7
Window_set_normal_button(70, 62, 14, 14, " ", 0, 1, 0); // 8
if (snapgrid)
Print_in_window(16, 65, "X", MC_Black, MC_Light);
if (Show_grid)
Print_in_window(74, 65, "X", MC_Black, MC_Light);
Print_in_window(32, 65,"Snap",MC_Dark,MC_Light);
Print_in_window(90, 65,"Show",MC_Dark,MC_Light);
Window_input_content(input_dy_button,str); Window_input_content(input_dy_button,str);
Update_window_area(0,0,Window_width, Window_height); Update_window_area(0,0,Window_width, Window_height);
@ -3568,6 +3585,20 @@ void Button_Grid_menu(void)
Window_input_content(input_dy_button,str); Window_input_content(input_dy_button,str);
Display_cursor(); Display_cursor();
case 7:
snapgrid = !snapgrid;
Hide_cursor();
Print_in_window(16, 65, snapgrid?"X":" ", MC_Black, MC_Light);
Display_cursor();
break;
case 8:
showgrid = !showgrid;
Hide_cursor();
Print_in_window(74, 65, showgrid?"X":" ", MC_Black, MC_Light);
Display_cursor();
break;
} }
if (Is_shortcut(Key,0x100+BUTTON_HELP)) if (Is_shortcut(Key,0x100+BUTTON_HELP))
Window_help(BUTTON_EFFECTS, "GRID"); Window_help(BUTTON_EFFECTS, "GRID");
@ -3580,14 +3611,12 @@ void Button_Grid_menu(void)
Snap_height=chosen_Y; Snap_height=chosen_Y;
Snap_offset_X=dx_selected; Snap_offset_X=dx_selected;
Snap_offset_Y=dy_selected; Snap_offset_Y=dy_selected;
Snap_mode=1; Snap_mode=snapgrid;
Show_grid=showgrid;
} }
Close_window(); Close_window();
if ( (clicked_button==2) && (!Snap_mode) )
Button_Snap_mode();
Display_cursor(); Display_cursor();
} }

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud
@ -112,6 +114,7 @@ enum FILE_FORMATS
FORMAT_C64, FORMAT_C64,
FORMAT_KCF, FORMAT_KCF,
FORMAT_PAL, FORMAT_PAL,
FORMAT_SCR,
FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image FORMAT_MISC, ///< Must be last of enum: others formats recognized by SDL_image
}; };

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Adrien Destugues Copyright 2008 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Adrien Destugues Copyright 2009 Adrien Destugues
@ -129,7 +131,6 @@ void Draw_script_name(word x, word y, word index, byte highlighted)
{ {
T_Fileselector_item * current_item; T_Fileselector_item * current_item;
DEBUG("draw",index);
if (Scripts_list.Nb_elements) if (Scripts_list.Nb_elements)
{ {
current_item = Get_item_by_index(&Scripts_list, index); current_item = Get_item_by_index(&Scripts_list, index);

View File

@ -1 +1,3 @@
/* vim:expandtab:ts=2 sw=2:
*/
void Button_Brush_Factory(void); void Button_Brush_Factory(void);

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Petter Lindquist Copyright 2009 Petter Lindquist

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Franck Charlet Copyright 2009 Franck Charlet
@ -1388,7 +1390,7 @@ byte Button_Load_or_Save(byte load, byte image)
if(load) if(load)
{ {
// Determine the type // Determine the type
if(File_exists(Main_filename)) if(File_exists(Main_filename))
{ {
Selected_type = 0; Selected_type = 0;
if(Directory_exists(Main_filename)) Selected_type = 1; if(Directory_exists(Main_filename)) Selected_type = 1;
@ -1403,7 +1405,9 @@ byte Button_Load_or_Save(byte load, byte image)
if(Directory_exists(Main_filename)) Selected_type = 1; if(Directory_exists(Main_filename)) Selected_type = 1;
else Selected_type = 0; else Selected_type = 0;
} }
has_clicked_ok=1;
// Now load immediately, but only if the user exited readline by pressing ENTER
if (Mouse_K == 0) has_clicked_ok = 1;
} }
else else
{ {

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Franck Charlet Copyright 2009 Franck Charlet

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007-2008 Adrien Destugues Copyright 2007-2008 Adrien Destugues

2
help.c
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon

2
help.h
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

2
init.c
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon

2
init.h
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Franck Charlet Copyright 2009 Franck Charlet

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

2
io.c
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

2
io.h
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Franck Charlet Copyright 2009 Franck Charlet

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

187
libraw2crtc.c Normal file
View File

@ -0,0 +1,187 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* GFX2CRTC - libraw2crtc.c
* CloudStrife - 20080921
* Diffusé sous licence libre CeCILL v2
* Voire LICENCE
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "global.h"
unsigned short addrCalc(unsigned char vcc, unsigned char rcc, unsigned char hcc, unsigned char cclk, unsigned char r1, unsigned char r12, unsigned char r13)
{
unsigned short MA;
unsigned short addr;
//MA = vcc*r1 + hcc + (0x0C)*256;
MA = vcc*r1 + hcc + r12*256 + r13;
addr = cclk | ((MA & 0x03FF) << 1);
addr = addr | ((rcc & 0x07) << 11);
addr = addr | ((MA & 0x3000) << 2);
return addr;
}
unsigned char mode0interlace(unsigned char x, unsigned char y)
{
unsigned char mode0pixel[] = {0, 64, 4, 68, 16, 80, 20, 84, 1, 65, 5, 69, 17, 81, 21, 85};
return mode0pixel[Read_pixel_function(x,y)] << 1 | mode0pixel[Read_pixel_function(x+1,y)];
}
unsigned char mode1interlace(unsigned char x, unsigned char y)
{
unsigned char mode1pixel[] = {0, 16, 1, 17};
return mode1pixel[Read_pixel_function(x,y)] << 3 | mode1pixel[Read_pixel_function(x+1,y)] << 2 | mode1pixel[Read_pixel_function(x+2,y)] << 1 | mode1pixel[Read_pixel_function(x+3,y)];
}
unsigned char mode2interlace(unsigned char x, unsigned char y)
{
unsigned char out = 0;
int i;
for(i = 0; i < 8; i++) out += ((Read_pixel_function(x+7-i,y)&1) << i);
return out;
}
unsigned char mode3interlace(unsigned char x, unsigned char y)
{
unsigned char mode3pixel[] = {0, 16, 1, 17};
return mode3pixel[Read_pixel_function(x,y)] << 3 | mode3pixel[Read_pixel_function(x+1,y)] << 2;
}
unsigned char (*ptrMode)(unsigned char x, unsigned char y);
unsigned char *raw2crtc(unsigned short width, unsigned short height, unsigned char mode, unsigned char r9, unsigned long *outSize, unsigned char *r1, unsigned char r12, unsigned char r13)
{
unsigned char *outBuffer;
unsigned char *tmpBuffer;
unsigned char *allocationBuffer;
unsigned short minAddr = 0;
unsigned char minAddrIsDefined = 0;
unsigned short maxAddr = 0;
unsigned char nbPixPerByte;
int y,x;
unsigned char r6;
unsigned short i;
unsigned char *ptrTmp;
unsigned char *ptrOut;
unsigned char vcc;
unsigned char rcc;
unsigned char hcc;
unsigned char cclk;
switch(mode)
{
case 0:
{
*r1 = (width+3)/4;
nbPixPerByte = 2;
ptrMode = mode0interlace;
break;
}
case 1:
{
*r1 = (width+7)/8;
nbPixPerByte = 4;
ptrMode = mode1interlace;
break;
}
case 2:
{
*r1 = (width+15)/16;
nbPixPerByte = 8;
ptrMode = mode2interlace;
break;
}
case 3:
{
*r1 = (width+3)/4;
nbPixPerByte = 2;
ptrMode = mode3interlace;
break;
}
default:
{
exit(4);
}
}
tmpBuffer = (unsigned char*)malloc(0xFFFF);
if (tmpBuffer == NULL)
{
printf("Allocation tmpBuffer raté\n");
exit(4);
}
allocationBuffer = (unsigned char*)malloc(0xFFFF);
if(allocationBuffer == NULL)
{
printf("Allocation allocationBuffer raté\n");
exit(4);
}
memset(allocationBuffer, 0, 0xFFFF);
r6 = height/(r9+1);
for(vcc = 0; vcc < r6; vcc++)
{
for(rcc = 0; rcc < (r9+1); rcc++)
{
for(hcc = 0; hcc < *r1; hcc++)
{
for(cclk = 0; cclk < 2; cclk++)
{
x = (hcc << 1 | cclk);
y = vcc*(r9+1) + rcc;
*(tmpBuffer + addrCalc(vcc, rcc, hcc, cclk, *r1, r12, r13)) = (*ptrMode)(x,y);
*(allocationBuffer + addrCalc(vcc, rcc, hcc, cclk, *r1, r12, r13)) += 1;
}
}
}
}
for(i = 0; i < 0xFFFF; i++)
{
if(*(allocationBuffer + i) > 1)
{
printf("Attention : Ecriture multiple a l'adresse mémoire %d\n",i);
}
if(*(allocationBuffer + i) > 0)
{
maxAddr = i;
}
if((*(allocationBuffer + i) == 1) && (minAddrIsDefined == 0))
{
minAddr = i;
minAddrIsDefined = 1;
}
}
*outSize = (maxAddr + 1) - minAddr;
outBuffer = (unsigned char*)malloc((*outSize));
if (outBuffer == NULL)
{
printf("Allocation outBuffer raté\n");
exit(4);
}
ptrTmp = tmpBuffer + minAddr;
ptrOut = outBuffer;
for(i = minAddr; i <= maxAddr; i++)
{
*(ptrOut++) = *(ptrTmp++);
}
free(tmpBuffer);
tmpBuffer = NULL;
free(allocationBuffer);
allocationBuffer = NULL;
return outBuffer;
}

14
libraw2crtc.h Normal file
View File

@ -0,0 +1,14 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* GFX2CRTC - libraw2crtc.h
* CloudStrife - 20080921
* Diffusé sous licence libre CeCILL v2
* Voire LICENCE
*/
#ifndef LIBRAW2CRTC_H
#define LIBRAW2CRTC_H 1
unsigned char * raw2crtc(unsigned short width, unsigned short height, unsigned char mode, unsigned char r9, unsigned long *outSize, unsigned char *r1, unsigned char r12, unsigned char r13);
#endif

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Petter Lindquist Copyright 2009 Petter Lindquist
@ -116,6 +118,9 @@ void Test_C64(void);
void Load_C64(void); void Load_C64(void);
void Save_C64(void); void Save_C64(void);
// -- SCR (Amstrad CPC)
void Save_SCR(void);
// -- PNG ------------------------------------------------------------------- // -- PNG -------------------------------------------------------------------
#ifndef __no_pnglib__ #ifndef __no_pnglib__
void Test_PNG(void); void Test_PNG(void);
@ -130,7 +135,7 @@ void Load_SDL_Image(void);
void Init_preview(short width,short height,long size,int format,enum PIXEL_RATIO ratio); void Init_preview(short width,short height,long size,int format,enum PIXEL_RATIO ratio);
// ENUM Name TestFunc LoadFunc SaveFunc Backup Comment Ext Exts // ENUM Name TestFunc LoadFunc SaveFunc Backup Comment Layers Ext Exts
T_Format File_formats[NB_KNOWN_FORMATS] = { T_Format File_formats[NB_KNOWN_FORMATS] = {
{FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "", "gif;png;bmp;pcx;pkm;lbm;iff;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"}, {FORMAT_ALL_IMAGES, "(all)", NULL, NULL, NULL, 0, 0, 0, "", "gif;png;bmp;pcx;pkm;lbm;iff;img;sci;scq;scf;scn;sco;pi1;pc1;cel;neo;kcf;pal;c64;koa;tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
{FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"}, {FORMAT_ALL_FILES, "(*.*)", NULL, NULL, NULL, 0, 0, 0, "", "*"},
@ -140,18 +145,19 @@ T_Format File_formats[NB_KNOWN_FORMATS] = {
#endif #endif
{FORMAT_BMP, " bmp", Test_BMP, Load_BMP, Save_BMP, 1, 0, 0, "bmp", "bmp"}, {FORMAT_BMP, " bmp", Test_BMP, Load_BMP, Save_BMP, 1, 0, 0, "bmp", "bmp"},
{FORMAT_PCX, " pcx", Test_PCX, Load_PCX, Save_PCX, 1, 0, 0, "pcx", "pcx"}, {FORMAT_PCX, " pcx", Test_PCX, Load_PCX, Save_PCX, 1, 0, 0, "pcx", "pcx"},
{FORMAT_PKM, " pkm", Test_PKM, Load_PKM, Save_PKM, 1, 1, 0, "pkm", "pkm"}, {FORMAT_PKM, " pkm", Test_PKM, Load_PKM, Save_PKM, 0, 1, 0, "pkm", "pkm"}, // Not a backup since it does not save the full palette
{FORMAT_LBM, " lbm", Test_LBM, Load_LBM, Save_LBM, 1, 0, 0, "lbm", "lbm;iff"}, {FORMAT_LBM, " lbm", Test_LBM, Load_LBM, Save_LBM, 1, 0, 0, "lbm", "lbm;iff"},
{FORMAT_IMG, " img", Test_IMG, Load_IMG, Save_IMG, 1, 0, 0, "img", "img"}, {FORMAT_IMG, " img", Test_IMG, Load_IMG, Save_IMG, 1, 0, 0, "img", "img"},
{FORMAT_SCx, " sc?", Test_SCx, Load_SCx, Save_SCx, 1, 0, 0, "sc?", "sci;scq;scf;scn;sco"}, {FORMAT_SCx, " sc?", Test_SCx, Load_SCx, Save_SCx, 1, 0, 0, "sc?", "sci;scq;scf;scn;sco"},
{FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 1, 0, 0, "pi1", "pi1"}, {FORMAT_PI1, " pi1", Test_PI1, Load_PI1, Save_PI1, 0, 0, 0, "pi1", "pi1"},
{FORMAT_PC1, " pc1", Test_PC1, Load_PC1, Save_PC1, 1, 0, 0, "pc1", "pc1"}, {FORMAT_PC1, " pc1", Test_PC1, Load_PC1, Save_PC1, 0, 0, 0, "pc1", "pc1"},
{FORMAT_CEL, " cel", Test_CEL, Load_CEL, Save_CEL, 1, 0, 0, "cel", "cel"}, {FORMAT_CEL, " cel", Test_CEL, Load_CEL, Save_CEL, 1, 0, 0, "cel", "cel"},
{FORMAT_NEO, " neo", Test_NEO, Load_NEO, Save_NEO, 1, 0, 0, "neo", "neo"}, {FORMAT_NEO, " neo", Test_NEO, Load_NEO, Save_NEO, 0, 0, 0, "neo", "neo"},
{FORMAT_KCF, " kcf", Test_KCF, Load_KCF, Save_KCF, 0, 0, 0, "kcf", "kcf"}, {FORMAT_KCF, " kcf", Test_KCF, Load_KCF, Save_KCF, 0, 0, 0, "kcf", "kcf"},
{FORMAT_PAL, " pal", Test_PAL, Load_PAL, Save_PAL, 0, 0, 0, "pal", "pal"}, {FORMAT_PAL, " pal", Test_PAL, Load_PAL, Save_PAL, 0, 0, 0, "pal", "pal"},
{FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 1, 1, 0, "c64", "c64;koa"}, {FORMAT_C64, " c64", Test_C64, Load_C64, Save_C64, 0, 1, 0, "c64", "c64;koa"},
{FORMAT_MISC,"misc.", NULL, NULL, NULL, 1, 0, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"}, {FORMAT_SCR, " cpc", NULL, NULL, Save_SCR, 0, 0, 0, "cpc", "cpc;scr"},
{FORMAT_MISC,"misc.",NULL, NULL, NULL, 1, 0, 0, "", "tga;pnm;xpm;xcf;jpg;jpeg;tif;tiff;ico"},
}; };
// Cette variable est alimentée après chargement réussi d'une image. // Cette variable est alimentée après chargement réussi d'une image.
@ -501,20 +507,6 @@ void Init_preview(short width,short height,long size,int format, enum PIXEL_RATI
} }
void Draw_palette_preview(void)
{
short index;
if (Pixel_load_function==Pixel_load_in_preview)
for (index=0; index<256; index++)
Window_rectangle(183+(index/16)*7,95+(index&15)*5,5,5,index);
Update_window_area(183,95,120,80);
}
// Calcul du nom complet du fichier // Calcul du nom complet du fichier
void Get_full_filename(char * filename, byte is_colorix_format) void Get_full_filename(char * filename, byte is_colorix_format)
{ {

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues
@ -69,10 +71,10 @@ T_Format * Get_fileformat(byte format);
// -- File formats // -- File formats
#ifndef __no_pnglib__ #ifndef __no_pnglib__
#define NB_KNOWN_FORMATS 18 ///< Total number of known file formats. #define NB_KNOWN_FORMATS 19 ///< Total number of known file formats.
#else #else
// Without pnglib // Without pnglib
#define NB_KNOWN_FORMATS 17 ///< Total number of known file formats. #define NB_KNOWN_FORMATS 18 ///< Total number of known file formats.
#endif #endif
// This is here and not in fileformats.c because the emergency save uses it... // This is here and not in fileformats.c because the emergency save uses it...

2
main.c
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon

2
misc.c
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

2
misc.h
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Petter Lindquist Copyright 2009 Petter Lindquist
@ -23,34 +25,61 @@
///@file miscfileformats.c ///@file miscfileformats.c
/// Formats that aren't fully saving, either because of palette restrictions or other things /// Formats that aren't fully saving, either because of palette restrictions or other things
#include "engine.h"
#include "errors.h"
#include "global.h" #include "global.h"
#include "io.h"
#include "libraw2crtc.h"
#include "limits.h" #include "limits.h"
#include "loadsave.h" #include "loadsave.h"
#include "misc.h"
#include "sdlscreen.h"
#include "struct.h" #include "struct.h"
#include "windows.h" #include "windows.h"
//////////////////////////////////// PAL //////////////////////////////////// //////////////////////////////////// PAL ////////////////////////////////////
//
void Draw_palette_preview(void)
{
short index;
if (Pixel_load_function==Pixel_load_in_preview)
for (index=0; index<256; index++)
Window_rectangle(183+(index/16)*7,95+(index&15)*5,5,5,index);
Update_window_area(183,95,120,80);
}
// -- Tester si un fichier est au format PAL -------------------------------- // -- Tester si un fichier est au format PAL --------------------------------
void Test_PAL(void) void Test_PAL(void)
{ {
FILE *file; // Fichier du fichier FILE *file; // Fichier du fichier
char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier char filename[MAX_PATH_CHARACTERS]; // Nom complet du fichier
long file_size; // Taille du fichier long file_size; // Taille du fichier
Get_full_filename(filename,0); Get_full_filename(filename, 0);
File_error=1; File_error = 1;
// Ouverture du fichier // Ouverture du fichier
if ((file=fopen(filename, "rb"))) if ((file = fopen(filename, "rb")))
{ {
// Lecture de la taille du fichier // Lecture de la taille du fichier
file_size=File_length_file(file); file_size = File_length_file(file);
fclose(file);
// Le fichier ne peut être au format PAL que si sa taille vaut 768 octets // Le fichier ne peut être au format PAL que si sa taille vaut 768 octets
if (file_size==sizeof(T_Palette)) if (file_size == sizeof(T_Palette))
File_error=0; File_error = 0;
else {
// Sinon c'est peut être un fichier palette ASCII "Jasc"
fread(filename, 1, 8, file);
if (strncmp(filename,"JASC-PAL",8) == 0)
{
File_error = 0;
}
}
fclose(file);
} }
} }
@ -69,22 +98,56 @@ void Load_PAL(void)
// Ouverture du fichier // Ouverture du fichier
if ((file=fopen(filename, "rb"))) if ((file=fopen(filename, "rb")))
{ {
T_Palette palette_64; long file_size = File_length_file(file);
// Init_preview(?); // Pas possible... pas d'image... // Le fichier ne peut être au format PAL que si sa taille vaut 768 octets
if (file_size == sizeof(T_Palette))
{
T_Palette palette_64;
// Init_preview(?); // Pas possible... pas d'image...
// Lecture du fichier dans Main_palette // Lecture du fichier dans Main_palette
if (Read_bytes(file,palette_64,sizeof(T_Palette))) if (Read_bytes(file, palette_64, sizeof(T_Palette)))
{ {
Palette_64_to_256(palette_64); Palette_64_to_256(palette_64);
memcpy(Main_palette,palette_64,sizeof(T_Palette)); memcpy(Main_palette, palette_64, sizeof(T_Palette));
Set_palette(Main_palette); Set_palette(Main_palette);
Remap_fileselector(); Remap_fileselector();
// On dessine une preview de la palette (si chargement=preview) // On dessine une preview de la palette (si chargement = preview)
Draw_palette_preview(); Draw_palette_preview();
} }
else else
File_error=2; File_error = 2;
} else {
fread(filename, 1, 8, file);
if (strncmp(filename,"JASC-PAL",8) == 0)
{
int i, n, r, g, b;
fscanf(file, "%d",&n);
if(n != 100)
{
File_error = 2;
fclose(file);
return;
}
// Read color count
fscanf(file, "%d",&n);
for (i = 0; i < n; i++)
{
fscanf(file, "%d %d %d",&r, &g, &b);
Main_palette[i].R = r;
Main_palette[i].G = g;
Main_palette[i].B = b;
Set_palette(Main_palette);
Remap_fileselector();
// On dessine une preview de la palette (si chargement = preview)
Draw_palette_preview();
}
} else File_error = 2;
}
// Fermeture du fichier // Fermeture du fichier
fclose(file); fclose(file);
@ -107,20 +170,12 @@ void Save_PAL(void)
File_error=0; File_error=0;
// Ouverture du fichier // Ouverture du fichier
if ((file=fopen(filename,"wb"))) if ((file=fopen(filename,"w")))
{ {
T_Palette palette_64; int i;
memcpy(palette_64,Main_palette,sizeof(T_Palette)); fputs("JASC-PAL\n0100\n256\n", file);
Palette_256_to_64(palette_64); for (i = 0; i < 256; i++)
// Enregistrement de Main_palette dans le fichier fprintf(file,"%d %d %d\n",Main_palette[i].R, Main_palette[i].G, Main_palette[i].B);
if (! Write_bytes(file,palette_64,sizeof(T_Palette)))
{
File_error=1;
fclose(file);
remove(filename);
}
else // Ecriture correcte => Fermeture normale du fichier
fclose(file);
} }
else // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur else // Si on n'a pas réussi à ouvrir le fichier, alors il y a eu une erreur
{ {
@ -2483,3 +2538,90 @@ void Save_C64(void)
File_error = Save_C64_multi(filename,saveWhat,loadAddr); File_error = Save_C64_multi(filename,saveWhat,loadAddr);
} }
// SCR (Amstrad CPC)
void Test_SCR(void)
{
// Mmh... not sure what we could test. Any idea ?
// The palette file can be tested, if it exists and have the right size it's
// ok. But if it's not there the pixel data may still be valid. And we can't
// use the filesize as this depends on the screen format.
// An AMSDOS header would be a good indication but in some cases it may not
// be there
}
void Load_SCR(void)
{
// The Amstrad CPC screen memory is mapped in a weird mode, somewhere
// between bitmap and textmode. Basically the only way to decode this is to
// emulate the video chip and read the bytes as needed...
// Moreover, the hardware allows the screen to have any size from 8x1 to
// 800x273 pixels, and there is no indication of that in the file besides
// its size. It can also use any of the 3 screen modes. Fortunately this
// last bit of information is stored in the palette file.
// Oh, and BTW, the picture can be offset, and it's even usual to do it,
// because letting 128 pixels unused at the beginning of the file make it a
// lot easier to handle screens using more than 16K of VRam.
// The pixel encoding change with the video mode so we have to know that
// before attempting to load anything...
// As if this wasn't enough, Advanced OCP Art Studio, the reference tool on
// Amstrad, can use RLE packing when saving files, meaning we also have to
// handle that.
// All this mess enforces us to load (and unpack if needed) the file to a
// temporary 32k buffer before actually decoding it.
// 1) Seek for a palette
// 2) If palette found get screenmode from there, else ask user
// 3) ask user for screen size (or register values)
// 4) Load color data from palette (if found)
// 5) Close palette
// 6) Open the file
// 7) Run around the screen to untangle the pixeldata
// 8) Close the file
}
void Save_SCR(void)
{
// TODO : Add possibility to set R9, R12, R13 values
// TODO : Add OCP packing support
// TODO : Add possibility to include AMSDOS header, with proper loading
// address guessed from r12/r13 values.
unsigned char* output;
unsigned long outsize;
unsigned char r1;
int cpc_mode;
FILE* file;
char filename[MAX_PATH_CHARACTERS];
Get_full_filename(filename,0);
switch(Pixel_ratio)
{
case PIXEL_WIDE:
case PIXEL_WIDE2:
cpc_mode = 0;
break;
case PIXEL_TALL:
case PIXEL_TALL2:
cpc_mode = 2;
break;
default:
cpc_mode = 1;
break;
}
output = raw2crtc(Main_image_width,Main_image_height,cpc_mode,7,&outsize,&r1,0,0);
file = fopen(filename,"wb");
Write_bytes(file, output, outsize);
fclose(file);
free (output);
File_error = 0;
}

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* mountlist.c -- return a list of mounted file systems /* mountlist.c -- return a list of mounted file systems
Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, Copyright (C) 1991, 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003,

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* mountlist.h -- declarations for list of mounted file systems /* mountlist.h -- declarations for list of mounted file systems
Copyright (C) 1991, 1992, 1998, 2000, 2001, 2002, 2003, 2004, 2005 Copyright (C) 1991, 1992, 1998, 2000, 2001, 2002, 2003, 2004, 2005

271
op_c.c
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues
@ -28,6 +30,8 @@
#include "op_c.h" #include "op_c.h"
#include "errors.h" #include "errors.h"
/// Convert RGB to HSL.
/// Both input and output are in the 0..255 range to use in the palette screen
void RGB_to_HSL(int r,int g,int b,byte * hr,byte * sr,byte* lr) void RGB_to_HSL(int r,int g,int b,byte * hr,byte * sr,byte* lr)
{ {
double rd,gd,bd,h,s,l,max,min; double rd,gd,bd,h,s,l,max,min;
@ -37,9 +41,6 @@ void RGB_to_HSL(int r,int g,int b,byte * hr,byte * sr,byte* lr)
gd = g / 255.0; gd = g / 255.0;
bd = b / 255.0; bd = b / 255.0;
// compute L
// l=(rd*0.30)+(gd*0.59)+(bd*0.11);
// compute maximum of rd,gd,bd // compute maximum of rd,gd,bd
if (rd>=gd) if (rd>=gd)
{ {
@ -97,6 +98,8 @@ void RGB_to_HSL(int r,int g,int b,byte * hr,byte * sr,byte* lr)
*sr = (s*255.0); *sr = (s*255.0);
} }
/// Convert HSL back to RGB
/// Input and output are all in range 0..255
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)
{ {
float rf =0 ,gf = 0,bf = 0; float rf =0 ,gf = 0,bf = 0;
@ -162,10 +165,14 @@ void HSL_to_RGB(byte h,byte s,byte l, byte* r, byte* g, byte* b)
*b = bf * (255); *b = bf * (255);
} }
///////////////////////////////////////////////////////////////////////////// // Conversion table handlers
///////////////////////////// Méthodes de gestion des tables de conversion // // 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 * CT_new(int nbb_r,int nbb_g,int nbb_b)
{ {
T_Conversion_table * n; T_Conversion_table * n;
@ -174,31 +181,34 @@ T_Conversion_table * CT_new(int nbb_r,int nbb_g,int nbb_b)
n=(T_Conversion_table *)malloc(sizeof(T_Conversion_table)); n=(T_Conversion_table *)malloc(sizeof(T_Conversion_table));
if (n!=NULL) if (n!=NULL)
{ {
// On recopie les paramŠtres demands // Copy the passed parameters
n->nbb_r=nbb_r; n->nbb_r=nbb_r;
n->nbb_g=nbb_g; n->nbb_g=nbb_g;
n->nbb_b=nbb_b; n->nbb_b=nbb_b;
// On calcule les autres // Calculate the others
// Value ranges (max value actually)
n->rng_r=(1<<nbb_r); n->rng_r=(1<<nbb_r);
n->rng_g=(1<<nbb_g); n->rng_g=(1<<nbb_g);
n->rng_b=(1<<nbb_b); n->rng_b=(1<<nbb_b);
// Shifts
n->dec_r=nbb_g+nbb_b; n->dec_r=nbb_g+nbb_b;
n->dec_g=nbb_b; n->dec_g=nbb_b;
n->dec_b=0; n->dec_b=0;
// Reductions (how many bits are lost)
n->red_r=8-nbb_r; n->red_r=8-nbb_r;
n->red_g=8-nbb_g; n->red_g=8-nbb_g;
n->red_b=8-nbb_b; n->red_b=8-nbb_b;
// On tente d'allouer la table // Allocate the table
size=(n->rng_r)*(n->rng_g)*(n->rng_b); size=(n->rng_r)*(n->rng_g)*(n->rng_b);
n->table=(byte *)malloc(size); n->table=(byte *)calloc(size, 1);
if (n->table!=NULL) if (n->table == NULL)
// C'est bon!
memset(n->table,0,size); // Inutile, mais plus propre
else
{ {
// Table impossible … allouer // Not enough memory
free(n); free(n);
n=NULL; n=NULL;
} }
@ -207,27 +217,33 @@ T_Conversion_table * CT_new(int nbb_r,int nbb_g,int nbb_b)
return n; return n;
} }
/// Delete a conversion table and release its memory
void CT_delete(T_Conversion_table * t) void CT_delete(T_Conversion_table * t)
{ {
free(t->table); free(t->table);
free(t); free(t);
} }
/// Get the best palette index for an (R, G, B) color
byte CT_get(T_Conversion_table * t,int r,int g,int b) byte CT_get(T_Conversion_table * t,int r,int g,int b)
{ {
int index; int index;
// On réduit le nombre de bits par couleur // Reduce the number of bits to the table precision
r=(r>>t->red_r); r=(r>>t->red_r);
g=(g>>t->red_g); g=(g>>t->red_g);
b=(b>>t->red_b); b=(b>>t->red_b);
// On recherche la couleur la plus proche dans la table de conversion // Find the nearest color
index=(r<<t->dec_r) | (g<<t->dec_g) | (b<<t->dec_b); index=(r<<t->dec_r) | (g<<t->dec_g) | (b<<t->dec_b);
return t->table[index]; 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) void CT_set(T_Conversion_table * t,int r,int g,int b,byte i)
{ {
int index; int index;
@ -237,19 +253,21 @@ void CT_set(T_Conversion_table * t,int r,int g,int b,byte i)
} }
// Handlers for the occurences tables
// 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
// decide which cluster to split.
///////////////////////////////////////////////////////////////////////////// /// Initialize an occurence table
/////////////////////////////// Mthodes de gestion des tables d'occurence //
/////////////////////////////////////////////////////////////////////////////
void OT_init(T_Occurrence_table * t) void OT_init(T_Occurrence_table * t)
{ {
int size; int size;
size=(t->rng_r)*(t->rng_g)*(t->rng_b)*sizeof(int); size=(t->rng_r)*(t->rng_g)*(t->rng_b)*sizeof(int);
memset(t->table,0,size); // On initialise … 0 memset(t->table,0,size); // Set it to 0
} }
/// Allocate an occurence table for given number of bits
T_Occurrence_table * OT_new(int nbb_r,int nbb_g,int nbb_b) T_Occurrence_table * OT_new(int nbb_r,int nbb_g,int nbb_b)
{ {
T_Occurrence_table * n; T_Occurrence_table * n;
@ -258,12 +276,12 @@ T_Occurrence_table * OT_new(int nbb_r,int nbb_g,int nbb_b)
n=(T_Occurrence_table *)malloc(sizeof(T_Occurrence_table)); n=(T_Occurrence_table *)malloc(sizeof(T_Occurrence_table));
if (n!=0) if (n!=0)
{ {
// On recopie les paramŠtres demands // Copy passed parameters
n->nbb_r=nbb_r; n->nbb_r=nbb_r;
n->nbb_g=nbb_g; n->nbb_g=nbb_g;
n->nbb_b=nbb_b; n->nbb_b=nbb_b;
// On calcule les autres // Compute others
n->rng_r=(1<<nbb_r); n->rng_r=(1<<nbb_r);
n->rng_g=(1<<nbb_g); n->rng_g=(1<<nbb_g);
n->rng_b=(1<<nbb_b); n->rng_b=(1<<nbb_b);
@ -274,15 +292,12 @@ T_Occurrence_table * OT_new(int nbb_r,int nbb_g,int nbb_b)
n->red_g=8-nbb_g; n->red_g=8-nbb_g;
n->red_b=8-nbb_b; n->red_b=8-nbb_b;
// On tente d'allouer la table // Allocate the table
size=(n->rng_r)*(n->rng_g)*(n->rng_b)*sizeof(int); size=(n->rng_r)*(n->rng_g)*(n->rng_b)*sizeof(int);
n->table=(int *)malloc(size); n->table=(int *)calloc(size, 1);
if (n->table!=0) if (n->table == NULL)
// C'est bon! On initialise … 0
OT_init(n);
else
{ {
// Table impossible … allouer // Not enough memory !
free(n); free(n);
n=0; n=0;
} }
@ -291,31 +306,42 @@ T_Occurrence_table * OT_new(int nbb_r,int nbb_g,int nbb_b)
return n; return n;
} }
/// Delete a table and free the memory
void OT_delete(T_Occurrence_table * t) void OT_delete(T_Occurrence_table * t)
{ {
free(t->table); free(t->table);
free(t); free(t);
} }
int OT_get(T_Occurrence_table * t,int r,int g,int b)
/// Get number of occurences for a given color
int OT_get(T_Occurrence_table * t, int r, int g, int b)
{ {
int index; int index;
// Drop bits as needed
index=(r<<t->dec_r) | (g<<t->dec_g) | (b<<t->dec_b); index=(r<<t->dec_r) | (g<<t->dec_g) | (b<<t->dec_b);
return t->table[index]; return t->table[index];
} }
/// Add 1 to the count for a color
void OT_inc(T_Occurrence_table * t,int r,int g,int b) void OT_inc(T_Occurrence_table * t,int r,int g,int b)
{ {
int index; int index;
// Drop bits as needed
r=(r>>t->red_r); r=(r>>t->red_r);
g=(g>>t->red_g); g=(g>>t->red_g);
b=(b>>t->red_b); b=(b>>t->red_b);
// Compute the address
index=(r<<t->dec_r) | (g<<t->dec_g) | (b<<t->dec_b); index=(r<<t->dec_r) | (g<<t->dec_g) | (b<<t->dec_b);
t->table[index]++; t->table[index]++;
} }
/// Count the use of each color in a 24bit picture and fill in the table
void OT_count_occurrences(T_Occurrence_table* t, T_Bitmap24B image, int size) void OT_count_occurrences(T_Occurrence_table* t, T_Bitmap24B image, int size)
{ {
T_Bitmap24B ptr; T_Bitmap24B ptr;
@ -325,11 +351,13 @@ void OT_count_occurrences(T_Occurrence_table* t, T_Bitmap24B image, int size)
OT_inc(t, ptr->R, ptr->G, ptr->B); OT_inc(t, ptr->R, ptr->G, ptr->B);
} }
/// Count the total number of pixels in an occurence table
int OT_count_colors(T_Occurrence_table * t) int OT_count_colors(T_Occurrence_table * t)
{ {
int val; // Valeur de retour int val; // Computed return value
int nb; // Nombre de couleurs … tester int nb; // Number of colors to test
int i; // Compteur de couleurs testes int i; // Loop index
val = 0; val = 0;
nb=(t->rng_r)*(t->rng_g)*(t->rng_b); nb=(t->rng_r)*(t->rng_g)*(t->rng_b);
@ -341,25 +369,41 @@ int OT_count_colors(T_Occurrence_table * t)
} }
// Cluster management
// Clusters are boxes in the RGB spaces, defined by 6 corner coordinates :
// Rmax, Rmin, Vmax (or Gmax), Vmin, Rmax, Rmin
// The median cut algorithm start with a single cluster covering the whole
// colorspace then split it in two smaller clusters on the longest axis until
// there are 256 non-empty clusters (with some tricks if the original image
// actually has less than 256 colors)
// Each cluster also store the number of pixels that are inside and the
// rmin, rmax, vmin, vmax, bmin, bmax values are the first/last values that
// actually are used by a pixel in the cluster
// When you split a big cluster there may be some space between the splitting
// plane and the first pixel actually in a cluster
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////// Mthodes de gestion des clusters //
/////////////////////////////////////////////////////////////////////////////
/// Pack a cluster, ie compute its {r,v,b}{min,max} values
void Cluster_pack(T_Cluster * c,T_Occurrence_table * to) void Cluster_pack(T_Cluster * c,T_Occurrence_table * to)
{ {
int rmin,rmax,vmin,vmax,bmin,bmax; int rmin,rmax,vmin,vmax,bmin,bmax;
int r,g,b; int r,g,b;
// On cherche les mins et les maxs de chaque composante sur la couverture // Find min. and max. values actually used for each component in this cluster
// int nbocc; // Pre-shift everything to avoid using OT_Get and be faster. This will only
// work if the occurence table actually has full precision, that is a
// On prédécale tout pour éviter de faire trop de bazar en se forçant à utiliser OT_get, plus rapide // 256^3*sizeof(int) = 64MB table. If your computer has less free ram and
// malloc fails, this will not work at all !
// GIMP use only 6 bits for G and B components in this table.
rmin=c->rmax <<16; rmax=c->rmin << 16; rmin=c->rmax <<16; rmax=c->rmin << 16;
vmin=c->vmax << 8; vmax=c->vmin << 8; vmin=c->vmax << 8; vmax=c->vmin << 8;
bmin=c->bmax; bmax=c->bmin; bmin=c->bmax; bmax=c->bmin;
c->occurences=0; c->occurences=0;
// Unoptimized code kept here for documentation purpose because the optimized
// one is unreadable : run over the whole cluster and find the min and max,
// and count the occurences at the same time.
/* /*
for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16) for (r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16)
for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8)
@ -379,9 +423,9 @@ void Cluster_pack(T_Cluster * c,T_Occurrence_table * to)
} }
*/ */
// On recherche le minimum et le maximum en parcourant le cluster selon chaque composante, // Optimized version : find the extremums one at a time, so we can reduce the
// ça évite des accès mémoires inutiles, de plus chaque boucle est plus petite que la // area to seek for the next one. Start at the edges of the cluster and go to
// précédente puisqu'on connait une borne supplémentaire // the center until we find a pixel.
for(r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16) for(r=c->rmin<<16;r<=c->rmax<<16;r+=1<<16)
for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) for(g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8)
@ -449,7 +493,8 @@ BMAX:
} }
} }
ENDCRUSH: ENDCRUSH:
// Il faut quand même parcourir la partie utile du cluster, pour savoir combien il y a d'occurences // We still need to seek the internal part of the cluster to count pixels
// inside it
for(r=rmin;r<=rmax;r+=1<<16) for(r=rmin;r<=rmax;r+=1<<16)
for(g=vmin;g<=vmax;g+=1<<8) for(g=vmin;g<=vmax;g+=1<<8)
for(b=bmin;b<=bmax;b++) for(b=bmin;b<=bmax;b++)
@ -457,11 +502,14 @@ ENDCRUSH:
c->occurences+=to->table[r + g + b]; // OT_get c->occurences+=to->table[r + g + b]; // OT_get
} }
// Unshift the values and put them in the cluster info
c->rmin=rmin>>16; c->rmax=rmax>>16; c->rmin=rmin>>16; c->rmax=rmax>>16;
c->vmin=vmin>>8; c->vmax=vmax>>8; c->vmin=vmin>>8; c->vmax=vmax>>8;
c->bmin=bmin; c->bmax=bmax; c->bmin=bmin; c->bmax=bmax;
// On regarde la composante qui a la variation la plus grande // Find the longest axis to know which way to split the cluster
// This multiplications are supposed to improve the result, but may or may not
// work, actually.
r=(c->rmax-c->rmin)*299; r=(c->rmax-c->rmin)*299;
g=(c->vmax-c->vmin)*587; g=(c->vmax-c->vmin)*587;
b=(c->bmax-c->bmin)*114; b=(c->bmax-c->bmin)*114;
@ -496,6 +544,9 @@ ENDCRUSH:
} }
} }
/// Split a cluster on its longest axis.
/// c = source cluster, c1, c2 = output after split
void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue, void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
T_Occurrence_table * to) T_Occurrence_table * to)
{ {
@ -503,10 +554,12 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
int cumul; int cumul;
int r, g, b; int r, g, b;
// Split criterion: each of the cluster will have the same number of pixels
limit = c->occurences / 2; limit = c->occurences / 2;
cumul = 0; cumul = 0;
if (hue == 0) if (hue == 0) // split on red
{ {
// Run over the cluster until we reach the requested number of pixels
for (r = c->rmin<<16; r<=c->rmax<<16; r+=1<<16) for (r = c->rmin<<16; r<=c->rmax<<16; r+=1<<16)
{ {
for (g = c->vmin<<8; g<=c->vmax<<8; g+=1<<8) for (g = c->vmin<<8; g<=c->vmax<<8; g+=1<<8)
@ -527,9 +580,11 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
r>>=16; r>>=16;
g>>=8; g>>=8;
// We tried to split on red, but found half of the pixels with r = rmin
// so we enforce some split to happen anyway, instead of creating an empty
// c2 and c1 == c
if (r==c->rmin) if (r==c->rmin)
r++; r++;
// R est la valeur de dbut du 2nd cluster
c1->Rmin=c->Rmin; c1->Rmax=r-1; c1->Rmin=c->Rmin; c1->Rmax=r-1;
c1->rmin=c->rmin; c1->rmax=r-1; c1->rmin=c->rmin; c1->rmax=r-1;
@ -546,7 +601,7 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
c2->bmin=c->bmin; c2->bmax=c->bmax; c2->bmin=c->bmin; c2->bmax=c->bmax;
} }
else else
if (hue==1) if (hue==1) // split on green
{ {
for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8) for (g=c->vmin<<8;g<=c->vmax<<8;g+=1<<8)
@ -570,7 +625,6 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
if (g==c->vmin) if (g==c->vmin)
g++; g++;
// G est la valeur de dbut du 2nd cluster
c1->Rmin=c->Rmin; c1->Rmax=c->Rmax; c1->Rmin=c->Rmin; c1->Rmax=c->Rmax;
c1->rmin=c->rmin; c1->rmax=c->rmax; c1->rmin=c->rmin; c1->rmax=c->rmax;
@ -586,7 +640,7 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
c2->Bmin=c->Bmin; c2->Bmax=c->Bmax; c2->Bmin=c->Bmin; c2->Bmax=c->Bmax;
c2->bmin=c->bmin; c2->bmax=c->bmax; c2->bmin=c->bmin; c2->bmax=c->bmax;
} }
else else // split on blue
{ {
for (b=c->bmin;b<=c->bmax;b++) for (b=c->bmin;b<=c->bmax;b++)
@ -610,7 +664,6 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
if (b==c->bmin) if (b==c->bmin)
b++; b++;
// B est la valeur de dbut du 2nd cluster
c1->Rmin=c->Rmin; c1->Rmax=c->Rmax; c1->Rmin=c->Rmin; c1->Rmax=c->Rmax;
c1->rmin=c->rmin; c1->rmax=c->rmax; c1->rmin=c->rmin; c1->rmax=c->rmax;
@ -628,6 +681,8 @@ void Cluster_split(T_Cluster * c, T_Cluster * c1, T_Cluster * c2, int hue,
} }
} }
/// Compute the mean R, G, B (for palette generation) and H, L (for palette sorting)
void Cluster_compute_hue(T_Cluster * c,T_Occurrence_table * to) void Cluster_compute_hue(T_Cluster * c,T_Occurrence_table * to)
{ {
int cumul_r,cumul_g,cumul_b; int cumul_r,cumul_g,cumul_b;
@ -657,10 +712,11 @@ void Cluster_compute_hue(T_Cluster * c,T_Occurrence_table * to)
} }
// Cluster set management
// A set of clusters in handled as a list, the median cut algorithm pops a
// cluster from the list, split it, and pushes back the two splitted clusters
// until the lit grows to 256 items
/////////////////////////////////////////////////////////////////////////////
//////////////////////////// Mthodes de gestion des ensembles de clusters //
/////////////////////////////////////////////////////////////////////////////
// Debug helper : check if a cluster set has the right count value // Debug helper : check if a cluster set has the right count value
/* /*
@ -679,6 +735,7 @@ void CS_Check(T_Cluster_set* cs)
*/ */
/// Setup the first cluster before we start the operations /// Setup the first cluster before we start the operations
/// This one covers the full palette range
void CS_Init(T_Cluster_set * cs, T_Occurrence_table * to) void CS_Init(T_Cluster_set * cs, T_Occurrence_table * to)
{ {
cs->clusters->Rmin = cs->clusters->rmin = 0; cs->clusters->Rmin = cs->clusters->rmin = 0;
@ -700,25 +757,23 @@ T_Cluster_set * CS_New(int nbmax, T_Occurrence_table * to)
n=(T_Cluster_set *)malloc(sizeof(T_Cluster_set)); n=(T_Cluster_set *)malloc(sizeof(T_Cluster_set));
if (n != NULL) if (n != NULL)
{ {
// On recopie les paramŠtres demands // Copy requested params
n->nb_max = OT_count_colors(to); n->nb_max = OT_count_colors(to);
// On vient de compter le nombre de couleurs existantes, s'il est plus grand // If the number of colors asked is > 256, we ceil it because we know we
// que 256 on limite à 256 // don't want more
// (nombre de couleurs voulu au final)
if (n->nb_max > nbmax) if (n->nb_max > nbmax)
{ {
n->nb_max = nbmax; n->nb_max = nbmax;
} }
// On tente d'allouer le premier cluster // Allocate the first cluster
n->clusters=(T_Cluster *)malloc(sizeof(T_Cluster)); n->clusters=(T_Cluster *)malloc(sizeof(T_Cluster));
if (n->clusters != NULL) if (n->clusters != NULL)
// C'est bon! On initialise
CS_Init(n, to); CS_Init(n, to);
else else
{ {
// Table impossible … allouer // No memory free ! Sorry !
free(n); free(n);
n = NULL; n = NULL;
} }
@ -740,12 +795,18 @@ void CS_Delete(T_Cluster_set * cs)
free(cs); free(cs);
} }
/// Pop a cluster from the cluster list
void CS_Get(T_Cluster_set * cs, T_Cluster * c) void CS_Get(T_Cluster_set * cs, T_Cluster * c)
{ {
T_Cluster* current = cs->clusters; T_Cluster* current = cs->clusters;
T_Cluster* prev = NULL; T_Cluster* prev = NULL;
// Search a cluster with at least 2 distinct colors so we can split it // Search a cluster with at least 2 distinct colors so we can split it
// Clusters are sorted by number of occurences, so a cluster may end up
// with a lot of pixelsand on top of the list, but only one color. We can't
// split it in that case. It should probably be stored on a list of unsplittable
// clusters to avoid running on it again on each iteration.
do do
{ {
if ( (current->rmin < current->rmax) || if ( (current->rmin < current->rmax) ||
@ -771,12 +832,14 @@ void CS_Get(T_Cluster_set * cs, T_Cluster * c)
current = NULL; current = NULL;
} }
/// Push a cluster in the list
void CS_Set(T_Cluster_set * cs,T_Cluster * c) void CS_Set(T_Cluster_set * cs,T_Cluster * c)
{ {
T_Cluster* current = cs->clusters; T_Cluster* current = cs->clusters;
T_Cluster* prev = NULL; T_Cluster* prev = NULL;
// Search the first cluster that is smaller than ours // Search the first cluster that is smaller than ours (less pixels)
while (current && current->occurences > c->occurences) while (current && current->occurences > c->occurences)
{ {
prev = current; prev = current;
@ -795,41 +858,44 @@ void CS_Set(T_Cluster_set * cs,T_Cluster * c)
cs->nb++; cs->nb++;
} }
// Détermination de la meilleure palette en utilisant l'algo Median Cut : /// This is the main median cut algorithm and the function actually called to
// 1) On considère l'espace (R,G,B) comme 1 boîte /// reduce the palette. We get the number of pixels for each collor in the
// 2) On cherche les extrêmes de la boîte en (R,G,B) /// occurence table and generate the cluster set from it.
// 3) On trie les pixels de l'image selon l'axe le plus long parmi (R,G,B) // 1) RGB space is a big box
// 4) On coupe la boîte en deux au milieu, et on compacte pour que chaque bord // 2) We seek the pixels with extreme values
// corresponde bien à un pixel extreme // 3) We split the box in 2 parts on its longest axis
// 5) On recommence à couper selon le plus grand axe toutes boîtes confondues // 4) We pack the 2 resulting boxes again to leave no empty space between the box border and the first pixel
// 6) On s'arrête quand on a le nombre de couleurs voulu // 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
void CS_Generate(T_Cluster_set * cs, T_Occurrence_table * to) void CS_Generate(T_Cluster_set * cs, T_Occurrence_table * to)
{ {
T_Cluster current; T_Cluster current;
T_Cluster Nouveau1; T_Cluster Nouveau1;
T_Cluster Nouveau2; T_Cluster Nouveau2;
// Tant qu'on a moins de 256 clusters // There are less than 256 boxes
while (cs->nb<cs->nb_max) while (cs->nb<cs->nb_max)
{ {
// On récupère le plus grand cluster // Get the biggest one
CS_Get(cs,&current); CS_Get(cs,&current);
// On le coupe en deux // Split it
Cluster_split(&current, &Nouveau1, &Nouveau2, current.plus_large, to); Cluster_split(&current, &Nouveau1, &Nouveau2, current.plus_large, to);
// On compacte ces deux nouveaux (il peut y avoir un espace entre l'endroit // Pack the 2 new clusters (the split may leave some empty space between the
// de la coupure et les premiers pixels du cluster) // box border and the first actual pixel)
Cluster_pack(&Nouveau1, to); Cluster_pack(&Nouveau1, to);
Cluster_pack(&Nouveau2, to); Cluster_pack(&Nouveau2, to);
// On les remet dans le set // Put them back in the list
CS_Set(cs,&Nouveau1); CS_Set(cs,&Nouveau1);
CS_Set(cs,&Nouveau2); CS_Set(cs,&Nouveau2);
} }
} }
/// Compute the color associated to each box in the list
void CS_Compute_colors(T_Cluster_set * cs, T_Occurrence_table * to) void CS_Compute_colors(T_Cluster_set * cs, T_Occurrence_table * to)
{ {
T_Cluster * c; T_Cluster * c;
@ -838,6 +904,11 @@ void CS_Compute_colors(T_Cluster_set * cs, T_Occurrence_table * to)
Cluster_compute_hue(c,to); Cluster_compute_hue(c,to);
} }
// We sort the clusters on two criterions to get a somewhat coherent palette.
// TODO : It would be better to do this in one single pass.
/// Sort the clusters by chrominance value
void CS_Sort_by_chrominance(T_Cluster_set * cs) void CS_Sort_by_chrominance(T_Cluster_set * cs)
{ {
T_Cluster* nc; T_Cluster* nc;
@ -866,10 +937,12 @@ void CS_Sort_by_chrominance(T_Cluster_set * cs)
prev = NULL; prev = NULL;
} }
// Put the new list bavk in place // Put the new list back in place
cs->clusters = newlist; cs->clusters = newlist;
} }
/// Sort the clusters by luminance value
void CS_Sort_by_luminance(T_Cluster_set * cs) void CS_Sort_by_luminance(T_Cluster_set * cs)
{ {
T_Cluster* nc; T_Cluster* nc;
@ -903,6 +976,8 @@ void CS_Sort_by_luminance(T_Cluster_set * cs)
cs->clusters = newlist; cs->clusters = newlist;
} }
/// 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,T_Conversion_table * tc,T_Components * palette)
{ {
int index; int index;
@ -1028,8 +1103,7 @@ void GS_Generate(T_Gradient_set * ds,T_Cluster_set * cs)
} }
/// Compute best palette for given picture.
T_Conversion_table * Optimize_palette(T_Bitmap24B image, int size, T_Conversion_table * 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)
{ {
@ -1038,7 +1112,7 @@ T_Conversion_table * Optimize_palette(T_Bitmap24B image, int size,
T_Cluster_set * cs; T_Cluster_set * cs;
T_Gradient_set * ds; T_Gradient_set * ds;
// Création des éléments nécessaires au calcul de palette optimisée: // Allocate all the elements
to = 0; tc = 0; cs = 0; ds = 0; to = 0; tc = 0; cs = 0; ds = 0;
to = OT_new(r, g, b); to = OT_new(r, g, b);
@ -1052,7 +1126,7 @@ T_Conversion_table * Optimize_palette(T_Bitmap24B image, int size,
return 0; return 0;
} }
// Première étape : on compte les pixels de chaque couleur pour pouvoir trier là dessus // Count pixels for each color
OT_count_occurrences(to, image, size); OT_count_occurrences(to, image, size);
cs = CS_New(256, to); cs = CS_New(256, to);
@ -1063,13 +1137,13 @@ T_Conversion_table * Optimize_palette(T_Bitmap24B image, int size,
return 0; return 0;
} }
//CS_Check(cs); //CS_Check(cs);
// C'est bon, on a pu tout allouer // Ok, everything was allocated
// On génère les clusters (avec l'algo du median cut) // Generate the cluster set with median cut algorithm
CS_Generate(cs, to); CS_Generate(cs, to);
//CS_Check(cs); //CS_Check(cs);
// On calcule la teinte de chaque pixel (Luminance et chrominance) // Compute the color data for each cluster (palette entry + HL)
CS_Compute_colors(cs, to); CS_Compute_colors(cs, to);
//CS_Check(cs); //CS_Check(cs);
@ -1079,15 +1153,13 @@ T_Conversion_table * Optimize_palette(T_Bitmap24B image, int size,
GS_Generate(ds, cs); GS_Generate(ds, cs);
GS_Delete(ds); GS_Delete(ds);
} }
// Enfin on trie les clusters (donc les couleurs de la palette) dans un ordre // Sort the clusters on L and H to get a nice palette
// sympa : par couleur, et par luminosité pour chaque couleur
CS_Sort_by_luminance(cs); CS_Sort_by_luminance(cs);
//CS_Check(cs); //CS_Check(cs);
CS_Sort_by_chrominance(cs); CS_Sort_by_chrominance(cs);
//CS_Check(cs); //CS_Check(cs);
// Enfin on génère la palette et la table de correspondance entre chaque // And finally generate the conversion table to map RGB > pal. index
// couleur 24b et sa couleur palette associée.
CS_Generate_color_table_and_palette(cs, tc, palette); CS_Generate_color_table_and_palette(cs, tc, palette);
//CS_Check(cs); //CS_Check(cs);
@ -1096,6 +1168,8 @@ T_Conversion_table * Optimize_palette(T_Bitmap24B image, int size,
return tc; return tc;
} }
/// Change a value with proper ceiling and flooring
int Modified_value(int value,int modif) int Modified_value(int value,int modif)
{ {
value+=modif; value+=modif;
@ -1110,10 +1184,11 @@ int Modified_value(int value,int modif)
return value; return value;
} }
/// Convert a 24b image to 256 colors (with a given palette and conversion table)
/// This destroys the 24b picture !
/// 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,T_Conversion_table * tc)
// Cette fonction dégrade au fur et à mesure le bitmap source, donc soit on ne
// s'en ressert pas, soit on passe à la fonction une copie de travail du
// bitmap original.
{ {
T_Bitmap24B current; T_Bitmap24B current;
T_Bitmap24B c_plus1; T_Bitmap24B c_plus1;
@ -1205,6 +1280,8 @@ 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
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) T_Conversion_table * tc)
@ -1241,6 +1318,8 @@ void Convert_24b_bitmap_to_256_nearest_neighbor(T_Bitmap256 dest,
} }
// These are the allowed precisions for all the tables.
// For some of them only the first one may work because of ugly optimizations
static const byte precision_24b[]= static const byte precision_24b[]=
{ {
8,8,8, 8,8,8,
@ -1257,11 +1336,7 @@ static const byte precision_24b[]=
3,3,2}; 3,3,2};
// Convertie avec le plus de précision possible une image 24b en 256c // Give this one a 24b source, get back the 256c bitmap and its palette
// Renvoie s'il y a eu une erreur ou pas..
// Cette fonction utilise l'algorithme "median cut" (Optimize_palette) pour trouver la palette, et diffuse les erreurs avec floyd-steinberg.
int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette) int Convert_24b_bitmap_to_256(T_Bitmap256 dest,T_Bitmap24B source,int width,int height,T_Components * palette)
{ {
T_Conversion_table * table; // table de conversion T_Conversion_table * table; // table de conversion

2
op_c.h
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1 +1,3 @@
/* vim:expandtab:ts=2 sw=2:
*/
char Program_version[]="layers wip"; char Program_version[]="layers wip";

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
#include <limits.h> #include <limits.h>
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Adrien Destugues Copyright 2008 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Peter Gordon Copyright 2008 Peter Gordon

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007 Adrien Destugues Copyright 2007 Adrien Destugues

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

2
text.c
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

2
text.h
View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Yves Rizoud Copyright 2008 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Yves Rizoud Copyright 2009 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2009 Yves Rizoud Copyright 2009 Yves Rizoud

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2008 Franck Charlet Copyright 2008 Franck Charlet
@ -914,28 +916,42 @@ void Verbose_error_message(const char * message)
{ {
short clicked_button; short clicked_button;
int line; int line;
int i; int last_space;
char buffer[36]; // 35 characters + \0 int nb_char;
char buffer[36];
Open_window(300,160,"Error!"); Open_window(300,160,"Error!");
// Word-wrap the message // Word-wrap the message
for (line=0; line < 10; line++) for (line=0; line < 12 && *message!='\0'; line++)
{ {
for (i=0;i<35 && *message!='\0';i++) last_space = -1;
for (nb_char=0; nb_char<35 && message[nb_char]!='\0'; nb_char++)
{ {
if (*message == '\n') buffer[nb_char]=message[nb_char];
if (message[nb_char] == ' ')
{ {
message++; last_space = nb_char;
}
else if (message[nb_char] == '\n')
{
last_space = nb_char;
break; break;
} }
buffer[i]=*message;
message++;
} }
buffer[i]='\0'; // Close line buffer
if (last_space == -1)
last_space = 34;
buffer[last_space]='\0';
// Print
Print_in_window(10,20+line*8,buffer,MC_Black,MC_Light); Print_in_window(10,20+line*8,buffer,MC_Black,MC_Light);
if (*message=='\0')
break; // Next line
message=message+last_space+1;
// Strip leading spaces
while (*message == ' ')
message++;
} }
Window_set_normal_button(300/2-20,160-23,40,14,"OK",1,1,SDLK_RETURN); // 1 Window_set_normal_button(300/2-20,160-23,40,14,"OK",1,1,SDLK_RETURN); // 1
@ -1518,15 +1534,22 @@ void Compute_magnifier_data(void)
} }
/// Changes magnifier factor and updates everything needed
// ------------ Changer le facteur de zoom et tout mettre à jour -------------
void Change_magnifier_factor(byte factor_index) void Change_magnifier_factor(byte factor_index)
{ {
short center_x; int center_x;
short center_y; int center_y;
center_x=Main_magnifier_offset_X+(Main_magnifier_width>>1); // Values that need to be computed before switching to the new zoom factor
center_y=Main_magnifier_offset_Y+(Main_magnifier_height>>1); if (Cursor_in_menu || !Main_magnifier_mode)
{
center_x=Main_magnifier_offset_X+(Main_magnifier_width>>1);
center_y=Main_magnifier_offset_Y+(Main_magnifier_height>>1);
} else {
// Zoom to cursor
center_x = (Paintbrush_X - Main_magnifier_offset_X) * 65536 / Main_magnifier_width;
center_y = (Paintbrush_Y - Main_magnifier_offset_Y) * 65536 / Main_magnifier_height;
}
Main_magnifier_factor=ZOOM_FACTOR[factor_index]; Main_magnifier_factor=ZOOM_FACTOR[factor_index];
Compute_magnifier_data(); Compute_magnifier_data();
@ -1535,8 +1558,14 @@ void Change_magnifier_factor(byte factor_index)
{ {
// Recalculer le décalage de la loupe // Recalculer le décalage de la loupe
// Centrage "brut" de lécran par rapport à la loupe // Centrage "brut" de lécran par rapport à la loupe
Main_magnifier_offset_X=center_x-(Main_magnifier_width>>1); if (Cursor_in_menu)
Main_magnifier_offset_Y=center_y-(Main_magnifier_height>>1); {
Main_magnifier_offset_X=center_x-(Main_magnifier_width>>1);
Main_magnifier_offset_Y=center_y-(Main_magnifier_height>>1);
} else {
Main_magnifier_offset_X = Paintbrush_X - center_x * Main_magnifier_width / 65536 ;
Main_magnifier_offset_Y = Paintbrush_Y - center_y * Main_magnifier_height / 65536 ;
}
// Correction en cas de débordement de l'image // Correction en cas de débordement de l'image
if (Main_magnifier_offset_X+Main_magnifier_width>Main_image_width) if (Main_magnifier_offset_X+Main_magnifier_width>Main_image_width)
Main_magnifier_offset_X=Main_image_width-Main_magnifier_width; Main_magnifier_offset_X=Main_image_width-Main_magnifier_width;

View File

@ -1,3 +1,5 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program /* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2007-2008 Adrien Destugues Copyright 2007-2008 Adrien Destugues