Skip to content

Commit

Permalink
Optimize ComputeImageOpacity
Browse files Browse the repository at this point in the history
  • Loading branch information
mateofio committed Jan 15, 2020
1 parent 7fd3711 commit 1f33b4c
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 22 deletions.
3 changes: 1 addition & 2 deletions bench/bitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,8 @@ BENCHMARK(BM_FindFormat);
static void BM_ComputeImageOpacity(benchmark::State& state) {
Bitmap::SetFormat(format_R8G8B8A8_a().format());
auto bm = Bitmap::Create(320, 240);
auto rect = bm->GetRect();
for (auto _: state) {
bm->ComputeImageOpacity(rect);
bm->ComputeImageOpacity();
}
}

Expand Down
62 changes: 42 additions & 20 deletions src/bitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,29 +212,51 @@ bool Bitmap::GetTransparent() const {
return format.alpha_type != PF::NoAlpha;
}

ImageOpacity Bitmap::ComputeImageOpacity(Rect rect) const {
bool all = true;
bool any = false;
ImageOpacity Bitmap::ComputeImageOpacity() const {
bool all_opaque = true;
bool all_transp = true;

auto* p = reinterpret_cast<const uint32_t*>(pixels());
const auto mask = pixel_format.rgba_to_uint32_t(0, 0, 0, 0xFF);

int n = GetSize() / sizeof(uint32_t);
for (int i = 0; i < n; ++i ) {
auto px = p[i] & mask;
all_opaque &= (px == mask);
all_transp &= (px == 0);
}

DynamicFormat format(32,8,24,8,16,8,8,8,0,PF::Alpha);
std::vector<uint32_t> pixels;
pixels.resize(rect.width * rect.height);
Bitmap bmp(reinterpret_cast<void*>(&pixels.front()), rect.width, rect.height, rect.width*4, format);
bmp.Blit(0, 0, *this, rect, Opacity::Opaque());

for (std::vector<uint32_t>::const_iterator p = pixels.begin(); p != pixels.end(); ++p) {
if ((*p & 0xFF) != 0)
any = true;
else
all = false;
if (any && !all)
break;
return
all_transp ? ImageOpacity::Transparent :
all_opaque ? ImageOpacity::Opaque :
ImageOpacity::Partial;
}

ImageOpacity Bitmap::ComputeImageOpacity(Rect rect) const {
bool all_opaque = true;
bool all_transp = true;

const auto full_rect = GetRect();
rect = full_rect.GetSubRect(rect);

auto* p = reinterpret_cast<const uint32_t*>(pixels());
const int stride = pitch() / sizeof(uint32_t);
const auto mask = pixel_format.rgba_to_uint32_t(0, 0, 0, 0xFF);

int xend = (rect.x + rect.width);
int yend = (rect.y + rect.height);
for (int y = rect.y * stride; y < yend * stride; y += stride) {
for (int x = rect.x; x < xend; ++x) {
auto px = p[x + y] & mask;
all_transp &= (px == 0);
all_opaque &= (px == mask);
}
}

return
all ? ImageOpacity::Opaque :
any ? ImageOpacity::Partial :
ImageOpacity::Transparent;
all_transp ? ImageOpacity::Transparent :
all_opaque ? ImageOpacity::Opaque :
ImageOpacity::Partial;
}

void Bitmap::CheckPixels(uint32_t flags) {
Expand Down Expand Up @@ -265,7 +287,7 @@ void Bitmap::CheckPixels(uint32_t flags) {
if (flags & Flag_ReadOnly) {
read_only = true;

image_opacity = ComputeImageOpacity(GetRect());
image_opacity = ComputeImageOpacity();
}
}

Expand Down
1 change: 1 addition & 0 deletions src/bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ class Bitmap {
int bpp() const;
int pitch() const;

ImageOpacity ComputeImageOpacity() const;
ImageOpacity ComputeImageOpacity(Rect rect) const;

protected:
Expand Down

0 comments on commit 1f33b4c

Please sign in to comment.