184 lines
4.9 KiB
C++
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; }
|
|
//------------------------------------------------------------------------------
|