Beispiel #1
0
void generate_optimal_paletteapply(Fl_Widget*,void*s){
	struct settings*set=(struct settings*)s;
	uint8_t * image;
	uint32_t w,h;
	if(set->sprite){
		unsigned msprt=curSpritemeta;
		w=currentProject->ms->sps[msprt].width(curSpritegroup);
		h=currentProject->ms->sps[msprt].height(curSpritegroup);
	}else{
		w=currentProject->tms->maps[currentProject->curPlane].mapSizeW;
		h=currentProject->tms->maps[currentProject->curPlane].mapSizeHA;
		w*=currentProject->tileC->sizew;
		h*=currentProject->tileC->sizeh;
	}

	unsigned maxRows,firstRow;
	int spRow=currentProject->fixedSpirtePalRow();
	if(spRow>=0&&set->sprite){
		maxRows=spRow+1;
		firstRow=spRow;
		if(!set->useRow[firstRow]){
			fl_alert("No rows specified");
			return;
		}
	}else{
		maxRows=currentProject->pal->getMaxRows(set->sprite);
		for(firstRow=0;(firstRow<maxRows)&&(!set->useRow[firstRow]);++firstRow);
		if(firstRow>=maxRows){
			fl_alert("No rows specified");
			return;
		}
	}
	unsigned rows=0;
	for(unsigned i=firstRow;i<maxRows;++i){
		if(set->useRow[i])
			++rows;
	}
	printf("First row: %u\n",firstRow);
	uint8_t found_colors[768];
	int rowAuto;
	if((rows==1)&&(!set->sprite))
		rowAuto = set->rowAuto;
	else if(!set->sprite){
		rowAuto = set->rowAuto;
		if(rowAuto<0)
			return;
	}else{
		puts("rowAuto forced to zero");
		rowAuto=0;
	}
	pushPaletteAll();//Save the old palette
	Fl_Window *win=0;
	Fl_Progress *progress=0;
	mkProgress(&win,&progress);
	image = (uint8_t *)malloc(w*h*3);
	if (rows==1){
		if (rowAuto)
			currentProject->tms->maps[currentProject->curPlane].allRowSet(firstRow);
		if(set->sprite){
			unsigned off=set->off[firstRow]+(firstRow*currentProject->pal->perRow);
			if(currentProject->gameSystem==NES)
				off+=16;
			reduceImage(image,found_colors,-1,off,progress,win,set->perRow[firstRow],set->colSpace,set->alg,true);
		}else
			reduceImage(image,found_colors,-1,firstRow*currentProject->pal->perRow+set->off[firstRow],progress,win,set->perRow[firstRow],set->colSpace,set->alg);
		if(window){
			window->damage(FL_DAMAGE_USER1);
			Fl::check();
		}
	}else{
		if(rowAuto==2){
			unsigned coltarget=0;
			for(unsigned i=0;i<currentProject->pal->getMaxRows(set->sprite);++i)
				coltarget+=set->perRow[i];	
			reduceImage(image,found_colors,-1,0,progress,win,coltarget,set->colSpace,set->alg);
			currentProject->tms->maps[currentProject->curPlane].pickRowDelta(true,progress,set->rowAutoEx[0],set->rowAutoEx[1]);
			if(window){
				window->damage(FL_DAMAGE_USER1);
				Fl::check();
			}
		}else{
			if (rowAuto==1)
				currentProject->tms->maps[currentProject->curPlane].pickRow(maxRows-firstRow,set->rowAutoEx[0],set->rowAutoEx[1]);
			else if(rowAuto==3)
				currentProject->tms->maps[currentProject->curPlane].pickTileRowQuantChoice(maxRows-firstRow);
			for (unsigned i=firstRow;i<maxRows;++i){
				if(set->useRow[i]){
					reduceImage(image,found_colors,i,(i*currentProject->pal->perRow)+set->off[i],progress,win,set->perRow[i],set->colSpace,set->alg);
					if(window){
						window->damage(FL_DAMAGE_USER1);
						Fl::check();
					}
				}
			}
		}
	}
	free(image);
	if(progress){
		win->remove(progress);// remove progress bar from window
		delete(progress);// deallocate it
	}
	if(win)
		delete win;
	palBar.updateSliders();
	if(set->ditherAfter){
		if(set->sprite){
			ditherSpriteAsImage(window->metaspritesel->value(),curSpritegroup);
		}else{
			pushTilesAll(tTypeTile);
			currentProject->tms->maps[currentProject->curPlane].ditherAsImage(set->entireRow);
		}
	}
	if(window){
		window->redraw();
		Fl::check();
	}
}
Beispiel #2
0
void sprites::importSpriteSheet(const char*fname){
	if(!fname){
		if(!load_file_generic("Load image"))
			return;
		fname=the_file.c_str();
	}
	if(fname){
		Fl_Shared_Image * loaded_image=Fl_Shared_Image::get(fname);
		if(!loaded_image){
			fl_alert("Error loading image");
			return;
		}
		unsigned depth=loaded_image->d();
		if (unlikely(depth != 3 && depth != 4 && depth!=1)){
			fl_alert("Please use color depth of 1,3 or 4\nYou Used %d",depth);
			loaded_image->release();
			return;
		}else
			printf("Image depth %d\n",depth);
		uint32_t w,h;
		w=loaded_image->w();
		h=loaded_image->h();
		bool grayscale;
		uint8_t*palMap;
		uint8_t*imgptr;
		unsigned remap[256];
		if(depth==1){
			grayscale=handle1byteImg(loaded_image,remap);
			if(!grayscale){
				palMap=(uint8_t*)loaded_image->data()[1];
				imgptr=(uint8_t*)loaded_image->data()[2];
			}
		}
		uint8_t mask[3];
		bool useAlpha;
		if(getMaskColorImg(loaded_image,grayscale,remap,palMap,mask,useAlpha)){
			std::vector<int> rects;//x0,x1,y0,y1
			Fl_Window *winP;
			Fl_Progress *progress;
			mkProgress(&winP,&progress);
			time_t lasttime=time(NULL);
			progress->maximum(h);
			Fl::check();
			for(int y=0;y<h;++y){
				for(int x=0;x<w;++x){
					if(!isMask(x,y,loaded_image,grayscale,useAlpha,mask)){
						rects.push_back(x);
						while(!isMask(x+1,y,loaded_image,grayscale,useAlpha,mask))
							++x;
						rects.push_back(x);
						rects.push_back(y);
						rects.push_back(y);
					}
				}
				if((time(NULL)-lasttime)>=1){
					lasttime=time(NULL);
					progress->value(h);
					Fl::check();
				}
			}
			progress->maximum(rects.size());
			progress->value(0);
			//Now combine the rectangles
			//Start by combining rectangles by that touch with y values
			bool canEnd;
			int pass=0;
			char txtbufstage[1024];
			char txtbuf[1024];
			do{
			canEnd=true;
			snprintf(txtbufstage,1024,"Stage 1 pass %d",pass++);
			winP->label(txtbufstage);
			Fl::check();
			for(int i=0;i<rects.size();i+=4){
				for(int j=0;j<rects.size();j+=4){
					if(i==j)
						continue;
					//See if rectangles are touching or overlap
					//if((inRange(rects[j+2],rects[i+2]-1,rects[i+3]+1)||inRange(rects[i+2],rects[j+2]-1,rects[j+3]+1))&&(!((rects[i+2]==rects[j+2])||(rects[i+3]==rects[j+3])))){//Is rectange j directly above or below i
					if((rects[j+3]-rects[i+2])==1){
						if((inRange(rects[j],rects[i]-1,rects[i+1]+1)||inRange(rects[i],rects[j]-1,rects[j+1]+1))){
							canEnd=false;
							//Merge the two squares obtaining maximum size
							//Now try and find the combination that results in the largest rectangle
							rects[i]=std::min(rects[i],rects[j]);
							rects[i+1]=std::max(rects[i+1],rects[j+1]);
							rects[i+2]=std::min(rects[i+2],rects[j+2]);
							rects[i+3]=std::max(rects[i+3],rects[j+3]);
							rects.erase(rects.begin()+j,rects.begin()+j+4);
							//Now try to find next in sequence
							bool foundit;
							do{
								foundit=false;
								for(int a=0;a<rects.size();a+=4){
									int look=rects[i+3]+1;
									if(rects[a+2]==look){
										if((inRange(rects[a],rects[i]-1,rects[i+1]+1)||inRange(rects[i],rects[a]-1,rects[a+1]+1))){
											foundit=true;
											rects[i]=std::min(rects[i],rects[a]);
											rects[i+1]=std::max(rects[i+1],rects[a+1]);
											rects[i+2]=std::min(rects[i+2],rects[a+2]);
											rects[i+3]=std::max(rects[i+3],rects[a+3]);
											rects.erase(rects.begin()+a,rects.begin()+a+4);
										}
									}
								}
							}while(foundit);
						}
					}
				}
				if((time(NULL)-lasttime)>=1){
					lasttime=time(NULL);
					progress->maximum(rects.size());
					progress->value(i);
					snprintf(txtbuf,1024,"Rectangles: %d",rects.size());
					progress->label(txtbuf);
					Fl::check();
				}
			}
			}while(!canEnd);
			pass=0;
			do{
				canEnd=true;
				snprintf(txtbufstage,1024,"Stage 2 pass %d",pass++);
				winP->label(txtbufstage);
				progress->maximum(rects.size());
				progress->value(0);
				Fl::check();
				for(int i=0;i<rects.size();i+=4){
					for(int j=0;j<rects.size();j+=4){
						if(i==j)
							continue;
						//Merge overlapping rectangles
						if((rects[i]<=rects[j+1])&&(rects[i+1]>=rects[j])&&(rects[i+2]<=rects[j+3])&&(rects[i+3]>=rects[j+2])){
							canEnd=false;
							rects[i]=std::min(rects[i],rects[j]);
							rects[i+1]=std::max(rects[i+1],rects[j+1]);
							rects[i+2]=std::min(rects[i+2],rects[j+2]);
							rects[i+3]=std::max(rects[i+3],rects[j+3]);
							rects.erase(rects.begin()+j,rects.begin()+j+4);
						}
						//Merge touching rectangles
						if(abs(rects[i+1]-rects[j])==1){
							if((inRange(rects[j+2],rects[i+2]-1,rects[i+3]+1)||inRange(rects[i+2],rects[j+2]-1,rects[j+3]+1))){
								canEnd=false;
								rects[i]=std::min(rects[i],rects[j]);
								rects[i+1]=std::max(rects[i+1],rects[j+1]);
								rects[i+2]=std::min(rects[i+2],rects[j+2]);
								rects[i+3]=std::max(rects[i+3],rects[j+3]);
								rects.erase(rects.begin()+j,rects.begin()+j+4);
							}
						}
					}
					if((time(NULL)-lasttime)>=1){
						lasttime=time(NULL);
						progress->maximum(rects.size());
						progress->value(i);
						snprintf(txtbuf,1024,"Rectangles: %d",rects.size());
						progress->label(txtbuf);
						Fl::check();
					}
				}
			}while(!canEnd);
			winP->remove(progress);// remove progress bar from window
			delete(progress);// deallocate it
			delete winP;
			std::vector<bool> deleted;
			deleted.resize(rects.size()/4);
			//Now show the window allowing user to adjust sprite settings
			if(window){
				win=new Fl_Double_Window(640,480,"Sprite selection");
				win->begin();
				win->resizable(win);
				Fl_Button * Ok=new Fl_Button(256,448,64,24,"Okay");
				Ok->callback(RetCB,(void*)1);
				Fl_Button * Cancel=new Fl_Button(320,448,64,24,"Cancel");
				Cancel->callback(RetCB,0);
				Fl_Scroll*scroll=new Fl_Scroll(8,8,624,440);
				box=new RectBox(8,8,w,h);
				box->scroll=scroll;
				box->rects=&rects;
				box->deleted=&deleted;
				box->image(loaded_image);
				scroll->end();
				win->end();
				win->set_modal();
				win->show();
				Fl::check();

				while(win->shown())
					Fl::wait();
				delete win;
			}else
				retOkay=true;
			if(retOkay){
				for(unsigned i=0;i<rects.size();i+=4){
					recttoSprite(rects[i],rects[i+1],rects[i+2],rects[i+3],-1,loaded_image,grayscale,remap,palMap,mask,true,useAlpha);
				}
				updateTileSelectAmt();
			}
			deleted.clear();
			rects.clear();
		}
		loaded_image->release();
	}
}