Exemplo n.º 1
0
uint16_t palette::to_sega_genesis_colorRGB(uint8_t r,uint8_t g,uint8_t b,uint16_t pal_index){
	//note this function only set the new rgb colors not the outputted sega genesis palette format
	pal_index*=3;
	r=nearest_color_index(r,0);
	g=nearest_color_index(g,0);
	b=nearest_color_index(b,0);
	rgbPal[pal_index]=palTab[r];
	rgbPal[pal_index+1]=palTab[g];
	rgbPal[pal_index+2]=palTab[b];
	//bgr format
	return (r<<1)|(g<<5)|(b<<9);
}
Exemplo n.º 2
0
uint16_t palette::to_sega_genesis_color(uint16_t pal_index){
	//note this function only set the new rgb colors not the outputted sega genesis palette format
	pal_index*=3;
	uint8_t r,g,b;
	r=nearest_color_index(rgbPal[pal_index]);
	g=nearest_color_index(rgbPal[pal_index+1]);
	b=nearest_color_index(rgbPal[pal_index+2]);
	rgbPal[pal_index]=palTab[r];
	rgbPal[pal_index+1]=palTab[g];
	rgbPal[pal_index+2]=palTab[b];
	//bgr format
	return ((r-palTypeGen)<<1)|((g-palTypeGen)<<5)|((b-palTypeGen)<<9);
}
Exemplo n.º 3
0
static void reduceImage(uint8_t * image,uint8_t * found_colors,int row,unsigned offsetPal,Fl_Progress *progress,Fl_Window*pwin,unsigned maxCol,unsigned yuv,unsigned alg,bool isSprite=false,bool ditherBefore=true){
	if(progress)
		progress->maximum(1.0);
	unsigned off2=offsetPal*2;
	unsigned off3=offsetPal*3;
	unsigned colors_found;
	unsigned w,h;
	unsigned maxPal=maxCol;
	unsigned msprt=curSpritemeta;
	if(isSprite){
		w=currentProject->ms->sps[msprt].width(curSpritegroup);
		h=currentProject->ms->sps[msprt].height(curSpritegroup);
		currentProject->ms->sps[msprt].spriteGroupToImage(image,curSpritegroup,row,false);
	}else{
		w=currentProject->tms->maps[currentProject->curPlane].mapSizeW;
		h=currentProject->tms->maps[currentProject->curPlane].mapSizeHA;
		w*=currentProject->tileC->sizew;
		h*=currentProject->tileC->sizeh;
		currentProject->tms->maps[currentProject->curPlane].truecolor_to_image(image,row,false);
	}
	if(progress){
		progress->label("Dithering to colorspace");
		Fl::check();
	}
	if((!yuv)&&ditherBefore)
		ditherImage(image,w,h,false,true);
	if(progress){
		progress->label("Quantizing image");
		Fl::check();
	}
	colors_found=count_colors(image,w,h,&found_colors[0],false);
	printf("Unique colors %d\n",colors_found);
	if (colors_found <= maxCol){
		printf("%d colors\n",colors_found);
		unsigned offsetTmp=offsetPal;
		for (unsigned x=0;x<colors_found;x++){
			uint_fast8_t r,g,b;
againFun:
			if (currentProject->pal->palType[offsetTmp]){
				++offsetTmp;
				if(offsetTmp>=maxPal)
					goto actullyNeededReduction;
				goto againFun;
			}
			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);
			if(currentProject->pal->shouldAddCol(offsetTmp,r,g,b,isSprite)){
				currentProject->pal->rgbToEntry(r,g,b,offsetTmp);
				currentProject->pal->updateRGBindex(offsetTmp);
				++offsetTmp;
			}
		}
		if(currentProject->gameSystem==NES)
			updateEmphesis();
		if(window)
			window->redraw();
	}else{
actullyNeededReduction:
		printf("More than %d colors reducing to %d colors\n",maxCol,maxCol);
		uint8_t user_pal[3][256];			
		uint8_t rgb_pal2[768];
		uint8_t rgb_pal3[768];
		unsigned colorz=maxCol;
		bool can_go_again=true;
		uint8_t*imageuse;
		uint8_t*output;
		if(alg==1)
			output=(uint8_t*)malloc(w*h*3);
		if(yuv){
			imageuse=(uint8_t*)malloc(w*h*3);
			uint32_t x,y;
			uint8_t*imageptr=image;
			uint8_t*outptr=imageuse;
			for(y=0;y<h;y++){
				for(x=0;x<w;x++){
					if(yuv==2){
						outptr[0]=CRGB2Y(imageptr[0],imageptr[1],imageptr[2]);
						outptr[1]=CRGB2Cb(imageptr[0],imageptr[1],imageptr[2]);
						outptr[2]=CRGB2Cr(imageptr[0],imageptr[1],imageptr[2]);
					}else{
						outptr[0]=RGB2Y(imageptr[0],imageptr[1],imageptr[2]);
						outptr[1]=RGB2U(imageptr[0],imageptr[1],imageptr[2]);
						outptr[2]=RGB2V(imageptr[0],imageptr[1],imageptr[2]);
					}
					imageptr+=3;
					outptr+=3;
				}
			}
		}else
			imageuse=image;
try_again_color:
		switch(alg){
			case 4:
				dl1quant(imageuse,w,h,colorz,user_pal);
			break;
			case 3:
				wu_quant(imageuse,w,h,colorz,user_pal);
			break;
			case 2:
				NEU_wrapper(w,h,imageuse,colorz,user_pal);
			break;
			case 1:
				scolorq_wrapper(imageuse,output,user_pal,w,h,colorz);
			break;
			default:
				dl3quant(imageuse,w,h,colorz,user_pal,true,progress);/*this uses denesis lee's v3 color quant which is found at http://www.gnu-darwin.org/www001/ports-1.5a-CURRENT/graphics/mtpaint/work/mtpaint-3.11/src/quantizer.c*/
		}
		for (unsigned x=0;x<colorz;x++){
			unsigned r,g,b;
			if(yuv){
				if(yuv==2){
					r=CYCbCr2R(user_pal[0][x],user_pal[1][x],user_pal[2][x]);
					g=CYCbCr2G(user_pal[0][x],user_pal[1][x],user_pal[2][x]);
					b=CYCbCr2B(user_pal[0][x],user_pal[1][x],user_pal[2][x]);
				}else{
					r=YUV2R(user_pal[0][x],user_pal[1][x],user_pal[2][x]);
					g=YUV2G(user_pal[0][x],user_pal[1][x],user_pal[2][x]);
					b=YUV2B(user_pal[0][x],user_pal[1][x],user_pal[2][x]);
				}
			}else{
				r=user_pal[0][x];
				g=user_pal[1][x];
				b=user_pal[2][x];
			}
			switch(currentProject->gameSystem){
				case segaGenesis:
					r=nearest_color_index(r);
					g=nearest_color_index(g);
					b=nearest_color_index(b);
					rgb_pal2[(x*3)]=palTab[r];
					rgb_pal2[(x*3)+1]=palTab[g];
					rgb_pal2[(x*3)+2]=palTab[b];
				break;
				case NES:
					{uint8_t temp=currentProject->pal->to_nes_color_rgb(r,g,b);
					uint32_t temp_rgb = nesPalToRgb(temp);
					rgb_pal2[(x*3)]=(temp_rgb>>16)&255;
					rgb_pal2[(x*3)+1]=(temp_rgb>>8)&255;
					rgb_pal2[(x*3)+2]=temp_rgb&255;}
				break;
				case masterSystem:
				case gameGear:
					{const uint8_t*palUseTab=currentProject->gameSystem==gameGear?palTabGameGear:palTabMasterSystem;
					unsigned colsTab=currentProject->gameSystem==gameGear?16:4;
					r=nearestOneChannel(r,palUseTab,colsTab);
					g=nearestOneChannel(g,palUseTab,colsTab);
					b=nearestOneChannel(b,palUseTab,colsTab);
					rgb_pal2[(x*3)]=palUseTab[r];
					rgb_pal2[(x*3)+1]=palUseTab[g];
					rgb_pal2[(x*3)+2]=palUseTab[b];}
				break;
				default:
					show_default_error
			}
		}
		unsigned new_colors = count_colors(rgb_pal2,colorz,1,rgb_pal3);
		printf("Unique colors in palette %u\n",new_colors);
			if (new_colors < maxCol){
				if (can_go_again == true){
					if (colorz != 512)
						colorz++;
					else
						can_go_again=false;
					char tmp[1024];
					snprintf(tmp,1024,"Found only %d colors trying again with %d",new_colors,colorz);
					tmp[sizeof(tmp)-1]=0;
					if(pwin){
						pwin->copy_label(tmp);
						Fl::check();
					}
					puts(tmp);
					goto try_again_color;
				}
			}
		if (new_colors > maxCol){
			can_go_again=false;
			if(pwin)
				pwin->label("Too many colors");
			colorz--;
			goto try_again_color;
		}
		unsigned offsetTmp=offsetPal;
		for (unsigned x=0;x<maxCol;x++){
againNerd:
			if (currentProject->pal->palType[offsetTmp]){
				++offsetTmp;
				if(offsetTmp>(maxPal+offsetPal)){
					if(maxCol>1){
						--colorz;
						printf("Needed to reduce colors generated due to locked colors %u\n",maxCol);
					}else{
						fl_alert("Cannot reduce maximum colors to make this happen...aborting");
						return;	
					}
					goto try_again_color;
				}
				goto againNerd;
			}
			unsigned r=rgb_pal3[x*3],g=rgb_pal3[x*3+1],b=rgb_pal3[x*3+2];
			if(currentProject->pal->shouldAddCol(offsetTmp,r,g,b,isSprite)){
				memcpy(currentProject->pal->rgbPal+(offsetTmp*3),rgb_pal3+(x*3),3);
				currentProject->pal->rgbToEntry(r,g,b,offsetTmp);
				++offsetTmp;
			}
		}
		if(currentProject->gameSystem==NES)
			updateEmphesis();
		if(alg==1){
			if(isSprite)
				currentProject->ms->sps[msprt].spriteImageToTiles(output,curSpritegroup,row,false);
			else
				currentProject->tms->maps[currentProject->curPlane].truecolorimageToTiles(output,row,false);
			free(output);
		}
		if(yuv)
			free(imageuse);
	}
}