Beispiel #1
0
/** glow fill algorithm, from the gosu forums **/ 
static void
glow_floodFill( int x, int y, rgba * seed_color, action_struct * cur, texture_info * tex, texture_info * tex2 )
{
    /* used to flood in both horizontal directions from the given point to form a line. */
    int fillL, fillR;     
    int i;

    /* initialize the flood directions */
    fillL = fillR = x;

    /* flood left until a new color is hit - or the edge of the image */
    do {
        /* for texture filling */
        if(tex2)
            cur->color = get_pixel_color(tex2, fillL % tex2->width, y % tex2->height);
        
        /* TWO VERSIONS of below */

        /* SLOW BUT MODERN VERSION */
        /*        set_pixel_color_with_style(cur, tex, fillL, y); */

        /* FAST but old version */
        set_pixel_color(&cur->color, tex, fillL, y);

        fillL--;
    } while( (fillL >= 0 ) && (cmp_color(get_pixel_color(tex, fillL, y), *seed_color)) );

    /* flood right until a new color is hit - or the edge of the image */
    do {
        //        for texture filling
        if(tex2)
            cur->color = get_pixel_color(tex2, fillR % tex2->width, y % tex2->height);
        
        /*        set_pixel_color_with_style(cur, tex, fillR, y); */
         
        set_pixel_color(&cur->color, tex, fillR, y);

        fillR++;
    } while( (fillR < cur->xmax - 1) && (cmp_color(get_pixel_color(tex, fillR, y), *seed_color)) );

    /* recurse to the line above and the line below at each point */
    for( i = fillL + 1; i < fillR; i++ ) {
        /* Flood above */
        if( ( y > 0 ) && ( cmp_color(get_pixel_color(tex, i, y - 1), *seed_color)  ) ) {
            
            glow_floodFill( i, y-1, seed_color, cur, tex, tex2 );
        }
        /* flood below */
        if( (y < cur->ymax - 1) && (cmp_color(get_pixel_color(tex, i, y + 1), *seed_color) )) {
            glow_floodFill( i, y+1, seed_color, cur, tex, tex2 );
        }
    }
}
Beispiel #2
0
/* utility func to manage both kinds of color comparions */
static bool
cmp_color_with_or_without_tolerance(rgba c1, rgba c2, action_struct * payload)
{
  return payload->pen.has_tolerance ? cmp_color_with_tolerance(c1, c2, payload->pen.tolerance) : cmp_color(c1, c2);
}
Beispiel #3
0
/** splice algorithm **/
void
splice_do_action(int x0, int y0, int cx1, int cy1, int cx2, int cy2, texture_info * splice_tex,
                 texture_info * tex, VALUE hash_arg, texplay_sync sync_mode,
                 bool primary, action_struct * payload)
{
    action_struct cur;
    int xbound;
    int ybound;
    rgba chromakey;
    float * image_buf = NULL;
    bool inverse_chroma = false;
    bool same_image = false;
    bool has_chroma = false;

    constrain_boundaries(&cx1, &cy1, &cx2, &cy2, splice_tex->width, splice_tex->height);
    xbound = cx2 - cx1 + 1;
    ybound = cy2 - cy1 + 1;

    draw_prologue(&cur, tex, x0, y0,
                  x0 + xbound, y0 + ybound, &hash_arg, sync_mode, primary, &payload);


    if(has_optional_hash_arg(hash_arg, "chroma_key")) {
        VALUE c = get_from_hash(hash_arg, "chroma_key");
        chromakey = convert_rb_color_to_rgba(c);
        has_chroma = true;
    }
    else if(has_optional_hash_arg(hash_arg, "chroma_key_not")) {
        chromakey = convert_rb_color_to_rgba(get_from_hash(hash_arg, "chroma_key_not"));
        inverse_chroma = true;
        has_chroma = true;
    }

    if(splice_tex->image == tex->image)
        same_image = true;

    /* NB: we do not use this in the general case since it's almost 1.5 times as slow.
       It is necessary for splicing from/to the same region of pixels though.
    */
    if(same_image) 
        image_buf = get_image_chunk(splice_tex, cx1, cy1, cx2, cy2);
    
    for(int y = 0; y < ybound; y++)
        for(int x = 0; x < xbound; x++) {
            
            if(!same_image)
                payload->color = get_pixel_color(splice_tex, cx1 + x, cy1 + y);
            else 
                payload->color = get_pixel_color_from_chunk(image_buf, xbound, ybound, x, y);
                
            if(has_chroma) {
                bool chroma_match = cmp_color(payload->color, chromakey);
                
                /* look at released 0.2.0 code to see how USED to do this.
                   this is now a simplified boolean expression (XOR) */
                if(chroma_match == inverse_chroma)
                    set_pixel_color_with_style(payload, tex, x0 + x, y0 + y);
            }
            else
                set_pixel_color_with_style(payload, tex, x0 + x, y0 + y);
        }

    if(same_image)
        free(image_buf);

    draw_epilogue(&cur, tex, primary);
}
Beispiel #4
0
void
scan_fill_do_action(int x, int y, texture_info * tex, VALUE hash_arg,
                    texplay_sync sync_mode, bool primary, action_struct * payload)
{
    action_struct cur;
    rgba old_color;
    int y1;
    bool spanLeft, spanRight;

    if(!bound_by_rect(x, y, 0, 0, tex->width - 1, tex->height - 1)) return;

    /* NB: using XMAX_OOB etc since we dont know the drawing area yet; drawing area will be set by
       update_bounds() function in main loop */
    draw_prologue(&cur, tex, XMAX_OOB, YMAX_OOB, XMIN_OOB, YMIN_OOB, &hash_arg, sync_mode, primary, &payload);

    /* fill hates alpha_blend so let's turn it off */
    payload->pen.alpha_blend = false;
    
    old_color = get_pixel_color(tex, x, y);

    if(cmp_color(old_color, cur.color)) return;
    
    emptyStack();
    
    if(!push(x, y, tex->width - 1)) return;
    
    while(pop(&x, &y, tex->width - 1))
        {    
            y1 = y;
            while(y1 >= 0 && cmp_color(old_color, get_pixel_color(tex, x, y1))) y1--;
            y1++;
            spanLeft = spanRight = false;
            while(y1 < tex->height && cmp_color(old_color, get_pixel_color(tex, x, y1)) )
                {
                    set_pixel_color_with_style(payload, tex, x, y1);

                    /* update the drawing rectangle */
                    update_bounds(payload, x, y1, x, y1);

                    if(!spanLeft && x > 0 && cmp_color(old_color, get_pixel_color(tex, x - 1, y1))) 
                        {
                            if(!push(x - 1, y1, tex->width - 1)) return;
                            spanLeft = true;
                        }

                    else if(spanLeft && !cmp_color(old_color, get_pixel_color(tex, x - 1, y1)))
                        {
                            spanLeft = false;
                        }

                    if(!spanRight && x < tex->width - 1 && cmp_color(old_color,
                                                                     get_pixel_color(tex, x + 1, y1))) 
                        {
                            if(!push(x + 1, y1, tex->width - 1)) return;
                            spanRight = true;
                        }

                    else if(spanRight && x < tex->width - 1 && !cmp_color(old_color,get_pixel_color(tex, x + 1, y1)))
                        {
                            spanRight = false;
                        } 
                    y1++;
                }
        }
    draw_epilogue(&cur, tex, primary);
}
Beispiel #5
0
void
flood_fill_do_action(int x, int y, texture_info * tex, VALUE hash_arg,
                     texplay_sync sync_mode, bool primary, action_struct * payload)
{
    int left, x1, x2, dy;
    rgba old_color;
    LINESEGMENT stack[MAXDEPTH], *sp = stack;

    action_struct cur;

    int nMinX, nMinY, nMaxX, nMaxY;
    
    /* NOTE: 1024 is just a place-holder to indicate maximum possible width/height.
       Values will be constrained to realistic dimensions by constrain_boundaries() function */
    draw_prologue(&cur, tex, 0, 0, 1024, 1024, &hash_arg, sync_mode, primary, &payload);

    /* fill hates alpha_blend so let's turn it off */
    payload->pen.alpha_blend = false;

    nMinX = cur.xmin; nMinY = cur.ymin;
    nMaxX = cur.xmax; nMaxY = cur.ymax;

    old_color = get_pixel_color(tex, x, y);
    if( cmp_color(old_color, cur.color) )
        return;

    if( x < nMinX || x > nMaxX || y < nMinX || y > nMaxY )
        return;

    PUSH(x, x, y, 1);        /* needed in some cases */
    PUSH(x, x, y + 1, -1);    /* seed segment (popped 1st) */

    while( sp > stack ) {
        POP(x1, x2, y, dy);

        for( x = x1; x >= nMinX && cmp_color(get_pixel_color(tex, x, y), old_color); --x ) {
            set_pixel_color_with_style(payload, tex, x, y);
        }

        if( x >= x1 )
            goto SKIP;

        left = x + 1;
        if( left < x1 )
            PUSH(y, left, x1 - 1, -dy);    /* leak on left? */

        x = x1 + 1;

        do {
            for( ; x <= nMaxX && cmp_color(get_pixel_color(tex, x, y), old_color); ++x ){
                set_pixel_color_with_style(payload, tex, x, y);
            }

            PUSH(left, x - 1, y, dy);

            if( x > x2 + 1 )
                PUSH(x2 + 1, x - 1, y, -dy);    /* leak on right? */

        SKIP:        for( ++x; x <= x2 && !cmp_color(get_pixel_color(tex, x, y), old_color); ++x ) {;}

            left = x;
        } while( x <= x2 );
    }

    draw_epilogue(&cur, tex, primary);
}