diff options
author | george82 <george82@3789f03b-4d11-0410-bbf8-ca57d06f2519> | 2006-11-20 15:55:05 +0000 |
---|---|---|
committer | george82 <george82@3789f03b-4d11-0410-bbf8-ca57d06f2519> | 2006-11-20 15:55:05 +0000 |
commit | 4ff6675967dcedfc240cb17f16c92a57455583b2 (patch) | |
tree | 91312c1c2c5bd36ed1ed1263edb4af3d2f972bab /common | |
parent | ba9299d327aa223b2452c9c58ce1e62b4026217c (diff) | |
download | tigervnc-4ff6675967dcedfc240cb17f16c92a57455583b2.tar.gz tigervnc-4ff6675967dcedfc240cb17f16c92a57455583b2.zip |
Now ScaledPixelBuffer class using the weighting tabs for
scaling. Maked ScaledPixelBuffer class code independent
from the scaling filter.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2118 3789f03b-4d11-0410-bbf8-ca57d06f2519
Diffstat (limited to 'common')
-rw-r--r-- | common/rfb/ScaledPixelBuffer.cxx | 141 | ||||
-rw-r--r-- | common/rfb/ScaledPixelBuffer.h | 18 |
2 files changed, 106 insertions, 53 deletions
diff --git a/common/rfb/ScaledPixelBuffer.cxx b/common/rfb/ScaledPixelBuffer.cxx index da624b21..820817e1 100644 --- a/common/rfb/ScaledPixelBuffer.cxx +++ b/common/rfb/ScaledPixelBuffer.cxx @@ -23,13 +23,15 @@ #include <math.h> #include <memory.h> +#include <stdlib.h> using namespace rdr; using namespace rfb; ScaledPixelBuffer::ScaledPixelBuffer(U8 **src_data_, int src_width_, int src_height_, int scale, PixelFormat pf_) - : scaled_data(0), scale_ratio(1) { + : xWeightTabs(0), yWeightTabs(0), scaled_data(0), scale_ratio(1), + scaleFilterID(scaleFilterBicubic) { setSourceBuffer(src_data_, src_width_, src_height_); setPF(pf_); @@ -37,93 +39,128 @@ ScaledPixelBuffer::ScaledPixelBuffer(U8 **src_data_, int src_width_, ScaledPixelBuffer::ScaledPixelBuffer() : src_data(0), src_width(0), src_height(0), scale_ratio(1), scaled_width(0), - scaled_height(0), pf(PixelFormat(32,24,0,1,255,255,255,0,8,16)), - scaled_data(0) { + xWeightTabs(0), yWeightTabs(0), scaled_height(0), scaled_data(0), + scaleFilterID(scaleFilterBicubic) { + memset(&pf, 0, sizeof(pf)); } ScaledPixelBuffer::~ScaledPixelBuffer() { + freeWeightTabs(); +} + +void ScaledPixelBuffer::freeWeightTabs() { + if (xWeightTabs) { + for (int i = 0; i < scaled_width; i++) delete [] xWeightTabs[i].weight; + delete [] xWeightTabs; + xWeightTabs = 0; + } + if (yWeightTabs) { + for (int i = 0; i < scaled_height; i++) delete [] yWeightTabs[i].weight; + delete [] yWeightTabs; + yWeightTabs = 0; + } } void ScaledPixelBuffer::setSourceBuffer(U8 **src_data_, int w, int h) { + freeWeightTabs(); src_data = src_data_; src_width = w; src_height = h; calculateScaledBufferSize(); + scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs); + scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs); } void ScaledPixelBuffer::setPF(const PixelFormat &pf_) { - if (pf_.depth != 24) throw rfb::UnsupportedPixelFormatException(); + ///if (pf_.depth != 24) throw rfb::UnsupportedPixelFormatException(); pf = pf_; } void ScaledPixelBuffer::setScaleRatio(double scale_ratio_) { if (scale_ratio != scale_ratio_) { + freeWeightTabs(); scale_ratio = scale_ratio_; calculateScaledBufferSize(); + scaleFilters.makeWeightTabs(scaleFilterID, src_width, scaled_width, &xWeightTabs); + scaleFilters.makeWeightTabs(scaleFilterID, src_height, scaled_height, &yWeightTabs); } } -void ScaledPixelBuffer::scaleRect(const Rect& r) { - static U8 *src_ptr, *ptr; - static U8 r0, r1, r2, r3; - static U8 g0, g1, g2, g3; - static U8 b0, b1, b2, b3; +inline void ScaledPixelBuffer::rgbFromPixel(U32 p, int &r, int &g, int &b) { + r = (((p >> pf.redShift ) & pf.redMax ) * 255 + pf.redMax /2) / pf.redMax; + g = (((p >> pf.greenShift) & pf.greenMax) * 255 + pf.greenMax/2) / pf.greenMax; + b = (((p >> pf.blueShift ) & pf.blueMax ) * 255 + pf.blueMax /2) / pf.blueMax; +} + +inline U32 ScaledPixelBuffer::getSourcePixel(int x, int y) { + int bytes_per_pixel = pf.bpp / 8; + U8 *ptr = &(*src_data)[(x + y*src_width)*bytes_per_pixel]; + if (bytes_per_pixel == 1) { + return *ptr; + } else if (bytes_per_pixel == 2) { + int b0 = *ptr++; int b1 = *ptr; + return b1 << 8 | b0; + } else if (bytes_per_pixel == 4) { + int b0 = *ptr++; int b1 = *ptr++; + int b2 = *ptr++; int b3 = *ptr; + return b3 << 24 | b2 << 16 | b1 << 8 | b0; + } else { + return 0; + } +} + +void ScaledPixelBuffer::scaleRect(const Rect& rect) { + U8 *src_ptr, *ptr; static double c1_sub_dx, c1_sub_dy; - static double dx, dy; - static int i, j; - static Rect changed_rect; + Rect changed_rect; + float rx, gx, bx; + float red, green, blue; + int r, g, b; + // Calculate the changed pixel rect in the scaled image - changed_rect = calculateScaleBoundary(r); + changed_rect = calculateScaleBoundary(rect); - // Scale the source rect to the destination image buffer using - // bilinear interplation - for (int y = changed_rect.tl.y; y < changed_rect.br.y; y++) { - j = (int)(dy = y / scale_ratio); - dy -= j; - c1_sub_dy = 1 - dy; + int bytesPerPixel = pf.bpp/8; + int bytesPerRow = src_width * bytesPerPixel; + for (int y = changed_rect.tl.y; y < changed_rect.br.y; y++) { + ptr = &(*scaled_data)[(changed_rect.tl.x + y*scaled_width) * bytesPerPixel]; + for (int x = changed_rect.tl.x; x < changed_rect.br.x; x++) { - ptr = &(*scaled_data)[(x + y*scaled_width) * 4]; - - i = (int)(dx = x / scale_ratio); - dx -= i; - c1_sub_dx = 1 - dx; - - src_ptr = &(*src_data)[(i + (j*src_width))*4]; - b0 = *src_ptr; g0 = *(src_ptr+1); r0 = *(src_ptr+2); - if (i+1 < src_width) { - b1 = *(src_ptr+4); g1 = *(src_ptr+5); r1 = *(src_ptr+6); - } else { - b1 = b0; r1 = r0; g1 = g0; - } - if (j+1 < src_height) { - src_ptr += src_width * 4; - b3 = *src_ptr; g3 = *(src_ptr+1); r3 = *(src_ptr+2); - } else { - b3 = b0; r3 = r0; g3 = g0; - } - if ((i+1 < src_width) && (j+1 < src_height)) { - b2 = *(src_ptr+4); g2 = *(src_ptr+5); r2 = *(src_ptr+6); - } else if (i+1 >= src_width) { - b2 = b3; r2 = r3; g2 = g3; - } else { - b2 = b1; r2 = r1; g2 = g1; + + int ywi = 0; red = 0; green = 0; blue = 0; + for (int ys = yWeightTabs[y].i0; ys < yWeightTabs[y].i1; ys++) { + + int xwi = 0; rx = 0; gx = 0; bx = 0; + for (int xs = xWeightTabs[x].i0; xs < xWeightTabs[x].i1; xs++) { + rgbFromPixel(getSourcePixel(xs, ys), r, g, b); + rx += r * xWeightTabs[x].weight[xwi]; + gx += g * xWeightTabs[x].weight[xwi]; + bx += b * xWeightTabs[x].weight[xwi]; + xwi++; + } + red += rx * yWeightTabs[y].weight[ywi]; + green += gx * yWeightTabs[y].weight[ywi]; + blue += bx * yWeightTabs[y].weight[ywi]; + ywi++; } - *ptr++ = (U8)((b0*c1_sub_dx+b1*dx)*c1_sub_dy + (b3*c1_sub_dx+b2*dx)*dy); - *ptr++ = (U8)((g0*c1_sub_dx+g1*dx)*c1_sub_dy + (g3*c1_sub_dx+g2*dx)*dy); - *ptr = (U8)((r0*c1_sub_dx+r1*dx)*c1_sub_dy + (r3*c1_sub_dx+r2*dx)*dy); + *ptr++ = U8(blue); + *ptr++ = U8(green); + *ptr++ = U8(red); + ptr++; } } } Rect ScaledPixelBuffer::calculateScaleBoundary(const Rect& r) { - static int x_start, y_start, x_end, y_end; - x_start = r.tl.x == 0 ? 0 : int(ceil((r.tl.x-1) * scale_ratio)); - y_start = r.tl.y == 0 ? 0 : int(ceil((r.tl.y-1) * scale_ratio)); - x_end = int(ceil(r.br.x * scale_ratio - 1)); + int x_start, y_start, x_end, y_end; + double sup = scaleFilters[scaleFilterID].radius; + x_start = r.tl.x-sup < 0 ? 0 : int((r.tl.x-sup) * scale_ratio + 1); + y_start = r.tl.y-sup < 0 ? 0 : int((r.tl.y-sup) * scale_ratio + 1); + x_end = int((r.br.x+sup-1) * scale_ratio); x_end = x_end < scaled_width ? x_end + 1 : scaled_width; - y_end = int(ceil(r.br.y * scale_ratio - 1)); + y_end = int((r.br.y+sup-1) * scale_ratio); y_end = y_end < scaled_height ? y_end + 1 : scaled_height; return Rect(x_start, y_start, x_end, y_end); } diff --git a/common/rfb/ScaledPixelBuffer.h b/common/rfb/ScaledPixelBuffer.h index 7e2b0f70..a29cbdfb 100644 --- a/common/rfb/ScaledPixelBuffer.h +++ b/common/rfb/ScaledPixelBuffer.h @@ -26,6 +26,7 @@ #include <rdr/Exception.h> #include <rfb/Rect.h> #include <rfb/PixelFormat.h> +#include <rfb/ScaleFilters.h> using namespace rdr; @@ -51,6 +52,10 @@ namespace rfb { int getScale() const { return int(scale_ratio * 100 + 0.5); } double getScaleRatio() const { return scale_ratio; } + // Pixel manipulation routines + inline U32 getSourcePixel(int x, int y); + inline void rgbFromPixel(U32 p, int &r, int &g, int &b); + // Get rectangle encompassing this buffer // Top-left of rectangle is either at (0,0), or the specified point. Rect getRect() const { return Rect(0, 0, scaled_width, scaled_height); } @@ -61,6 +66,10 @@ namespace rfb { // Set the new source buffer and its parameters void setSourceBuffer(U8 **src_data, int w, int h); + void setScaledBuffer(U8 **scaled_data_) { + scaled_data = scaled_data_; + }; + // Set the new pixel format void setPF(const PixelFormat &pf); @@ -80,7 +89,10 @@ namespace rfb { // Calculate the scaled buffer size depending on the source buffer // parameters (width, height, pixel format) - void calculateScaledBufferSize(); + virtual void calculateScaledBufferSize(); + + // Free the weight tabs for x and y + virtual void freeWeightTabs(); int src_width; @@ -89,6 +101,10 @@ namespace rfb { int scaled_height; PixelFormat pf; double scale_ratio; + unsigned int scaleFilterID; + ScaleFilters scaleFilters; + SFilterWeightTab *xWeightTabs; + SFilterWeightTab *yWeightTabs; U8 **src_data; U8 **scaled_data; }; |