Re: [AD] stretch_blit() ob1 error

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


On 2003-02-14, Eric <ebotcazou@xxxxxxxxxx> wrote:
> > Yes, that's what I was afraid of (the part about being too broad; I
> > don't fully understand what I changed, just recognised it as a similar
> > problem to floating point imprecisions).
> 
> Exactly. The problem is that n*(1/n) < 1 in most cases for computers, so 
> adding a correction factor is necessary.

Thanks for the confirmation.

> 
> > That seems good.  Also, I think the first hunk would be better moved out
> > of the per-line loop.  I'll test it a bit more.
> 
> If I understand correctly the stretching code, that doesn't really matter 
> because the loop at stake is involved in the _compilation_ of the stretcher, 
> not its execution.

Oh well, either way.  Attached is a patch, and a fugly tester program
(source w,h, dest w,h fields at the top (press enter after changing);
also adjustable with qwerasdf keys; you can also change source x,y with
ijkl).  It appears that no adverse effects were introduced.

Credit for the bug report should include David Gowers (on allegro.cc).

-- 
王浩禎
--- istretch.c.~1.5.~	Sat Aug 17 13:59:40 2002
+++ istretch.c	Fri Feb 14 16:21:46 2003
@@ -317,6 +317,15 @@
 	 return;
    }
 
+   /* compensate for a problem where the first column or row can get
+    * an extra pixel than it should do for little -> big scaling, due
+    * to fixed point number representation imprecisions
+    */
+   if (sxd < itofix(1))
+      sx += (sxd >> 1);
+   if (syd < itofix(1))
+      sy += (syd >> 1);
+
    /* search the cache */
    stretcher_count++;
    if (stretcher_count <= 0) {
#include <allegro.h>

void run_test(void)
{
    int white = makecol(255, 255, 255);
    int black = makecol(0, 0, 0);
    int red   = makecol(255, 0, 0);

    BITMAP *source = NULL;
    int source_x = 0;
    int source_y = 0;

    char source_width[5]  = "1";
    char source_height[5] = "1";
    char dest_width[5]    = "1";
    char dest_height[5]   = "1";

    int enter_pressed(void)
    {
	int sw = atoi(source_width);
	int sh = atoi(source_height);

	if (source)
	    destroy_bitmap(source);

	source = create_bitmap(sw, sh);
	clear_to_color(source, black);
	rect(source, 0, 0, sw-1, sh-1, red);
	if (sw > 4 && sh > 4) {
	    line(source, 0, 0, sw-1, sh-1, red);
	    line(source, sw-1, 0, 0, sh-1, red);
	}

	return D_REDRAW;
    }

    int draw_source(int msg, DIALOG *d, int c)
    {
	if (msg == MSG_DRAW) blit(source, screen, 0, 0, d->x, d->y, source->w, source->h);
	return D_O_K;
    }

    int draw_dest(int msg, DIALOG *d, int c)
    {
	if (msg == MSG_DRAW) {
	    int sw = source->w - source_x;
	    int sh = source->h - source_y;
	    int dw = atoi(dest_width);
	    int dh = atoi(dest_height);
	    stretch_blit(source, screen,
			 source_x, source_y, sw, sh,
			 d->x, d->y, dw, dh);
	}
	return D_O_K;
    }

    int qwerasdf(int msg, DIALOG *d, int c)
    {
	void inc(char *s)
	{
	    sprintf(s, "%d", atoi(s) + 1);
	    enter_pressed();
	}

	void dec(char *s)
	{
	    sprintf(s, "%d", atoi(s) - 1);
	    enter_pressed();
	}

	if (msg != MSG_XCHAR)
	    return D_O_K;

	switch (c & 0xff) {
	    case 'q': inc(source_width); break;
	    case 'a': dec(source_width); break;
	    case 'w': inc(source_height); break;
	    case 's': dec(source_height); break;
	    case 'e': inc(dest_width); break;
	    case 'd': dec(dest_width); break;
	    case 'r': inc(dest_height); break;
	    case 'f': dec(dest_height); break;
	    case 'i': if (source_y > 0) source_y--; break;
	    case 'k': if (source_y < source->h-1) source_y++; break;
	    case 'j': if (source_x > 0) source_x--; break;
	    case 'l': if (source_x < source->w-1) source_x++; break;
	    default:  return D_O_K;
	}

	broadcast_dialog_message(MSG_DRAW, 0);
	return D_USED_CHAR;
    }

    DIALOG dlg[] =
    {
	/* (dialog proc)     (x)   (y)   (w)   (h)   (fg)  (bg)  (key) (flags)  (d1)                    (d2)  (dp)              (dp2) (dp3) */
	{ d_clear_proc,      0,    0,    0,    0,    0,    white,0,    0,       0,                      0,    NULL,             NULL, NULL  },
	{ d_edit_proc,       2,    2,    50,   20,   black,white,0,    0,       sizeof source_width-1,  0,    source_width,     NULL, NULL  },
	{ d_edit_proc,       60,   2,    50,   20,   black,white,0,    0,       sizeof source_height-1, 0,    source_height,    NULL, NULL  },
	{ d_edit_proc,       120,  2,    50,   20,   black,white,0,    0,       sizeof dest_width-1,    0,    dest_width,       NULL, NULL  },
	{ d_edit_proc,       180,  2,    50,   20,   black,white,0,    0,       sizeof dest_height-1,   0,    dest_height,      NULL, NULL  },
	{ draw_source,       2,    25,   0,    0,    0,    0,    0,    0,       0,                      0,    NULL,             NULL, NULL  },
	{ draw_dest,         160,  25,   0,    0,    0,    0,    0,    0,       0,                      0,    NULL,             NULL, NULL  },
	{ d_keyboard_proc,   0,    0,    0,    0,    0,    0,    13,   0,       0,                      0,    enter_pressed,    NULL, NULL  },
	{ qwerasdf,          0,    0,    0,    0,    0,    0,    0,    0,       0,                      0,    NULL,             NULL, NULL  },
	{ d_button_proc,     0,    0,    640,  2,    white,black,0,    0,       0,                      0,    "",               NULL, NULL  },
	{ NULL,              0,    0,    0,    0,    0,    0,    0,    0,       0,                      0,    NULL,             NULL, NULL  }
    };

    enter_pressed();
    do_dialog(dlg, -1);
}

int main(void)
{
    allegro_init();
    set_color_depth(8);
    if (set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0) != 0)
	return 1;
    install_timer();
    install_mouse();
    install_keyboard();

    run_test();

    return 0;
}

END_OF_MAIN()


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/