Reworking of video frame interface, into more general RGB(A) image interface

Originally committed to SVN as r1485.
This commit is contained in:
Niels Martin Hansen 2007-08-14 00:20:59 +00:00
parent 43149f9276
commit 2699972427
5 changed files with 205 additions and 107 deletions

View file

@ -24,6 +24,9 @@
*/ */
// Must be included before <windows.h>, otherwise some macros from <windows.h> get in the way
#include "video_frame.h"
#include <windows.h> #include <windows.h>
#include <string.h> #include <string.h>
#include <memory.h> #include <memory.h>
@ -95,11 +98,11 @@ public:
try { try {
switch (vi.pixel_type) { switch (vi.pixel_type) {
case VideoInfo::CS_BGR24: { case VideoInfo::CS_BGR24: {
OverLuaVideoFrameBGR *frame = new OverLuaVideoFrameBGR(vi.width, vi.height, stride, plane); ImageBGR *frame = new ImageBGR(vi.width, vi.height, stride, plane);
script->RenderFrameRGB(*frame, frametime); script->RenderFrameRGB(*frame, frametime);
} break; } break;
case VideoInfo::CS_BGR32: { case VideoInfo::CS_BGR32: {
OverLuaVideoFrameBGRX *frame = new OverLuaVideoFrameBGRX(vi.width, vi.height, stride, plane); ImageBGRX *frame = new ImageBGRX(vi.width, vi.height, stride, plane);
script->RenderFrameRGB(*frame, frametime); script->RenderFrameRGB(*frame, frametime);
} break; } break;
} }

View file

@ -24,6 +24,9 @@
*/ */
// CSRI interface is unmaintained for now
#if 0
#include <string.h> #include <string.h>
#include <memory.h> #include <memory.h>
@ -112,22 +115,22 @@ CSRIAPI void csri_render(csri_inst *inst, struct csri_frame *frame, double time)
// check for correct pixfmt // check for correct pixfmt
if (frame->pixfmt != inst->frame_format.pixfmt) return; if (frame->pixfmt != inst->frame_format.pixfmt) return;
OverLuaFrameAggregate *olframe = 0; BaseImageAggregate *olframe = 0;
switch (frame->pixfmt) { switch (frame->pixfmt) {
#define HANDLE_RGB_FORMAT(fmtname, Rpos, Gpos, Bpos, PixelWidth) \ #define HANDLE_RGB_FORMAT(fmtname, PixFmt) \
case fmtname: \ case fmtname: \
olframe = new OverLuaFrameAggregateImpl<Rpos,Gpos,Bpos,PixelWidth>(inst->frame_format.width, inst->frame_format.height, frame->strides[0], frame->planes[0]); \ olframe = new BaseImageAggregateImpl<PixelFormat:: ## PixFmt>(inst->frame_format.width, inst->frame_format.height, frame->strides[0], frame->planes[0]); \
break; break;
HANDLE_RGB_FORMAT(CSRI_F_RGBA, 0, 1, 2, 4) HANDLE_RGB_FORMAT(CSRI_F_RGBA, RGBA)
HANDLE_RGB_FORMAT(CSRI_F_ARGB, 1, 2, 3, 4) HANDLE_RGB_FORMAT(CSRI_F_ARGB, ARGB)
HANDLE_RGB_FORMAT(CSRI_F_BGRA, 2, 1, 0, 4) HANDLE_RGB_FORMAT(CSRI_F_BGRA, BGRA)
HANDLE_RGB_FORMAT(CSRI_F_ABGR, 3, 2, 1, 4) HANDLE_RGB_FORMAT(CSRI_F_ABGR, ABGR)
HANDLE_RGB_FORMAT(CSRI_F_RGB_, 0, 1, 2, 4) HANDLE_RGB_FORMAT(CSRI_F_RGB_, RGBX)
HANDLE_RGB_FORMAT(CSRI_F__RGB, 1, 2, 3, 4) HANDLE_RGB_FORMAT(CSRI_F__RGB, XRGB)
HANDLE_RGB_FORMAT(CSRI_F_BGR_, 2, 1, 0, 4) HANDLE_RGB_FORMAT(CSRI_F_BGR_, BGRX)
HANDLE_RGB_FORMAT(CSRI_F__BGR, 3, 2, 1, 4) HANDLE_RGB_FORMAT(CSRI_F__BGR, XBGR)
HANDLE_RGB_FORMAT(CSRI_F_RGB, 0, 1, 2, 3) HANDLE_RGB_FORMAT(CSRI_F_RGB, RGB)
HANDLE_RGB_FORMAT(CSRI_F_BGR, 2, 1, 0, 3) HANDLE_RGB_FORMAT(CSRI_F_BGR, BGR)
default: break; // what, we don't support this! default: break; // what, we don't support this!
#undef HANDLE_RGB_FORMAT #undef HANDLE_RGB_FORMAT
} }
@ -200,3 +203,5 @@ CSRIAPI csri_rend *csri_renderer_next(csri_rend *prev)
else else
return 0; return 0;
} }
#endif

View file

@ -105,7 +105,7 @@ OverLuaScript::~OverLuaScript()
lua_close(L); lua_close(L);
} }
void OverLuaScript::RenderFrameRGB(OverLuaFrameAggregate &frame, double time) void OverLuaScript::RenderFrameRGB(BaseImageAggregate &frame, double time)
{ {
lua_getglobal(L, "render_frame"); lua_getglobal(L, "render_frame");
frame.CreateLuaObject(L); frame.CreateLuaObject(L);

View file

@ -89,7 +89,7 @@ public:
OverLuaScript(const void *data, size_t length, const char *_datastring = 0); OverLuaScript(const void *data, size_t length, const char *_datastring = 0);
virtual ~OverLuaScript(); virtual ~OverLuaScript();
void RenderFrameRGB(OverLuaFrameAggregate &frame, double time); void RenderFrameRGB(BaseImageAggregate &frame, double time);
}; };

View file

@ -28,63 +28,159 @@
#define VIDEO_FRAME_H #define VIDEO_FRAME_H
#include "../lua51/src/lua.h" #include "../lua51/src/lua.h"
#include "../lua51/src/lauxlib.h"
#include "cairo_wrap.h" #include "cairo_wrap.h"
#include <stddef.h> #include <stddef.h>
#include <memory.h> #include <memory.h>
#include <stdint.h> #include <stdint.h>
#include <omp.h> #include <omp.h>
// Forward
class OverLuaFrameAggregate;
// store a colour value // Forward
struct RGBPixel { class BaseImageAggregate;
unsigned char r, g, b;
RGBPixel(unsigned char R, unsigned char G, unsigned char B) : r(R), g(G), b(B) { }
// Supported pixel formats
namespace PixelFormat {
// A constant value with a fake assignment operator
template <class T, T v>
struct NopAssigningConstant {
operator T() { return v; }
void operator = (const T &n) { }
};
typedef NopAssigningConstant<uint8_t,255> ROA; // "read only alpha"
// 24 bit formats
struct RGB {
uint8_t r, g, b;
inline uint8_t &R() { return r; } inline uint8_t R() const { return r; }
inline uint8_t &G() { return g; } inline uint8_t G() const { return g; }
inline uint8_t &B() { return b; } inline uint8_t B() const { return b; }
inline ROA A() const { return ROA(); }
RGB() : r(0), g(0), b(0) { }
template <class PixFmt> RGB(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); }
};
struct BGR {
uint8_t b, g, r;
inline uint8_t &R() { return r; } inline uint8_t R() const { return r; }
inline uint8_t &G() { return g; } inline uint8_t G() const { return g; }
inline uint8_t &B() { return b; } inline uint8_t B() const { return b; }
inline ROA A() const { return ROA(); }
BGR() : r(0), g(0), b(0) { }
template <class PixFmt> BGR(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); }
};
// 32 bit alpha-less formats
struct RGBX {
uint8_t r, g, b, x;
inline uint8_t &R() { return r; } inline uint8_t R() const { return r; }
inline uint8_t &G() { return g; } inline uint8_t G() const { return g; }
inline uint8_t &B() { return b; } inline uint8_t B() const { return b; }
inline ROA A() const { return ROA(); }
RGBX() : r(0), g(0), b(0) { }
template <class PixFmt> RGBX(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); }
};
struct BGRX {
uint8_t b, g, r, x;
inline uint8_t &R() { return r; } inline uint8_t R() const { return r; }
inline uint8_t &G() { return g; } inline uint8_t G() const { return g; }
inline uint8_t &B() { return b; } inline uint8_t B() const { return b; }
inline ROA A() const { return ROA(); }
BGRX() : r(0), g(0), b(0) { }
template <class PixFmt> BGRX(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); }
};
struct XRGB {
uint8_t x, r, g, b;
inline uint8_t &R() { return r; } inline uint8_t R() const { return r; }
inline uint8_t &G() { return g; } inline uint8_t G() const { return g; }
inline uint8_t &B() { return b; } inline uint8_t B() const { return b; }
inline ROA A() const { return ROA(); }
XRGB() : r(0), g(0), b(0) { }
template <class PixFmt> XRGB(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); }
};
struct XBGR {
uint8_t x, b, g, r;
inline uint8_t &R() { return r; } inline uint8_t R() const { return r; }
inline uint8_t &G() { return g; } inline uint8_t G() const { return g; }
inline uint8_t &B() { return b; } inline uint8_t B() const { return b; }
inline ROA A() const { return ROA(); }
XBGR() : r(0), g(0), b(0) { }
template <class PixFmt> XBGR(const PixFmt &src) { r = src.R(); g = src.G(); b = src.B(); }
};
// 32 bit with alpha
struct RGBA {
uint8_t r, g, b, a;
inline uint8_t &R() { return r; } inline uint8_t R() const { return r; }
inline uint8_t &G() { return g; } inline uint8_t G() const { return g; }
inline uint8_t &B() { return b; } inline uint8_t B() const { return b; }
inline uint8_t &A() { return a; } inline uint8_t A() const { return a; }
RGBA() : r(0), g(0), b(0), a(0) { }
template <class PixFmt> RGBA(const PixFmt &src) { a = src.A(); r = src.R(); g = src.G(); b = src.B(); }
};
struct BGRA {
uint8_t b, g, r, a;
inline uint8_t &R() { return r; } inline uint8_t R() const { return r; }
inline uint8_t &G() { return g; } inline uint8_t G() const { return g; }
inline uint8_t &B() { return b; } inline uint8_t B() const { return b; }
inline uint8_t &A() { return a; } inline uint8_t A() const { return a; }
BGRA() : r(0), g(0), b(0), a(0) { }
template <class PixFmt> BGRA(const PixFmt &src) { a = src.A(); r = src.R(); g = src.G(); b = src.B(); }
};
struct ARGB {
uint8_t a, r, g, b;
inline uint8_t &R() { return r; } inline uint8_t R() const { return r; }
inline uint8_t &G() { return g; } inline uint8_t G() const { return g; }
inline uint8_t &B() { return b; } inline uint8_t B() const { return b; }
inline uint8_t &A() { return a; } inline uint8_t A() const { return a; }
ARGB() : r(0), g(0), b(0), a(0) { }
template <class PixFmt> ARGB(const PixFmt &src) { a = src.A(); r = src.R(); g = src.G(); b = src.B(); }
};
struct ABGR {
uint8_t a, b, g, r;
inline uint8_t &R() { return r; } inline uint8_t R() const { return r; }
inline uint8_t &G() { return g; } inline uint8_t G() const { return g; }
inline uint8_t &B() { return b; } inline uint8_t B() const { return b; }
inline uint8_t &A() { return a; } inline uint8_t A() const { return a; }
ABGR() : r(0), g(0), b(0), a(0) { }
template <class PixFmt> ABGR(const PixFmt &src) { a = src.A(); r = src.R(); g = src.G(); b = src.B(); }
};
}; };
// Support any interleaved RGB format with 8 bit per channel // Support any interleaved RGB format with 8 bit per channel
// You usually don't want to instance this class directly, // You usually don't want to instance this class directly,
// look at OverLuaFrameAggregate defined below // look at OverLuaFrameAggregate defined below
template<ptrdiff_t Rpos, ptrdiff_t Gpos, ptrdiff_t Bpos, ptrdiff_t PixelWidth> template<class PixFmt>
class OverLuaVideoFrame { class BaseImage {
public: public:
typedef OverLuaVideoFrame<Rpos,Gpos,Bpos,PixelWidth> MyType; typedef BaseImage<PixFmt> MyType;
// video properties // video properties
unsigned width; int width;
unsigned height; int height;
ptrdiff_t stride; ptrdiff_t stride;
unsigned char *data; unsigned char *data;
// read a pixel value // Access a pixel value
inline const RGBPixel GetPixel(unsigned x, unsigned y) inline const PixFmt &Pixel(int x, int y) const
{ {
RGBPixel res(0, 0, 0); return *((PixFmt*)(data + y*stride) + x)
unsigned char *ptr = data + y*stride + x*PixelWidth;
res.r = ptr[Rpos];
res.g = ptr[Gpos];
res.b = ptr[Bpos];
return res;
} }
// write a pixel value inline PixFmt &Pixel(int x, int y)
inline void SetPixel(unsigned x, unsigned y, const RGBPixel &val)
{ {
unsigned char *ptr = data + y*stride + x*PixelWidth; return *((PixFmt*)(data + y*stride) + x);
ptr[Rpos] = val.r;
ptr[Gpos] = val.g;
ptr[Bpos] = val.b;
} }
OverLuaVideoFrame(unsigned _width, unsigned _height, ptrdiff_t _stride, unsigned char *_data) BaseImage(unsigned _width, unsigned _height, ptrdiff_t _stride, unsigned char *_data)
: width(_width), height(_height), stride(_stride), data(_data) : width(_width), height(_height), stride(_stride), data(_data)
{ {
owndata = false; owndata = false;
// nothing further to init // nothing further to init
} }
OverLuaVideoFrame(const MyType &src, bool copydata = false) BaseImage(const MyType &src, bool copydata = false)
{ {
width = src.width; width = src.width;
height = src.height; height = src.height;
@ -98,14 +194,14 @@ public:
} }
} }
~OverLuaVideoFrame() ~BaseImage()
{ {
if (owndata) if (owndata)
delete[] data; delete[] data;
} }
// should never be called more than once on the same C++ object // should never be called more than once on the same C++ object
void CreateLuaObject(lua_State *L, OverLuaFrameAggregate *aggregate = 0) void CreateLuaObject(lua_State *L, BaseImageAggregate *aggregate = 0)
{ {
// create userdata object // create userdata object
MyType **ud = (MyType**)lua_newuserdata(L, sizeof(MyType*)); MyType **ud = (MyType**)lua_newuserdata(L, sizeof(MyType*));
@ -123,7 +219,7 @@ public:
lua_setfield(L, -2, "__gc"); lua_setfield(L, -2, "__gc");
if (aggregate) { if (aggregate) {
lua_pushlightuserdata(L, aggregate); lua_pushlightuserdata(L, aggregate);
lua_setfield(L, -2, "videoframe"); lua_setfield(L, -2, "image");
} }
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
} }
@ -142,32 +238,32 @@ private:
if (lua_isnumber(L, 2)) { if (lua_isnumber(L, 2)) {
if (lua_istable(L, 3)) { if (lua_istable(L, 3)) {
int n = (int)lua_tointeger(L, 2); int n = (int)lua_tointeger(L, 2);
unsigned x = n % (*ud)->width; int x = n % (*ud)->width;
unsigned y = n / (*ud)->width; int y = n / (*ud)->width;
if (x < 0 || y < 0 || x >= (*ud)->width || y >= (*ud)->height) return 0; if (x < 0 || y < 0 || x >= (*ud)->width || y >= (*ud)->height) return 0;
// read first three entries from table // read first three entries from table
RGBPixel color(0,0,0); PixFmt color;
lua_pushnil(L); lua_pushnil(L);
if (!lua_next(L, 3)) goto badtable; if (!lua_next(L, 3)) goto badtable;
if (!lua_isnumber(L, -1)) goto badtable; if (!lua_isnumber(L, -1)) goto badtable;
color.r = (unsigned char)lua_tointeger(L, -1); color.R() = (unsigned char)lua_tointeger(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
if (!lua_next(L, 3)) goto badtable; if (!lua_next(L, 3)) goto badtable;
if (!lua_isnumber(L, -1)) goto badtable; if (!lua_isnumber(L, -1)) goto badtable;
color.g = (unsigned char)lua_tointeger(L, -1); color.G() = (unsigned char)lua_tointeger(L, -1);
lua_pop(L, 1); lua_pop(L, 1);
if (!lua_next(L, 3)) goto badtable; if (!lua_next(L, 3)) goto badtable;
if (!lua_isnumber(L, -1)) goto badtable; if (!lua_isnumber(L, -1)) goto badtable;
color.b = (unsigned char)lua_tointeger(L, -1); color.B() = (unsigned char)lua_tointeger(L, -1);
lua_pop(L, 2); lua_pop(L, 2);
(*ud)->SetPixel(x, y, color); (*ud)->Pixel(x, y) = color;
return 0; return 0;
} else { } else {
badtable: badtable:
lua_pushliteral(L, "Value set into video frame pixel must be a table with at least 3 entries"); lua_pushliteral(L, "Value set into image pixel must be a table with at least 3 entries");
lua_error(L); lua_error(L);
return 0; return 0;
} }
@ -201,7 +297,7 @@ badtable:
lua_pushvalue(L, 1); lua_pushvalue(L, 1);
lua_pushcclosure(L, lua_overlay_cairo_surface, 1); lua_pushcclosure(L, lua_overlay_cairo_surface, 1);
} else { } else {
lua_pushfstring(L, "Undefined field name in video frame: %s", fieldname); lua_pushfstring(L, "Undefined field name in image: %s", fieldname);
lua_error(L); lua_error(L);
} }
@ -209,7 +305,7 @@ badtable:
} }
lua_pushfstring(L, "Unhandled field type indexing video frame: %s", lua_typename(L, lua_type(L, 2))); lua_pushfstring(L, "Unhandled field type indexing image: %s", lua_typename(L, lua_type(L, 2)));
lua_error(L); lua_error(L);
return 0; return 0;
} }
@ -221,19 +317,19 @@ badtable:
// third arg = y // third arg = y
MyType **ud = (MyType**)lua_touserdata(L, 1); MyType **ud = (MyType**)lua_touserdata(L, 1);
unsigned x = luaL_checkint(L, 2); int x = luaL_checkint(L, 2);
unsigned y = luaL_checkint(L, 3); int y = luaL_checkint(L, 3);
RGBPixel color(0,0,0);
if (x < 0 || y < 0 || x >= (*ud)->width || y >= (*ud)->height) { if (x < 0 || y < 0 || x >= (*ud)->width || y >= (*ud)->height) {
// already black, leave it lua_pushinteger(L, 0);
lua_pushinteger(L, 0);
lua_pushinteger(L, 0);
} else { } else {
// get it const PixFmt &p = (*ud)->Pixel(x, y);
color = (*ud)->GetPixel(x, y); lua_pushinteger(L, p.r);
lua_pushinteger(L, p.g);
lua_pushinteger(L, p.b);
} }
lua_pushinteger(L, color.r);
lua_pushinteger(L, color.g);
lua_pushinteger(L, color.b);
return 3; return 3;
} }
@ -274,12 +370,11 @@ badtable:
int width = (*ud)->width; int width = (*ud)->width;
#pragma omp parallel for #pragma omp parallel for
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
uint32_t *opix = (uint32_t*)(surfdata + y*surfstride); PixFmt *ipix = (PixFmt*)((*ud)->data + y*((*ud)->stride));
PixelFormat::XBGR *opix = (PixelFormat::XBGR*)(surfdata + y*surfstride);
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
// Hoping this will get optimised at least a bit by the compiler // Hoping this will get optimised at least a bit by the compiler
RGBPixel ipix = (*ud)->GetPixel(x, y); *opix++ = PixelFormat::XBGR(*ipix++);
*opix = ipix.r << 16 | ipix.g << 8 | ipix.b;
opix++;
} }
} }
cairo_surface_mark_dirty(surf); cairo_surface_mark_dirty(surf);
@ -338,17 +433,16 @@ badtable:
int lines_to_compose = (slines_to_compose<flines_to_compose)?slines_to_compose:flines_to_compose; int lines_to_compose = (slines_to_compose<flines_to_compose)?slines_to_compose:flines_to_compose;
#pragma omp parallel for #pragma omp parallel for
for (int composition_line = 0; composition_line < lines_to_compose; composition_line++) { for (int composition_line = 0; composition_line < lines_to_compose; composition_line++) {
uint32_t *sline = (uint32_t*)(sdata + composition_line*sstride); PixelFormat::ARGB *sline = (PixelFormat::ARGB*)(sdata + composition_line*sstride);
int fx = xpos; int fx = xpos;
int sx = 0; int sx = 0;
if (fx < 0) fx = 0, sx = -xpos; if (fx < 0) fx = 0, sx = -xpos;
for ( ; sx < swidth && fx < fwidth; fx++, sx++) { for ( ; sx < swidth && fx < fwidth; fx++, sx++) {
RGBPixel pix = (*ud)->GetPixel(fx, fy+composition_line); PixFmt &pix = (*ud)->Pixel(fx, fy+composition_line);
unsigned char a = 0xff - ((sline[sx] & 0xff000000) >> 24); unsigned char a = 0xff - sline[sx].A();
pix.r = ((sline[sx] & 0x00ff0000) >> 16) + a*pix.r/255; pix.R() = sline[sx].R() + a*pix.R()/255;
pix.g = ((sline[sx] & 0x0000ff00) >> 8) + a*pix.g/255; pix.G() = sline[sx].G() + a*pix.G()/255;
pix.b = (sline[sx] & 0x000000ff) + a*pix.b/255; pix.B() = sline[sx].B() + a*pix.B()/255;
(*ud)->SetPixel(fx, fy+composition_line, pix);
} }
} }
} }
@ -361,16 +455,12 @@ badtable:
int lines_to_compose = (slines_to_compose<flines_to_compose)?slines_to_compose:flines_to_compose; int lines_to_compose = (slines_to_compose<flines_to_compose)?slines_to_compose:flines_to_compose;
#pragma omp parallel for #pragma omp parallel for
for (int composition_line = 0; composition_line < lines_to_compose; composition_line++) { for (int composition_line = 0; composition_line < lines_to_compose; composition_line++) {
uint32_t *sline = (uint32_t*)(sdata + composition_line*sstride); PixelFormat::XRGB *sline = (PixelFormat::XRGB*)(sdata + composition_line*sstride);
int fx = xpos; int fx = xpos;
int sx = 0; int sx = 0;
if (fx < 0) fx = 0, sx = -xpos; if (fx < 0) fx = 0, sx = -xpos;
for ( ; sx < swidth && fx < fwidth; fx++, sx++) { for ( ; sx < swidth && fx < fwidth; fx++, sx++) {
RGBPixel pix( sline[sx] = PixelFormat::XRGB((*ud)->Pixel(fx, fy+composition_line));
(sline[sx] & 0x00ff0000) >> 16,
(sline[sx] & 0x0000ff00) >> 8,
sline[sx] & 0x000000ff);
(*ud)->SetPixel(fx, fy+composition_line, pix);
} }
} }
} }
@ -409,45 +499,45 @@ badtable:
// in the C++ code. It nicely hides all templatyness away into various implementations. // in the C++ code. It nicely hides all templatyness away into various implementations.
// This could probably have been designed better. Shame on me. // This could probably have been designed better. Shame on me.
class OverLuaFrameAggregate { class BaseImageAggregate {
public: public:
virtual RGBPixel GetPixel(unsigned x, unsigned y) = 0; virtual PixelFormat::ARGB GetPixel(int x, int y) = 0;
virtual void SetPixel(unsigned x, unsigned y, const RGBPixel &val) = 0; virtual void SetPixel(int x, int y, const PixelFormat::ARGB &val) = 0;
virtual unsigned GetWidth() = 0; virtual unsigned GetWidth() = 0;
virtual unsigned GetHeight() = 0; virtual unsigned GetHeight() = 0;
virtual void CreateLuaObject(lua_State *L) = 0; virtual void CreateLuaObject(lua_State *L) = 0;
}; };
template <ptrdiff_t Rpos, ptrdiff_t Gpos, ptrdiff_t Bpos, ptrdiff_t PixelWidth> template <class PixFmt>
class OverLuaFrameAggregateImpl : public OverLuaFrameAggregate { class BaseImageAggregateImpl : public BaseImageAggregate {
public: public:
typedef OverLuaVideoFrame<Rpos, Gpos, Bpos, PixelWidth> VideoFrameType; typedef BaseImage<PixFmt> ImageType;
private: private:
VideoFrameType *frame; ImageType *frame;
bool ownframe; bool ownframe;
public: public:
OverLuaFrameAggregateImpl(unsigned _width, unsigned _height, ptrdiff_t _stride, unsigned char *_data) BaseImageAggregateImpl(unsigned _width, unsigned _height, ptrdiff_t _stride, unsigned char *_data)
{ {
frame = new VideoFrameType(_width, _height, _stride, _data); frame = new ImageType(_width, _height, _stride, _data);
ownframe = true; ownframe = true;
} }
OverLuaFrameAggregateImpl(VideoFrameType *_frame) BaseImageAggregateImpl(ImageType *_frame)
{ {
frame = _frame; frame = _frame;
ownframe = false; ownframe = false;
} }
RGBPixel GetPixel(unsigned x, unsigned y) PixelFormat::ARGB GetPixel(int x, int y)
{ {
return frame->GetPixel(x, y); return PixelFormat::ARGB(frame->Pixel(x, y));
} }
void SetPixel(unsigned x, unsigned y, const RGBPixel &val) void SetPixel(int x, int y, const PixelFormat::ARGB &val)
{ {
frame->SetPixel(x, y, val); frame->Pixel(x, y) = PixFmt(val);
} }
unsigned GetWidth() unsigned GetWidth()
@ -468,15 +558,15 @@ public:
}; };
// All common, sensible formats // All common, sensible formats
typedef OverLuaFrameAggregateImpl<2, 1, 0, 3> OverLuaVideoFrameBGR; typedef BaseImageAggregateImpl<PixelFormat::RGB> ImageRGB;
typedef OverLuaFrameAggregateImpl<2, 1, 0, 4> OverLuaVideoFrameBGRX; typedef BaseImageAggregateImpl<PixelFormat::BGR> ImageBGR;
typedef OverLuaFrameAggregateImpl<2, 1, 0, 4> OverLuaVideoFrameBGRA; typedef BaseImageAggregateImpl<PixelFormat::RGBX> ImageRGBX;
typedef OverLuaFrameAggregateImpl<0, 1, 2, 3> OverLuaVideoFrameRGB; typedef BaseImageAggregateImpl<PixelFormat::BGRX> ImageBGRX;
typedef OverLuaFrameAggregateImpl<0, 1, 2, 4> OverLuaVideoFrameRGBX; typedef BaseImageAggregateImpl<PixelFormat::XRGB> ImageXRGB;
typedef OverLuaFrameAggregateImpl<0, 1, 2, 4> OverLuaVideoFrameRGBA; typedef BaseImageAggregateImpl<PixelFormat::XBGR> ImageXBGR;
typedef OverLuaFrameAggregateImpl<1, 2, 3, 4> OverLuaVideoFrameXRGB; typedef BaseImageAggregateImpl<PixelFormat::RGBA> ImageRGBA;
typedef OverLuaFrameAggregateImpl<1, 2, 3, 4> OverLuaVideoFrameARGB; typedef BaseImageAggregateImpl<PixelFormat::BGRA> ImageBGRA;
typedef OverLuaFrameAggregateImpl<3, 2, 1, 4> OverLuaVideoFrameXBGR; typedef BaseImageAggregateImpl<PixelFormat::ARGB> ImageARGB;
typedef OverLuaFrameAggregateImpl<3, 2, 1, 4> OverLuaVideoFrameABGR; typedef BaseImageAggregateImpl<PixelFormat::ABGR> ImageABGR;
#endif #endif