Ejemplo n.º 1
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;
}
Ejemplo n.º 2
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)>
}
Ejemplo n.º 3
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;
}
Ejemplo n.º 4
0
/*!	Prepares the work dib for export, i.e. converts to the final
	bitdepth, compresses the data and fills in \a gr._gfxRec.
*/
bool grit_prep_gfx(GritRec *gr)
{
    lprintf(LOG_STATUS, "Graphics preparation.\n");

    int srcB= dib_get_bpp(gr->_dib);	// should be 8 or 16 by now
    int srcP= dib_get_pitch(gr->_dib);
    int srcS= dib_get_size_img(gr->_dib);
    BYTE *srcD= dib_get_img(gr->_dib);

    int dstB= gr->gfxBpp;
    // # dst bytes, with # src pixels as 'width'
    int dstS= dib_align(srcS*8/srcB, dstB);
    dstS= ALIGN4(dstS);
    BYTE *dstD= (BYTE*)malloc(dstS);
    if(dstD == NULL)
    {
        lprintf(LOG_ERROR, "  Can't allocate graphics data.\n");
        return false;
    }

    // Convert to final bitdepth
    // NOTE: do not use dib_convert here, because of potential
    //   problems with padding
    // NOTE: we're already at 8 or 16 bpp here, with 16 bpp already
    //   accounted for. Only have to do 8->1,2,4
    // TODO: offset
    if(srcB == 8 && srcB != dstB)
    {
        lprintf(LOG_STATUS, "  Bitpacking: %d -> %d.\n", srcB, dstB);
        data_bit_pack(dstD, srcD, srcS, srcB, dstB, 0);
    }
    else
        memcpy(dstD, srcD, dstS);

    RECORD rec= { 1, dstS, dstD };

    if( BYTE_ORDER == BIG_ENDIAN && gr->gfxBpp > 8 )
        data_byte_rev(rec.data, rec.data, rec_size(&rec), gr->gfxBpp/8);

    // attach and compress graphics
    grit_compress(&rec, &rec, gr->gfxCompression);
    rec_alias(&gr->_gfxRec, &rec);

    lprintf(LOG_STATUS, "Graphics preparation complete.\n");
    return true;
}
Ejemplo n.º 5
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
Ejemplo n.º 6
0
/*!	\param dib	DIB to reduce the palette of. Must be paletted. Pixels 
		will be rearranged to match the palette.
	\param extPal	External palette record. \a dib will use this 
		and its own palette. Can be NULL. The new reduced palette goes here too.
	\return	Number of reduced colors, or 0 if not 8bpp. 
	\note	The order of colors is the order of appearance, except for the 
		first one.
*/
int dib_pal_reduce(CLDIB *dib, RECORD *extPal)
{
	// Only for 8bpp (for now)
	if(dib == NULL || dib_get_bpp(dib) != 8)
		return 0;

	int ii, jj, kk, ix, iy;

	int dibW, dibH, dibP;
	dib_get_attr(dib, &dibW, &dibH, NULL, &dibP);

	BYTE *dibD= dib_get_img(dib);

	// Get palette histogram
	int histo[256];

	memset(histo, 0, sizeof(histo));
	for(iy=0; iy<dibH; iy++)
		for(ix=0; ix<dibW; ix++)
			histo[dibD[iy*dibP+ix]]++;

	// Allocate room for new palette and init with ext pal
	// NOTE: extPal is assumed reduced!
	// NOTE: double-size for rdxPal for worst-case scenario.
	// NOTE: the *Clr things are just to make comparisons easier.
	//		 pointers ftw!

	int count;
	RGBQUAD *rdxPal= (RGBQUAD*)malloc(512*RGB_SIZE);
	COLORREF *rdxClr= (COLORREF*)rdxPal, *dibClr= (COLORREF*)dib_get_pal(dib);

	memset(rdxPal, 0, 512*RGB_SIZE);
	if(extPal != NULL && extPal->data != NULL)
	{
		memcpy(rdxPal, extPal->data, rec_size(extPal));
		count= extPal->height;
	}
	else
	{
		rdxClr[0]= dibClr[0];
		count= 1;
	}

	// PONDER: always keep index 0 ?

	// Create reduced palette and prep tables for pixel conversion.
	DWORD srcIdx[PAL_MAX], dstIdx[PAL_MAX];

	kk=0;
	for(ii=0; ii<PAL_MAX; ii++)
	{
		if(histo[ii])
		{
			for(jj=0; jj<count; jj++)
				if(rdxClr[jj] == dibClr[ii])
					break;
			// Match: add color to table
			if(jj == count)
			{
				rdxClr[jj]= dibClr[ii];
				count++;
			}
			srcIdx[kk]= jj;
			dstIdx[kk]= ii;
			kk++;
		}
	}

	// PONDER: what *should* happen if nn > PAL_MAX ?
	// Fail, trunc or re-quantize?

	//  Update palette and remap pixels
	memcpy(dibClr, rdxClr, PAL_MAX*RGB_SIZE);
	dib_pixel_replace(dib, dstIdx, srcIdx, kk);

	// Update rdxPal's data
	if(extPal)
	{
		extPal->width= RGB_SIZE;
		extPal->height= count;
		free(extPal->data);

		extPal->data= (BYTE*)malloc(count*RGB_SIZE);
		memcpy(extPal->data, rdxClr, count*RGB_SIZE);
	}

	return count;
}
Ejemplo n.º 7
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();
		}	
	}
}
Ejemplo n.º 8
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;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
// Yes, you can use LoadImage too, but that creates a device 
// dependent bitmap and you want to stay the fsck away from those.
bool CBmpFile::Load(const char *fpath)
{
	FILE *fp= fopen(fpath, "rb");
	CLDIB *dib= NULL;

	try
	{
		if(!fp)
			throw CImgFile::sMsgs[ERR_NO_FILE];

		BITMAPFILEHEADER bmfh;
		fread(&bmfh,  sizeof(BITMAPFILEHEADER), 1,fp);

		// Whoa, not a bitmap, back off
		if(bmfh.bfType != BMP_TYPE)	// 4D42h = "BM". 
			throw CImgFile::sMsgs[ERR_FORMAT];

		BITMAPINFOHEADER bmih;
		bool bCore;

		// check for bm version first :(
		fread(&bmih, 4, 1, fp);
		if(bmih.biSize == sizeof(BITMAPCOREHEADER))		// crap! v2.x BMP
		{
			bCore= true;
			bmih.biSize= BMIH_SIZE; 
			WORD wd;
			fread(&wd, 2,1,fp);
			bmih.biWidth= wd;
			fread(&wd, 2,1,fp);
			bmih.biHeight= wd;
			fread(&bmih.biPlanes, 2,1,fp);
			fread(&bmih.biBitCount, 2,1,fp);
			memset(&bmih.biCompression, 0, 
				BMIH_SIZE-sizeof(BITMAPCOREHEADER));
		}
		else		// normal v3.0 BMP
			fread(&bmih.biWidth, BMIH_SIZE-4, 1, fp);

		if(bmih.biPlanes > 1)				// no color planes, plz
			throw sMsgs[ERR_BMP_PLANES];
		if(bmih.biCompression != BI_RGB)	// no compression either
			throw sMsgs[ERR_BMP_CPRS];

		int dibP, dibHa, dibS;

		dibHa= abs(bmih.biHeight);
		dibP= dib_align(bmih.biWidth, bmih.biBitCount);
		dibS= dibP*dibHa;
		// set manually, just to be sure
		bmih.biSizeImage= dibS;

		// ditto for ClrUsed
		if(bmih.biBitCount <=8 && bmih.biClrUsed == 0)
			bmih.biClrUsed= 1<<bmih.biBitCount;

		// now we set-up the full bitmap
		dib= dib_alloc(bmih.biWidth, dibHa, bmih.biBitCount, NULL, true);
		if(dib == NULL)
			throw CImgFile::sMsgs[ERR_ALLOC];

		// read the palette
		fread(dib_get_pal(dib), RGB_SIZE, bmih.biClrUsed, fp);

		// read image
		fread(dib_get_img(dib), dibS, 1, fp);
		if(bmih.biHeight>=0)	// -> TD image
			dib_vflip(dib);

	}	// </try>
	catch(const char *msg)
	{
		SetMsg(msg);
		dib_free(dib);
		dib= NULL;
	}
	if(fp)
		fclose(fp);
	if(!dib)
		return false;

	// if we're here we've succeeded
	SetMsg(CImgFile::sMsgs[ERR_NONE]);
	dib_free(Attach(dib));

	SetBpp(dib_get_bpp(dib));
	SetPath(fpath);

	return true;
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
// xxx_load(const char *fname, PDIBDATA *ppdib, IMG_FMT_INFO *pifi)
bool CTgaFile::Load(const char *fpath)
{
	FILE *fp= fopen(fpath, "rb");
	CLDIB *dib= NULL;
	TGAHDR hdr;

	try
	{
		if(!fp)
			throw CImgFile::sMsgs[ERR_NO_FILE];

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

		// ignore image desc (if any)
		fseek(fp, hdr.id_len, SEEK_CUR);

		int imgW, imgH, imgB, imgP;
		imgW= hdr.width;
		imgH= hdr.height;
		imgB= hdr.img_bpp;
		imgP= dib_align(imgW, imgB);

		// Set-up the full bitmap
		dib= dib_alloc(imgW, imgH, imgB, NULL, true);
		if(dib == NULL)
			throw CImgFile::sMsgs[ERR_ALLOC];

		// === get color map ===
		if(hdr.has_table)
		{
			if(!tga_read_pal(dib, &hdr, fp))
				throw sMsgs[ERR_TGA_BADPAL];
		}

		int ii;
		int tgaP= (imgW*imgB+7)/8;
		BYTE *imgD= dib_get_img(dib);

		switch(hdr.type)
		{
		case TGA_BW:
		case TGA_PAL:
		case TGA_true:
			for(ii=0; ii<imgH; ii++)
				fread(&imgD[ii*imgP], 1, tgaP, fp);
			break;
		case TGA_BW_RLE:
		case TGA_PAL_RLE:
		case TGA_true_RLE:
			tga_unrle(dib, &hdr, fp);
			break;
		default:
			throw sMsgs[ERR_TGA_VERSION];
		}

		// TGA's are bottom-up by default, flip if necessary
		if(~hdr.img_desc & TGA_VFLIP)
			dib_vflip(dib);

	}	// </try>
	catch(const char *msg)
	{
		SetMsg(msg);
		dib_free(dib);
		dib= NULL;
	}
	// cleanup
	if(!dib)
		return false;

	// if we're here we've succeeded
	SetMsg(CImgFile::sMsgs[ERR_NONE]);
	dib_free(Attach(dib));

	SetBpp(dib_get_bpp(dib));
	SetPath(fpath);

	return true;
}
Ejemplo n.º 13
0
/*!	\note	Works at the byte level. If you have sub-8 bpps, you'll
*	  still have to shift a bit.
*/
BYTE *dib_get_img_at(CLDIB *dib, int x, int y)
{
	BYTE *dibD= dib_get_img(dib);
	return &dibD[x*dib_get_bpp(dib)/8 + y*dib_get_pitch(dib)];
}