Retro Graphics Toolkit

Talk about development tools here

Moderator: BigEvilCorporation

sega16
Very interested
Posts: 251
Joined: Sat Jan 29, 2011 3:16 pm
Location: U.S.A.

Post by sega16 » Fri Jun 07, 2013 4:32 pm

frederic wrote:
r57shell wrote:It will just change quantized colors in genesis ones.
Yes, it won't break an image into 16-colors tiles. It may be possible to write a script that combines several imagemagick commands to do that. Imagemagick may not be the best tool to do such a thing.
That is why there is Retro Graphics Toolkit.

Ti_
Very interested
Posts: 97
Joined: Tue Aug 30, 2011 7:50 am
Contact:

Post by Ti_ » Sat Jun 08, 2013 7:43 am

frederic wrote:
r57shell wrote:It will just change quantized colors in genesis ones.
Yes, it won't break an image into 16-colors tiles. It may be possible to write a script that combines several imagemagick commands to do that. Imagemagick may not be the best tool to do such a thing.
Nope. Tiles not needed.
You just not show where to specify color count in you scripts. So it just reduce from 24 bit to 9 bit . (that can be done more easily by "imgtosega").
Already found it in another topic ( - colors 15).
frederic wrote: colorsyo.png is an image that contains all the colors of the Genesis palette. You can get this image here: http://img11.imageshack.us/img11/5651/colorsyo.png (I don't remember where I got it from, it may be inaccurate).
yes, it's inaccurate. wrong color interval (white color 224/224/224 instead of 255/255/255)

Ti_
Very interested
Posts: 97
Joined: Tue Aug 30, 2011 7:50 am
Contact:

Post by Ti_ » Sat Jun 08, 2013 8:38 am

I've tested ImageImigick - it's doesn't work as needed.

It's just reduce to 9 bit image, and after that cut-off colors.

In my image - when I specify 16 colors, it makes 15 colors image.
When 17 - make 17. How to make 16?

Retrographics use special algorithm , first - it makes 16 colors optimal palette and after reduce to that palette.
It provides better picture.

retrogfx: 16color (old version with classic palette, that used by emulator not hardware)
Image

imagegimmick:
convert input.png -dither None -colors 16 -remap colorsyo.png output.png (colorsyo also created with emulators palette - so both pictures uses same colors)
Image



source pic link

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Post by r57shell » Sat Jun 08, 2013 11:12 am

Ok, I have done some comparison.

Left to right: ImageMagick, Retro Graphics Toolkit, Ximagic
original
Image

16 colors without dither.
Image Image Image

16 colors with dither.
Image Image Image
Image

Dither settings:
ImageMagick: Riemersma, FloydSteinberg
Retro Graphics Toolkit: FloydSteinberg 63
Ximagic... I don't want to write all settings here :).
Make conclusions yourself.

sega16, what quanization method you use? I have image, where your quantization with 31 color gives bad result. :( ImageMagick gives better.

Ok, here is this img. Original, ImageMagick 1, ImageMagick 2, Retro Graphics Toolkit, Ximagic, pngnq with tricks, scolorq, scolorq trick.
Image Image Image Image Image Image Image Image
Last edited by r57shell on Sat Jun 08, 2013 5:10 pm, edited 6 times in total.
Image

Ti_
Very interested
Posts: 97
Joined: Tue Aug 30, 2011 7:50 am
Contact:

Post by Ti_ » Sat Jun 08, 2013 12:31 pm

r57shell wrote: sega16, what quanization method you use? I have image, where your quantization with 31 color gives bad result. :( ImageMagick gives better.
all makes bad result:

imagemagic made 29 colors from 31 you wanted. (because first recude to 9 bit, and after reduce colors - that why 2 colors lost)

retrographics made 25 colors.
(looks like it generate 16 colors pallete, and after that - other 16 colors palette for next raw - same as for 1-layer Image.) - but for 2-layer-image palette must picked from 32 unique colors (same as in 16 colors method) in 1 pass.

Xmagic doesn't work at all - because color count is 191.

Ti_
Very interested
Posts: 97
Joined: Tue Aug 30, 2011 7:50 am
Contact:

Post by Ti_ » Sat Jun 08, 2013 12:43 pm

This is code from RetroGfx that generate 16 colors palette.
Can it be modified to any count?

Code: Select all

void generate_optimal_palette(Fl_Widget*,void * row)
{
	/*
	This function is one of the more importan features of the program
	This will look at the tile map and based on that find an optimal palette
	*/
	uint8_t * image;
	//uint8_t * colors;
	uint32_t w,h;
	w=currentProject->tileMapC->mapSizeW*8;
	h=currentProject->tileMapC->mapSizeH*8;
	uint32_t colors_found;
	uint8_t * found_colors;
	switch (game_system)
	{
		case sega_genesis:
			switch((uintptr_t)row)
			{
				case 0:
					//this is easy we just convert tilemap to image count unique colors if less than 16 then just use that else reduce palete
					image = (uint8_t *)malloc(w*h*3);
					found_colors = (uint8_t *)malloc(w*3+3);
					truecolor_to_image(image,-1,false);
					colors_found=count_colors(image,w,h,found_colors);
					printf("Unique colors %d\n",colors_found);
					if (colors_found < 17)
					{
						printf("16 or less colors\n");
						for (uint8_t x=0;x<colors_found;x++)
						{
							uint8_t r,g,b;
							r=found_colors[(x*3)];
							g=found_colors[(x*3)+1];
							b=found_colors[(x*3)+2];
							printf("R=%d G=%d B=%d\n",r,g,b);
							r=(r+18)/36;
							g=(g+18)/36;
							b=(b+18)/36;
							r*=2;
							g*=2;
							b*=2;
							//bgr
							currentProject->palDat[x*2]=b;
							currentProject->palDat[(x*2)+1]=r+(g<<4);
							currentProject->rgbPal[(x*3)]=r*18;
							currentProject->rgbPal[(x*3)+1]=g*18;
							currentProject->rgbPal[(x*3)+2]=b*18;
						}

						window->redraw();
					}
					else
					{
						printf("More than 16 colors reducing to 16 colors\n");
						/*this uses denesis lee's v3 color quant which is fonund at http://www.gnu-darwin.org/www001/ports-1.5a-CURRENT/graphics/mtpaint/work/mtpaint-3.11/src/quantizer.c*/
						uint8_t user_pal[3][256];
						
						uint8_t rgb_pal2[768];
						uint8_t colorz=16;
						bool can_go_again=true;
try_again_color:
						dl3quant(image,w,h,colorz,user_pal);
						for (uint16_t x=0;x<colorz;x++)
						{
							uint8_t r=0,g=0,b=0;
							
							r=user_pal[0][x];
							g=user_pal[1][x];
							b=user_pal[2][x];
							//printf("R=%d G=%d B=%d\n",r,g,b);
							r=(int16_t)(r+18)/36;//prevents overflow glitch
							g=(int16_t)(g+18)/36;
							b=(int16_t)(b+18)/36;
							//r*=2;
							//g*=2;
							//b*=2;
							//bgr
							//currentProject->palDat[x*2]=b;
							//currentProject->palDat[(x*2)+1]=r+(g<<4);
							rgb_pal2[(x*3)]=r*36;
							rgb_pal2[(x*3)+1]=g*36;
							rgb_pal2[(x*3)+2]=b*36;
						}
						uint8_t new_colors = count_colors(rgb_pal2,colorz,1,currentProject->rgbPal);
						printf("Unique colors in palette %d\n",new_colors);
						if (new_colors < 16)
						{
							if (can_go_again == true)
							{
								printf("Trying again needs more color\n");
								if (colorz != 255)
								{
									colorz++;
								}
								else
								{
									can_go_again=false;
								}
								goto try_again_color;
							}
						}
						if (new_colors > 16)
						{
							can_go_again=false;
							printf("Woops too many colors\n");
							colorz--;
							goto try_again_color;
						}
						for (uint8_t x=0;x<16;x++)
						{
							uint8_t r=0,g=0,b=0;
							
							r=currentProject->rgbPal[x*3];
							g=currentProject->rgbPal[(x*3)+1];
							b=currentProject->rgbPal[(x*3)+2];
							r/=36;
							g/=36;
							b/=36;
							r*=2;
							g*=2;
							b*=2;
							currentProject->palDat[x*2]=b;
							currentProject->palDat[(x*2)+1]=r+(g<<4);
						}
						
						//free(image_2);
					}
					free(image);
					free(found_colors);
					window->redraw();
				break;

				default:
					show_default_error
				break;
			}
		break;

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Post by r57shell » Sat Jun 08, 2013 12:47 pm

Ti_ wrote:Xmagic doesn't work at all - because color count is 191.
It's my mistake. Image corrected. pngnq version added. Ok, I will redo ImageMagick Versions.
Image

Ti_
Very interested
Posts: 97
Joined: Tue Aug 30, 2011 7:50 am
Contact:

Post by Ti_ » Sat Jun 08, 2013 2:23 pm

R57Shell:
X_magic good because saves details. But colors is to bright (Jax is too red, and green borders)
PngNQ good color, but lost details (Jade mask)
but this programs is exist for windows? and they are simple to use? I don't know how to use them.

image magic, good but not always ( 1st: sometimes impossible to get color count you want: I getting 15 or 17, but retro can do 16 in same pic.!)
2nd: not 1 file, requires picture with colors
3rd: most times you must use greater value to get actual: if i write colors -55 - result 48...)

So, sure I can use imagemagic, but also suggest to make simple utility that convert colors as in RetroGraphics, but with user specified count and png output. (And maybe method of retrogfx will produce more good picture if fix it to work properly with any color count).
And if someone will do it, please also add selection : emulators sega colors and hardware sega colors.

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Post by r57shell » Sat Jun 08, 2013 2:59 pm

Haha! I have found among the best way for me :)
1) img.png scolorq filter size 3 = out1.png
2) out1.png -remap genesis_colormap.png = out2.png
3) img.png -remap out2.png = out.png
See out2 and out.png in previous post, I added as "scolorq, scolorq trick"
Needs only to reduce dither.
Image

sega16
Very interested
Posts: 251
Joined: Sat Jan 29, 2011 3:16 pm
Location: U.S.A.

Post by sega16 » Sat Jun 08, 2013 3:06 pm

Ti_ wrote:This is code from RetroGfx that generate 16 colors palette.
Can it be modified to any count?

Code: Select all

void generate_optimal_palette(Fl_Widget*,void * row)
{
	/*
	This function is one of the more importan features of the program
	This will look at the tile map and based on that find an optimal palette
	*/
	uint8_t * image;
	//uint8_t * colors;
	uint32_t w,h;
	w=currentProject->tileMapC->mapSizeW*8;
	h=currentProject->tileMapC->mapSizeH*8;
	uint32_t colors_found;
	uint8_t * found_colors;
	switch (game_system)
	{
		case sega_genesis:
			switch((uintptr_t)row)
			{
				case 0:
					//this is easy we just convert tilemap to image count unique colors if less than 16 then just use that else reduce palete
					image = (uint8_t *)malloc(w*h*3);
					found_colors = (uint8_t *)malloc(w*3+3);
					truecolor_to_image(image,-1,false);
					colors_found=count_colors(image,w,h,found_colors);
					printf("Unique colors %d\n",colors_found);
					if (colors_found < 17)
					{
						printf("16 or less colors\n");
						for (uint8_t x=0;x<colors_found;x++)
						{
							uint8_t r,g,b;
							r=found_colors[(x*3)];
							g=found_colors[(x*3)+1];
							b=found_colors[(x*3)+2];
							printf("R=%d G=%d B=%d\n",r,g,b);
							r=(r+18)/36;
							g=(g+18)/36;
							b=(b+18)/36;
							r*=2;
							g*=2;
							b*=2;
							//bgr
							currentProject->palDat[x*2]=b;
							currentProject->palDat[(x*2)+1]=r+(g<<4);
							currentProject->rgbPal[(x*3)]=r*18;
							currentProject->rgbPal[(x*3)+1]=g*18;
							currentProject->rgbPal[(x*3)+2]=b*18;
						}

						window->redraw();
					}
					else
					{
						printf("More than 16 colors reducing to 16 colors\n");
						/*this uses denesis lee's v3 color quant which is fonund at http://www.gnu-darwin.org/www001/ports-1.5a-CURRENT/graphics/mtpaint/work/mtpaint-3.11/src/quantizer.c*/
						uint8_t user_pal[3][256];
						
						uint8_t rgb_pal2[768];
						uint8_t colorz=16;
						bool can_go_again=true;
try_again_color:
						dl3quant(image,w,h,colorz,user_pal);
						for (uint16_t x=0;x<colorz;x++)
						{
							uint8_t r=0,g=0,b=0;
							
							r=user_pal[0][x];
							g=user_pal[1][x];
							b=user_pal[2][x];
							//printf("R=%d G=%d B=%d\n",r,g,b);
							r=(int16_t)(r+18)/36;//prevents overflow glitch
							g=(int16_t)(g+18)/36;
							b=(int16_t)(b+18)/36;
							//r*=2;
							//g*=2;
							//b*=2;
							//bgr
							//currentProject->palDat[x*2]=b;
							//currentProject->palDat[(x*2)+1]=r+(g<<4);
							rgb_pal2[(x*3)]=r*36;
							rgb_pal2[(x*3)+1]=g*36;
							rgb_pal2[(x*3)+2]=b*36;
						}
						uint8_t new_colors = count_colors(rgb_pal2,colorz,1,currentProject->rgbPal);
						printf("Unique colors in palette %d\n",new_colors);
						if (new_colors < 16)
						{
							if (can_go_again == true)
							{
								printf("Trying again needs more color\n");
								if (colorz != 255)
								{
									colorz++;
								}
								else
								{
									can_go_again=false;
								}
								goto try_again_color;
							}
						}
						if (new_colors > 16)
						{
							can_go_again=false;
							printf("Woops too many colors\n");
							colorz--;
							goto try_again_color;
						}
						for (uint8_t x=0;x<16;x++)
						{
							uint8_t r=0,g=0,b=0;
							
							r=currentProject->rgbPal[x*3];
							g=currentProject->rgbPal[(x*3)+1];
							b=currentProject->rgbPal[(x*3)+2];
							r/=36;
							g/=36;
							b/=36;
							r*=2;
							g*=2;
							b*=2;
							currentProject->palDat[x*2]=b;
							currentProject->palDat[(x*2)+1]=r+(g<<4);
						}
						
						//free(image_2);
					}
					free(image);
					free(found_colors);
					window->redraw();
				break;

				default:
					show_default_error
				break;
			}
		break;
That is an old version here is the most recent source from https://github.com/ComputerNerd/Retro-G ... ilemap.cpp
I do not know where you got the old version from.

Code: Select all

void generate_optimal_palette(Fl_Widget*,void*)
{
	uint8_t perRow[4];
	char temp[4];
	uint8_t rowSize;
	uint8_t rows;
	switch (game_system) {
		case sega_genesis:
			strcpy(temp,"64");
			rowSize=16;
		break;
		case NES:
			strcpy(temp,"16");
			rowSize=4;
		break;
	}
	char * returned=(char *)fl_input("How many colors would you like?",temp);
	if (returned==0)
		return;
	if (verify_str_number_only(returned) == false)
			return;
	int8_t colors=atoi(returned);
	uint8_t asdf;
	for (asdf=0;asdf<4;asdf++) {
		perRow[asdf]=colors > rowSize ? rowSize:colors;
		colors-=rowSize;
		printf("Colors %d\n",colors);
		if (colors <= 0)
			break;
	}
	rows=asdf+1;
	printf("Using %d rows\n",rows);
	Fl_Window *win;
	Fl_Progress *progress;
	win = new Fl_Window(250,45,"Progress");           // access parent window
	win->begin();                                // add progress bar to it..
	progress = new Fl_Progress(25,7,200,30);
	progress->minimum(0);                      // set progress range to be 0.0 ~ 1.0
	progress->maximum(1);
	progress->color(0x88888800);               // background color
	progress->selection_color(0x4444ff00);     // progress bar color
	progress->labelcolor(FL_WHITE);            // percent text color
	win->end();                                  // end adding to window
	win->show();
	/*
	This function is one of the more importan features of the program
	This will look at the tile map and based on that find an optimal palette
	*/
	uint8_t * image;
	//uint8_t * colors;
	uint32_t w,h;
	w=currentProject->tileMapC->mapSizeW*8;
	h=currentProject->tileMapC->mapSizeH*8;
	uint32_t colors_found;
	//uint8_t * found_colors;
	uint8_t found_colors[768];
	uint8_t rowAuto;
	if (rows==1)
		rowAuto = fl_ask("Would you like all tiles on the tilemap to be set to row 0? (This is where all generated colors will apear)");
	else
		 rowAuto = fl_ask("Since you used more than one row tiles can be selected based on the hue\nDo you want which row each tile to use be selected automaticlly by hue\nBy pressing no this assumes that you have already picked which tile uses what row");
	switch (game_system) {
		case sega_genesis:
			if (rows==1) {
				if (rowAuto)
					currentProject->tileMapC->allRowZero();
				image = (uint8_t *)malloc(w*h*3);
				reduceImageGenesis(image,found_colors,-1,0,progress,perRow[0]);
				free(image);
				//free(found_colors);
				window->redraw();
			}
			else {
				image = (uint8_t *)malloc(w*h*3);
				if (rowAuto)
					currentProject->tileMapC->pickRow(rows);
				for (uint8_t nerdL=0;nerdL<rows;nerdL++) {
					reduceImageGenesis(image,found_colors,nerdL,nerdL*16,progress,perRow[nerdL]);
					window->damage(FL_DAMAGE_USER1);
					Fl::check();
				}
				//currentProject->tileMapC->pickRowDelta();
				free(image);
			}
		break;
		case NES:
			if (rows==1) {
				if (rowAuto)
					currentProject->tileMapC->allRowZero();
				image = (uint8_t *)malloc(w*h*3);
				reduceImageNES(image,found_colors,-1,0,progress,perRow[0]);
				free(image);
				//free(found_colors);
				window->redraw();
			}
			else {
					image = (uint8_t *)malloc(w*h*3);
					if (rowAuto)
						currentProject->tileMapC->pickRow(rows);
					for (uint8_t nerdL=0;nerdL<rows;nerdL++)
					{
						reduceImageNES(image,found_colors,nerdL,nerdL*4,progress,perRow[nerdL]);
						window->damage(FL_DAMAGE_USER1);
						Fl::check();
					}
					free(image);
					window->redraw();
			}
			break;
		default:
			show_default_error
		break;
	}
	win->remove(progress);// remove progress bar from window
	delete(progress);// deallocate it
	//w->draw();
	delete win;
	Fl::check();
}
Also it uses Dennis lee v3 quantization
I updated the windows binary if you are using that make sure when you press help->about it says jun 8 2013 10:10:19
Here is the binary.
https://github.com/ComputerNerd/Retro-G ... kit.exe.7z

Ti_
Very interested
Posts: 97
Joined: Tue Aug 30, 2011 7:50 am
Contact:

Post by Ti_ » Sat Jun 08, 2013 3:31 pm

r57shell wrote:Haha! I have found among the best way for me :)
1) img.png scolorq filter size 3 = out1.png
2) out1.png -remap genesis_colormap.png = out2.png
3) img.png -remap out2.png = out.png
See out2 and out.png in previous post, I added as "scolorq, scolorq trick"
Needs only to reduce dither.
last image good, but if you scale and see there's too many rose dots everywhere.

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Post by r57shell » Sat Jun 08, 2013 3:45 pm

sega16 wrote:Also it uses Dennis lee v3 quantization
Requests:
1) Make all calculations in YCbCr (YUV).
2) Implement NeuQuant quantization.
Here some interesting tests: http://bisqwit.iki.fi/jutut/colorquant/
Image

Ti_
Very interested
Posts: 97
Joined: Tue Aug 30, 2011 7:50 am
Contact:

Post by Ti_ » Sat Jun 08, 2013 3:47 pm

sega16 wrote: Also it uses Dennis lee v3 quantization
I updated the windows binary if you are using that make sure when you press help->about it says jun 8 2013 10:10:19
That not care what is version of code, current or old.
They both for 16 colors.
(yes, in new you can specify color count, but part of them will be duplicated in 2nd row) - because it for 1-layered image.)

But I am asking about program that uses same algorithm which reduce to color count, but not limited by column lenght=16 (Png to Png), that's why I post older version of code.

r57shell wrote: Here some interesting tests: http://bisqwit.iki.fi/jutut/colorquant/
I think scolorq with minumum dithering is best. :D

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Post by r57shell » Sat Jun 08, 2013 4:12 pm

Ti_ wrote:I think scolorq with minumum dithering is best. :D
Sadly, but windows version does not support dither setting.
Image

Ti_
Very interested
Posts: 97
Joined: Tue Aug 30, 2011 7:50 am
Contact:

Post by Ti_ » Sat Jun 08, 2013 4:25 pm

r57shell wrote:
Ti_ wrote:I think scolorq with minumum dithering is best. :D
Sadly, but windows version does not support dither setting.
windows version? I've found only plugin exist.
Okay I used this plugin with xnview, but the problem is not in dithering (just uncheck error dithering): you can't set what colors count you want: you set 9 bit color, and after tries to change color quanity - and bits changed too! So you can't specify bits and color quanity separetaly - I don't know what trick you do, and how to do same in plugin.

Post Reply