[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17399] branches/projection-paint/source/ blender/src/imagepaint.c: * float image buffer support
Campbell Barton
ideasman42 at gmail.com
Tue Nov 11 04:43:23 CET 2008
Revision: 17399
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17399
Author: campbellbarton
Date: 2008-11-11 04:43:21 +0100 (Tue, 11 Nov 2008)
Log Message:
-----------
* float image buffer support
* bicubic interpolation for the clone tool
Modified Paths:
--------------
branches/projection-paint/source/blender/src/imagepaint.c
Modified: branches/projection-paint/source/blender/src/imagepaint.c
===================================================================
--- branches/projection-paint/source/blender/src/imagepaint.c 2008-11-11 03:12:31 UTC (rev 17398)
+++ branches/projection-paint/source/blender/src/imagepaint.c 2008-11-11 03:43:21 UTC (rev 17399)
@@ -98,12 +98,13 @@
/* Defines and Structs */
-#define IMAPAINT_CHAR_TO_FLOAT(c) (c/255.0f)
+#define IMAPAINT_CHAR_TO_FLOAT(c) ((c)/255.0f)
-#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { c[0]=FTOCHAR(f[0]); \
- c[1]=FTOCHAR(f[1]); c[2]=FTOCHAR(f[2]); }
-#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { f[0]=IMAPAINT_CHAR_TO_FLOAT(c[0]); \
- f[1]=IMAPAINT_CHAR_TO_FLOAT(c[1]); f[2]=IMAPAINT_CHAR_TO_FLOAT(c[2]); }
+#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { (c)[0]=FTOCHAR((f)[0]); (c)[1]=FTOCHAR((f)[1]); (c)[2]=FTOCHAR((f)[2]); }
+#define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { (c)[0]=FTOCHAR((f)[0]); (c)[1]=FTOCHAR((f)[1]); (c)[2]=FTOCHAR((f)[2]); (c)[3]=FTOCHAR((f)[3]); }
+
+#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { (f)[0]=IMAPAINT_CHAR_TO_FLOAT((c)[0]); (f)[1]=IMAPAINT_CHAR_TO_FLOAT((c)[1]); (f)[2]=IMAPAINT_CHAR_TO_FLOAT((c)[2]); }
+#define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c) { (f)[0]=IMAPAINT_CHAR_TO_FLOAT((c)[0]); (f)[1]=IMAPAINT_CHAR_TO_FLOAT((c)[1]); (f)[2]=IMAPAINT_CHAR_TO_FLOAT((c)[2]); (f)[3]=IMAPAINT_CHAR_TO_FLOAT((c)[3]); }
#define IMAPAINT_FLOAT_RGB_COPY(a, b) VECCOPY(a, b)
#define IMAPAINT_TILE_BITS 6
@@ -187,6 +188,7 @@
int bucketsY;
Image **projectImages; /* array of images we are painting onto while, use so we can tag for updates */
+ ImBuf **projectImBufs; /* array of imbufs we are painting onto while, use so we can get the rect and rect_float quickly */
int projectImageTotal; /* size of projectImages array */
int imaContextIndex; /* current image, use for context switching */
@@ -221,17 +223,20 @@
typedef struct ProjectPixel {
float projCo2D[2]; /* the floating point screen projection of this pixel */
- char *pixel;
+ void *pixel;
int image_index;
} ProjectPixel;
typedef struct ProjectPixelClone {
struct ProjectPixel __pp;
- /*char backbuf[4]; *//* TODO - float buffer? */
- char clonebuf[4];
- //void *source; /* pointer to source pixels */
+ char clonepx[4];
} ProjectPixelClone;
+typedef struct ProjectPixelCloneFloat {
+ struct ProjectPixel __pp;
+ float clonepx[4];
+} ProjectPixelCloneFloat;
+
/* Finish projection painting structs */
@@ -391,7 +396,7 @@
}
-static int project_paint_BucketOffset(ProjectPaintState *ps, float *projCo2D)
+static int project_paint_BucketOffset(ProjectPaintState *ps, float projCo2D[2])
{
/* If we were not dealing with screenspace 2D coords we could simple do...
* ps->projectBuckets[x + (y*ps->bucketsY)] */
@@ -407,7 +412,7 @@
( ( (int)(( (projCo2D[1] - ps->viewMin2D[1]) / ps->viewHeight) * ps->bucketsY)) * ps->bucketsX );
}
-static int project_paint_BucketOffsetSafe(ProjectPaintState *ps, float *projCo2D)
+static int project_paint_BucketOffsetSafe(ProjectPaintState *ps, float projCo2D[2])
{
int bucket_index = project_paint_BucketOffset(ps, projCo2D);
@@ -556,17 +561,106 @@
return best_face_index; /* will be -1 or a valid face */
}
+/**************************************************************************
+* INTERPOLATIONS
+*
+* Reference and docs:
+* http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms
+***************************************************************************/
+
+/* BICUBIC Interpolation functions */
+/* More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation
+*/
+/* function assumes out to be zero'ed, only does RGBA */
+static float P(float k){
+ return (float)(1.0f/6.0f)*( pow( MAX2(k+2.0f,0) , 3.0f ) - 4.0f * pow( MAX2(k+1.0f,0) , 3.0f ) + 6.0f * pow( MAX2(k,0) , 3.0f ) - 4.0f * pow( MAX2(k-1.0f,0) , 3.0f));
+}
+
+static void bicubic_interpolation_px(ImBuf *in, float x, float y, float rgba_fp[4], char rgba[4])
+{
+ int i,j,n,m,x1,y1;
+ unsigned char *dataI;
+ float a,b,w,wx,wy[4], outR,outG,outB,outA,*dataF,*outF;
+ int do_rect=0, do_float=0;
+
+ if (in == NULL) return;
+ if (in->rect == NULL && in->rect_float == NULL) return;
+
+ if (in->rect_float) do_float = 1;
+ else do_rect = 1;
+
+ i= (int)floor(x);
+ j= (int)floor(y);
+ a= x - i;
+ b= y - j;
+
+ outR= 0.0f;
+ outG= 0.0f;
+ outB= 0.0f;
+ outA= 0.0f;
+
+ /* avoid calling multiple times */
+ wy[0] = P(b-(-1));
+ wy[1] = P(b- 0);
+ wy[2] = P(b- 1);
+ wy[3] = P(b- 2);
+
+ for(n= -1; n<= 2; n++){
+ x1= i+n;
+ if (x1>0 && x1 < in->x) {
+ wx = P(n-a);
+ for(m= -1; m<= 2; m++){
+ y1= j+m;
+ if (y1>0 && y1<in->y) {
+ /* normally we could do this */
+ /* w = P(n-a) * P(b-m); */
+ /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */
+ w = wx * wy[m+1];
+
+ if (do_float) {
+ dataF= in->rect_float + in->x * y1 * 4 + 4*x1;
+ outR+= dataF[0] * w;
+ outG+= dataF[1] * w;
+ outB+= dataF[2] * w;
+ outA+= dataF[3] * w;
+ }
+ if (do_rect) {
+ dataI= (unsigned char*)in->rect + in->x * y1 * 4 + 4*x1;
+ outR+= dataI[0] * w;
+ outG+= dataI[1] * w;
+ outB+= dataI[2] * w;
+ outA+= dataI[3] * w;
+ }
+ }
+ }
+ }
+ }
+ if (do_rect) {
+ rgba[0]= (int)outR;
+ rgba[1]= (int)outG;
+ rgba[2]= (int)outB;
+ rgba[3]= (int)outA;
+ }
+ if (do_float) {
+ rgba_fp[0]= outR;
+ rgba_fp[1]= outG;
+ rgba_fp[2]= outB;
+ rgba_fp[3]= outA;
+ }
+}
+
/* bucket_index is optional, since in some cases we know it */
-static int screenco_pickcol(ProjectPaintState *ps, float pt[2], char rgba[4], int interp)
+/* TODO FLOAT */ /* add a function that does this for float buffers */
+static int screenco_pickcol(ProjectPaintState *ps, float pt[2], float *rgba_fp, char *rgba, int interp)
{
float w[3], uv[2];
int side;
int face_index;
MTFace *tf;
ImBuf *ibuf;
- int x,y;
- char *pixel;
+ int xi,yi;
+
face_index = screenco_pickface(ps,pt,w, &side);
if (face_index == -1)
@@ -584,17 +678,51 @@
ibuf = BKE_image_get_ibuf((Image *)tf->tpage, NULL); /* TODO - this may be slow */
- x = uv[0]*ibuf->x;
- y = uv[1]*ibuf->y;
+
- if (x<0 || x>=ibuf->x || y<0 || y>=ibuf->y) return 0;
-
- pixel = (( char * ) ibuf->rect) + (( x + y * ibuf->x ) * 4);
-
- rgba[0] = pixel[0];
- rgba[1] = pixel[1];
- rgba[2] = pixel[2];
- rgba[3] = pixel[3];
+ if (interp) {
+ float x,y;
+ x = uv[0]*ibuf->x;
+ y = uv[1]*ibuf->y;
+ if (ibuf->rect_float) {
+ if (rgba_fp) {
+ bicubic_interpolation_px(ibuf, x, y, rgba_fp, NULL);
+ } else {
+ float rgba_tmp_fp[4];
+ bicubic_interpolation_px(ibuf, x, y, rgba_tmp_fp, NULL);
+ IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_fp);
+ }
+ } else {
+ if (rgba) {
+ bicubic_interpolation_px(ibuf, x, y, NULL, rgba);
+ } else {
+ char rgba_tmp[4];
+ bicubic_interpolation_px(ibuf, x, y, NULL, rgba_tmp);
+ IMAPAINT_CHAR_RGBA_TO_FLOAT( rgba_fp, rgba_tmp);
+ }
+ }
+ } else {
+ xi = uv[0]*ibuf->x;
+ yi = uv[1]*ibuf->y;
+
+ if (xi<0 || xi>=ibuf->x || yi<0 || yi>=ibuf->y) return 0;
+
+ if (rgba) {
+ if (ibuf->rect_float) {
+ IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, ((( float * ) ibuf->rect_float) + (( xi + yi * ibuf->x ) * 4)));
+ } else {
+ *((unsigned int *)rgba) = *(unsigned int *) ((( char * ) ibuf->rect) + (( xi + yi * ibuf->x ) * 4));
+ }
+ }
+
+ if (rgba_fp) {
+ if (ibuf->rect_float) {
+ QUATCOPY(rgba_fp, ((( float * ) ibuf->rect_float) + (( xi + yi * ibuf->x ) * 4)));
+ } else {
+ IMAPAINT_CHAR_RGBA_TO_FLOAT( rgba_fp, ((( char * ) ibuf->rect) + (( xi + yi * ibuf->x ) * 4)));
+ }
+ }
+ }
return 1;
}
@@ -1151,6 +1279,7 @@
static void project_paint_uvpixel_init(ProjectPaintState *ps, ImBuf *ibuf, int x, int y, int bucket_index, int face_index, float pixelScreenCo[4])
{
ProjectPixel *projPixel;
+ short size;
// printf("adding px (%d %d), (%f %f)\n", x,y,uv[0],uv[1]);
@@ -1162,39 +1291,53 @@
/* screenco_pickface is less complex, use for testing */
//if (screenco_pickface(ps, pixelScreenCo, w, &side) == face_index) {
if (ps->projectIsOcclude==0 || !project_bucket_point_occluded(ps, bucket_index, face_index, pixelScreenCo)) {
+
+ if (ps->tool==PAINT_TOOL_CLONE) {
+ if (ibuf->rect_float) {
+ size = sizeof(ProjectPixelCloneFloat);
+ } else {
+ size = sizeof(ProjectPixelClone);
+ }
+ } else if (ps->tool==PAINT_TOOL_SMEAR) {
+ size = sizeof(ProjectPixelClone);
+ }
+
+ projPixel = (ProjectPixel *)BLI_memarena_alloc(ps->projectArena, size);
+
+ if (ibuf->rect_float) {
+ projPixel->pixel = (void *) ((( float * ) ibuf->rect_float) + (( x + y * ibuf->x ) * pixel_size));
+ } else {
+ projPixel->pixel = (void *) ((( char * ) ibuf->rect) + (( x + y * ibuf->x ) * pixel_size));
+ }
+
+ VECCOPY2D(projPixel->projCo2D, pixelScreenCo);
+
/* done with view3d_project_float inline */
if (ps->tool==PAINT_TOOL_CLONE) {
float co[2];
- projPixel = (ProjectPixel *)BLI_memarena_alloc(ps->projectArena, sizeof(ProjectPixelClone));
- projPixel->pixel = (( char * ) ibuf->rect) + (( x + y * ibuf->x ) * pixel_size);
- VECCOPY2D(projPixel->projCo2D, pixelScreenCo);
-
- /* copy pixel color to backbuf - not used yet */
- /* memcpy( &(((ProjectPixelClone *)projPixel)->backbuf), projPixel->pixel, pixel_size); */
- //((ProjectPixelClone *)projPixel)->source = NULL; /* must be set later */
-
-
/* Initialize clone pixels - note that this is a bit of a waste since some of these are being indirectly initialized :/ */
/* TODO - possibly only run this for directly ativated buckets when cloning */
Vec2Subf(co, projPixel->projCo2D, ps->cloneOfs);
/* no need to initialize the bucket, we're only checking buckets faces and for this
* the faces are alredy initialized in project_paint_delayed_face_init(...) */
- if (!screenco_pickcol(ps, co, ((ProjectPixelClone *)projPixel)->clonebuf, 1)) {
- ((ProjectPixelClone *)projPixel)->clonebuf[3] = 0; /* zero alpha - ignore */
+ if (ibuf->rect_float) {
+ if (!screenco_pickcol(ps, co, ((ProjectPixelCloneFloat *)projPixel)->clonepx, NULL, 1)) {
+ ((ProjectPixelCloneFloat *)projPixel)->clonepx[3] = 0; /* zero alpha - ignore */
+ }
+ } else {
+ if (!screenco_pickcol(ps, co, NULL, ((ProjectPixelClone *)projPixel)->clonepx, 1)) {
+ ((ProjectPixelClone *)projPixel)->clonepx[3] = 0; /* zero alpha - ignore */
+ }
}
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list