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