mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-16 22:18:30 +00:00
Added image_fixup_transparent_colors function.
Fixed image_resize.
This commit is contained in:
parent
b84fa3a8c6
commit
0e2fba2396
@ -92,6 +92,7 @@ protected:
|
||||
int h = scale_y(image->h);
|
||||
Image* new_image = image_new(image->imgtype, MAX(1, w), MAX(1, h));
|
||||
|
||||
image_fixup_transparent_colors(image);
|
||||
image_resize(image, new_image,
|
||||
m_resize_method,
|
||||
get_current_palette(),
|
||||
@ -108,17 +109,26 @@ protected:
|
||||
|
||||
// resize mask
|
||||
if (m_sprite->mask->bitmap) {
|
||||
int w = scale_x(m_sprite->mask->bitmap->w);
|
||||
int h = scale_y(m_sprite->mask->bitmap->h);
|
||||
Image* old_bitmap = image_crop(m_sprite->mask->bitmap, -1, -1,
|
||||
m_sprite->mask->bitmap->w+2,
|
||||
m_sprite->mask->bitmap->h+2, 0);
|
||||
|
||||
int w = scale_x(old_bitmap->w);
|
||||
int h = scale_y(old_bitmap->h);
|
||||
Mask* new_mask = mask_new();
|
||||
mask_replace(new_mask,
|
||||
scale_x(m_sprite->mask->x),
|
||||
scale_y(m_sprite->mask->y), MAX(1, w), MAX(1, h));
|
||||
|
||||
image_resize(m_sprite->mask->bitmap, new_mask->bitmap,
|
||||
RESIZE_METHOD_NEAREST_NEIGHBOR,
|
||||
scale_x(m_sprite->mask->x-1),
|
||||
scale_y(m_sprite->mask->y-1), MAX(1, w), MAX(1, h));
|
||||
image_resize(old_bitmap, new_mask->bitmap,
|
||||
m_resize_method,
|
||||
get_current_palette(),
|
||||
orig_rgb_map);
|
||||
image_free(old_bitmap);
|
||||
|
||||
// reshrink
|
||||
mask_intersect(new_mask,
|
||||
new_mask->x, new_mask->y,
|
||||
new_mask->w, new_mask->h);
|
||||
|
||||
undoable.copy_to_current_mask(new_mask);
|
||||
mask_free(new_mask);
|
||||
|
@ -318,15 +318,106 @@ void image_ellipsefill(Image* image, int x1, int y1, int x2, int y2, int color)
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
/*********************************************************************
|
||||
Allegro <-> Image
|
||||
*********************************************************************/
|
||||
|
||||
void image_to_allegro(const Image* image, BITMAP *bmp, int x, int y)
|
||||
{
|
||||
image->to_allegro(bmp, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine does not modify the image to the human eye, but
|
||||
* internally tries to fixup all colors that are completelly
|
||||
* transparent (alpha = 0) with the average of its 4-neighbors.
|
||||
*/
|
||||
void image_fixup_transparent_colors(Image* image)
|
||||
{
|
||||
int x, y, u, v;
|
||||
|
||||
switch (image->imgtype) {
|
||||
|
||||
case IMAGE_RGB: {
|
||||
ase_uint32 c;
|
||||
int r, g, b, count;
|
||||
|
||||
for (y=0; y<image->h; ++y) {
|
||||
for (x=0; x<image->w; ++x) {
|
||||
c = image_getpixel_fast<RgbTraits>(image, x, y);
|
||||
|
||||
// if this is a completelly-transparent pixel...
|
||||
if (_rgba_geta(c) == 0) {
|
||||
count = 0;
|
||||
r = g = b = 0;
|
||||
|
||||
for (v=y-1; v<=y+1; ++v) {
|
||||
for (u=x-1; u<=x+1; ++u) {
|
||||
if ((u >= 0) && (v >= 0) && (u < image->w) && (v < image->h)) {
|
||||
c = image_getpixel_fast<RgbTraits>(image, u, v);
|
||||
if (_rgba_geta(c) > 0) {
|
||||
r += _rgba_getr(c);
|
||||
g += _rgba_getg(c);
|
||||
b += _rgba_getb(c);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
r /= count;
|
||||
g /= count;
|
||||
b /= count;
|
||||
image_putpixel_fast<RgbTraits>(image, x, y, _rgba(r, g, b, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IMAGE_GRAYSCALE: {
|
||||
ase_uint16 c;
|
||||
int k, count;
|
||||
|
||||
for (y=0; y<image->h; ++y) {
|
||||
for (x=0; x<image->w; ++x) {
|
||||
c = image_getpixel_fast<GrayscaleTraits>(image, x, y);
|
||||
|
||||
// if this is a completelly-transparent pixel...
|
||||
if (_graya_geta(c) == 0) {
|
||||
count = 0;
|
||||
k = 0;
|
||||
|
||||
for (v=y-1; v<=y+1; ++v) {
|
||||
for (u=x-1; u<=x+1; ++u) {
|
||||
if ((u >= 0) && (v >= 0) && (u < image->w) && (v < image->h)) {
|
||||
c = image_getpixel_fast<GrayscaleTraits>(image, u, v);
|
||||
if (_graya_geta(c) > 0) {
|
||||
k += _graya_getv(c);
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
k /= count;
|
||||
image_putpixel_fast<GrayscaleTraits>(image, x, y, _graya(k, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the source image @a src to the destination image @a dst.
|
||||
*
|
||||
* @warning If you are using the RESIZE_METHOD_BILINEAR, it is
|
||||
* recommended to use @ref image_fixup_transparent_colors function
|
||||
* over the source image @a src before using this routine.
|
||||
*/
|
||||
void image_resize(const Image* src, Image* dst, ResizeMethod method, Palette* pal, RGB_MAP* rgb_map)
|
||||
{
|
||||
switch (method) {
|
||||
@ -353,29 +444,47 @@ void image_resize(const Image* src, Image* dst, ResizeMethod method, Palette* pa
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO optimize this
|
||||
// TODO optimize this
|
||||
case RESIZE_METHOD_BILINEAR: {
|
||||
ase_uint32 color[4], dst_color;
|
||||
double u, v, du, dv;
|
||||
int u_floor, u_floor2;
|
||||
int v_floor, v_floor2;
|
||||
int x, y;
|
||||
|
||||
u = v = 0.0;
|
||||
du = src->w * 1.0 / dst->w;
|
||||
dv = src->h * 1.0 / dst->h;
|
||||
du = (src->w-1) * 1.0 / (dst->w-1);
|
||||
dv = (src->h-1) * 1.0 / (dst->h-1);
|
||||
for (y=0; y<dst->h; ++y) {
|
||||
for (x=0; x<dst->w; ++x) {
|
||||
int u_floor = floor(u);
|
||||
int v_floor = floor(v);
|
||||
u_floor = floor(u);
|
||||
v_floor = floor(v);
|
||||
|
||||
color[0] = src->getpixel(MID(0, u_floor, src->w-1),
|
||||
MID(0, v_floor, src->h-1));
|
||||
color[1] = src->getpixel(MID(0, u_floor+1, src->w-1),
|
||||
MID(0, v_floor, src->h-1));
|
||||
color[2] = src->getpixel(MID(0, u_floor, src->w-1),
|
||||
MID(0, v_floor+1, src->h-1));
|
||||
color[3] = src->getpixel(MID(0, u_floor+1, src->w-1),
|
||||
MID(0, v_floor+1, src->h-1));
|
||||
if (u_floor > src->w-1) {
|
||||
u_floor = src->w-1;
|
||||
u_floor2 = src->w-1;
|
||||
}
|
||||
else if (u_floor == src->w-1)
|
||||
u_floor2 = u_floor;
|
||||
else
|
||||
u_floor2 = u_floor+1;
|
||||
|
||||
if (v_floor > src->h-1) {
|
||||
v_floor = src->h-1;
|
||||
v_floor2 = src->h-1;
|
||||
}
|
||||
else if (v_floor == src->h-1)
|
||||
v_floor2 = v_floor;
|
||||
else
|
||||
v_floor2 = v_floor+1;
|
||||
|
||||
// get the four colors
|
||||
color[0] = src->getpixel(u_floor, v_floor);
|
||||
color[1] = src->getpixel(u_floor2, v_floor);
|
||||
color[2] = src->getpixel(u_floor, v_floor2);
|
||||
color[3] = src->getpixel(u_floor2, v_floor2);
|
||||
|
||||
// calculate the interpolated color
|
||||
double u1 = u - u_floor;
|
||||
double v1 = v - v_floor;
|
||||
double u2 = 1 - u1;
|
||||
@ -409,11 +518,17 @@ void image_resize(const Image* src, Image* dst, ResizeMethod method, Palette* pa
|
||||
(_rgba_getg(pal->color[color[2]])*u2 + _rgba_getg(pal->color[color[3]])*u1)*v1);
|
||||
int b = ((_rgba_getb(pal->color[color[0]])*u2 + _rgba_getb(pal->color[color[1]])*u1)*v2 +
|
||||
(_rgba_getb(pal->color[color[2]])*u2 + _rgba_getb(pal->color[color[3]])*u1)*v1);
|
||||
int a = ((_rgba_geta(pal->color[color[0]])*u2 + _rgba_geta(pal->color[color[1]])*u1)*v2 +
|
||||
(_rgba_geta(pal->color[color[2]])*u2 + _rgba_geta(pal->color[color[3]])*u1)*v1);
|
||||
int a = (((color[0] == 0 ? 0: 255)*u2 + (color[1] == 0 ? 0: 255)*u1)*v2 +
|
||||
((color[2] == 0 ? 0: 255)*u2 + (color[3] == 0 ? 0: 255)*u1)*v1);
|
||||
dst_color = a > 127 ? rgb_map->data[r>>3][g>>3][b>>3]: 0;
|
||||
break;
|
||||
}
|
||||
case IMAGE_BITMAP: {
|
||||
int g = ((255*color[0]*u2 + 255*color[1]*u1)*v2 +
|
||||
(255*color[2]*u2 + 255*color[3]*u1)*v1);
|
||||
dst_color = g > 127 ? 1: 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dst->putpixel(x, y, dst_color);
|
||||
|
@ -88,6 +88,7 @@ void image_ellipsefill(Image* image, int x1, int y1, int x2, int y2, int color);
|
||||
|
||||
void image_to_allegro(const Image* image, BITMAP* bmp, int x, int y);
|
||||
|
||||
void image_fixup_transparent_colors(Image* image);
|
||||
void image_resize(const Image* src, Image* dst, ResizeMethod method, Palette* palette, RGB_MAP* rgb_map);
|
||||
int image_count_diff(const Image* i1, const Image* i2);
|
||||
bool image_shrink_rect(Image *image, int *x1, int *y1, int *x2, int *y2, int refpixel);
|
||||
|
Loading…
Reference in New Issue
Block a user