Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksey Lim <alsroot@member.fsf.org>2009-02-19 06:34:10 (GMT)
committer Aleksey Lim <alsroot@member.fsf.org>2009-02-20 00:03:07 (GMT)
commit3bf19ed84024bf7005e3fe6639d3394405df4867 (patch)
tree05f22b775967ba191e8aee62278d805811a82457
parent1c66573c30e9ebec4ad78dab282c702de12f9552 (diff)
Support 24/32 screen depths in color picker; optimization
-rwxr-xr-xcolors.py4
-rw-r--r--colorsc/Makefile2
-rw-r--r--colorsc/canvas.h121
-rw-r--r--colorsc/colorsc.h14
-rw-r--r--colorsc/palette.h97
5 files changed, 172 insertions, 66 deletions
diff --git a/colors.py b/colors.py
index 1823620..9d27853 100755
--- a/colors.py
+++ b/colors.py
@@ -1833,12 +1833,12 @@ class Colors(activity.Activity, ExportedGObject):
canvasimage = gtk.gdk.Image(gtk.gdk.IMAGE_FASTEST, gtk.gdk.visual_get_system(), 1200, 800)
start = time.time()
for i in range(0,100):
- canvas.blit_2x(canvasimage, 0, 0, 600, 400)
+ canvas.blit_2x(canvasimage, 0, 0, 0, 0, 600, 400, False)
log.debug("Canvas 2.0x blit benchmark: %f sec", time.time()-start)
# Benchmark a Palette object.
palette = Palette(500)
- paletteimage = gtk.gdk.Image(gtk.gdk.IMAGE_FASTEST, gtk.gdk.visual_get_system(), 500, 500)
+ paletteimage = gtk.gdk.Image(gtk.gdk.IMAGE_FASTEST, gtk.gdk.visual_get_system(), BrushControlsPanel.PALETTE_SIZE, BrushControlsPanel.PALETTE_SIZE)
start = time.time()
for i in range(0,100):
palette.render_wheel(paletteimage)
diff --git a/colorsc/Makefile b/colorsc/Makefile
index 87bfff0..eefc014 100644
--- a/colorsc/Makefile
+++ b/colorsc/Makefile
@@ -2,7 +2,7 @@ CXXFLAGS = $(shell pkg-config --cflags gdk-x11-2.0) \
$(shell pkg-config --cflags gstreamer-0.10) \
$(shell pkg-config --cflags pygtk-2.0) \
$(shell python-config --cflags) \
- -fPIC
+ -fPIC -O2
LDFLAGS = $(shell pkg-config --libs gdk-x11-2.0) \
$(shell pkg-config --libs gstreamer-0.10) \
$(shell pkg-config --libs pygtk-2.0) \
diff --git a/colorsc/canvas.h b/colorsc/canvas.h
index 6877758..7951d65 100644
--- a/colorsc/canvas.h
+++ b/colorsc/canvas.h
@@ -1042,9 +1042,6 @@ public:
// Draws a region of the canvas into a GdkImage for display on the screen, with optional scaling
// and darkening.
- typedef guint16 depth16_t;
- typedef guint32 depth24_t;
-
inline
void to_pixel(guint src, depth16_t *dst)
{
@@ -1060,18 +1057,70 @@ public:
*dst = src & 0xffffff;
}
- template <typename pixel_t> inline
- void fill_pixel(pixel_t **rows, int scale, pixel_t value)
+ struct scale1_t
{
- for (int y = scale; y--;)
- for (int x = scale; x--;)
- *rows[y]++ = value;
- }
+ static const int value = 1;
+
+ template <typename pixel_t> inline static
+ void fill_pixel(pixel_t **rows, pixel_t value)
+ {
+ *rows[0]++ = value;
+ }
+ };
+
+ struct scale2_t
+ {
+ static const int value = 2;
+
+ template <typename pixel_t> inline static
+ void fill_pixel(pixel_t **rows, pixel_t value)
+ {
+ *rows[0]++ = value; *rows[0]++ = value;
+
+ *rows[1]++ = value; *rows[1]++ = value;
+ }
+ };
+
+ struct scale4_t
+ {
+ static const int value = 4;
- template <typename pixel_t>
+ template <typename pixel_t> inline static
+ void fill_pixel(pixel_t **rows, pixel_t value)
+ {
+ *rows[0]++ = value; *rows[0]++ = value;
+ *rows[0]++ = value; *rows[0]++ = value;
+
+ *rows[1]++ = value; *rows[1]++ = value;
+ *rows[1]++ = value; *rows[1]++ = value;
+ }
+ };
+
+ struct scale8_t
+ {
+ static const int value = 8;
+
+ template <typename pixel_t> inline static
+ void fill_pixel(pixel_t **rows, pixel_t value)
+ {
+ *rows[0]++ = value; *rows[0]++ = value;
+ *rows[0]++ = value; *rows[0]++ = value;
+ *rows[0]++ = value; *rows[0]++ = value;
+ *rows[0]++ = value; *rows[0]++ = value;
+
+ *rows[1]++ = value; *rows[1]++ = value;
+ *rows[1]++ = value; *rows[1]++ = value;
+ *rows[1]++ = value; *rows[1]++ = value;
+ *rows[1]++ = value; *rows[1]++ = value;
+ }
+ };
+
+ template <typename pixel_t, typename scale_t> inline
void blit(GdkImage *img, int src_x, int src_y, int dest_x,
- int dest_y, int dest_w, int dest_h, bool overlay, int scale)
+ int dest_y, int dest_w, int dest_h, bool overlay)
{
+ if (scale_t::value != 2) return;
+ int scale = 2;
pixel_t *pixels = (pixel_t*)img->mem;
int pitch = img->bpl/sizeof(pixel_t);
@@ -1098,14 +1147,14 @@ public:
pixel_t* __restrict rows[scale];
rows[0] = &pixels[cdy*pitch+dest_x];
- for (int i = 1; i < scale; ++i) rows[i] = rows[i-1] + pitch;
+ rows[1] = rows[0] + pitch;
if (csy < 0 || csy >= height)
{
for (int cdx = 0; cdx < dest_w; cdx += scale)
{
pixel_t p = 0;
- fill_pixel((pixel_t**)rows, scale, p);
+ scale_t::fill_pixel((pixel_t**)rows, p);
}
}
else
@@ -1118,7 +1167,7 @@ public:
while (csx < 0 && cdx < dest_w)
{
pixel_t p = 0;
- fill_pixel((pixel_t**)rows, scale, p);
+ scale_t::fill_pixel((pixel_t**)rows, p);
src++;
csx++;
cdx += scale;
@@ -1133,7 +1182,7 @@ public:
p >>= 2;
pixel_t rgb;
to_pixel(p, &rgb);
- fill_pixel((pixel_t**)rows, scale, rgb);
+ scale_t::fill_pixel((pixel_t**)rows, rgb);
src++;
csx++;
cdx += scale;
@@ -1145,7 +1194,7 @@ public:
{
pixel_t rgb;
to_pixel(*src, &rgb);
- fill_pixel((pixel_t**)rows, scale, rgb);
+ scale_t::fill_pixel((pixel_t**)rows, rgb);
src++;
csx++;
cdx += scale;
@@ -1155,7 +1204,7 @@ public:
while (cdx < dest_w)
{
pixel_t p = 0;
- fill_pixel((pixel_t**)rows, scale, p);
+ scale_t::fill_pixel((pixel_t**)rows, p);
src++;
csx++;
cdx += scale;
@@ -1166,36 +1215,44 @@ public:
}
}
- inline
+ template <typename scale_t> inline
void blit_x(GdkImage *img, int src_x, int src_y, int dest_x, int dest_y,
- int dest_w, int dest_h, bool overlay, int scale)
+ int dest_w, int dest_h, bool overlay)
{
if (img->depth == 16)
- blit<depth16_t>(img, src_x, src_y, dest_x, dest_y, dest_w, dest_h,
- overlay, scale);
+ blit<depth16_t, scale_t>(img, src_x, src_y, dest_x, dest_y,
+ dest_w, dest_h, overlay);
else
- blit<depth24_t>(img, src_x, src_y, dest_x, dest_y, dest_w, dest_h,
- overlay, scale);
+ blit<depth24_t, scale_t>(img, src_x, src_y, dest_x, dest_y,
+ dest_w, dest_h, overlay);
}
- void blit_1x(GdkImage* img, int src_x, int src_y, int dest_x, int dest_y, int dest_w, int dest_h, bool overlay)
+ void blit_1x(GdkImage* img, int src_x, int src_y, int dest_x, int dest_y,
+ int dest_w, int dest_h, bool overlay)
{
- blit_x(img, src_x, src_y, dest_x, dest_y, dest_w, dest_h, overlay, 1);
+ blit_x<scale1_t> (img, src_x, src_y, dest_x, dest_y, dest_w, dest_h,
+ overlay);
}
- void blit_2x(GdkImage* img, int src_x, int src_y, int dest_x, int dest_y, int dest_w, int dest_h, bool overlay)
+ void blit_2x(GdkImage* img, int src_x, int src_y, int dest_x, int dest_y,
+ int dest_w, int dest_h, bool overlay)
{
- blit_x(img, src_x, src_y, dest_x, dest_y, dest_w, dest_h, overlay, 2);
+ blit<depth16_t, scale2_t>(img, src_x, src_y, dest_x, dest_y, dest_w, dest_h, overlay);
}
- void blit_4x(GdkImage* img, int src_x, int src_y, int dest_x, int dest_y, int dest_w, int dest_h, bool overlay)
+ void blit_4x(GdkImage* img, int src_x, int src_y, int dest_x, int dest_y,
+ int dest_w, int dest_h, bool overlay)
{
- blit_x(img, src_x, src_y, dest_x, dest_y, dest_w, dest_h, overlay, 4);
+ blit_x<scale4_t> (img, src_x, src_y, dest_x, dest_y, dest_w, dest_h,
+ overlay);
}
-
- void blit_8x(GdkImage* img, int src_x, int src_y, int dest_x, int dest_y, int dest_w, int dest_h, bool overlay)
+
+
+ void blit_8x(GdkImage* img, int src_x, int src_y, int dest_x, int dest_y,
+ int dest_w, int dest_h, bool overlay)
{
- blit_x(img, src_x, src_y, dest_x, dest_y, dest_w, dest_h, overlay, 8);
+ blit_x<scale8_t> (img, src_x, src_y, dest_x, dest_y, dest_w, dest_h,
+ overlay);
}
//---------------------------------------------------------------------------------------------
diff --git a/colorsc/colorsc.h b/colorsc/colorsc.h
index 2e4c372..7e4c1fa 100644
--- a/colorsc/colorsc.h
+++ b/colorsc/colorsc.h
@@ -27,6 +27,9 @@ using namespace std;
#include <cmath>
#include <float.h>
+typedef guint16 depth16_t;
+typedef guint32 depth24_t;
+
static const float PI = 3.14159f;
inline float sgn(float a) { if (a>0) return 1; if (a<0) return -1; return 0; }
@@ -107,6 +110,17 @@ struct Color
return c;
}
unsigned int get_r5g6b5() { return ((r>>3)<<11) | ((g>>2)<<5) | (b>>3); }
+
+ void to_pixel(depth16_t *pixel)
+ {
+ *pixel = ((r>>3)<<11) | ((g>>2)<<5) | (b>>3);
+ }
+
+ void to_pixel(depth24_t *pixel)
+ {
+ *pixel = (r<<16) | (g<<8) | b;
+ }
+
static Color create_from_r5g6b5(unsigned short v)
{
Color c;
diff --git a/colorsc/palette.h b/colorsc/palette.h
index 03d51eb..9bdeb33 100644
--- a/colorsc/palette.h
+++ b/colorsc/palette.h
@@ -181,10 +181,10 @@ public:
*p2 = center + Pos::create_from_angle(palette_h+240.0f, size/2-WHEEL_WIDTH);
}
- // The wheel never changes, so it can be rendered once here. This also clears the image background.
- void render_wheel(GdkImage* image)
+ template <typename pixel_t> inline
+ void _render_wheel(GdkImage* image)
{
- if (image->width != size || image->height != size || image->bits_per_pixel != 16)
+ if (image->width != size || image->height != size)
{
fprintf(stderr, "Error: Invalid Palette GdkImage.\n");
return;
@@ -196,12 +196,12 @@ public:
float ring_min_sqr = sqr(wheel_radius-WHEEL_WIDTH);
float ring_max_sqr = sqr(wheel_radius);
- unsigned short* pixels = (unsigned short*)image->mem;
- int stride = image->bpl/sizeof(unsigned short);
+ pixel_t* pixels = (pixel_t*)image->mem;
+ int stride = image->bpl/sizeof(pixel_t);
for (int y = 0; y < size; y++)
{
- unsigned short* row = &pixels[y*stride];
+ pixel_t* row = &pixels[y*stride];
for (int x = 0; x < size; x++)
{
// Get radius from center of palette.
@@ -218,28 +218,36 @@ public:
while (h>360.0f) h -= 360.0f;
float r, g, b;
hsv_to_rgb(&r, &g, &b, h, 1.0f, 1.0f);
- *row++ = Color::create_from_float(r, g, b, 1).get_r5g6b5();
+ Color::create_from_float(r, g, b, 1).to_pixel(row);
}
else
- *row++ = bkg.get_r5g6b5();
+ bkg.to_pixel(row);
+ ++row;
}
}
}
- // Clears out the inner circle and redraws the color triangle, as fast as possible.
- // Scales up implicitly by 2x to improve performance.
- // The appearance was an accident which creates a kind of blobby triangle, like the intersection of three circles.
- // But I like the look so I'm keeping it!
- void render_triangle(GdkImage* image)
+ // The wheel never changes, so it can be rendered once here. This also clears the image background.
+ void render_wheel(GdkImage* image)
{
- if (image->width != size || image->height != size || image->bits_per_pixel != 16 || (size&1))
+ if (image->depth == 16)
+ _render_wheel<depth16_t>(image);
+ else
+ _render_wheel<depth24_t>(image);
+ }
+
+ template <typename pixel_t>
+ void _render_triangle(GdkImage* image)
+ {
+ if (image->width != size || image->height != size || (size&1))
{
fprintf(stderr, "Error: Invalid Palette GdkImage.\n");
return;
}
Color bkg(64, 64, 64, 0);
- unsigned short bkgc = bkg.get_r5g6b5();
+ pixel_t bkgc;
+ bkg.to_pixel(&bkgc);
Pos p0, p1, p2;
get_triangle_points(&p0, &p1, &p2);
@@ -253,15 +261,15 @@ public:
int x0 = WHEEL_WIDTH;
int x1 = size-WHEEL_WIDTH;
- unsigned short* pixels = (unsigned short*)image->mem;
- int stride = image->bpl/sizeof(unsigned short);
+ pixel_t* pixels = (pixel_t*)image->mem;
+ int stride = image->bpl/sizeof(pixel_t);
Pos p(x0,x0);
for (int y = x0; y < x1; y+=2, p.y += 2.0f)
{
p.x = x0;
- unsigned short* __restrict row0 = &pixels[(y+0)*stride+x0];
- unsigned short* __restrict row1 = &pixels[(y+1)*stride+x0];
+ pixel_t* __restrict row0 = &pixels[(y+0)*stride+x0];
+ pixel_t* __restrict row1 = &pixels[(y+1)*stride+x0];
for (int x = x0; x < x1; x+=2, p.x += 2.0f)
{
// Calculate position inside triangle. If inside, then use as HSV.
@@ -272,7 +280,8 @@ public:
{
float r, g, b;
hsv_to_rgb(&r, &g, &b, palette_h, 1.0f-sqrtf(d0_sqr)*inv_triangle_side, sqrtf(d2_sqr)*inv_triangle_side);
- unsigned short c = Color::create_from_float(r, g, b, 1).get_r5g6b5();
+ pixel_t c;
+ Color::create_from_float(r, g, b, 1).to_pixel(&c);
row0[0] = c;
row0[1] = c;
row1[0] = c;
@@ -295,6 +304,18 @@ public:
}
}
+ // Clears out the inner circle and redraws the color triangle, as fast as possible.
+ // Scales up implicitly by 2x to improve performance.
+ // The appearance was an accident which creates a kind of blobby triangle, like the intersection of three circles.
+ // But I like the look so I'm keeping it!
+ void render_triangle(GdkImage* image)
+ {
+ if (image->depth == 16)
+ _render_triangle<depth16_t>(image);
+ else
+ _render_triangle<depth24_t>(image);
+ }
+
Pos get_wheel_pos()
{
float a = palette_h*PI/180.0f;
@@ -388,9 +409,10 @@ public:
{
}
- void render(GdkImage* image)
+ template <typename pixel_t> inline
+ void _render(GdkImage* image)
{
- if (image->width != size || image->height != size || image->bits_per_pixel != 16 || (size&1))
+ if (image->width != size || image->height != size || (size&1))
{
fprintf(stderr, "Error: Invalid BrushPreview GdkImage.\n");
return;
@@ -410,16 +432,20 @@ public:
int opacity = int(round(255.0f * brush.opacity));
- unsigned short* pixels = (unsigned short*)image->mem;
- int stride = image->bpl/sizeof(unsigned short);
+ pixel_t* pixels = (pixel_t*)image->mem;
+ int stride = image->bpl/sizeof(pixel_t);
+
+ Color bkg(0xff, 0xff, 0xff, 0);
+ pixel_t bkgc;
+ bkg.to_pixel(&bkgc);
// Interpolate the distance table over the area. For each pixel find the distance, and look the
// brush-intensity up in the brush-table
for (int y = 0; y < size; y+=2)
{
float x2b = xb;
- unsigned short* __restrict row0 = &pixels[(y+0)*stride];
- unsigned short* __restrict row1 = &pixels[(y+1)*stride];
+ pixel_t* __restrict row0 = &pixels[(y+0)*stride];
+ pixel_t* __restrict row1 = &pixels[(y+1)*stride];
for (int x = 0; x < size; x+=2)
{
// Find brush-intensity and mulitply that with incoming opacity
@@ -430,7 +456,8 @@ public:
Color i = Color::create_from_a8r8g8b8(0xffffffff);
//Color i = Color::create_from_a8r8g8b8(image[y*size+x]);
i = Color::create_from_lerp(brush.color, i, intensity);
- unsigned short c = i.get_r5g6b5();
+ pixel_t c;
+ i.to_pixel(&c);
row0[0] = c;
row0[1] = c;
row1[0] = c;
@@ -438,10 +465,10 @@ public:
}
else
{
- row0[0] = 0xffff;
- row0[1] = 0xffff;
- row1[0] = 0xffff;
- row1[1] = 0xffff;
+ row0[0] = bkgc;
+ row0[1] = bkgc;
+ row1[0] = bkgc;
+ row1[1] = bkgc;
}
row0 += 2;
@@ -452,6 +479,14 @@ public:
yb += db*2;
}
}
+
+ void render(GdkImage* image)
+ {
+ if (image->depth == 16)
+ _render<depth16_t>(image);
+ else
+ _render<depth24_t>(image);
+ }
};
#endif