From 3f1d49626e1a38bd8a26617d2818f0a701f22207 Mon Sep 17 00:00:00 2001 From: Albert Cahalan Date: Thu, 9 Dec 2004 23:12:45 +0000 Subject: [PATCH] handle wrong-sized saved images better --- docs/CHANGES.txt | 8 ++ src/tuxpaint.c | 343 +++++++++++++++++++++++++---------------------- 2 files changed, 192 insertions(+), 159 deletions(-) diff --git a/docs/CHANGES.txt b/docs/CHANGES.txt index 8fe43a938..58f1ab92a 100644 --- a/docs/CHANGES.txt +++ b/docs/CHANGES.txt @@ -8,6 +8,14 @@ http://www.newbreedsoftware.com/tuxpaint/ 2004.December.5 (0.9.15) + * Somewhat better treatment of wrong-sized images when loading them. + It works well for typical kid drawings, as long as objects don't + touch the edge of the screen. (the earth and sky -- and anything + else at the edge -- get extended to fill the space) This could be + better done with wavelets I think, or some vector-based notion of + what lies at the edge of the screen. Starters, as usual, need work. + Albert Cahalan + * Magic blur effect now gamma-aware, circular, and modifying all points within the brush instead of just 25% of them. Albert Cahalan diff --git a/src/tuxpaint.c b/src/tuxpaint.c index 15be671d7..ebace67a8 100644 --- a/src/tuxpaint.c +++ b/src/tuxpaint.c @@ -9359,6 +9359,187 @@ static void do_wait(void) } +static void autoscale_copy_smear_free(SDL_Surface *src, SDL_Surface *dst) +{ + SDL_Surface *src1; + SDL_Rect dest; + // What to do when in 640x480 mode, and loading an + // 800x600 (or larger) image!? Scale it. Starters must + // be scaled too. Keep the pixels square though, filling + // in the gaps via a smear. + if(src->w != dst->w || src->h != dst->h) + { + if(src->w / (float)dst->w > src->h / (float)dst->h) + src1 = thumbnail(src, dst->w, src->h*dst->w/src->w, 0); + else + src1 = thumbnail(src, src->w*dst->h/src->h, dst->h, 0); + SDL_FreeSurface(src); + src = src1; + } + + dest.x = (dst->w - src->w) / 2; + dest.y = (dst->h - src->h) / 2; + SDL_BlitSurface(src, NULL, dst, &dest); + + if(src->w != dst->w) + { + // we know that the heights match, and src is narrower + SDL_Rect sour; + int i = (dst->w - src->w) / 2; + sour.w = 1; + sour.x = 0; + sour.h = src->h; + sour.y = 0; + while(i-- > 0) + { + dest.x = i; + SDL_BlitSurface(src, &sour, dst, &dest); + } + sour.x = src->w - 1; + i = (dst->w - src->w) / 2 + src->w - 1; + while(++i < dst->w) + { + dest.x = i; + SDL_BlitSurface(src, &sour, dst, &dest); + } + } + + if(src->h != dst->h) + { + // we know that the widths match, and src is shorter + SDL_Rect sour; + int i = (dst->h - src->h) / 2; + sour.w = src->w; + sour.x = 0; + sour.h = 1; + sour.y = 0; + while(i-- > 0) + { + dest.y = i; + SDL_BlitSurface(src, &sour, dst, &dest); + } + sour.y = src->h - 1; + i = (dst->h - src->h) / 2 + src->h - 1; + while(++i < dst->h) + { + dest.y = i; + SDL_BlitSurface(src, &sour, dst, &dest); + } + } + + SDL_FreeSurface(src); +} + + +static void load_starter_id(char * saved_id) +{ + char * rname; + char fname[32]; + FILE * fi; + + snprintf(fname, sizeof(fname), "saved/%s.dat", saved_id); + rname = get_fname(fname); + + starter_id[0] = '\0'; + + fi = fopen(rname, "r"); + if (fi != NULL) + { + fgets(starter_id, sizeof(starter_id), fi); + starter_id[strlen(starter_id) - 1] = '\0'; + + fscanf(fi, "%d", &starter_mirrored); + fscanf(fi, "%d", &starter_flipped); + + fclose(fi); + } + + free(rname); +} + + + +static void load_starter(char * img_id) +{ + char * dirname; + char fname[256]; + SDL_Surface * tmp_surf; + + /* Determine path to starter files: */ + + dirname = strdup(DATA_PREFIX "starters"); + + /* Clear them to NULL first: */ + img_starter = NULL; + img_starter_bkgd = NULL; + + /* Load the core image: */ + snprintf(fname, sizeof(fname), "%s/%s.png", dirname, img_id); + tmp_surf = IMG_Load(fname); + + if (tmp_surf != NULL) + { + img_starter = SDL_DisplayFormatAlpha(tmp_surf); + SDL_FreeSurface(tmp_surf); + } + + if (img_starter != NULL && + (img_starter->w != canvas->w || img_starter->h != canvas->h)) + { + tmp_surf = img_starter; + + img_starter = SDL_CreateRGBSurface(canvas->flags, + canvas->w, canvas->h, + tmp_surf->format->BitsPerPixel, + tmp_surf->format->Rmask, + tmp_surf->format->Gmask, + tmp_surf->format->Bmask, + tmp_surf->format->Amask); + + SDL_SetAlpha(tmp_surf, 0, 0); + autoscale_copy_smear_free(tmp_surf,img_starter); + } + + + /* Try to load the a background image: */ + + /* (JPEG first) */ + snprintf(fname, sizeof(fname), "%s/%s-back.jpeg", dirname, img_id); + tmp_surf = IMG_Load(fname); + + /* (Failed? Try PNG next) */ + if (tmp_surf == NULL) + { + snprintf(fname, sizeof(fname), "%s/%s-back.png", dirname, img_id); + tmp_surf = IMG_Load(fname); + } + + if (tmp_surf != NULL) + { + img_starter_bkgd = SDL_DisplayFormat(tmp_surf); + SDL_FreeSurface(tmp_surf); + } + + if (img_starter_bkgd != NULL && + (img_starter_bkgd->w != canvas->w || img_starter_bkgd->h != canvas->h)) + { + tmp_surf = img_starter_bkgd; + + img_starter_bkgd = SDL_CreateRGBSurface(SDL_SWSURFACE, + canvas->w, canvas->h, + canvas->format->BitsPerPixel, + canvas->format->Rmask, + canvas->format->Gmask, + canvas->format->Bmask, + 0); + + autoscale_copy_smear_free(tmp_surf,img_starter_bkgd); + } + + free(dirname); +} + + /* Load current (if any) image: */ static void load_current(void) @@ -9367,8 +9548,6 @@ static void load_current(void) char * fname; char ftmp[1024]; FILE * fi; - SDL_Rect dest; - /* Determine the current picture's ID: */ @@ -9425,15 +9604,7 @@ static void load_current(void) } else { - SDL_FillRect(canvas, NULL, SDL_MapRGB(canvas->format, 255, 255, 255)); - - dest.x = (canvas->w - tmp->w) / 2; - dest.y = (canvas->h - tmp->h) / 2; - SDL_BlitSurface(tmp, NULL, canvas, &dest); - - SDL_FreeSurface(tmp); - - + autoscale_copy_smear_free(tmp,canvas); load_starter_id(file_id); load_starter(starter_id); @@ -10766,6 +10937,7 @@ static int do_quit(void) } + /* Open a saved image: */ #define PLACE_STARTERS_DIR 0 @@ -10798,11 +10970,8 @@ static int do_open(int want_new_tool) int last_click_which, last_click_button; int places_to_look; - - do_setcursor(cursor_watch); - /* Allocate some space: */ things_alloced = 32; @@ -11730,19 +11899,8 @@ static int do_open(int want_new_tool) free_surface(&img_starter_bkgd); starter_mirrored = 0; starter_flipped = 0; - - SDL_FillRect(canvas, NULL, - SDL_MapRGB(canvas->format, 255, 255, 255)); - /* FIXME: What to do when in 640x480 mode, and loading an - 800x600 (or larger) image!? */ - - dest.x = (canvas->w - img->w) / 2; - dest.y = (canvas->h - img->h) / 2; - - SDL_BlitSurface(img, NULL, canvas, &dest); - SDL_FreeSurface(img); - + autoscale_copy_smear_free(img,canvas); cur_undo = 0; oldest_undo = 0; @@ -13852,139 +14010,6 @@ static int mySDL_PollEvent(SDL_Event *event) } -static void load_starter_id(char * saved_id) -{ - char * rname; - char fname[32]; - FILE * fi; - - snprintf(fname, sizeof(fname), "saved/%s.dat", saved_id); - rname = get_fname(fname); - - starter_id[0] = '\0'; - - fi = fopen(rname, "r"); - if (fi != NULL) - { - fgets(starter_id, sizeof(starter_id), fi); - starter_id[strlen(starter_id) - 1] = '\0'; - - fscanf(fi, "%d", &starter_mirrored); - fscanf(fi, "%d", &starter_flipped); - - fclose(fi); - } - - free(rname); -} - -static void load_starter(char * img_id) -{ - char * dirname; - char fname[256]; - SDL_Surface * tmp_surf; - SDL_Rect dest; - - - /* Determine path to starter files: */ - - /* FIXME: On Windows, MacOSX, BeOS, etc. -- do it their way! */ -#if defined(WIN32) || defined(__BEOS__) - dirname = strdup(DATA_PREFIX "starters"); -#else - dirname = strdup("/usr/local/share/tuxpaint/starters"); -#endif - - - /* Clear them to NULL first: */ - - img_starter = NULL; - img_starter_bkgd = NULL; - - - /* Load the core image: */ - - snprintf(fname, sizeof(fname), "%s/%s.png", dirname, img_id); - tmp_surf = IMG_Load(fname); - - if (tmp_surf != NULL) - { - img_starter = SDL_DisplayFormatAlpha(tmp_surf); - SDL_FreeSurface(tmp_surf); - } - - if (img_starter != NULL && - (img_starter->w != canvas->w || img_starter->h != canvas->h)) - { - tmp_surf = img_starter; - - img_starter = SDL_CreateRGBSurface(canvas->flags, - canvas->w, canvas->h, - tmp_surf->format->BitsPerPixel, - tmp_surf->format->Rmask, - tmp_surf->format->Gmask, - tmp_surf->format->Bmask, - tmp_surf->format->Amask); - - SDL_SetAlpha(tmp_surf, 0, 0); - - if (img_starter != NULL) - { - dest.x = (canvas->w - tmp_surf->w) / 2; - dest.y = (canvas->h - tmp_surf->h) / 2; - - SDL_BlitSurface(tmp_surf, NULL, img_starter, &dest); - SDL_FreeSurface(tmp_surf); - } - } - - - /* Try to load the a background image: */ - - /* (JPEG first) */ - snprintf(fname, sizeof(fname), "%s/%s-back.jpeg", dirname, img_id); - tmp_surf = IMG_Load(fname); - - /* (Failed? Try PNG next) */ - if (tmp_surf == NULL) - { - snprintf(fname, sizeof(fname), "%s/%s-back.png", dirname, img_id); - tmp_surf = IMG_Load(fname); - } - - if (tmp_surf != NULL) - { - img_starter_bkgd = SDL_DisplayFormat(tmp_surf); - SDL_FreeSurface(tmp_surf); - } - - if (img_starter_bkgd != NULL && - (img_starter_bkgd->w != canvas->w || img_starter_bkgd->h != canvas->h)) - { - tmp_surf = img_starter_bkgd; - - img_starter_bkgd = SDL_CreateRGBSurface(SDL_SWSURFACE, - canvas->w, canvas->h, - canvas->format->BitsPerPixel, - canvas->format->Rmask, - canvas->format->Gmask, - canvas->format->Bmask, - 0); - - if (img_starter_bkgd != NULL) - { - dest.x = (canvas->w - tmp_surf->w) / 2; - dest.y = (canvas->h - tmp_surf->h) / 2; - - SDL_BlitSurface(tmp_surf, NULL, img_starter_bkgd, &dest); - SDL_FreeSurface(tmp_surf); - } - } - - free(dirname); -} - - static TTF_Font *try_alternate_font(int language) { char str[128];