00001 #ifndef _FRAMEBUFFER_H_
00002 #define _FRAMEBUFFER_H_
00003
00004 #include <stdio.h>
00005 #include <string.h>
00006
00007 #include "vuColour.h"
00008
00009
00010 #define FB_FLOAT
00011
00012
00013
00014 typedef float fbtype;
00015
00021 template <int N>
00022 class FrameBuffer
00023 {
00024 friend class vuColour<N>;
00025 public:
00026
00028 FrameBuffer() {m_Buffer = 0; }
00029
00031 FrameBuffer(int width, int height)
00032 {
00033 m_Buffer = 0;
00034 setSize(width, height);
00035 }
00036
00038 ~FrameBuffer()
00039 {
00040 freeBuffer();
00041 }
00042
00044 int getNumberOfChannels() { return N; }
00046 int getHeight() { return m_Height; }
00048 int getWidth() { return m_Width; }
00050 float* getData() { return m_Buffer; }
00051
00053 bool setSize(int width, int height)
00054 {
00055 freeBuffer();
00056 m_Buffer = new float[ width * height * N];
00057 if(!m_Buffer) return false;
00058 m_Width = width;
00059 m_Height = height;
00060 return true;
00061 }
00062
00064 bool freeBuffer()
00065 {
00066 if(m_Buffer) delete [] m_Buffer;
00067 m_Buffer = 0;
00068 m_Width = 0;
00069 m_Height = 0;
00070 return true;
00071 }
00072
00078 bool copy(FrameBuffer<N>& fb, int x, int y)
00079 {
00080 if ((!fb.m_Buffer) ||
00081 (N != fb.getNumberOfChannels()) ||
00082 (x < 0 || y < 0) ||
00083 (x + fb.m_Width>m_Width)||
00084 (y + fb.m_Height>m_Height)) return false;
00085
00086 if(fb.getNumberOfChannels() == N)
00087 {
00088 int h = m_Height;
00089 int incdst = m_Width * N;
00090 int incsrc = fb.m_Width * N;
00091 float* src = fb.m_Buffer;
00092 float* dst = m_Buffer[y*m_Width + x];
00093 for(h=m_Height; h!=0; h--)
00094 {
00095 memcpy(dst,src,m_Width);
00096 dst += incdst;
00097 src += incsrc;
00098 }
00099 }
00100 else
00101 {
00102
00103 }
00104 return true;
00105 }
00106
00111 bool add(FrameBuffer<N>& fb, int x, int y)
00112 {
00113 if ((!fb.m_Buffer) ||
00114 (x < 0 || y < 0) ||
00115 (x + fb.m_Width>m_Width)||
00116 (y + fb.m_Height>m_Height)) return false;
00117
00118 int h = m_Height;
00119 int incdst = (m_Width-fb.m_Width) * N;
00120 register float* src = fb.m_Buffer;
00121 register float* dst = &m_Buffer[y*m_Width + x];
00122 for(h=m_Height; h!=0; h--)
00123 {
00124 for(int len = fb.m_Width * N;len!=0;len--)
00125 *(dst++) += *(src++);
00126 dst += incdst;
00127 }
00128 return true;
00129 }
00130
00131
00136 bool addColourWithMask(FrameBuffer<1>& fb, vuColour<N>& colour, int x, int y)
00137 {
00138 if ((!fb.getData()) ||
00139 (x < 0 || y < 0) ||
00140 (x + fb.getWidth()>m_Width)||
00141 (y + fb.getHeight()>m_Height)) return false;
00142
00143 int cpyh = fb.getHeight();
00144 int cpyw = fb.getWidth();
00145 int incdst = (m_Width-fb.getWidth()) * N;
00146 register float* src = fb.getData();
00147 register float* dst = &m_Buffer[(y*m_Width + x)*N];
00148 for(int h=cpyh; h!=0; h--) {
00149 for(register int len = cpyw; len!=0; len--) {
00150 register float *colval = colour.getData();
00151 register float alpha = (*src)*colour[3];
00152 for(register int comp = N-1; comp!=0; comp--, colval++) {
00153 *(dst++) += alpha*(*colval);
00154 }
00155 *(dst++) += *(src++)*(*colval);
00156 }
00157 dst += incdst;
00158 }
00159 return true;
00160 }
00161
00166 bool subColourWithMask(FrameBuffer<1>& fb, vuColour<N>& colour, int x, int y)
00167 {
00168 if ((!fb.getData()) ||
00169 (x < 0 || y < 0) ||
00170 (x + fb.getWidth()>m_Width)||
00171 (y + fb.getHeight()>m_Height)) return false;
00172
00173 int cpyh = fb.getHeight();
00174 int cpyw = fb.getWidth();
00175 int incdst = (m_Width-fb.getWidth()) * N;
00176 register float* src = fb.getData();
00177 register float* dst = &m_Buffer[(y*m_Width + x)*N];
00178 for(int h=cpyh; h!=0; h--) {
00179 for(register int len = cpyw; len!=0; len--) {
00180 register float *colval = colour;
00181 for(register int comp = N-1; comp!=0; comp--, colval++) {
00182 *(dst++) -= (*src)*(*colval);
00183 }
00184 *(dst++) -= *(src++)*(*colval);
00185 }
00186 dst += incdst;
00187 }
00188 return true;
00189 }
00190
00195 bool addColourWithM1subM2(FrameBuffer<1>& m1, FrameBuffer<1>& m2,
00196 vuColour<N>& colour, const int x, const int y)
00197 {
00198 if ((!m1.getData()) ||
00199 (!m2.getData()) ||
00200 ( m1.getWidth()!=m2.getWidth()) ||
00201 ( m1.getHeight()!=m2.getHeight()) ||
00202 (x < 0 || y < 0) ||
00203 (x + m1.getWidth()>m_Width)||
00204 (y + m1.getHeight()>m_Height)) return false;
00205
00206 int cpyh = m1.getHeight();
00207 int cpyw = m1.getWidth();
00208 int incdst = (m_Width-m1.getWidth()) * N;
00209 if (N != 4) {
00210 register float* datm1 = m1.getData();
00211 register float* datm2 = m2.getData();
00212 register float* dst = &m_Buffer[(y*m_Width + x)*N];
00213 float *col = colour.getData();
00214 for(int h=cpyh; h!=0; h--) {
00215 for(register int len = cpyw; len!=0; len--) {
00216 float a = ((*datm1)-(*datm2))*col[N-1];
00217 for(int comp = 0; comp<N-1; comp++) {
00218 *(dst++) += a*col[comp];
00219 }
00220 *(dst++) += a;
00221 if(*(dst-1)>1) {
00222
00223 *(dst-1) = .99;
00224 }
00225 datm1++; datm2++;
00226 }
00227 dst += incdst;
00228 }
00229 } else {
00230 register float* datm1 = m1.getData();
00231 register float* datm2 = m2.getData();
00232 register float* dst = &m_Buffer[(y*m_Width + x)*N];
00233 float *col = colour.getData();
00234 for(int h=cpyh; h!=0; h--) {
00235 for(register int len = cpyw; len!=0; len--) {
00236 register float a = ((*datm1)-(*datm2))*col[N-1];
00237 register float *comp = col;
00238 *(dst++) += a*(*comp++);
00239 *(dst++) += a*(*comp++);
00240 *(dst++) += a*(*comp++);
00241 *(dst++) += a;
00242 datm1++; datm2++;
00243 }
00244 dst += incdst;
00245 }
00246 }
00247 return true;
00248 }
00249
00251 bool blendOver(FrameBuffer<N>& fb, int x, int y)
00252 {
00253 if ((!fb.getData()) ||
00254 (x < 0 || y < 0) ||
00255 (x + fb.getWidth()>m_Width)||
00256 (y + fb.getHeight()>m_Height)) return false;
00257
00258 int cpyh = fb.getHeight();
00259 int cpyw = fb.getWidth();
00260 int incdst = (m_Width-fb.getWidth()) * N;
00261 register float* src = fb.getData();
00262 register float* dst = &m_Buffer[(y*m_Width + x)*N];
00263 for(int h=cpyh; h!=0; h--) {
00264 for(register int len = cpyw; len!=0; len--) {
00265
00266 float a2 = 1-src[N-1];
00267 for(register int comp = 0;
00268 comp<N-1;
00269 comp++, dst++, src++) {
00270 *(dst) = (*dst)*a2 + (*src);
00271 }
00272 dst++;
00273 src++;
00274 }
00275 dst += incdst;
00276 }
00277 return true;
00278 }
00279
00281 bool blendOver(FrameBuffer<N>& fb)
00282 {
00283 if ((!fb.getData()) ||
00284 (fb.getWidth()!=m_Width)||
00285 (fb.getHeight()!=m_Height)) return false;
00286 if(N!=4) {
00287 int cpylen = fb.getHeight()*fb.getWidth();
00288 register float* src = fb.getData();
00289 register float* dst = m_Buffer;
00290 for(register int len = cpylen; len!=0; len--) {
00291 float a2 = 1-src[N-1];
00292 for(register int comp = 0;
00293 comp<N-1;
00294 comp++, dst++, src++) {
00295 *(dst) = (*dst)*a2 + (*src);
00296 }
00297 dst++;
00298 src++;
00299 }
00300 } else {
00301 int cpylen = fb.getHeight()*fb.getWidth();
00302 register float* src = fb.getData();
00303 register float* dst = m_Buffer;
00304 for(register int len = cpylen; len!=0; len--) {
00305 register float a2 = 1-src[N-1];
00306
00307 *(dst++) = (*dst)*a2 + (*src++);
00308 *(dst++) = (*dst)*a2 + (*src++);
00309 *(dst++) = (*dst)*a2 + (*src++);
00310
00311 dst++;
00312 src++;
00313 }
00314 }
00315 return true;
00316 }
00317
00321 bool blendUnder(FrameBuffer<N>& fb, int x, int y)
00322 {
00323 if ((!fb.getData()) ||
00324 (x < 0 || y < 0) ||
00325 (x + fb.getWidth()>m_Width)||
00326 (y + fb.getHeight()>m_Height)) return false;
00327
00328 int cpyh = fb.getHeight();
00329 int cpyw = fb.getWidth();
00330 int incdst = (m_Width-fb.getWidth()) * N;
00331 register float* src = fb.getData();
00332 register float* dst = &m_Buffer[(y*m_Width + x)*N];
00333 for(int h=cpyh; h!=0; h--) {
00334 for(register int len = cpyw; len!=0; len--) {
00335 float a = src[N-1]*dst[N-1];
00336 float t = 1-dst[N-1];
00337 for(register int comp = 0;
00338 comp<N-1;
00339 comp++, dst++, src++) {
00340 *(dst) = *(dst)*t + (*src)*a;
00341 }
00342 *(dst++) *= 1-(*(src++));
00343 }
00344 dst += incdst;
00345 }
00346 return true;
00347 }
00348
00350 bool blendUnder(FrameBuffer<N>& fb)
00351 {
00352 if ((!fb.getData()) ||
00353 (fb.getWidth()!=m_Width)||
00354 (fb.getHeight()!=m_Height)) return false;
00355 if(N!=4) {
00356 int cpylen = fb.getHeight()*fb.getWidth();
00357 register float* src = fb.getData();
00358 register float* dst = m_Buffer;
00359 for(register int len = cpylen; len!=0; len--) {
00360 float a2 = 1-src[N-1];
00361 for(register int comp = 0;
00362 comp<N-1;
00363 comp++, dst++, src++) {
00364 *(dst) = (*dst)*a2 + (*src);
00365 }
00366 dst++;
00367 src++;
00368 }
00369 } else {
00370 int cpylen = fb.getHeight()*fb.getWidth();
00371 register float* src = fb.getData();
00372 register float* dst = m_Buffer;
00373 for(register int len = cpylen; len!=0; len--) {
00374 register float t = (1-dst[N-1]);
00375
00376 *(dst++) += *(src++)*t;
00377 *(dst++) += *(src++)*t;
00378 *(dst++) += *(src++)*t;
00379
00380 *(dst++) += *(src++)*t;
00381 }
00382 }
00383 return true;
00384 }
00385
00387 bool clear(const vuColour<N> colour)
00388 {
00389 if(m_Buffer == 0) return false;
00390 float col[] = {colour[0],colour[1],colour[2],colour[3]};
00391 float *dst = m_Buffer;
00392 for(register int i = m_Width*m_Height; i!=0; i--) {
00393 memcpy(dst,col,sizeof(float)*N);
00394 dst += N;
00395 }
00396 return true;
00397 }
00398
00401 bool print()
00402 {
00403 if(m_Buffer == 0) return false;
00404 float *buf = m_Buffer;
00405 for(int i = 0; i<m_Height; i++) {
00406 for(int j = 0;j<m_Width; j++) {
00407 printf("[%3i,%3i] = (%4.5f", j, i, *(buf++));
00408 for(int c = 1; c<N; c++, buf++){
00409 printf(", %4.5f", *buf);
00410 }
00411 printf(")\n");
00412 }
00413 putchar('\n');
00414 }
00415 return true;
00416 }
00417
00418 protected:
00419 int m_Width, m_Height;
00420 float *m_Buffer;
00421 };
00422
00423
00425 typedef FrameBuffer<1> AlphaMask;
00429 typedef FrameBuffer<4> RGBABuffer;
00430
00431
00432
00433 #endif