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()