207 lines
4.1 KiB
C++
207 lines
4.1 KiB
C++
/* -----------------------------------------------------------------------------
|
|
GSFramework
|
|
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
|
----------------------------------------------------------------------------- */
|
|
|
|
|
|
#include "picture/pict.h"
|
|
#include "color/color.h"
|
|
|
|
using namespace GS;
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
bool Picture::Resize(uint nwidth, uint nheight)
|
|
{
|
|
if (!nwidth && !nheight)
|
|
return false;
|
|
|
|
if (!nwidth)
|
|
nwidth = (GetWidth() * nheight) / GetHeight();
|
|
if (!nheight)
|
|
nheight = (GetHeight() * nwidth) / GetWidth();
|
|
|
|
if ((nwidth == GetWidth()) && (nheight == GetHeight()))
|
|
return true;
|
|
|
|
if (pxformat.IsReal())
|
|
{
|
|
float *new_data = (float *)AllocMemory(sizeof(float) * nwidth * nheight * 3);
|
|
if (!new_data)
|
|
return false;
|
|
|
|
float *pdst = (float *)new_data;
|
|
float ku = 1.f / (float)nwidth,
|
|
kv = 1.f / (float)nheight;
|
|
|
|
Color out;
|
|
|
|
float v = kv * 0.5f - 0.5f / height;
|
|
if (data)
|
|
for (uint y = 0; y < nheight; ++y)
|
|
{
|
|
float u = ku * 0.5f - 0.5f / width;
|
|
for (uint x = 0; x < nwidth; ++x)
|
|
{
|
|
Sample(u, v, out);
|
|
pdst[0] = out.x;
|
|
pdst[1] = out.y;
|
|
pdst[2] = out.z;
|
|
pdst += 3;
|
|
u += ku;
|
|
}
|
|
v += kv;
|
|
}
|
|
|
|
SetData(new_data, nwidth, nheight, PixelFormat::RGBAF, true);
|
|
//SetData(new_data, nwidth, nheight, PixelFormat::RGBF, true);
|
|
}
|
|
else if (GetBpp() == 32)
|
|
{
|
|
uchar *new_data = (uchar *)AllocMemory(sizeof(uchar) * nwidth * nheight * 4);
|
|
if (!new_data)
|
|
return false;
|
|
|
|
uint *pdst = (uint*)new_data;
|
|
float ku = 1.f / (float)nwidth,
|
|
kv = 1.f / (float)nheight;
|
|
|
|
float v = kv * 0.5f - 0.5f / height;
|
|
if (data)
|
|
for (uint y = 0; y < nheight; ++y)
|
|
{
|
|
float u = ku * 0.5f - 0.5f / width;
|
|
for (uint x = 0; x < nwidth; ++x)
|
|
{
|
|
Sample(u, v, *pdst++);
|
|
u += ku;
|
|
}
|
|
v += kv;
|
|
}
|
|
|
|
SetData(new_data, nwidth, nheight, GetPixelFormat().GetDesc(), true);
|
|
}
|
|
else
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
bool Picture::Downscale(uint nwidth, uint nheight)
|
|
{
|
|
if (!nwidth && !nheight)
|
|
return false;
|
|
|
|
if (!nwidth)
|
|
nwidth = (GetWidth() * nheight) / GetHeight();
|
|
if (!nheight)
|
|
nheight = (GetHeight() * nwidth) / GetWidth();
|
|
|
|
if ((nwidth > GetWidth()) || (nheight > GetHeight()))
|
|
return Resize(nwidth, nheight);
|
|
|
|
if (GetBpp() == 32)
|
|
{
|
|
uchar *new_data = (uchar *)AllocMemory(sizeof(uchar) * nwidth * nheight * 4);
|
|
if (!new_data)
|
|
return false;
|
|
|
|
uchar *pdst = new_data;
|
|
Array <float> accu(nwidth * 4);
|
|
|
|
if (accu)
|
|
{
|
|
float ku = (float)GetWidth() / (float)nwidth,
|
|
kv = (float)GetHeight() / (float)nheight;
|
|
float u, v;
|
|
|
|
//
|
|
v = 0.f;
|
|
|
|
// Accumulate scan lines.
|
|
uchar *psrc = GetData();
|
|
|
|
for (uint y = 0; y < nheight; y++)
|
|
{
|
|
uint n;
|
|
for (n = 0; n < (nwidth * 4); n++)
|
|
accu[n] = 0.f;
|
|
|
|
float tv = kv, nv = kv;
|
|
|
|
for (;;)
|
|
{
|
|
float k = GS::Math::Ceil(v) - v;
|
|
tv -= k;
|
|
if (tv < 0.f)
|
|
k += tv; // readjust
|
|
v += k;
|
|
|
|
if (v >= GetHeight())
|
|
{
|
|
nv -= k;
|
|
break;
|
|
}
|
|
|
|
//
|
|
u = 0.f;
|
|
|
|
// Accumulate texels.
|
|
uchar *lsrc = psrc;
|
|
float *paccu = accu;
|
|
float texel[4];
|
|
|
|
for (uint x = 0; x < nwidth; x++)
|
|
{
|
|
for (n = 0; n < 4; n++)
|
|
texel[n] = 0.f;
|
|
|
|
float tu = ku, nu = ku;
|
|
|
|
for (;;)
|
|
{
|
|
float k = GS::Math::Ceil(u) - u;
|
|
tu -= k;
|
|
if (tu < 0.f)
|
|
k += tu; // readjust
|
|
u += k;
|
|
|
|
if (u >= GetWidth())
|
|
{
|
|
nu -= k;
|
|
break;
|
|
}
|
|
|
|
for (n = 0; n < 4; n++)
|
|
texel[n] += (float)(lsrc[n]) * k;
|
|
|
|
if (tu < 0.f)
|
|
break;
|
|
|
|
lsrc += 4;
|
|
}
|
|
|
|
tu = k / nu;
|
|
for (n = 0; n < 4; n++)
|
|
paccu[n] += texel[n] * tu;
|
|
paccu += 4;
|
|
}
|
|
if (tv < 0.f)
|
|
break;
|
|
|
|
psrc += GetWidth() * 4;
|
|
}
|
|
|
|
tv = 1.f / nv;
|
|
for (n = 0; n < (nwidth * 4); n++)
|
|
pdst[n] = (uchar)(accu[n] * tv);
|
|
pdst += nwidth * 4;
|
|
}
|
|
|
|
SetData(new_data, nwidth, nheight, GetPixelFormat().GetDesc(), true);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
//------------------------------------------------------------------------------
|