Skip to content

Commit

Permalink
Merge pull request #91 from r-ralph/alloc_exception
Browse files Browse the repository at this point in the history
Catch std::bad_alloc exception
  • Loading branch information
r-ralph committed May 7, 2021
2 parents a9dfdda + f63812d commit a12d187
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 8 deletions.
2 changes: 1 addition & 1 deletion apng-drawable/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ android {
cmake {
cppFlags += "-std=c++17"
cppFlags += "-fno-rtti"
cppFlags += "-fno-exceptions"
cppFlags += "-fexceptions"
}
}
}
Expand Down
29 changes: 23 additions & 6 deletions apng-drawable/src/main/cpp/apng-drawbale/ApngDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ std::unique_ptr<ApngImage> ApngDecoder::decode(
png_uint_32 frames = 1;
png_uint_32 plays = 0;
bool has_acTL = png_get_acTL(png_ptr, info_ptr, &frames, &plays) != 0;
LOGV(" | acTL result=%d, frames=%d, plays=%d", has_acTL, frames, plays);
if (!has_acTL) {
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
result = ERR_INVALID_FILE_FORMAT;
Expand Down Expand Up @@ -209,6 +210,7 @@ std::unique_ptr<ApngImage> ApngDecoder::decode(
std::unique_ptr<png_bytep[]> rows_frame(new png_bytep[row_ptr_array_size]);
std::unique_ptr<png_bytep[]> rows_buffer(new png_bytep[row_ptr_array_size]);
if (!p_frame || !p_buffer || !p_previous_frame || !rows_frame || !rows_buffer) {
LOGV(" | failed to allocate buffers");
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
result = ERR_OUT_OF_MEMORY;
return nullptr;
Expand All @@ -220,12 +222,27 @@ std::unique_ptr<ApngImage> ApngDecoder::decode(
rows_buffer[j] = p_buffer.get() + j * row_bytes;
}

std::unique_ptr<ApngImage> png(new ApngImage(
width,
height,
static_cast<uint32_t>(frames),
static_cast<uint32_t>(plays)
));
std::unique_ptr<ApngImage> png;
try {
png = std::make_unique<ApngImage>(
width,
height,
static_cast<uint32_t>(frames),
static_cast<uint32_t>(plays)
);
} catch (const std::bad_alloc &) {
LOGV(" | failed to allocate ApngImage due to std::bad_alloc");
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
result = ERR_OUT_OF_MEMORY;
return nullptr;
}

if (!png) {
LOGV(" | failed to allocate ApngImage");
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
result = ERR_OUT_OF_MEMORY;
return nullptr;
}

// Point to handle error (everything until done decoding)
if (setjmp(png_jmpbuf(png_ptr)) != 0) { // NOLINT(cert-err52-cpp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
import com.linecorp.apng.ApngDrawable
import com.linecorp.apng.RepeatAnimationCallback
import com.linecorp.apng.decoder.ApngException
import com.linecorp.apngsample.databinding.ActivityMainBinding
import com.linecorp.lich.lifecycle.AutoResetLifecycleScope
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -95,12 +96,18 @@ class MainActivity : AppCompatActivity() {
drawable?.clearAnimationCallbacks()
drawable = null
binding.imageView.setImageDrawable(null)
binding.textCallback.text = null
val isApng = assets.open(name).buffered().use {
ApngDrawable.isApng(it)
}
binding.textStatus.text = "isApng: $isApng"
if (isApng) {
drawable = ApngDrawable.decode(assets, name, width, height)
try {
drawable = ApngDrawable.decode(assets, name, width, height)
} catch (e: ApngException) {
binding.textCallback.text = "Failed to decode: ${e.errorCode}"
return
}
drawable?.loopCount = 5
drawable?.setTargetDensity(resources.displayMetrics)
drawable?.registerAnimationCallback(animationCallback)
Expand Down

0 comments on commit a12d187

Please sign in to comment.