Fix bug not re-using a tile when A=0 and RGB values are different

When alpha=0, we can ignore RGB values and re-use a tile in the
tileset.
This commit is contained in:
David Capello 2021-04-19 16:56:30 -03:00
parent 684ae08112
commit e6bf19e1c1
5 changed files with 48 additions and 2 deletions

View File

@ -405,6 +405,8 @@ void draw_image_into_new_tilemap_cel(
if (grid.hasMask())
mask_image(tileImage.get(), grid.mask().get());
preprocess_transparent_pixels(tileImage.get());
doc::tile_index tileIndex;
if (!tileset->findTileIndex(tileImage, tileIndex)) {
auto addTile = new cmd::AddTile(tileset, tileImage);
@ -538,6 +540,8 @@ void modify_tilemap_cel_region(
if (grid.hasMask())
mask_image(tileImage.get(), grid.mask().get());
preprocess_transparent_pixels(tileImage.get());
tile_index tileIndex;
if (tileset->findTileIndex(tileImage, tileIndex)) {
// We can re-use an existent tile (tileIndex) from the tileset

View File

@ -312,7 +312,7 @@ bool is_plain_image_templ(const Image* img, const color_t color)
const LockImageBits<ImageTraits> bits(img);
typename LockImageBits<ImageTraits>::const_iterator it, end;
for (it=bits.begin(), end=bits.end(); it!=end; ++it) {
if (*it != color)
if (!ImageTraits::same_color(*it, color))
return false;
}
ASSERT(it == end);
@ -482,4 +482,31 @@ uint32_t calculate_image_hash(const Image* img, const gfx::Rect& bounds)
return 0;
}
void preprocess_transparent_pixels(Image* image)
{
switch (image->pixelFormat()) {
case IMAGE_RGB: {
LockImageBits<RgbTraits> bits(image);
auto it = bits.begin(), end = bits.end();
for (; it != end; ++it) {
if (rgba_geta(*it) == 0)
*it = 0;
}
break;
}
case IMAGE_GRAYSCALE: {
LockImageBits<RgbTraits> bits(image);
auto it = bits.begin(), end = bits.end();
for (; it != end; ++it) {
if (graya_geta(*it) == 0)
*it = 0;
}
break;
}
}
}
} // namespace doc

View File

@ -1,5 +1,5 @@
// Aseprite Document Library
// Copyright (c) 2018-2019 Igara Studio S.A.
// Copyright (c) 2018-2021 Igara Studio S.A.
// Copyright (c) 2001-2016 David Capello
//
// This file is released under the terms of the MIT license.
@ -53,6 +53,10 @@ namespace doc {
uint32_t calculate_image_hash(const Image* image,
const gfx::Rect& bounds);
// Sets RGB values to 0 when alpha=0 (to match images with alpha=0
// in tilesets/calculate_image_hash)
void preprocess_transparent_pixels(Image* image);
} // namespace doc
#endif

View File

@ -129,7 +129,9 @@ void Tileset::set(const tile_index ti,
removeFromHash(ti, false);
preprocess_transparent_pixels(image.get());
m_tiles[ti] = image;
if (!m_hash.empty())
hashImage(ti, image);
}
@ -140,6 +142,7 @@ tile_index Tileset::add(const ImageRef& image)
ASSERT(image->width() == m_grid.tileSize().w);
ASSERT(image->height() == m_grid.tileSize().h);
preprocess_transparent_pixels(image.get());
m_tiles.push_back(image);
const tile_index newIndex = tile_index(m_tiles.size()-1);
@ -162,6 +165,7 @@ void Tileset::insert(const tile_index ti,
ASSERT(image->height() == m_grid.tileSize().h);
ASSERT(ti >= 0 && ti <= m_tiles.size()+1);
preprocess_transparent_pixels(image.get());
m_tiles.insert(m_tiles.begin()+ti, image);
if (!m_hash.empty()) {
@ -256,6 +260,10 @@ void Tileset::notifyTileContentChange(const tile_index ti)
// only way to make it work correctly)
(void)ti; // unused
if (ti >= 0 && ti < m_tiles.size() && m_tiles[ti])
preprocess_transparent_pixels(m_tiles[ti].get());
rehash();
#endif

View File

@ -95,6 +95,9 @@ namespace doc {
// given "tileImage", this function returns true and the index of
// that tile in the "ti" parameter. Returns false if the image is
// not in the tileset.
//
// Warning: Use preprocess_transparent_pixels() with tileImage
// before calling this function.
bool findTileIndex(const ImageRef& tileImage,
tile_index& ti);