static void affine_max_output( double affine[3][3], double *w, double *h, double dz, double max_width, double max_height ) { int tlx = MapX( affine, -max_width, max_height ) / dz; int tly = MapY( affine, -max_width, max_height ) / dz; int trx = MapX( affine, max_width, max_height ) / dz; int try = MapY( affine, max_width, max_height ) / dz; int blx = MapX( affine, -max_width, -max_height ) / dz; int bly = MapY( affine, -max_width, -max_height ) / dz; int brx = MapX( affine, max_width, -max_height ) / dz; int bry = MapY( affine, max_width, -max_height ) / dz; int max_x; int max_y; int min_x; int min_y; max_x = MAX( tlx, trx ); max_x = MAX( max_x, blx ); max_x = MAX( max_x, brx ); min_x = MIN( tlx, trx ); min_x = MIN( min_x, blx ); min_x = MIN( min_x, brx ); max_y = MAX( tly, try ); max_y = MAX( max_y, bly ); max_y = MAX( max_y, bry ); min_y = MIN( tly, try ); min_y = MIN( min_y, bly ); min_y = MIN( min_y, bry ); *w = ( double )( max_x - min_x + 1 ) / max_width / 2.0; *h = ( double )( max_y - min_y + 1 ) / max_height / 2.0; }
static void affine_max_output( float affine[3][3], float *w, float *h, float dz, float max_width, float max_height ) { int tlx = MapX( affine, -max_width, max_height ) / dz; int tly = MapY( affine, -max_width, max_height ) / dz; int trx = MapX( affine, max_width, max_height ) / dz; int try = MapY( affine, max_width, max_height ) / dz; int blx = MapX( affine, -max_width, -max_height ) / dz; int bly = MapY( affine, -max_width, -max_height ) / dz; int brx = MapX( affine, max_width, -max_height ) / dz; int bry = MapY( affine, max_width, -max_height ) / dz; int max_x; int max_y; int min_x; int min_y; max_x = MAX( tlx, trx ); max_x = MAX( max_x, blx ); max_x = MAX( max_x, brx ); min_x = MIN( tlx, trx ); min_x = MIN( min_x, blx ); min_x = MIN( min_x, brx ); max_y = MAX( tly, try ); max_y = MAX( max_y, bly ); max_y = MAX( max_y, bry ); min_y = MIN( tly, try ); min_y = MIN( min_y, bly ); min_y = MIN( min_y, bry ); *w = ( float )( max_x - min_x + 1 ) / max_width / 2.0; *h = ( float )( max_y - min_y + 1 ) / max_height / 2.0; }
/* map points to float points */ void FMapPoints(FGC fgc, XPoint points[], int npoints, FXPoint fpoints_return[]) { int i; for (i=0; i<npoints; i++) { fpoints_return[i].fx = MapX(fgc,points[i].x); fpoints_return[i].fy = MapY(fgc,points[i].y); } }
static int sliced_proc( int id, int index, int jobs, void* cookie ) { (void) id; // unused struct sliced_desc ctx = *((struct sliced_desc*) cookie); int height_slice = (ctx.a_height + jobs / 2) / jobs; int starty = height_slice * index; double x, y; double dx, dy; int i, j; ctx.a_image += (index * height_slice) * (ctx.a_width * 4); for (i = 0, y = ctx.lower_y; i < ctx.a_height; i++, y++) { if (i >= starty && i < (starty + height_slice)) { for (j = 0, x = ctx.lower_x; j < ctx.a_width; j++, x++) { dx = MapX( ctx.affine.matrix, x, y ) / ctx.dz + ctx.x_offset; dy = MapY( ctx.affine.matrix, x, y ) / ctx.dz + ctx.y_offset; if (dx >= ctx.minima && dx <= ctx.xmax && dy >= ctx.minima && dy <= ctx.ymax) ctx.interp(ctx.b_image, ctx.b_width, ctx.b_height, dx, dy, ctx.mix, ctx.a_image, ctx.b_alpha); ctx.a_image += 4; } } } return 0; }
void MapPoint(MATRIX_2D *M, FPOINT &A, FPOINT &B) { B.x = MapX (M, A.x, A.y); B.y = MapY (M, A.x, A.y); }
static void drawimage (Display *dpy, Drawable dbl, Region region, FGC fgc, Model *m, float fmin, float fmax, int style) { int scr=-1; int x,y,width,height; int i,j,k,line,iline,jline,widthpad; unsigned long pmin,pmax,p; float fx,fy,s,base,scale; Tri *t=NULL; TriAttributes *ta; XRectangle rect; XImage *image=NULL; int bitmap_pad=0; int nbpr=0; #if 0 /* OLD VERSION . See JG fix below */ unsigned char *data=NULL; scr=DefaultScreen(dpy); /* Kludge to fix problem with XCreateImage introduced in */ /* Xorg 7.0 update for security */ if (BitmapPad(dpy)>16) { bitmap_pad = 16; } else if (BitmapPad(dpy) < 16) { bitmap_pad = 8; } /* determine smallest box enclosing region */ XClipBox(region,&rect); x = rect.x; y = rect.y; width = rect.width; height = rect.height; if (width==0 || height==0) return; /* allocate memory for image data */ widthpad = (1+(width-1)/bitmap_pad)*bitmap_pad; nbpr = widthpad-1; data = alloc1(widthpad*height,sizeof(unsigned char)); if (data==NULL) err("width,widthpad,height = %d %d %d", width,widthpad,height); warn("nbpr = %d widthpad = %d height = %d bitmap_pad = %d ", nbpr,widthpad,height,bitmap_pad); /* determine min and max pixels from standard colormap */ pmin = XtcwpGetFirstPixel(dpy); pmax = XtcwpGetLastPixel(dpy); /* determine base and scale factor */ scale = (fmax!=fmin) ? ((float) (pmax-pmin))/(fmax-fmin) : 0.0; base = ((float) pmin)-fmin*scale; /* loop over scan lines */ for (line=0; line<height; line++) { iline = line*width; jline = line*widthpad; /* loop over pixels in scan line */ for (i=iline,j=jline,k=0; k<width; ++i,++j,++k) { /* determine float x and y coordinates */ if (style==XtcwpNORMAL) { fx = MapX(fgc,x+k); fy = MapY(fgc,y+line); } else { fx = MapY(fgc,y+line); fy = MapX(fgc,x+k); } /* determine sloth */ t = insideTriInModel(m,t,fx,fy); ta = (TriAttributes*)t->fa; s = ta->s00+fy*ta->dsdx+fx*ta->dsdz; /* convert to pixel and put in image */ p = (unsigned long) (base+s*scale); if (p<pmin) p = pmin; if (p>pmax) p = pmax; data[j] = (unsigned char) p; } for (j=jline+width,k=width; k<widthpad; ++j,++k) data[j] = data[jline+width-1]; } /* create, put, and destroy image */ image = XCreateImage( (Display *) dpy, (Visual *) DefaultVisual(dpy,scr), (unsigned int) DefaultDepth(dpy,scr), (int)ZPixmap, (int) 0, (char*)data, (unsigned int) widthpad, (unsigned int) height, (int) bitmap_pad, (int) nbpr); #else char *data=NULL; char noCmap; scr=DefaultScreen(dpy); /* JG: get bitmap_pad from X */ bitmap_pad = BitmapPad(dpy); /* determine smallest box enclosing region */ XClipBox(region,&rect); x = rect.x; y = rect.y; width = rect.width; height = rect.height; if (width==0 || height==0) return; /* allocate memory for image data */ widthpad = (1+(width-1)/bitmap_pad)*bitmap_pad; nbpr = widthpad-1; /* create image & determine alloc size from X */ image = XCreateImage( (Display *) dpy, (Visual *) DefaultVisual(dpy,scr), (unsigned int) DefaultDepth(dpy,scr), (int)ZPixmap, (int) 0, NULL , (unsigned int) widthpad, (unsigned int) height, (int) bitmap_pad, 0); /* JG XCreateImage(....,0) gets X to compute the size it needs. Then we alloc. */ image->data = (char *)calloc(image->bytes_per_line, image->height); if (image->data==NULL) err("width,widthpad,height = %d %d %d", width,widthpad,height); /* warn("nbpr = %d widthpad = %d height = %d bitmap_pad = %d ", nbpr,widthpad,height,bitmap_pad); */ /* determine min and max pixels from standard colormap */ pmin = XtcwpGetFirstPixel(dpy); pmax = XtcwpGetLastPixel(dpy); /* JGHACK ... When colormap fails, we get pmax=pmin=0 */ noCmap = (pmax==0 && pmin==0) ? 1:0; if (noCmap) { pmax = 255; warn("No colormap found...."); } /* ...JGHACK */ /* determine base and scale factor */ scale = (fmax!=fmin) ? ((float) (pmax-pmin))/(fmax-fmin) : 0.0; base = ((float) pmin)-fmin*scale; data = (char *)image->data ; /* loop over scan lines */ for (line=0; line<height; line++) { iline = line*width; jline = line*widthpad; /* loop over pixels in scan line */ for (i=iline,j=jline,k=0; k<width; ++i,++j,++k) { /* determine float x and y coordinates */ if (style==XtcwpNORMAL) { fx = MapX(fgc,x+k); fy = MapY(fgc,y+line); } else { fx = MapY(fgc,y+line); fy = MapX(fgc,x+k); } /* determine sloth */ t = insideTriInModel(m,t,fx,fy); ta = (TriAttributes*)t->fa; s = ta->s00+fy*ta->dsdx+fx*ta->dsdz; /* convert to pixel and put in image */ p = (unsigned long) (base+s*scale); if (p<pmin) p = pmin; if (p>pmax) p = pmax; if (noCmap) { /* JG. Can't get colormap. Might as well write RGB pixels as grayscale */ XPutPixel(image,k,line, p | (p<<8)| (p<<16)); } else { /* original */ /* data[j] = (unsigned char) p; */ XPutPixel(image,k,line,p); } } /* original. Not sure this is needed JG */ /* for (j=jline+width,k=width; k<widthpad; ++j,++k) data[j] = data[jline+width-1]; */ } #endif XPutImage(dpy,dbl,fgc->gc,image,0,0,x,y,image->width,image->height); /* free(data); */ XDestroyImage(image); }
static int transition_get_image( mlt_frame a_frame, uint8_t **image, mlt_image_format *format, int *width, int *height, int writable ) { // Get the b frame from the stack mlt_frame b_frame = mlt_frame_pop_frame( a_frame ); // Get the transition object mlt_transition transition = mlt_frame_pop_service( a_frame ); // Get the properties of the transition mlt_properties properties = MLT_TRANSITION_PROPERTIES( transition ); // Get the properties of the a frame mlt_properties a_props = MLT_FRAME_PROPERTIES( a_frame ); // Get the properties of the b frame mlt_properties b_props = MLT_FRAME_PROPERTIES( b_frame ); // Image, format, width, height and image for the b frame uint8_t *b_image = NULL; mlt_image_format b_format = mlt_image_rgb24a; int b_width; int b_height; // Assign the current position mlt_position position = mlt_transition_get_position( transition, a_frame ); int mirror = mlt_properties_get_position( properties, "mirror" ); int length = mlt_transition_get_length( transition ); if ( mlt_properties_get_int( properties, "always_active" ) ) { mlt_properties props = mlt_properties_get_data( b_props, "_producer", NULL ); mlt_position in = mlt_properties_get_int( props, "in" ); mlt_position out = mlt_properties_get_int( props, "out" ); length = out - in + 1; } // Obtain the normalised width and height from the a_frame mlt_profile profile = mlt_service_profile( MLT_TRANSITION_SERVICE( transition ) ); int normalised_width = profile->width; int normalised_height = profile->height; double consumer_ar = mlt_profile_sar( mlt_service_profile( MLT_TRANSITION_SERVICE(transition) ) ); // Structures for geometry struct mlt_geometry_item_s result; if ( mirror && position > length / 2 ) position = abs( position - length ); // Fetch the a frame image *format = mlt_image_rgb24a; mlt_frame_get_image( a_frame, image, format, width, height, 1 ); // Calculate the region now mlt_service_lock( MLT_TRANSITION_SERVICE( transition ) ); composite_calculate( transition, &result, normalised_width, normalised_height, ( float )position ); mlt_service_unlock( MLT_TRANSITION_SERVICE( transition ) ); // Fetch the b frame image result.w = ( result.w * *width / normalised_width ); result.h = ( result.h * *height / normalised_height ); result.x = ( result.x * *width / normalised_width ); result.y = ( result.y * *height / normalised_height ); // Request full resolution of b frame image. b_width = mlt_properties_get_int( b_props, "meta.media.width" ); b_height = mlt_properties_get_int( b_props, "meta.media.height" ); mlt_properties_set_int( b_props, "rescale_width", b_width ); mlt_properties_set_int( b_props, "rescale_height", b_height ); // Suppress padding and aspect normalization. char *interps = mlt_properties_get( a_props, "rescale.interp" ); if ( interps ) interps = strdup( interps ); mlt_properties_set( b_props, "rescale.interp", "none" ); // This is not a field-aware transform. mlt_properties_set_int( b_props, "consumer_deinterlace", 1 ); mlt_frame_get_image( b_frame, &b_image, &b_format, &b_width, &b_height, 0 ); // Check that both images are of the correct format and process if ( *format == mlt_image_rgb24a && b_format == mlt_image_rgb24a ) { float x, y; float dx, dy; float dz; float sw, sh; uint8_t *p = *image; // Get values from the transition float scale_x = mlt_properties_get_double( properties, "scale_x" ); float scale_y = mlt_properties_get_double( properties, "scale_y" ); int scale = mlt_properties_get_int( properties, "scale" ); int b_alpha = mlt_properties_get_int( properties, "b_alpha" ); float geom_scale_x = (float) b_width / result.w; float geom_scale_y = (float) b_height / result.h; float cx = result.x + result.w / 2.0; float cy = result.y + result.h / 2.0; float lower_x = - cx; float lower_y = - cy; float x_offset = (float) b_width / 2.0; float y_offset = (float) b_height / 2.0; affine_t affine; interpp interp = interpBL_b32; int i, j; // loop counters affine_init( affine.matrix ); // Compute the affine transform get_affine( &affine, transition, ( float )position ); dz = MapZ( affine.matrix, 0, 0 ); if ( ( int )abs( dz * 1000 ) < 25 ) { if ( interps ) free( interps ); return 0; } // Factor scaling into the transformation based on output resolution. if ( mlt_properties_get_int( properties, "distort" ) ) { scale_x = geom_scale_x * ( scale_x == 0 ? 1 : scale_x ); scale_y = geom_scale_y * ( scale_y == 0 ? 1 : scale_y ); } else { // Determine scale with respect to aspect ratio. double consumer_dar = consumer_ar * normalised_width / normalised_height; double b_ar = mlt_properties_get_double( b_props, "aspect_ratio" ); double b_dar = b_ar * b_width / b_height; if ( b_dar > consumer_dar ) { scale_x = geom_scale_x * ( scale_x == 0 ? 1 : scale_x ); scale_y = geom_scale_x * ( scale_y == 0 ? 1 : scale_y ); } else { scale_x = geom_scale_y * ( scale_x == 0 ? 1 : scale_x ); scale_y = geom_scale_y * ( scale_y == 0 ? 1 : scale_y ); } scale_x *= consumer_ar / b_ar; } if ( scale ) { affine_max_output( affine.matrix, &sw, &sh, dz, *width, *height ); affine_scale( affine.matrix, sw * MIN( geom_scale_x, geom_scale_y ), sh * MIN( geom_scale_x, geom_scale_y ) ); } else if ( scale_x != 0 && scale_y != 0 ) { affine_scale( affine.matrix, scale_x, scale_y ); } // Set the interpolation function if ( interps == NULL || strcmp( interps, "nearest" ) == 0 || strcmp( interps, "neighbor" ) == 0 ) interp = interpNN_b32; else if ( strcmp( interps, "tiles" ) == 0 || strcmp( interps, "fast_bilinear" ) == 0 ) interp = interpNN_b32; else if ( strcmp( interps, "bilinear" ) == 0 ) interp = interpBL_b32; else if ( strcmp( interps, "bicubic" ) == 0 ) interp = interpBC_b32; // TODO: lanczos 8x8 else if ( strcmp( interps, "hyper" ) == 0 || strcmp( interps, "sinc" ) == 0 || strcmp( interps, "lanczos" ) == 0 ) interp = interpBC_b32; else if ( strcmp( interps, "spline" ) == 0 ) // TODO: spline 4x4 or 6x6 interp = interpBC_b32; // Do the transform with interpolation for ( i = 0, y = lower_y; i < *height; i++, y++ ) { for ( j = 0, x = lower_x; j < *width; j++, x++ ) { dx = MapX( affine.matrix, x, y ) / dz + x_offset; dy = MapY( affine.matrix, x, y ) / dz + y_offset; if ( dx >= 0 && dx < (b_width - 1) && dy >=0 && dy < (b_height - 1) ) interp( b_image, b_width, b_height, dx, dy, result.mix/100.0, p, b_alpha ); p += 4; } } } if ( interps ) free( interps ); return 0; }
void MapPoint(MATRIX_2D *M, const FPOINT &A, FPOINT* B) { B->x = MapX(M, A.x, A.y); B->y = MapY(M, A.x, A.y); }
/* map x,y to float x,y */ void FMapPoint(FGC fgc, int x, int y, float *fx_return, float *fy_return) { *fx_return = MapX(fgc,x); *fy_return = MapY(fgc,y); }