webp: Add support for animated webp

This commit is contained in:
Joel16 2022-01-12 23:49:19 -05:00
parent f6681ffed6
commit 977ea941fe
4 changed files with 58 additions and 7 deletions

View File

@ -88,6 +88,7 @@ add_executable(${PROJECT_NAME}
target_link_libraries(${PROJECT_NAME}
freetype
tiff
webpdemux
webp
turbojpeg
jpeg

View File

@ -9,7 +9,7 @@ typedef struct {
GLuint id = 0;
int width = 0;
int height = 0;
int delay = 0;
SceUInt delay = 0; // microseconds
} Tex;
extern std::vector<Tex> icons;

View File

@ -19,7 +19,7 @@ namespace Windows {
(data.textures[data.frame_count].height * data.zoom_factor))) * 0.5f);
if (data.textures.size() > 1) {
sceKernelDelayThread(data.textures[data.frame_count].delay * 10000);
sceKernelDelayThread(data.textures[data.frame_count].delay);
ImGui::Image(reinterpret_cast<ImTextureID>(data.textures[data.frame_count].id), ImVec2(data.textures[data.frame_count].width * data.zoom_factor,
data.textures[data.frame_count].height * data.zoom_factor));

View File

@ -44,6 +44,7 @@
// WEBP
#include <webp/decode.h>
#include <webp/demux.h>
#include "fs.h"
#include "imgui.h"
@ -241,7 +242,7 @@ namespace Textures {
textures[i].width = gif.width;
textures[i].height = gif.height;
textures[i].delay = gif.frames->frame_delay;
textures[i].delay = gif.frames->frame_delay * 10000;
ret = Textures::LoadImage(static_cast<unsigned char *>(gif.frame_image), GL_RGBA, textures[i], nullptr);
}
}
@ -425,9 +426,58 @@ namespace Textures {
return false;
}
static bool LoadImageWEBP(unsigned char **data, SceOff &size, Tex &texture) {
*data = WebPDecodeRGBA(*data, size, &texture.width, &texture.height);
bool ret = Textures::LoadImage(*data, GL_RGBA, texture, nullptr);
static bool LoadImageWEBP(unsigned char **data, SceOff &size, std::vector<Tex> &textures) {
bool ret = false;
VP8StatusCode status = VP8_STATUS_OK;
WebPBitstreamFeatures features = {0};
status = WebPGetFeatures(*data, size, &features);
if (status != VP8_STATUS_OK)
return ret;
if (features.has_animation) {
int frame_index = 0, prev_timestamp = 0;
WebPData webp_data = {0};
WebPAnimDecoder *dec = {0};
WebPAnimInfo info = {0};
WebPDataInit(&webp_data);
webp_data.bytes = *data;
webp_data.size = size;
dec = WebPAnimDecoderNew(&webp_data, nullptr);
if (dec == nullptr)
return ret;
if (!WebPAnimDecoderGetInfo(dec, &info)) {
WebPAnimDecoderDelete(dec);
return ret;
}
textures.resize(info.frame_count);
while (WebPAnimDecoderHasMoreFrames(dec)) {
unsigned char *frame_rgba = nullptr;
int timestamp = 0;
if (!WebPAnimDecoderGetNext(dec, &frame_rgba, &timestamp)) {
WebPAnimDecoderDelete(dec);
return ret;
}
textures[frame_index].width = info.canvas_width;
textures[frame_index].height = info.canvas_height;
textures[frame_index].delay = (timestamp - prev_timestamp) * 1000;
ret = Textures::LoadImage(frame_rgba, GL_RGBA, textures[frame_index], nullptr);
++frame_index;
prev_timestamp = timestamp;
}
}
else {
*data = WebPDecodeRGBA(*data, size, &textures[0].width, &textures[0].height);
ret = Textures::LoadImage(*data, GL_RGBA, textures[0], nullptr);
}
return ret;
}
@ -467,7 +517,7 @@ namespace Textures {
else if (ext == ".SVG")
ret = Textures::LoadImageSVG(&data, textures[0]);
else if (ext == ".WEBP")
ret = Textures::LoadImageWEBP(&data, size, textures[0]);
ret = Textures::LoadImageWEBP(&data, size, textures);
delete[] data;
}