Beispiel #1
0
/*!	\param hdc	Destination DC.
*	\param rectDest	Destination rectangle. If NULL, the DIB's 
*	  dimensions are used.
*	\param dib	DIB to blit.
*	\param rectSrc	Source rectangle. If NULL, the DIB's 
*	  dimensions is used.
*	\param flags	Blit flags.
*	\note	Tested for top-down and bottom-up DIB's
*/
int dib_to_hdc(HDC hdc, const RECT *rectDst, 
			CLDIB *dib, const RECT *rectSrc, DWORD flags)
{
	RECT dstR, srcR;
	int dibHa= dib_get_height(dib);

	if(rectDst == NULL)
		SetRect(&dstR, 0, 0, dib_get_width(dib), dibHa);
	else
		CopyRect(&dstR, rectDst);

	if(rectSrc == NULL)
		SetRect(&srcR, 0, 0, dib_get_width(dib), dibHa);
	else
		CopyRect(&srcR, rectSrc);

	int srcW= srcR.right-srcR.left, srcH= srcR.bottom-srcR.top;
	int dstW= dstR.right-dstR.left, dstH= dstR.bottom-dstR.top;

	SetStretchBltMode(hdc, COLORONCOLOR);
	return StretchDIBits( hdc, 
		dstR.left, dstR.bottom, dstW, -dstH, 
		srcR.left, dibHa-srcR.top, srcW, -srcH, 
		dib_get_img(dib), dib_get_info(dib), 
		DIB_RGB_COLORS, flags);	
}
Beispiel #2
0
BOOL CxpGbaDlg::OnInitDialog() 
{
	ASSERT(mpDib);
	
	int nclrs= dib_get_nclrs(mpDib);
	if(nclrs > 0 && mPalStart+mPalCount>nclrs)
	{
		mPalStart= 0;
		mPalCount= nclrs;
	}
	if(moAreaSize != 0)
	{
		mAreaLeft= 0;	mAreaWidth= dib_get_width(mpDib);
		mAreaTop=0;		mAreaHeight= dib_get_height(mpDib);
	}
	if(mbSymChk == FALSE)
		mSymName= mDstTitle;

	CDialog::OnInitDialog();
	OnPalChk();
	OnGfxChk();
	OnMapChk();
	UpdateObj();
	UpdateMap();
	UpdateArea();

	GetDlgItem(IDC_VAR_NAME)->EnableWindow(mbSymChk);

	//UpdateSummary();

	return TRUE;
}
Beispiel #3
0
//! Initialize palette and gfx-related functions from the DIB.
bool grit_init_from_dib(GritRec *gr)
{
	if(gr == NULL)
		return false;

	CLDIB *dib= gr->srcDib;
	if(dib == NULL)
	{
		lprintf(LOG_ERROR, "No bitmap to initialize GritRec from.\n");
		return false;
	}

 	int nclrs = dib_get_nclrs(dib);
	gr->palEnd= ( nclrs ? nclrs : 256 );

	if(dib_get_bpp(dib) > 8)
		gr->gfxBpp= 16;
	else
		gr->gfxBpp= dib_get_bpp(dib);

	gr->areaRight= dib_get_width(dib);
	gr->areaBottom=dib_get_height(dib);

	return true;
}
Beispiel #4
0
/*!
	\param dib		Bitmap to retile.
	\param dstW		Destination width (= tile width).
	\param tileH	Tile height.
	\param tileN	Number of tiles.
	\notes	If dstW<srcW, it will convert from matrix to array; 
			if dstW>srcW, the transformation is from array to matrix.
*/
bool dib_redim(CLDIB *dib, int dstW, int tileH, int tileN)
{
	// Nothing to do
	if(dib && dib_get_width(dib)==dstW)
		return true;

	CLDIB *tmp= dib_redim_copy(dib, dstW, tileH, tileN);
	return dib_mov(dib, tmp);
}
Beispiel #5
0
// TGA RLE;
// * lines are byte-aligned
// * RLE can cross lines
// * RLE works by the pixel for true clr, by byte for paletted
// * The RLE header byte, ch:
//   ch{0-6} : # chunks -1
//   ch{7}   : stretch.
void tga_unrle(CLDIB *dib, TGAHDR *hdr, FILE *fp)
{
	int ii, ix, iy;
	int imgW= dib_get_width(dib);
	int imgH= dib_get_height(dib);
	int imgB= dib_get_bpp(dib);
	int imgP= dib_get_pitch(dib);
	BYTE *imgL= dib_get_img(dib), *imgEnd= imgL+imgH*imgP;

	int tgaP= (imgW*imgB+7)/8;	// pseudo pitch
	int tgaN= (imgB+7)/8;		// chunk size
	BYTE ch, chunk[4];

	ix=0, iy=0;
	while(1)
	{
		ch= fgetc(fp);
		if(ch>127)			// stretch
		{
			ch -= 127;
			fread(chunk, 1, tgaN, fp);
			while(ch--)
			{
				for(ii=0; ii<tgaN; ii++)
					imgL[ix+ii]= chunk[ii];
				ix += tgaN;

				if(ix >= tgaP)
				{
					imgL += imgP;
					ix= 0;
					if(imgL >= imgEnd)
						return;
				}
			}
		} // </stretch>
		else				// no stretch
		{
			ch++;
			while(ch--)
			{
				fread(&imgL[ix], 1, tgaN, fp);
				ix += tgaN;
				if(ix >= tgaP)
				{
					imgL += imgP;
					ix= 0;
					if(imgL >= imgEnd)
						return;
				}
			}
		} // </no stretch>
	} // </while(1)>
}
Beispiel #6
0
/*!	This only runs for tiled images and can have up to three
	stages. First, Rearrange into screen-blocks (option -mLs); then
	into metatiles (-Mw, -Mh), then base-tiles.
*/
bool grit_prep_tiles(GritRec *gr)
{
    lprintf(LOG_STATUS, "Tile preparation.\n");

    // Main sizes
    int imgW= dib_get_width(gr->_dib), imgH= dib_get_height(gr->_dib);
    int tileW= gr->tileWidth, tileH= gr->tileHeight;
    int metaW= gr->metaWidth, metaH= gr->metaHeight;

    // Tiling sizes for stages
    int frameW=tileW*metaW, frameH=tileH*metaH;		// For meta tiling

    bool bMeta= gr->isMetaTiled();
    bool bTile= tileW*tileH > 1;

    // Change things for column-major ordering
    if(gr->bColMajor)
    {
        int lastH= imgH, tmp;
        if(bMeta)	SWAP3(frameH, lastH, tmp);
        if(bTile)	SWAP3(tileH, lastH, tmp);
    }

    // Meta redim
    if(bMeta)
    {
        lprintf(LOG_STATUS, "  tiling to %dx%d tiles.\n", frameW, frameH);
        if(!dib_redim(gr->_dib, frameW, frameH, 0))
        {
            lprintf(LOG_ERROR, "  meta-tiling failed.\n");
            return false;
        }
    }

    // Tile redim
    if(bTile)
    {
        lprintf(LOG_STATUS, "  tiling to %dx%d tiles.\n", tileW, tileH);

        if(!dib_redim(gr->_dib, tileW, tileH, 0))
        {
            lprintf(LOG_ERROR, "  tiling failed.\n");
            return false;
        }
    }

    lprintf(LOG_STATUS, "Tile preparation complete.\n");
    return true;
}
Beispiel #7
0
//! Get the main attributes of a DIB
bool dib_get_attr(CLDIB *dib, int *width, int *height, int *bpp, int *pitch)
{
	if(dib == NULL)
		return false;

	if(width)
		*width= dib_get_width(dib);
	if(height)
		*height= dib_get_height(dib);
	if(bpp)
		*bpp= dib_get_bpp(dib);
	if(pitch)
		*pitch= dib_get_pitch(dib);
	return true;
}
Beispiel #8
0
void CWingritView::OnDraw(CDC* pdc)
{
	CWingritDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);

	CLDIB *dib= pDoc->GetDib();

	if(dib != NULL)
	{
		int ww= dib_get_width(dib), hh= dib_get_height(dib);
		dib_blit(pdc->GetSafeHdc(), 
			mptOrg.x, mptOrg.y, mZoom*ww>>8, mZoom*hh>>8, 
			dib, 
			0, 0, ww, hh, 
			SRCCOPY);
	}
Beispiel #9
0
/*! Similar to \c dib_clone, but can crop the image too. The 
*	boundaries of the new bitmap need not fit inside the source; the 
*	outside parts will be zeroed.
*	\param src Source bitmap.
*	\param ll Left of rectangle.
*	\param tt Top of rectangle.
*	\param rr Right of rectangle.
*	\param bb Bottom of rectangle.
*	\param bClip If \c true, the rectangle will be clipped to the 
*	  dimensions of \c src.
*	\return Copied and cropped bitmap.	
*/
CLDIB *dib_copy(CLDIB *src, int ll, int tt, int rr, int bb, bool bClip)
{
	if(src==NULL || ll==rr || tt==bb)
		return NULL;

	int srcW= dib_get_width(src);
	int srcH= dib_get_height(src);
	int srcB= dib_get_bpp(src);
	int srcP= dib_get_pitch(src);

	// Normalize rect
	if(rr<ll)
	{	int tmp=ll; ll=rr; rr=tmp;	}
	if(bb<tt)
	{	int tmp=tt; tt=bb; bb=tmp;	}

	// Clip if requested
	if(bClip)
	{
		if(ll<0)	ll= 0;
		if(tt<0)	tt= 0;
		if(rr>srcW)	rr= srcW;
		if(bb>srcH) bb= srcH; 
	}

	int dstW= rr-ll, dstH= bb-tt;
	CLDIB *dst= dib_alloc(dstW, dstH, srcB, NULL, true);
	if(dst==NULL)
		return NULL;
	
	dib_pal_cpy(dst, src);

	// set base src,dst pointers
	int dstP= dib_get_pitch(dst);
	BYTE *srcL= dib_get_img(src), *dstL= dib_get_img(dst);

	if(ll>=0)	// set horz base
		srcL += ll*srcB>>3;
	else
Beispiel #10
0
void CxpGbaDlg::OnOK() 
{
	CString logpath;
	
	GetRootDir(logpath);
	logpath += "\\gxplog.txt";


	FILE *fp= fopen(logpath, "w");
	if(fp)
		log_init(LOG_STATUS, fp);

	if(Validate() == FALSE)
	{
		if(fp)
		{
			log_exit();
			fclose(fp);
		}		
		return;
	}

	GritShared *grs= mgr->shared;

	// Read external tileset if required
	// PONDER: move inside grit_run?
	if(mgr->gfxIsShared)
	{
		// read file
		grs->dib= dib_load(grs->tilePath, NULL);

		if(grs->dib)
		{
			if( dib_get_bpp(grs->dib) != 8 )
			{
				lprintf(LOG_WARNING, "  External tileset must be 8bpp. Converting.\n");
				dib_convert(grs->dib, 8, 0);
			}

			if( dib_get_width(grs->dib) != 8 )
			{
				lprintf(LOG_WARNING, "  External tileset not tiled yet. Doing so now.\n");
				dib_redim(grs->dib, 8, 8, 0);
			}
		}
		else
			lprintf(LOG_WARNING, "  Couldn't load external tileset from \n    %s.\n", 
				grs->tilePath);

		// PONDER: reduce here too?
	}

	int res= grit_run(mgr);

	// Save external tileset if required
	// PONDER: move inside grit_run?
	if(mgr->gfxIsShared)
	{
		if( !dib_save(grs->dib, grs->tilePath, NULL) )
			lprintf(LOG_WARNING, "  Couldn't save external tileset to \n    %s.\n", 
				grs->tilePath);
	}


	if(fp)
	{
		log_exit();
		fclose(fp);
	}

	if(res == TRUE)
	{
		// PONDER: ask to see log?
		res= MessageBox("Export succeeded. Show log?", NULL, 
			MB_ICONINFORMATION | MB_YESNO | MB_DEFBUTTON2);	
		if(res == IDYES)
		{
			CLogDlg dlg;
			dlg.SetTextFromFile(logpath);
			dlg.DoModal();
		}
		CDialog::OnOK();
	}
	else
	{
		// PONDER: ask to see log?
		res= MessageBox("Export failed. Show Log?", NULL, 
			MB_ICONEXCLAMATION | MB_YESNO);	
		if(res == IDYES)
		{
			CLogDlg dlg;
			dlg.SetTextFromFile(logpath);
			dlg.DoModal();
		}	
	}
}
Beispiel #11
0
BOOL CxpGbaDlg::UpdateGritRec(BOOL b2gr)
{
	DWORD dw;
	char str[MAXPATHLEN];

	// TODO: al/gfx trans ; img modes ; tileset

	if(b2gr)	// data -> gr
	{
		UpdateData(TRUE);

		SetDstPath(mDstPath);

		// clear previous gr data
		grit_clear(mgr);
		grs_clear(mgr->shared);

		mgr->bExport= true;

		// Yes, yes, very wasteful
		mgr->srcDib= dib_clone(mpDib);

		mgr->bHeader= mbHeader==TRUE;
		mgr->bAppend= mbAppend==TRUE;
		mgr->fileType= mFileType;

		// TODO check whether this is all OK!!
		if(mbSymChk)
			mgr->symName= strdup(mSymName);
		else
			mgr->symName= strdup(mDstTitle);

		// make sure it's a valid C varname
		str_fix_ident(mgr->symName, mgr->symName, 
			strlen(mgr->symName));

		sprintf(str, "%s/%s.%s", mDstDir, mDstTitle, c_fileTypes[mFileType]);
		mgr->dstPath= strdup(str);

		// --- palette ---
		if(mbPal)
		{
			mgr->palProcMode= GRIT_EXPORT;

			mgr->palStart= mPalStart;
			mgr->palEnd= mPalStart+mPalCount;
			if(mgr->palEnd > 256)
				mgr->palEnd= 256;

			if(mPalTrans != 0)
			{
				mgr->palHasAlpha= true;
				mgr->palAlphaId= mPalTrans;
			}
		}

		// --- image ---
		// NOTE: we should probably always process the image, 
		//   just not necessarily export
		if(1)
		{
			if(mbGfx)
				mgr->gfxProcMode= GRIT_EXPORT;

			switch(mGfxMode)
			{
			case GFX_MODE_TILE:
				mgr->gfxMode= GRIT_GFX_TILE;
				break;
			case GFX_MODE_BMP:
				mgr->gfxMode= GRIT_GFX_BMP;
				break;
			case GFX_MODE_BMP_A:
				mgr->gfxMode= GRIT_GFX_BMP_A;
				break;
			case GFX_MODE_BMP_T:
				mgr->gfxMode= GRIT_GFX_BMP;

				// Empty color && non-zero pal-trans -> use pal-trans
				// Empty color otherwise: use FF00FF
				// non-empty: use non-empty
				dw= strlen(mGfxTransStr);

				if( dw != 0 || !mgr->palHasAlpha )
				{
					if(dw==0)
						mGfxTransStr= "FF00FF";
					mgr->gfxAlphaColor= str2rgb(mGfxTransStr);
					mgr->gfxHasAlpha= true;
				}
				break;				
			}

			mgr->gfxOffset= 0;
			mgr->gfxBpp= 1<<mGfxBpp;
			mgr->gfxCompression= mGfxCprs;

		}
		// --- map ---
		if(mbMap)
		{
			mgr->mapProcMode= GRIT_EXPORT;	
			mgr->mapCompression= mMapCprs;

			if(mbMapRdx)
			{
				mgr->mapRedux |= GRIT_RDX_TILE;
				if(mbMapRdxFlip)
					mgr->mapRedux |= GRIT_RDX_FLIP;
				if(mbMapRdxPal)
					mgr->mapRedux |= GRIT_RDX_PBANK;
			}

			if(mbMetaPal)
				mgr->mapRedux |= GRIT_META_PAL;

			mgr->mapLayout= moMapFormat;
			if(mgr->mapLayout == GRIT_MAP_AFFINE)
				mgr->msFormat= c_mapselGbaAffine;
			else
				mgr->msFormat= c_mapselGbaText;

			mgr->msFormat.base= mMapOffset;

			// Add external tileset stuff
			if(mbTileset)
			{
				if(mTilesetPath.IsEmpty())
					mTilesetPath= mDstDir + mDstTitle + "tiles.bmp";
				mgr->shared->tilePath= strdup(mTilesetPath);
				mgr->gfxIsShared= true;
			}
		}

		if(mbObjCustom)
		{
			mgr->metaWidth= mObjHorz;
			mgr->metaHeight= mObjVert;
		}
		else
		{
			dw= moObjShape*4 + moObjSize;
			mgr->metaWidth= cObjSizes[dw][0];
			mgr->metaHeight= cObjSizes[dw][1];
		}
		// area
		dw= moAreaSize+IDC_AREA_CSM;
		if(dw == IDC_AREA_CSM)
		{
			mgr->areaLeft  = mAreaLeft;
			mgr->areaTop   = mAreaTop;
			mgr->areaRight = mAreaLeft+mAreaWidth;
			mgr->areaBottom= mAreaTop+mAreaHeight;
		}
		else
		{
			mgr->areaLeft  = 0;
			mgr->areaTop   = 0;
			mgr->areaRight = dib_get_width(mpDib);
			mgr->areaBottom= dib_get_height(mpDib);
		}

		mgr->gfxDataType= moVarChunk;
		mgr->mapDataType= moVarChunk;
		mgr->palDataType= moVarChunk;

		// RIFF overrides
		if(IsRiffed())
		{
			mgr->bRiff= true;
			if(mgr->gfxCompression==GRIT_CPRS_OFF)
				mgr->gfxCompression= GRIT_CPRS_HEADER;

			if(mgr->mapCompression==GRIT_CPRS_OFF)
				mgr->mapCompression= GRIT_CPRS_HEADER;

			if(mgr->palCompression==GRIT_CPRS_OFF)
				mgr->palCompression= GRIT_CPRS_HEADER;
		}
	}
	else		// gr -> data
	{
		// --- file ---
		mbHeader = mgr->bHeader;
		mbAppend = mgr->bAppend;
		
		// --- palette ---
		mPalStart= mgr->palStart;
		mPalCount= mgr->palEnd-mgr->palStart;
		mPalTrans= mgr->palAlphaId;

		// --- image ---
		if(mgr->gfxHasAlpha)
		{
			RGBQUAD *rgb= &mgr->gfxAlphaColor;
			mGfxMode= GFX_MODE_BMP_T;
			mGfxTransStr.Format("%02X%02X%02X", rgb->rgbRed, 
				rgb->rgbGreen, rgb->rgbBlue);
		}
		else if(mgr->gfxMode == GRIT_GFX_BMP_A)
			mGfxMode= GFX_MODE_BMP_T;			
		else if(mgr->gfxMode == GRIT_GFX_BMP)
			mGfxMode= GFX_MODE_BMP;			
		else
			mGfxMode= GFX_MODE_TILE;			

		//mgr->gfx_ofs;
		//mgr->gfxBpp;

		// map
		if(mbMap)
		{
			moMapFormat= mgr->mapLayout;

			if(mgr->mapRedux & GRIT_RDX_TILE)
			{	
				mbMapRdx= TRUE;
				mbMapRdxFlip= mbMapRdxPal= FALSE;
				if(mgr->mapRedux & GRIT_RDX_FLIP)
					mbMapRdxFlip= TRUE;
				if(mgr->mapRedux & GRIT_RDX_PBANK)
					mbMapRdxPal= TRUE;
			}
			mMapOffset= mgr->msFormat.base;
		}
		// meta
		if(mbObjCustom)
		{
			mObjHorz= mgr->metaWidth;
			mObjVert= mgr->metaHeight;
		}
		// area
		mAreaLeft= mgr->areaLeft;
		mAreaTop= mgr->areaTop;
		mAreaWidth= mgr->areaRight-mgr->areaLeft;
		mAreaHeight= mgr->areaBottom-mgr->areaTop;

		UpdateData(FALSE);
	}

	return TRUE;
}
Beispiel #12
0
// TODO: reformat for new options
void CxpGbaDlg::UpdateSummary()
{
	// anti-bounce code (trust me, you need this)
	if(!mbBusy)
		UpdateData(TRUE);
	DWORD dw;
	CString sPal, sGfx, sArea, sMeta, sMap, sFiles;
	CString str;
	BOOL bPal, bGfx, bMeta, bMap, bArea;

	ASSERT(moMapFormat<3);

	bPal= mbPal;
	bGfx= mbGfx;
	bArea= mbGfx || mbMap;
	bMeta= GetDlgItem(IDC_OBJ_CUSTOM)->IsWindowEnabled();
	bMap= mbMap && IsTiled();

	// TODO: Validation!!!

	// --- image ---
	if(bGfx)
	{
		// TODO: transparent color
		GetDlgItem(IDC_IMG_MODE)->GetWindowText(str);
		sGfx= "gfx: " + str;
		if(mGfxMode == GFX_MODE_BMP_T)
		{
			RGBQUAD rgb= str2rgb(mGfxTransStr);
			str.Format(" (%d, %d, %d)", rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
			sGfx += str;
		}
		str.Format(", %dbpp, cprs: ", (1<<mGfxBpp));
		sGfx += str;
		GetDlgItem(IDC_IMG_CPRS)->GetWindowText(str);
		sGfx += str;
	}
	else
		sGfx= "gfx: -";
	
	// --- area ---
	if(bArea)
	{
		dw= moAreaSize+IDC_AREA_CSM;
		if(dw == IDC_AREA_CSM)
		{
			sArea.Format("area: (%d,%d)-(%d,%d)   [%d, %d]", 
				mAreaLeft, mAreaTop, mAreaLeft+mAreaWidth, mAreaTop+mAreaHeight, 
				mAreaWidth, mAreaHeight);
		}
		else if(dw == IDC_AREA_IMG)
		{
			sArea.Format("area: (%d,%d)-(%d,%d)   [%d, %d]", 
				0, 0, dib_get_width(mpDib), dib_get_height(mpDib), 
				dib_get_width(mpDib), dib_get_height(mpDib));
		}
	}
	else
		sArea="area: -";

	// --- object ---
	if(bMeta)
	{
		SIZE sz;
		if(mbObjCustom)
		{	sz.cx= mObjHorz; sz.cy= mObjVert;	}
		else
		{
			sz.cx= cObjSizes[moObjShape*4 + moObjSize][0];
			sz.cy= cObjSizes[moObjShape*4 + moObjSize][1];
		}

		sMeta.Format("meta: %dx%d tiles (%dx%d px)", 
			sz.cx, sz.cy, sz.cx<<3, sz.cy<<3);
	}
	else
		sMeta= "obj: -";

	// --- map ---
	if(bMap)
	{
		dw= moMapFormat+IDC_MAP_FLAT;
		switch(dw)
		{
		case IDC_MAP_FLAT:
			str= "flat";	break;
		case IDC_MAP_SBB:
			str= "in SBBs";	break;
		case IDC_MAP_AFF:
			str= "affine";	break;
		}
		sMap.Format("map: %s, +%d ", str, mMapOffset);
		if(IsRdx())
		{
			sMap += "reduced [t";
			if(mbMapRdxFlip)
				sMap += "f";
			if(mbMapRdxPal)
				sMap += "p";
			sMap += "]";
		}
	}
	else
		sMap= "map: -";
	
	// --- palette ---
	if(bPal)
	{
		if(mPalStart+mPalCount>256)
			mPalCount= 256-mPalStart;
		//GetDlgItem(IDC_START)->GetWindowText(str);
		sPal.Format("pal: %d-%d [%d]", mPalStart, mPalStart+mPalCount, mPalCount);

		// TODO: palette transparency index
	}
	else
		sPal= "pal: -";

	// --- files ---
	// TODO: add tileset file

	switch(mFileType)
	{
	case FMT_C:		// C (+h)
		str= mDstTitle + ".c   ";
		break;
	case FMT_GAS:		// assembly (+h)
		str= mDstTitle + ".s   ";
		break;
	case -1:		// COFF (+h)
		str= mDstTitle + ".o   ";
		break;
	case FMT_BIN:
		str.Empty();
		if(bPal)
			str += mDstTitle + ".pal.bin   ";
		if(bGfx)
			str += mDstTitle + ".img.bin   ";
		if(bMap)
			str += mDstTitle + ".map.bin   ";
	case FMT_GBFS:
		str= mDstTitle + ".gbfs   ";
	}

	sFiles= "files:  ";

	if(mbHeader)
		sFiles += mDstTitle + ".h   ";
	sFiles += str;

	mSummary.Format("%s\r\n%s\r\n%s\r\n%s\r\n%s\r\n%s", sGfx, sArea, 
		sMeta, sMap, sPal, sFiles);
	GetDlgItem(IDC_SUMMARY)->SetWindowText(mSummary);
}
Beispiel #13
0
bool grit_validate_area(GritRec *gr)
{
	int tmp;

	//# FIXME: consider other proc-modes?
	// area size
	if(gr->gfxProcMode != GRIT_EXCLUDE || gr->mapProcMode != GRIT_EXCLUDE)
	{
		int al, at, ar, ab;		// area
		int aw, ah;				// area size
		int blockW, blockH;		// block size

		al= gr->areaLeft;	at= gr->areaTop;
		ar= gr->areaRight;	ab= gr->areaBottom;

		// Normalize
		if(al > ar)
		{
			lprintf(LOG_WARNING, "  Area: left (%d) > right (%d). Swapping.\n", 
				gr->areaLeft, gr->areaRight);

			SWAP3(al, ar, tmp);
		}

		if(at > ab)
		{
			lprintf(LOG_WARNING, "  Area: top (%d) > bottom (%d). Swapping.\n", 
				gr->areaTop, gr->areaBottom);

			SWAP3(at, ab, tmp);
		}

		if(ar == 0)	ar= dib_get_width(gr->srcDib);
		if(ab == 0)	ab= dib_get_height(gr->srcDib);

		aw= ar-al;
		ah= ab-at;
		
		// metatile size (in px)
		// area MUST fit at least one metatile
		// Tiles: either 
		// - one meta tile
		// - one screenblock if in SBB layout
		// PONDER: non-integral metatile/sbb ??

		if(gr->metaWidth  < 1)	gr->metaWidth = 1;
		if(gr->metaHeight < 1)	gr->metaHeight= 1;

		if(gr->gfxMode == GRIT_GFX_TILE)
		{
			if(gr->tileWidth  < 4)	gr->tileWidth = 8;
			if(gr->tileHeight < 4)	gr->tileHeight= 8;
		}
		else
		{
			if(gr->tileWidth  < 1)	gr->tileWidth = 1;
			if(gr->tileHeight < 1)	gr->tileHeight= 1;
		}

		// Normally, the blocks are tw*mw, th*mh in size.
		// But for SBB-aligned maps it's a little different.
		if(!(gr->mapProcMode==GRIT_EXPORT && gr->mapLayout==GRIT_MAP_REG))
		{
			blockW= gr->mtileWidth();
			blockH= gr->mtileHeight();
		}
		else
			blockW= blockH= 256;

		if(aw%blockW != 0)
		{
			lprintf(LOG_WARNING, "Non-integer tiling in width (%d vs %d)\n", 
				aw, blockW);
			aw= align(aw, blockW);
		}

		if(ah%blockH != 0)
		{
			lprintf(LOG_WARNING, "Non-integer tiling in height (%d vs %d)\n", 
				ah, blockH);
			ah= align(ah, blockH);
		}

		// area must be multiple of metas (rounding up here)
		//aw= (aw+blw-1)/blw * blw;
		//ah= (ah+blh-1)/blh * blh;

		// PONDER: but what about the image size?
		//  *shrug* what about it?
		ar= al+aw;
		ab= at+ah;	

		gr->areaLeft= al;	gr->areaTop= at;
		gr->areaRight= ar;	gr->areaBottom= ab;
	}

	return true;	
}
Beispiel #14
0
/*!	Does map creation and layout, tileset reduction and map
	compression. Updates \a gr._dib with the new tileset, and fills
	in \a gr._mapRec and \a gr._metaRec.
	\note The work bitmap must be 8 bpp here, and already rearranged
	to a tile strip, which are the results of \c grit_prep_work_dib()
	and \c grit_prep_tiles(), respectively.
*/
bool grit_prep_map(GritRec *gr)
{
    if(dib_get_bpp(gr->_dib) < 8)
    {
        lprintf(LOG_ERROR, "  Can't map for bpp<8.\n");
        return false;
    }

    CLDIB *workDib= gr->_dib;

    // --- if SBB-mode, tile to 256x256. ---
    if(gr->mapLayout == GRIT_MAP_REG)
    {
        lprintf(LOG_STATUS, "  tiling to Screenblock size (256x256p).\n");

        int blockW= 256, blockH= 256;
        if(gr->bColMajor)
        {
            blockW= dib_get_width(workDib);
            blockH= dib_get_height(workDib);
            dib_redim(workDib, 256, blockH, 0);
        }

        if(!dib_redim(workDib, blockW, blockH, 0))
        {
            lprintf(LOG_ERROR, "  SBB tiling failed.\n");
            return false;
        }
    }

    ETmapFlags flags;
    Tilemap *metaMap= NULL, *map= NULL;
    RECORD metaRec= { 0, 0, NULL }, mapRec= { 0, 0, NULL };
    MapselFormat mf;

    CLDIB *extDib= NULL;
    int tileN= 0;
    uint extW= 0, extH= 0, tileW= gr->tileWidth, tileH= gr->tileHeight;
    uint mtileW= gr->mtileWidth(), mtileH= gr->mtileHeight();

    if(gr->gfxIsShared)
    {
        extDib= gr->shared->dib;
        extW= extDib ? dib_get_width(extDib) : 0;
        extH= extDib ? dib_get_height(extDib) : 0;
    }

    // --- If metatiled, convert to metatiles. ---
    if(gr->isMetaTiled())
    {
        lprintf(LOG_STATUS, "  Performing metatile reduction: tiles%s%s\n",
                (gr->mapRedux & GRIT_META_PAL ? ", palette" : "") );

        flags  = TMAP_DEFAULT;
        if(gr->mapRedux & GRIT_META_PAL)
            flags |= TMAP_PBANK;
        if(gr->bColMajor)
            flags |= TMAP_COLMAJOR;

        metaMap= tmap_alloc();
        if(extW == mtileW)
        {
            lprintf(LOG_STATUS, "  Using external metatileset.\n");
            tmap_init_from_dib(metaMap, workDib, mtileW, mtileH, flags, extDib);
        }
        else
            tmap_init_from_dib(metaMap, workDib, mtileW, mtileH, flags, NULL);

        mf= c_mapselGbaText;
        tileN= tmap_get_tilecount(metaMap);
        if(tileN >= (1<<mf.idLen))
            lprintf(LOG_WARNING, "  Number of metatiles (%d) exceeds field limit (%d).\n",
                    tileN, 1<<mf.idLen);

        tmap_pack(metaMap, &metaRec, &mf);
        if( BYTE_ORDER == BIG_ENDIAN && mf.bitDepth > 8 )
            data_byte_rev(metaRec.data, metaRec.data, rec_size(&metaRec), mf.bitDepth/8);

        // Make temp copy for base-tiling and try to avoid aliasing pointers.
        // Gawd, I hate manual mem-mgt >_<.
        dib_free(workDib);
        if(gr->bColMajor)
            workDib= dib_redim_copy(metaMap->tiles, tileN*mtileW, mtileH, 0);
        else
            workDib= dib_clone(metaMap->tiles);
    }

    // ---Convert to base tiles. ---
    flags = 0;
    if(gr->mapRedux & GRIT_RDX_TILE)
        flags |= TMAP_TILE;
    if(gr->mapRedux & GRIT_RDX_FLIP)
        flags |= TMAP_FLIP;
    if(gr->mapRedux & GRIT_RDX_PBANK)
        flags |= TMAP_PBANK;
    if(gr->bColMajor)
        flags |= TMAP_COLMAJOR;

    lprintf(LOG_STATUS, "  Performing tile reduction: %s%s%s\n",
            (flags & TMAP_TILE  ? "unique tiles; " : ""),
            (flags & TMAP_FLIP  ? "flip; " : ""),
            (flags & TMAP_PBANK ? "palswap; " : ""));

    map= tmap_alloc();
    if(extW == tileW)
    {
        lprintf(LOG_STATUS, "  Using external tileset.\n");
        tmap_init_from_dib(map, workDib, tileW, tileH, flags, extDib);
    }
    else
        tmap_init_from_dib(map, workDib, tileW, tileH, flags, NULL);

    // --- Pack/Reformat and compress ---
    //# TODO: allow custom mapsel format.
    mf= gr->msFormat;

    tileN= tmap_get_tilecount(metaMap);
    if(tileN >= (1<<mf.idLen))
        lprintf(LOG_WARNING, "  Number of tiles (%d) exceeds field limit (%d).\n",
                tileN, 1<<mf.idLen);

    tmap_pack(map, &mapRec, &mf);

    if( BYTE_ORDER == BIG_ENDIAN && mf.bitDepth > 8 )
        data_byte_rev(mapRec.data, mapRec.data, rec_size(&mapRec), mf.bitDepth/8);

    grit_compress(&mapRec, &mapRec, gr->mapCompression);

    // --- Cleanup ---

    // Make extra copy for external tile dib.
    if(gr->gfxIsShared)
    {
        dib_free(gr->shared->dib);

        // Use metatileset for external, unless the old external was a
        // base tileset.
        if(gr->isMetaTiled() && extW != tileW)
            gr->shared->dib= dib_clone(metaMap->tiles);
        else
            gr->shared->dib= dib_clone(map->tiles);
    }

    // Attach tileset for later processing.
    gr->_dib= tmap_detach_tiles(map);

    rec_alias(&gr->_mapRec, &mapRec);
    rec_alias(&gr->_metaRec, &metaRec);

    tmap_free(map);
    tmap_free(metaMap);

    lprintf(LOG_STATUS, "Map preparation complete.\n");
    return true;
}
Beispiel #15
0
/*!	This basically does two things. First, create a bitmap from the
	designated area of the source bitmap. Then, converts it 8 or
	16 bpp, depending on \a gr.gfxBpp. Conversion to lower bpp is
	done later, when it's more convenient. The resultant bitmap is
	put into \a gr._dib, and will be used in later preparation.
*/
bool grit_prep_work_dib(GritRec *gr)
{
    int ii, nn;
    RGBQUAD *rgb;

    lprintf(LOG_STATUS, "Work-DIB creation.\n");

    // --- resize ---
    CLDIB *dib= dib_copy(gr->srcDib,
                         gr->areaLeft, gr->areaTop, gr->areaRight, gr->areaBottom,
                         false);
    if(dib == NULL)
    {
        lprintf(LOG_ERROR, "  Work-DIB creation failed.\n");
        return false;
    }
    // ... that's it? Yeah, looks like.

    // --- resample (to 8 or 16) ---
    //
    int dibB= dib_get_bpp(dib);

    // Convert to 16bpp, but ONLY for bitmaps
    if( gr->gfxBpp == 16 && gr->gfxMode != GRIT_GFX_TILE )
    {
        if(dibB != 16)
        {
            lprintf(LOG_WARNING, "  converting from %d bpp to %d bpp.\n",
                    dibB, gr->gfxBpp);

            CLDIB *dib2= dib_convert_copy(dib, 16, 0);

            // If paletted src AND -pT AND NOT -gT[!]
            //   use trans color pal[T]
            //# PONDER: did I fix this right?
            if(dibB <= 8 && gr->palHasAlpha && !gr->gfxHasAlpha)
            {
                rgb= &dib_get_pal(dib)[gr->palAlphaId];
                lprintf(LOG_WARNING,
                        "  pal->true-color conversion with transp pal-id option.\n"
                        "    using color %02X%02X%02X",
                        rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);

                gr->gfxHasAlpha= true;
                gr->gfxAlphaColor= *rgb;
            }

            dib_free(dib);

            if(dib2 == NULL)
            {
                lprintf(LOG_ERROR, "prep: Bpp conversion failed.\n");
                return false;
            }
            dib= dib2;
        }

        // --- Dealing with 16bpp images ---
        // Modes:
        // 555      | GBA           | swap R_B
        // 555+A=1  | NDS           | swap R_B + add NDS_ALPHA
        // 555+A    | NDS, transp   | swap R_B + NDS_ALPHA if !trans-clr
        // src-pal + -pT -> NDS, transp

        // Swap palette bRGB to bBGR
        // And resolve -gT
        nn= dib_get_size_img(dib)/2;
        WORD *dibD2= (WORD*)dib_get_img(dib);

        // Single transparent color
        if(gr->gfxHasAlpha)
        {
            rgb= &gr->gfxAlphaColor;
            WORD clr= RGB16(rgb->rgbBlue, rgb->rgbGreen, rgb->rgbRed), wd;

            lprintf(LOG_STATUS,
                    "  converting to: 16bpp BGR, alpha=1, except for 0x%04X.\n",
                    clr);

            for(ii=0; ii<nn; ii++)
            {
                wd= swap_rgb16(dibD2[ii]);
                dibD2[ii]= (wd == clr ? wd : wd | NDS_ALPHA);
            }
        }
        else if(gr->gfxMode == GRIT_GFX_BMP_A)
        {
            lprintf(LOG_STATUS, "converting to: 16bpp BGR, alpha=1.\n");

            for(ii=0; ii<nn; ii++)
                dibD2[ii]= swap_rgb16(dibD2[ii]) | NDS_ALPHA;
        }
        else
        {
            lprintf(LOG_STATUS, "converting to: 16bpp, BGR.\n");

            for(ii=0; ii<nn; ii++)
                dibD2[ii]= swap_rgb16(dibD2[ii]);
        }
    }
    else if(dibB != 8)	// otherwise, convert to 8bpp
    {
        lprintf(LOG_WARNING, "  converting from %d bpp to %d bpp.\n",
                dibB, gr->gfxBpp);

        if(!dib_convert(dib, 8, 0))
        {
            dib_free(dib);
            lprintf(LOG_ERROR, "  Bpp conversion failed.\n");
            return false;
        }
    }

    // Palette transparency additions.
    if(dib_get_bpp(dib)==8)
    {
        // If gfx-trans && !pal-trans:
        //   Find gfx-trans in palette and use that
        if(gr->gfxHasAlpha && !gr->palHasAlpha)
        {
            rgb= &gr->gfxAlphaColor;
            RGBQUAD *pal= dib_get_pal(dib);

            lprintf(LOG_WARNING,
                    "  tru/pal -> pal conversion with transp color option.\n"
                    "    looking for color %02X%02X%02X in palette.\n",
                    rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);

            uint ii_min= 0, dist, dist_min;
            dist_min= rgb_dist(rgb, &pal[0]);

            for(ii=1; ii<256; ii++)
            {
                dist= rgb_dist(rgb, &pal[ii]);
                if(dist < dist_min)
                {
                    ii_min= ii;
                    dist_min= dist;
                }
            }

            // HACK: count 'match' only if average error is < +/-14
            if(dist_min < 576)
            {
                gr->palHasAlpha= true;
                gr->palAlphaId= ii_min;
            }
        }

        // Swap alpha and pixels palette entry
        if(gr->palHasAlpha)
        {
            lprintf(LOG_STATUS, "  Palette transparency: pal[%d].\n",
                    gr->palAlphaId);
            BYTE *imgD= dib_get_img(dib);
            nn= dib_get_size_img(dib);

            for(ii=0; ii<nn; ii++)
            {
                if(imgD[ii] == 0)
                    imgD[ii]= gr->palAlphaId;
                else if(imgD[ii] == gr->palAlphaId)
                    imgD[ii]= 0;
            }
            RGBQUAD tmp, *pal= dib_get_pal(dib);
            SWAP3(pal[0], pal[gr->palAlphaId], tmp);
        }

        // TODO: Palette merging.
        if(gr->palIsShared)
        {
            lprintf(LOG_STATUS, "  Palette merging\n");
            nn= dib_pal_reduce(dib, &gr->shared->palRec);
            if(nn>PAL_MAX)
                lprintf(LOG_WARNING, "    New palette exceeds 256. Truncating.\n");
        }
    }

    dib_free(gr->_dib);
    gr->_dib= dib;

    lprintf(LOG_STATUS, "Work-DIB creation complete: %dx%d@%d.\n",
            dib_get_width(gr->_dib), dib_get_height(gr->_dib),
            dib_get_bpp(gr->_dib));
    return true;
}
Beispiel #16
0
bool CTgaFile::Save(const char *fpath)
{

	int ii, iy;
	FILE *fp= NULL;
	bool bOK= true;

	try
	{
		if(!mDib)
			throw CImgFile::sMsgs[ERR_GENERAL];

		fp = fopen(fpath, "wb");
		if(!fp)
			throw CImgFile::sMsgs[ERR_NO_FILE];

		int imgW= dib_get_width(mDib);
		int imgH= dib_get_height(mDib), imgHs= dib_get_height2(mDib);
		int imgP= dib_get_pitch(mDib);
		int imgB= dib_get_bpp(mDib);
		int imgS= imgH*imgP, nclrs= dib_get_nclrs(mDib);

		TGAHDR hdr;
		memset(&hdr, 0, sizeof(TGAHDR));

		if(imgB==1)
			hdr.type= TGA_BW;
		else if(imgB <= 8)
			hdr.type= TGA_PAL;
		else
			hdr.type= TGA_true;

		if(imgB<=8)		// paletted
		{
			hdr.has_table= 1;
			hdr.pal_len= dib_get_nclrs(mDib);
			hdr.pal_bpp= 24;
		}
		else			// true color
			hdr.has_table=0;

		hdr.width= imgW;
		hdr.height= imgH;
		hdr.img_bpp= imgB;
		hdr.img_desc= 0;

		fwrite(&hdr, 1, sizeof(TGAHDR), fp);

		// write palette
		if(imgB <= 8)
		{
			RGBQUAD *pal= dib_get_pal(mDib);
			for(ii=0; ii<hdr.pal_len; ii++)
				fwrite(&pal[ii], 1, 3, fp);
		}

		// TGA should be bottom up:
		BYTE *imgL= dib_get_img(mDib);
		if(dib_is_topdown(mDib))
		{
			imgL += imgP*(imgH-1);
			imgP= -imgP;
		}

		// write image (not RLEd, because that's awful to do)
		int tgaP= (imgW*imgB+7)/8;
		for(iy=0; iy<imgH; iy++)
			fwrite(&imgL[iy*imgP], 1, tgaP, fp);
	}
	catch(const char *msg)
	{
		SetMsg(msg);
		bOK= false;
	}

	if(fp)
		fclose(fp);	

	return bOK;
}