mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-29 12:32:52 +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);
|
int h = scale_y(image->h);
|
||||||
Image* new_image = image_new(image->imgtype, MAX(1, w), MAX(1, h));
|
Image* new_image = image_new(image->imgtype, MAX(1, w), MAX(1, h));
|
||||||
|
|
||||||
|
image_fixup_transparent_colors(image);
|
||||||
image_resize(image, new_image,
|
image_resize(image, new_image,
|
||||||
m_resize_method,
|
m_resize_method,
|
||||||
get_current_palette(),
|
get_current_palette(),
|
||||||
@ -108,17 +109,26 @@ protected:
|
|||||||
|
|
||||||
// resize mask
|
// resize mask
|
||||||
if (m_sprite->mask->bitmap) {
|
if (m_sprite->mask->bitmap) {
|
||||||
int w = scale_x(m_sprite->mask->bitmap->w);
|
Image* old_bitmap = image_crop(m_sprite->mask->bitmap, -1, -1,
|
||||||
int h = scale_y(m_sprite->mask->bitmap->h);
|
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* new_mask = mask_new();
|
||||||
mask_replace(new_mask,
|
mask_replace(new_mask,
|
||||||
scale_x(m_sprite->mask->x),
|
scale_x(m_sprite->mask->x-1),
|
||||||
scale_y(m_sprite->mask->y), MAX(1, w), MAX(1, h));
|
scale_y(m_sprite->mask->y-1), MAX(1, w), MAX(1, h));
|
||||||
|
image_resize(old_bitmap, new_mask->bitmap,
|
||||||
image_resize(m_sprite->mask->bitmap, new_mask->bitmap,
|
m_resize_method,
|
||||||
RESIZE_METHOD_NEAREST_NEIGHBOR,
|
|
||||||
get_current_palette(),
|
get_current_palette(),
|
||||||
orig_rgb_map);
|
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);
|
undoable.copy_to_current_mask(new_mask);
|
||||||
mask_free(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)
|
void image_to_allegro(const Image* image, BITMAP *bmp, int x, int y)
|
||||||
{
|
{
|
||||||
image->to_allegro(bmp, x, 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)
|
void image_resize(const Image* src, Image* dst, ResizeMethod method, Palette* pal, RGB_MAP* rgb_map)
|
||||||
{
|
{
|
||||||
switch (method) {
|
switch (method) {
|
||||||
@ -353,29 +444,47 @@ void image_resize(const Image* src, Image* dst, ResizeMethod method, Palette* pa
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO optimize this
|
// TODO optimize this
|
||||||
case RESIZE_METHOD_BILINEAR: {
|
case RESIZE_METHOD_BILINEAR: {
|
||||||
ase_uint32 color[4], dst_color;
|
ase_uint32 color[4], dst_color;
|
||||||
double u, v, du, dv;
|
double u, v, du, dv;
|
||||||
|
int u_floor, u_floor2;
|
||||||
|
int v_floor, v_floor2;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
u = v = 0.0;
|
u = v = 0.0;
|
||||||
du = src->w * 1.0 / dst->w;
|
du = (src->w-1) * 1.0 / (dst->w-1);
|
||||||
dv = src->h * 1.0 / dst->h;
|
dv = (src->h-1) * 1.0 / (dst->h-1);
|
||||||
for (y=0; y<dst->h; ++y) {
|
for (y=0; y<dst->h; ++y) {
|
||||||
for (x=0; x<dst->w; ++x) {
|
for (x=0; x<dst->w; ++x) {
|
||||||
int u_floor = floor(u);
|
u_floor = floor(u);
|
||||||
int v_floor = floor(v);
|
v_floor = floor(v);
|
||||||
|
|
||||||
color[0] = src->getpixel(MID(0, u_floor, src->w-1),
|
if (u_floor > src->w-1) {
|
||||||
MID(0, v_floor, src->h-1));
|
u_floor = src->w-1;
|
||||||
color[1] = src->getpixel(MID(0, u_floor+1, src->w-1),
|
u_floor2 = src->w-1;
|
||||||
MID(0, v_floor, src->h-1));
|
}
|
||||||
color[2] = src->getpixel(MID(0, u_floor, src->w-1),
|
else if (u_floor == src->w-1)
|
||||||
MID(0, v_floor+1, src->h-1));
|
u_floor2 = u_floor;
|
||||||
color[3] = src->getpixel(MID(0, u_floor+1, src->w-1),
|
else
|
||||||
MID(0, v_floor+1, src->h-1));
|
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 u1 = u - u_floor;
|
||||||
double v1 = v - v_floor;
|
double v1 = v - v_floor;
|
||||||
double u2 = 1 - u1;
|
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);
|
(_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 +
|
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);
|
(_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 +
|
int a = (((color[0] == 0 ? 0: 255)*u2 + (color[1] == 0 ? 0: 255)*u1)*v2 +
|
||||||
(_rgba_geta(pal->color[color[2]])*u2 + _rgba_geta(pal->color[color[3]])*u1)*v1);
|
((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;
|
dst_color = a > 127 ? rgb_map->data[r>>3][g>>3][b>>3]: 0;
|
||||||
break;
|
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);
|
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_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);
|
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);
|
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);
|
bool image_shrink_rect(Image *image, int *x1, int *y1, int *x2, int *y2, int refpixel);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user