Files
Webcam/include/framework/picture/pict_scaler.cpp

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;
}
//------------------------------------------------------------------------------