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

184 lines
4.9 KiB
C++

/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "picture/pict.h"
#include "color/color.h"
using namespace GS;
//------------------------------------------------------------------------------
void Picture::Sample(float u, float v, Color &out, uint _w, uint _h) const
{
if (!GetData())
{
out.Set(1, 0, 1);
return;
}
if (!GetPixelFormat().IsReal())
{
uint _out;
Sample(u, v, _out, _w, _h);
out.FromInteger(_out);
}
else
{
if (!_w) _w = GetWidth();
if (!_h) _h = GetHeight();
u *= _w; v *= _h;
if (u < 0) u = 0;
if (v < 0) v = 0;
if (u >= _w) u = (float)(_w - 1);
if (v >= _h) v = (float)(_h - 1);
uint iu = (uint)u, iv = (uint)v;
Color sample[4];
float *pdata = (float *)GetData();
pdata += (iu + iv * _w) * 3;
//---------------------------------------
#define EXTRACT_FSAMPLE(_S_, _P_) \
{ \
(_S_).z = (_P_)[2]; \
(_S_).y = (_P_)[1]; \
(_S_).x = (_P_)[0]; \
}
//---------------------------------------
EXTRACT_FSAMPLE(sample[0], pdata + 0);
if (iu < (_w - 1))
EXTRACT_FSAMPLE(sample[1], pdata + 3)
else sample[1] = sample[0];
if (iv < (_h - 1))
EXTRACT_FSAMPLE(sample[2], pdata + _w * 3)
else sample[2] = sample[0];
if ((iu < (_w - 1)) && (iv < (_h - 1)))
EXTRACT_FSAMPLE(sample[3], pdata + (_w + 1) * 3)
else sample[3] = sample[0];
// Bilinear sample.
float k[4], uf = u - (float)iu, vf = v - (float)iv;
k[0] = (1.f - uf) * (1.f - vf);
k[1] = uf * (1.f - vf);
k[2] = (1.f - uf) * vf;
k[3] = uf * vf;
out = sample[0] * k[0] + sample[1] * k[1] + sample[2] * k[2] + sample[3] * k[3];
out.w = sample[0].w * k[0] + sample[1].w * k[1] + sample[2].w * k[2] + sample[3].w * k[3];
}
}
void Picture::Sample(float u, float v, uint &out, uint _w, uint _h) const
{
if (!GetData())
{
out = 0xffff00ff;
return;
}
if (GetPixelFormat().IsReal())
{
Color _out;
Sample(u, v, _out, _w, _h);
out = _out.AsInteger();
}
else
{
if (!_w) _w = GetWidth();
if (!_h) _h = GetHeight();
u *= _w; v *= _h;
if (u < 0) u = 0;
if (v < 0) v = 0;
if (u >= _w) u = (float)(_w - 1);
if (v >= _h) v = (float)(_h - 1);
uint iu = (uint)u, iv = (uint)v;
struct iVector
{
int x, y, z, w;
iVector operator + (const iVector &b) const
{ return iVector(x + b.x, y + b.y, z + b.z, w + b.w); }
iVector operator * (const int v) const
{ return iVector(x * v, y * v, z * v, w * v); }
iVector operator >> (const int v) const
{ return iVector(x >> v, y >> v, z >> v, w >> v); }
iVector(int _x, int _y, int _z, int _w = 255)
{ x = _x; y = _y; z = _z; w = _w; }
iVector()
{}
};
iVector sample[4];
uint *pdata = (uint *)GetData();
pdata += iu + iv * _w;
//----------------------------------------------------------------------
#define EXTRACT_SAMPLE(_S_, _P_) \
{ \
const uchar *_t_p = (const uchar *)&(_P_); \
(_S_).x = _t_p[0]; \
(_S_).y = _t_p[1]; \
(_S_).z = _t_p[2]; \
(_S_).w = _t_p[3]; \
}
//----------------------------------------------------------------------
EXTRACT_SAMPLE(sample[0], pdata[0]);
if (iu < (_w - 1))
EXTRACT_SAMPLE(sample[1], pdata[1])
else sample[1] = sample[0];
if (iv < (_h - 1))
EXTRACT_SAMPLE(sample[2], pdata[_w])
else sample[2] = sample[0];
if ((iu < (_w - 1)) && (iv < (_h - 1)))
EXTRACT_SAMPLE(sample[3], pdata[_w + 1])
else sample[3] = sample[0];
int k[4], uf = int((u - (float)iu) * 256), vf = int((v - (float)iv) * 256);
k[0] = (256 - uf) * (256 - vf); // 16bit fixed point.
k[1] = uf * (256 - vf);
k[2] = (256 - uf) * vf;
k[3] = uf * vf;
iVector r = (sample[0] * k[0] + sample[1] * k[1] + sample[2] * k[2] + sample[3] * k[3]) >> 16;
uchar *_out = (uchar *)&out;
_out[0] = (uchar)r.x;
_out[1] = (uchar)r.y;
_out[2] = (uchar)r.z;
_out[3] = (uchar)r.w;
}
}
void Picture::SampleRGBA(float u, float v, Color &o, uint _w, uint _h) const
{
Color s;
Sample(u, v, s, _w, _h);
o[0] = s[pxformat.rshift >> 3];
o[1] = s[pxformat.gshift >> 3];
o[2] = s[pxformat.bshift >> 3];
o[3] = s[pxformat.ashift >> 3];
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
uint Picture::SampleInteger(float u, float v, uint _w, uint _h) const
{ uint s; Sample(u, v, s, _w, _h); return s; }
Color Picture::SampleColor(float u, float v, uint _w, uint _h) const
{ Color s; Sample(u, v, s, _w, _h); return s; }
Color Picture::SampleRGBAColor(float u, float v, uint _w, uint _h) const
{ Color s; SampleRGBA(u, v, s, _w, _h); return s; }
//------------------------------------------------------------------------------