Esempio n. 1
0
bool CSurface::Create(unsigned int width, unsigned int height, CSurface::FORMAT format)
{
  if (m_surface)
  {
    SDL_FreeSurface(m_surface);
    m_surface = NULL;
  }

  m_info.width = width;
  m_info.height = height;
  m_info.format = format;

  if (format == FMT_LIN_ARGB)
  { // round width to multiple of 64 pixels
    m_width = (width + 63) & ~63;
    m_height = height;
  }
  else
  { // round up to nearest power of 2
    m_width = PadPow2(width);
    m_height = PadPow2(height);
  }
  m_bpp = (format == FMT_PALETTED) ? 1 : 4;

  m_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, m_width, m_height, m_bpp * 8, 
                                  RMASK, GMASK, BMASK, AMASK);

  if (0 == m_surface)
    return false;

  Clear();
  return true;
}
Esempio n. 2
0
void CBaseTexture::Allocate(unsigned int width, unsigned int height, unsigned int format)
{
  m_imageWidth = width;
  m_imageHeight = height;
  m_format = format;
  m_orientation = 0;

  m_textureWidth = m_imageWidth;
  m_textureHeight = m_imageHeight;

  if (m_format & XB_FMT_DXT_MASK)
    while (GetPitch() < g_Windowing.GetMinDXTPitch())
      m_textureWidth += GetBlockSize();

  if (!g_Windowing.SupportsNPOT((m_format & XB_FMT_DXT_MASK) != 0))
  {
    m_textureWidth = PadPow2(m_textureWidth);
    m_textureHeight = PadPow2(m_textureHeight);
  }
  if (m_format & XB_FMT_DXT_MASK)
  { // DXT textures must be a multiple of 4 in width and height
    m_textureWidth = ((m_textureWidth + 3) / 4) * 4;
    m_textureHeight = ((m_textureHeight + 3) / 4) * 4;
  }

  // check for max texture size
  #define CLAMP(x, y) { if (x > y) x = y; }
  CLAMP(m_textureWidth, g_Windowing.GetMaxTextureSize());
  CLAMP(m_textureHeight, g_Windowing.GetMaxTextureSize());
  CLAMP(m_imageWidth, m_textureWidth);
  CLAMP(m_imageHeight, m_textureHeight);

  delete[] m_pixels;
  m_pixels = new unsigned char[GetPitch() * GetRows()];
}
Esempio n. 3
0
bool CSurface::Create(unsigned int width, unsigned int height, CSurface::FORMAT format)
{
  if (m_surface)
  {
    m_surface->Release();
    m_surface = NULL;
  }

  m_info.width = width;
  m_info.height = height;
  m_info.format = format;

  if (format == FMT_LIN_ARGB)
  { // round width to multiple of 64 pixels
    m_width = (width + 63) & ~63;
    m_height = height;
  }
  else
  { // round up to nearest power of 2
    m_width = PadPow2(width);
    m_height = PadPow2(height);
  }
  m_bpp = (format == FMT_PALETTED) ? 1 : 4;

  if (!g_device.CreateSurface(m_width, m_height, format, this))
    return false;

  Clear();
  return true;
}
Esempio n. 4
0
void CBaseTexture::Allocate(unsigned int width, unsigned int height, unsigned int format)
{
  m_imageWidth = m_originalWidth = width;
  m_imageHeight = m_originalHeight = height;
  m_format = format;
  m_orientation = 0;

  m_textureWidth = m_imageWidth;
  m_textureHeight = m_imageHeight;

  if (m_format & XB_FMT_DXT_MASK)
    while (GetPitch() < CServiceBroker::GetRenderSystem().GetMinDXTPitch())
      m_textureWidth += GetBlockSize();

  if (!CServiceBroker::GetRenderSystem().SupportsNPOT((m_format & XB_FMT_DXT_MASK) != 0))
  {
    m_textureWidth = PadPow2(m_textureWidth);
    m_textureHeight = PadPow2(m_textureHeight);
  }
  if (m_format & XB_FMT_DXT_MASK)
  { // DXT textures must be a multiple of 4 in width and height
    m_textureWidth = ((m_textureWidth + 3) / 4) * 4;
    m_textureHeight = ((m_textureHeight + 3) / 4) * 4;
  }
  else
  {
    // align all textures so that they have an even width
    // in some circumstances when we downsize a thumbnail
    // which has an uneven number of pixels in width
    // we crash in CPicture::ScaleImage in ffmpegs swscale
    // because it tries to access beyond the source memory
    // (happens on osx and ios)
    // UPDATE: don't just update to be on an even width;
    // ffmpegs swscale relies on a 16-byte stride on some systems
    // so the textureWidth needs to be a multiple of 16. see ffmpeg
    // swscale headers for more info.
    m_textureWidth = ((m_textureWidth + 15) / 16) * 16;
  }

  // check for max texture size
  #define CLAMP(x, y) { if (x > y) x = y; }
  CLAMP(m_textureWidth, CServiceBroker::GetRenderSystem().GetMaxTextureSize());
  CLAMP(m_textureHeight, CServiceBroker::GetRenderSystem().GetMaxTextureSize());
  CLAMP(m_imageWidth, m_textureWidth);
  CLAMP(m_imageHeight, m_textureHeight);

  _aligned_free(m_pixels);
  m_pixels = NULL;
  if (GetPitch() * GetRows() > 0)
  {
    size_t size = GetPitch() * GetRows();
    m_pixels = (unsigned char*) _aligned_malloc(size, 32);

    if (m_pixels == nullptr)
    {
      CLog::Log(LOGERROR, "%s - Could not allocate %zu bytes. Out of memory.", __FUNCTION__, size);
    }
  }
}
Esempio n. 5
0
bool GetFormatMSE(const D3DXIMAGE_INFO& info, LPDIRECT3DSURFACE8 pSrcSurf, D3DFORMAT fmt, double& CMSE, double& AMSE)
{
	LPDIRECT3DSURFACE8 pCompSurf = 0, pDstSurf = 0;
	HRESULT hr;

	// Compress
	int Width = PadPow2(info.Width), Height = PadPow2(info.Height);
	hr = pD3DDevice->CreateImageSurface(Width, Height, fmt, &pCompSurf);
	CheckHR(hr);

	hr = D3DXLoadSurfaceFromSurface(pCompSurf, NULL, NULL, pSrcSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
	CheckHR(hr);

	// Decompress
	hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pDstSurf);
	CheckHR(hr);

	hr = D3DXLoadSurfaceFromSurface(pDstSurf, NULL, NULL, pCompSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
	CheckHR(hr);

	pCompSurf->Release(); pCompSurf = 0;

	// calculate mean square error
	D3DLOCKED_RECT slr, dlr;
	hr = pSrcSurf->LockRect(&slr, NULL, D3DLOCK_READONLY);
	CheckHR(hr);
	hr = pDstSurf->LockRect(&dlr, NULL, D3DLOCK_READONLY);
	CheckHR(hr);

	double CTSE = 0.0; // total colour square error
	double ATSE = 0.0; // total alpha square error

	RGBCOLOUR* src = (RGBCOLOUR*)slr.pBits;
	RGBCOLOUR* dst = (RGBCOLOUR*)dlr.pBits;
	for (UINT y = 0; y < info.Height; ++y)
	{
		for (UINT x = 0; x < info.Width; ++x)
		{
			CTSE += (src->b - dst->b) * (src->b - dst->b);
			CTSE += (src->g - dst->g) * (src->g - dst->g);
			CTSE += (src->r - dst->r) * (src->r - dst->r);
			ATSE += (src->a - dst->a) * (src->a - dst->a);
			++src; ++dst;
		}
		src += (slr.Pitch - info.Width*sizeof(RGBCOLOUR)) / sizeof(RGBCOLOUR);
		dst += (dlr.Pitch - info.Width*sizeof(RGBCOLOUR)) / sizeof(RGBCOLOUR);
	}
	CMSE = CTSE / double(info.Width * info.Height * 3);
	AMSE = ATSE / double(info.Width * info.Height);

	pSrcSurf->UnlockRect();
	pDstSurf->UnlockRect();
	pDstSurf->Release(); pDstSurf = 0;

	return true;
}
Esempio n. 6
0
void CBaseTexture::Allocate(unsigned int width, unsigned int height, unsigned int format)
{
  m_imageWidth = m_originalWidth = width;
  m_imageHeight = m_originalHeight = height;
  m_format = format;
  m_orientation = 0;

  m_textureWidth = m_imageWidth;
  m_textureHeight = m_imageHeight;

  if (m_format & XB_FMT_DXT_MASK)
    while (GetPitch() < g_Windowing.GetMinDXTPitch())
      m_textureWidth += GetBlockSize();

  if (!g_Windowing.SupportsNPOT((m_format & XB_FMT_DXT_MASK) != 0))
  {
    m_textureWidth = PadPow2(m_textureWidth);
    m_textureHeight = PadPow2(m_textureHeight);
  }
  if (m_format & XB_FMT_DXT_MASK)
  { // DXT textures must be a multiple of 4 in width and height
    m_textureWidth = ((m_textureWidth + 3) / 4) * 4;
    m_textureHeight = ((m_textureHeight + 3) / 4) * 4;
  }
  else
  {
    // align all textures so that they have an even width
    // in some circumstances when we downsize a thumbnail
    // which has an uneven number of pixels in width
    // we crash in CPicture::ScaleImage in ffmpegs swscale
    // because it tries to access beyond the source memory
    // (happens on osx and ios)
    // UPDATE: don't just update to be on an even width;
    // ffmpegs swscale relies on a 16-byte stride on some systems
    // so the textureWidth needs to be a multiple of 16. see ffmpeg
    // swscale headers for more info.
    m_textureWidth = ((m_textureWidth + 15) / 16) * 16;
  }

  // check for max texture size
  #define CLAMP(x, y) { if (x > y) x = y; }
  CLAMP(m_textureWidth, g_Windowing.GetMaxTextureSize());
  CLAMP(m_textureHeight, g_Windowing.GetMaxTextureSize());
  CLAMP(m_imageWidth, m_textureWidth);
  CLAMP(m_imageHeight, m_textureHeight);

  delete[] m_pixels;
  m_pixels = NULL;
  if (GetPitch() * GetRows() > 0)
  {
    m_pixels = new unsigned char[GetPitch() * GetRows()];
  }
}
Esempio n. 7
0
void CBaseTexture::Allocate(unsigned int width, unsigned int height, unsigned int format)
{
  m_imageWidth = m_originalWidth = width;
  m_imageHeight = m_originalHeight = height;
  m_format = format;
  m_orientation = 0;

  m_textureWidth = m_imageWidth;
  m_textureHeight = m_imageHeight;

  if (m_format & XB_FMT_DXT_MASK)
    while (GetPitch() < g_Windowing.GetMinDXTPitch())
      m_textureWidth += GetBlockSize();

#if !defined(TARGET_RASPBERRY_PI)
  if (!g_Windowing.SupportsNPOT((m_format & XB_FMT_DXT_MASK) != 0))
  {
    m_textureWidth = PadPow2(m_textureWidth);
    m_textureHeight = PadPow2(m_textureHeight);
  }
#endif
  if (m_format & XB_FMT_DXT_MASK)
  { // DXT textures must be a multiple of 4 in width and height
    m_textureWidth = ((m_textureWidth + 3) / 4) * 4;
    m_textureHeight = ((m_textureHeight + 3) / 4) * 4;
  }
  else
  {
    // align all textures so that they have an even width
    // in some circumstances when we downsize a thumbnail
    // which has an uneven number of pixels in width
    // we crash in CPicture::ScaleImage in ffmpegs swscale
    // because it tries to access beyond the source memory
    // (happens on osx and ios)
    m_textureWidth = ((m_textureWidth + 1) / 2) * 2;
  }

  // check for max texture size
  #define CLAMP(x, y) { if (x > y) x = y; }
  CLAMP(m_textureWidth, g_Windowing.GetMaxTextureSize());
  CLAMP(m_textureHeight, g_Windowing.GetMaxTextureSize());
  CLAMP(m_imageWidth, m_textureWidth);
  CLAMP(m_imageHeight, m_textureHeight);
  delete[] m_pixels;
  m_pixels = new unsigned char[GetPitch() * GetRows()];
}
Esempio n. 8
0
// Init: Allocates space for raster and palette in GDI-compatible structures.
void CAnimatedGif::Init(int iWidth, int iHeight, int iBPP, int iLoops)
{
    if (Raster)
    {
        delete[] Raster;
        Raster=NULL;
    }

    if (pbmi)
    {
        delete[] pbmi;
        pbmi=NULL;
    }
    // Standard members setup
    Transparent =-1;
    BytesPerRow = PadPow2(Width = iWidth);
    Height      = iHeight;
    BPP         = iBPP;
    // Animation Extra members setup:
    xPos = yPos = Delay = Transparency = 0;
    nLoops=iLoops;

    if (BPP==24)
    {
        BytesPerRow*=3;
        pbmi=(GUIBITMAPINFO*)new char [sizeof(GUIBITMAPINFO)];
    }
    else
    {
        pbmi=(GUIBITMAPINFO*)new char[sizeof(GUIBITMAPINFOHEADER)+(1<<BPP)*sizeof(COLOR)];
        Palette=(COLOR*)((char*)pbmi+sizeof(GUIBITMAPINFOHEADER));
    }

    Raster = new char [BytesPerRow*Height];

    pbmi->bmiHeader.biSize=sizeof (GUIBITMAPINFOHEADER);
    pbmi->bmiHeader.biWidth=Width;
    pbmi->bmiHeader.biHeight=-Height;     // negative means up-to-bottom
    pbmi->bmiHeader.biPlanes=1;
    pbmi->bmiHeader.biBitCount=(BPP<8?8:BPP); // Our raster is byte-aligned
    pbmi->bmiHeader.biCompression=BI_RGB;
    pbmi->bmiHeader.biSizeImage=0;
    pbmi->bmiHeader.biXPelsPerMeter=11811;
    pbmi->bmiHeader.biYPelsPerMeter=11811;
    pbmi->bmiHeader.biClrUsed=0;
    pbmi->bmiHeader.biClrImportant=0;
}
Esempio n. 9
0
// only works for gifs or other 256-colour anims
void ConvertAnim(const char* Dir, const char* Filename, double MaxMSE)
{
	HRESULT hr;
	LPDIRECT3DSURFACE8 pSrcSurf = NULL;

	char OutFilename[52];
	if (Dir)
		_snprintf(OutFilename, 52, "%s\\%s", Dir, Filename);
	else
		_snprintf(OutFilename, 52, "%s", Filename);
	OutFilename[51] = 0;

	printf("%s: ", OutFilename);
	TRACE1("%s:\n", OutFilename);
	int n = strlen(OutFilename);
	if (n < 40)
		printf("%*c", 40-n, ' ');

	// Load up the file
	CAnimatedGifSet Anim;
	int nImages = Anim.LoadGIF(Filename);
	if (!nImages)
	{
		puts("ERROR: Unable to load gif (file corrupt?)");
		return;
	}
	if (nImages > 65535)
	{
		printf("ERROR: Too many frames in gif (%d > 65535)\n", nImages);
		return;
	}

	PrintAnimInfo(Anim);

	UINT Width = PadPow2(Anim.FrameWidth);
	UINT Height = PadPow2(Anim.FrameHeight);

	D3DXIMAGE_INFO info;
	info.Width = Anim.FrameWidth;
	info.Height = Anim.FrameHeight;
	info.MipLevels = 1;
	info.Depth = 0;
	info.ResourceType = D3DRTYPE_SURFACE;
	info.Format = D3DFMT_P8;
	info.ImageFileFormat = D3DXIFF_PNG;

	PALETTEENTRY pal[256];
	memcpy(pal, Anim.m_vecimg[0]->Palette, 256 * sizeof(PALETTEENTRY));
	for (int i = 0; i < 256; i++)
		pal[i].peFlags = 0xff; // alpha
	if (Anim.m_vecimg[0]->Transparency && Anim.m_vecimg[0]->Transparent >= 0)
		memset(&pal[Anim.m_vecimg[0]->Transparent], 0, sizeof(PALETTEENTRY));

	// setup xpr header
	WriteXPRHeader((DWORD*)pal, nImages);
	if (nImages > 1)
	{
		XPRFile.AnimInfo->RealSize = (info.Width & 0xffff) | ((info.Height & 0xffff) << 16);
		XPRFile.AnimInfo->nLoops = Anim.nLoops;
	}

	int nActualImages = 0;

	TotalSrcPixels += info.Width * info.Height * nImages;
	TotalDstPixels += Width * Height * nImages;
	float Waste = 100.f * (float)(Width * Height - info.Width * info.Height) / (float)(Width * Height);

	// alloc hash buffer
	BYTE (*HashBuf)[20] = new BYTE[nImages][20];

	for (int i = 0; i < nImages; ++i)
	{
		if (pSrcSurf)
			pSrcSurf->Release();
		pSrcSurf = NULL;

		printf("%3d%%\b\b\b\b", 100 * i / nImages);

		UncompressedSize += Width * Height;
		CAnimatedGif* pGif = Anim.m_vecimg[i];

		if (nImages > 1)
			XPRFile.Texture[i].RealSize = pGif->Delay;

		// generate sha1 hash
		SHA1((BYTE*)pGif->Raster, pGif->BytesPerRow * pGif->Height, HashBuf[i]);

		// duplicate scan
		int j;
		for (j = 0; j < i; ++j)
		{
			if (!memcmp(HashBuf[j], HashBuf[i], 20))
			{
				// duplicate image!
				TRACE2(" %03d: Duplicate of %03d\n", i, j);
				AppendXPRImageLink(j);
				break;
			}
		}
		if (j < i)
			continue;

		++nActualImages;

		// DXT1 for P8s if lossless
		hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pSrcSurf);
		CheckHR(hr);

		D3DLOCKED_RECT slr;
		hr = pSrcSurf->LockRect(&slr, NULL, D3DLOCK_READONLY);
		CheckHR(hr);

		BYTE* src = (BYTE*)pGif->Raster;
		DWORD* dst = (DWORD*)slr.pBits;
		DWORD* dwPal = (DWORD*)pal;
		for (int y = 0; y < pGif->Height; ++y)
		{
			for (UINT x = 0; x < Width; ++x)
				*dst++ = dwPal[*src++];
		}
		memset(dst, 0, (Height - pGif->Height) * slr.Pitch);

		pSrcSurf->UnlockRect();

		double CMSE, AMSE;
		TRACE1(" %03d: Checking DXT1: ", i);
		if (!GetFormatMSE(info, pSrcSurf, D3DFMT_DXT1, CMSE, AMSE))
			return;
		TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE);
		
		if (CMSE <= 1e-6 && AMSE <= 1e-6)
		{
			TRACE1(" %03d: Selected Format: DXT1\n", i);
			AppendXPRImage(info, pSrcSurf, XB_D3DFMT_DXT1);
		}
		else
		{	
			pSrcSurf->Release();

			hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_P8, &pSrcSurf);
			CheckHR(hr);

			hr = pSrcSurf->LockRect(&slr, NULL, D3DLOCK_READONLY);
			CheckHR(hr);

			memcpy((BYTE*)slr.pBits, pGif->Raster, pGif->Height * slr.Pitch);
			memset((BYTE*)slr.pBits + pGif->Height * slr.Pitch, pGif->Transparent, (Height - pGif->Height) * slr.Pitch);

			pSrcSurf->UnlockRect();

			TRACE1(" %03d: Selected Format: P8\n", i);
			AppendXPRImage(info, pSrcSurf, XB_D3DFMT_P8);
		}
	}

	delete [] HashBuf;
	
	printf("(%5df) %4dx%-4d (%5.2f%% waste)\n", nActualImages, Width, Height, Waste);

	CommitXPR(OutFilename);
	if (pSrcSurf)
		pSrcSurf->Release();
}
Esempio n. 10
0
void ConvertFile(const char* Dir, const char* Filename, double MaxMSE)
{
	HRESULT hr;
	LPDIRECT3DSURFACE8 pSrcSurf = NULL;
	char OutFilename[52];
	if (Dir)
		_snprintf(OutFilename, 52, "%s\\%s", Dir, Filename);
	else
		_snprintf(OutFilename, 52, "%s", Filename);
	OutFilename[51] = 0;

	printf("%s: ", OutFilename);
	TRACE1("%s:\n", OutFilename);
	int n = strlen(OutFilename);
	if (n < 40)
		printf("%*c", 40-n, ' ');

	if (pSrcSurf)
		pSrcSurf->Release();
	pSrcSurf = NULL;

	// Load up the file
	D3DXIMAGE_INFO info;
	hr = D3DXGetImageInfoFromFile(Filename, &info);
	CheckHR(hr);

	PrintImageInfo(info);

	UINT Width = PadPow2(info.Width);
	UINT Height = PadPow2(info.Height);

	float Waste = 100.f * (float)(Width * Height - info.Width * info.Height) / (float)(Width * Height);

	UncompressedSize += Width * Height * 4;
	TotalSrcPixels += info.Width * info.Height;
	TotalDstPixels += Width * Height;

  // Special case for 256-colour files - just directly drop into a P8 xpr
	if (info.Format == D3DFMT_P8)
	{
		hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pSrcSurf);
		CheckHR(hr);

		hr = D3DXLoadSurfaceFromFile(pSrcSurf, NULL, NULL, Filename, NULL, D3DX_FILTER_NONE, 0, NULL);
		CheckHR(hr);

		FixTransparency(pSrcSurf);

		if (Width * Height > 4096)
		{
			// DXT1 for P8s if lossless and more than 4k image
			LPDIRECT3DSURFACE8 pTempSurf;
			hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pTempSurf);
			CheckHR(hr);

			hr = D3DXLoadSurfaceFromSurface(pTempSurf, NULL, NULL, pSrcSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
			CheckHR(hr);

			double CMSE, AMSE;
			TRACE0(" Checking     DXT1: ");
			if (!GetFormatMSE(info, pTempSurf, D3DFMT_DXT1, CMSE, AMSE))
			{
				pTempSurf->Release();
				return;
			}
			TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE);
			if (CMSE <= 1e-6 && AMSE <= 1e-6)
			{
				printf("DXT1     %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste);
				TRACE0(" Selected Format: DXT1\n");
				WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_DXT1, NULL);

				pTempSurf->Release();
				return;
			}
			pTempSurf->Release();
		}

		printf("P8       %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste);
		TRACE0(" Selected Format: P8\n");

		LPDIRECT3DSURFACE8 pTempSurf;
		DWORD pal[256];
		ConvertP8(pSrcSurf, pTempSurf, pal, info);

		WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_P8, pal);
		pTempSurf->Release();
		return;
	}

  // test linear format versus non-linear format
  // Linear format requires 64 pixel aligned width, whereas
  // Non-linear format requires power of 2 width and height
  bool useLinearFormat(false);
  UINT linearWidth = (info.Width + 0x3f) & ~0x3f;
  if (AllowLinear && linearWidth * info.Height < Width * Height)
    useLinearFormat = true;

	hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pSrcSurf);
	CheckHR(hr);
  
	hr = D3DXLoadSurfaceFromFile(pSrcSurf, NULL, NULL, Filename, NULL, D3DX_FILTER_NONE, 0, NULL);
	CheckHR(hr);

  // create the linear version as well
	LPDIRECT3DSURFACE8 pLinearSrcSurf = NULL;
  if (useLinearFormat)
  {
	  hr = pD3DDevice->CreateImageSurface(linearWidth, info.Height, D3DFMT_A8R8G8B8, &pLinearSrcSurf);
	  CheckHR(hr);
	  hr = D3DXLoadSurfaceFromFile(pLinearSrcSurf, NULL, NULL, Filename, NULL, D3DX_FILTER_NONE, 0, NULL);
	  CheckHR(hr);
  }


	// special case for small files - all textures are alloced on page granularity so just output uncompressed
	// dxt is crap on small files anyway
	if (Width * Height <= 1024)
	{
    if (useLinearFormat)
    {
      // correct sizing amounts
	    UncompressedSize -= Width * Height * 4;
      UncompressedSize += linearWidth * info.Height * 4;
	    TotalDstPixels -= Width * Height;
      TotalDstPixels += linearWidth * info.Height;

	    Waste = 100.f * (float)(linearWidth * info.Height - info.Width * info.Height) / (float)(linearWidth * info.Height);
		  printf("LIN_A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", linearWidth, info.Height, Waste);
		  TRACE0(" Selected Format: LIN_A8R8G8B8\n");
      WriteXPR(OutFilename, info, pLinearSrcSurf, XB_D3DFMT_LIN_A8R8G8B8, NULL);
    }
    else
    {
		  printf("A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste);
		  TRACE0(" Selected Format: A8R8G8B8\n");
      WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_A8R8G8B8, NULL);
    }
		return;
	}

	FixTransparency(pSrcSurf);

	// Find the best format within specified tolerance
	double CMSE, AMSE[2];

	// DXT1 is the preferred format as it's smallest
	TRACE0(" Checking     DXT1: ");
	if (!GetFormatMSE(info, pSrcSurf, D3DFMT_DXT1, CMSE, AMSE[0]))
		return;
	TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[0]);
	if (CMSE <= MaxMSE && AMSE[0] <= MaxMSE)
	{
		printf("DXT1     %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste);
		TRACE0(" Selected Format: DXT1\n");

		WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_DXT1, NULL);
		return;
	}

	// Use P8 is possible as it's lossless
	LPDIRECT3DSURFACE8 pTempSurf;
	DWORD pal[256];
	if (ConvertP8(pSrcSurf, pTempSurf, pal, info))
	{
		printf("P8       %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste);
		TRACE0(" Selected Format: P8\n");

		WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_P8, pal);
		pTempSurf->Release();
		return;
	}

	// DXT3/5 are the same size so use whichever is better if good enough
	// CMSE will be equal for both
	TRACE0(" Checking     DXT3: ");
	if (!GetFormatMSE(info, pSrcSurf, D3DFMT_DXT3, CMSE, AMSE[0]))
		return;
	TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[0]);

	TRACE0(" Checking     DXT5: ");
	if (!GetFormatMSE(info, pSrcSurf, D3DFMT_DXT5, CMSE, AMSE[1]))
		return;
	TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[1]);

	if (AMSE[0] <= AMSE[1])
	{
		if (CMSE <= MaxMSE && AMSE[0] <= MaxMSE)
		{
			printf("DXT3     %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste);
			TRACE0(" Selected Format: DXT3\n");

			WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_DXT3, NULL);
			return;
		}
	}
	else
	{
		if (CMSE <= MaxMSE && AMSE[1] <= MaxMSE)
		{
			printf("DXT5     %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste);
			TRACE0(" Selected Format: DXT5\n");

			WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_DXT5, NULL);
			return;
		}
	}

	// No good compressed format so use uncompressed

	// A1R5G5B5 is worth a try I guess...
	TRACE0(" Checking A1R5G5B5: ");
	if (!GetFormatMSE(info, pSrcSurf, D3DFMT_A1R5G5B5, CMSE, AMSE[0]))
		return;
	TRACE2("CMSE=%05.2f, AMSE=%07.2f\n", CMSE, AMSE[0]);
	if (CMSE <= MaxMSE && AMSE[0] <= MaxMSE)
	{
		printf("A1R5G5B5 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste);
		TRACE0(" Selected Format: A1R5G5B5\n");

		LPDIRECT3DSURFACE8 pTempSurf;
		hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A1R5G5B5, &pTempSurf);
		CheckHR(hr);

		hr = D3DXLoadSurfaceFromSurface(pTempSurf, NULL, NULL, pSrcSurf, NULL, NULL, D3DX_FILTER_NONE, 0);
		CheckHR(hr);

		WriteXPR(OutFilename, info, pTempSurf, XB_D3DFMT_A1R5G5B5, NULL);

		pTempSurf->Release();
		return;
	}

	// Use A8R8G8B8
  if (useLinearFormat)
  {
    // correct sizing information
	  UncompressedSize -= Width * Height * 4;
    UncompressedSize += linearWidth * info.Height * 4;
	  TotalDstPixels -= Width * Height;
    TotalDstPixels += linearWidth * info.Height;
	  Waste = 100.f * (float)(linearWidth * info.Height - info.Width * info.Height) / (float)(linearWidth * info.Height);
		printf("LIN_A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", linearWidth, info.Height, Waste);
		TRACE0(" Selected Format: LIN_A8R8G8B8\n");
    WriteXPR(OutFilename, info, pLinearSrcSurf, XB_D3DFMT_LIN_A8R8G8B8, NULL);
  }
  else
  {
		printf("A8R8G8B8 %4dx%-4d (%5.2f%% waste)\n", Width, Height, Waste);
		TRACE0(" Selected Format: A8R8G8B8\n");
    WriteXPR(OutFilename, info, pSrcSurf, XB_D3DFMT_A8R8G8B8, NULL);
  }

	if (pSrcSurf)
		pSrcSurf->Release();
}
Esempio n. 11
0
// Converts to P8 format is colours <= 256
bool ConvertP8(LPDIRECT3DSURFACE8 pSrcSurf, LPDIRECT3DSURFACE8& pDstSurf, DWORD* pal, D3DXIMAGE_INFO &info)
{
	pDstSurf = 0;

	D3DSURFACE_DESC desc;
	pSrcSurf->GetDesc(&desc);

	// convert to p8
  UINT Width = PadPow2(desc.Width);
  UINT Height = PadPow2(desc.Height);
	HRESULT hr = pD3DDevice->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &pDstSurf);
	CheckHR(hr);

	D3DLOCKED_RECT slr, dlr;
	hr = pDstSurf->LockRect(&dlr, NULL, 0);
	CheckHR(hr);
	hr = pSrcSurf->LockRect(&slr, NULL, D3DLOCK_READONLY);
	CheckHR(hr);

	DWORD* src = (DWORD*)slr.pBits;
	BYTE* dst = (BYTE*)dlr.pBits;
	int n = 0, i;
	for (UINT y = 0; y < info.Height; ++y)
	{
		for (UINT x = 0; x < info.Width; ++x)
		{
			for (i = 0; i < n; ++i)
			{
				if (pal[i] == *src)
					break;
			}
			if (i == n)
			{
				if (n >= 256)
				{
					TRACE0(" Too many colours for P8\n");
					pSrcSurf->UnlockRect();
					pDstSurf->UnlockRect();
					pDstSurf->Release();
					return false;
				}
				pal[n++] = *src;
			}
			*dst++ = i;
			++src;
		}
		for (UINT x = info.Width; x < Width; ++x)
		{
			*dst++ = 0; // we don't care about the colour outside of our real image
			++src;
    }
	}
  for (UINT y = info.Height; y < Height; ++y)
  {
		for (UINT x = 0; x < Width; ++x)
		{
			*dst++ = 0; // we don't care about the colour outside of our real image
			++src;
    }
  }
	TRACE1(" Colours Used: %d\n", n);

	pDstSurf->UnlockRect();
	pSrcSurf->UnlockRect();

	return true;
}