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} target_link_libraries(${PROJECT_NAME}
freetype freetype
tiff tiff
webpdemux
webp webp
turbojpeg turbojpeg
jpeg jpeg

View File

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

View File

@ -19,7 +19,7 @@ namespace Windows {
(data.textures[data.frame_count].height * data.zoom_factor))) * 0.5f); (data.textures[data.frame_count].height * data.zoom_factor))) * 0.5f);
if (data.textures.size() > 1) { 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, 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)); data.textures[data.frame_count].height * data.zoom_factor));

View File

@ -44,6 +44,7 @@
// WEBP // WEBP
#include <webp/decode.h> #include <webp/decode.h>
#include <webp/demux.h>
#include "fs.h" #include "fs.h"
#include "imgui.h" #include "imgui.h"
@ -241,7 +242,7 @@ namespace Textures {
textures[i].width = gif.width; textures[i].width = gif.width;
textures[i].height = gif.height; 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); ret = Textures::LoadImage(static_cast<unsigned char *>(gif.frame_image), GL_RGBA, textures[i], nullptr);
} }
} }
@ -425,9 +426,58 @@ namespace Textures {
return false; return false;
} }
static bool LoadImageWEBP(unsigned char **data, SceOff &size, Tex &texture) { static bool LoadImageWEBP(unsigned char **data, SceOff &size, std::vector<Tex> &textures) {
*data = WebPDecodeRGBA(*data, size, &texture.width, &texture.height); bool ret = false;
bool ret = Textures::LoadImage(*data, GL_RGBA, texture, nullptr); 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; return ret;
} }
@ -467,7 +517,7 @@ namespace Textures {
else if (ext == ".SVG") else if (ext == ".SVG")
ret = Textures::LoadImageSVG(&data, textures[0]); ret = Textures::LoadImageSVG(&data, textures[0]);
else if (ext == ".WEBP") else if (ext == ".WEBP")
ret = Textures::LoadImageWEBP(&data, size, textures[0]); ret = Textures::LoadImageWEBP(&data, size, textures);
delete[] data; delete[] data;
} }