in animated-gif/src/main/jni/gifimage/gif.cpp [681:763]
jobject createFromDataWrapper(JNIEnv* pEnv, std::shared_ptr<DataWrapper> spDataWrapper, int maxDimension, bool forceStatic) {
std::unique_ptr<GifImageNativeContext> spNativeContext(new GifImageNativeContext());
if (!spNativeContext) {
throwOutOfMemoryError(pEnv, "Unable to allocate native context");
return 0;
}
int gifError = 0;
auto spGifFileIn = std::unique_ptr<GifFileType, decltype(&DGifCloseFile2)> {
DGifOpen(
(void*) spDataWrapper.get(),
&directByteBufferReadFun,
&gifError),
DGifCloseFile2
};
if (spGifFileIn == nullptr) {
throwIllegalStateException(pEnv, "Error %d", gifError);
return nullptr;
}
int width = spGifFileIn->SWidth;
int height = spGifFileIn->SHeight;
size_t wxh = width * height;
if (wxh < 1 || wxh > SIZE_MAX || width > maxDimension || height > maxDimension) {
throwIllegalStateException(pEnv, "Invalid dimensions");
return nullptr;
}
// Create the GifWrapper
spNativeContext->spGifWrapper = std::shared_ptr<GifWrapper>(
new GifWrapper(std::move(spGifFileIn), spDataWrapper));
GifFileType* pGifFile = spNativeContext->spGifWrapper->get();
spNativeContext->pixelWidth = width;
spNativeContext->pixelHeight = height;
int error = modifiedDGifSlurp(spNativeContext->spGifWrapper.get(), maxDimension, forceStatic);
if (error != GIF_OK) {
throwIllegalStateException(pEnv, "Failed to slurp image %d", error);
return nullptr;
}
if (pGifFile->ImageCount < 1) {
throwIllegalStateException(pEnv, "No frames in image");
return nullptr;
}
spNativeContext->numFrames = pGifFile->ImageCount;
// Compute cached fields that require iterating the frames.
int durationMs = 0;
std::vector<jint> frameDurationsMs;
ReaderLock rlock_{spNativeContext->spGifWrapper->getSavedImagesRWLock()};
for (int i = 0; i < pGifFile->ImageCount; i++) {
SavedImage* pSavedImage = &pGifFile->SavedImages[i];
GraphicsControlBlock gcp;
if (getGraphicsControlBlockForImage(pSavedImage, &gcp)) {
int frameDurationMs = gcp.DelayTime * 10;
durationMs += frameDurationMs;
frameDurationsMs.push_back(frameDurationMs);
} else {
frameDurationsMs.push_back(0);
}
}
spNativeContext->durationMs = durationMs;
spNativeContext->frameDurationsMs = frameDurationsMs;
// Cache loop count
spNativeContext->loopCount = spNativeContext->spGifWrapper->getLoopCount();
// Create the GifImage with the native context.
jobject ret = pEnv->NewObject(
sClazzGifImage,
sGifImageConstructor,
(jlong) spNativeContext.get());
if (ret != nullptr) {
// Ownership was transferred.
spNativeContext->refCount = 1;
spNativeContext.release();
}
return ret;
}