diff options
author | Emery Hemingway <emery@dmz.rs> | 2024-09-03T10·54+0300 |
---|---|---|
committer | emery <emery@dmz.rs> | 2024-09-03T19·44+0000 |
commit | 1c898f7ddc5b3ad223d73972465c9fee206c9815 (patch) | |
tree | efb35c2af80c74073cf2d956bf4ed91c24a848f7 /tools/eaglemode | |
parent | e4714db2d5f2b38b60f1ec8a200d0eb3bea0d79f (diff) |
feat(tools/eaglemode/plugins/avif): AVIF image plugin r/8647
Animation not implemented. https: //en.wikipedia.org/wiki/AVIF Change-Id: I80f8c4132c4335b2e60ce7b70eb424457e50c73f Reviewed-on: https://cl.tvl.fyi/c/depot/+/12428 Tested-by: BuildkiteCI Reviewed-by: tazjin <tazjin@tvl.su>
Diffstat (limited to 'tools/eaglemode')
-rw-r--r-- | tools/eaglemode/plugins/avif/default.nix | 16 | ||||
-rw-r--r-- | tools/eaglemode/plugins/avif/etc/emCore/FpPlugins/PlAvif.emFpPlugin | 6 | ||||
-rw-r--r-- | tools/eaglemode/plugins/avif/makers/PlAvif.maker.pm | 64 | ||||
-rw-r--r-- | tools/eaglemode/plugins/avif/src/PlAvif.cpp | 190 |
4 files changed, 276 insertions, 0 deletions
diff --git a/tools/eaglemode/plugins/avif/default.nix b/tools/eaglemode/plugins/avif/default.nix new file mode 100644 index 000000000000..5def86a6ed82 --- /dev/null +++ b/tools/eaglemode/plugins/avif/default.nix @@ -0,0 +1,16 @@ +{ depot, pkgs, ... }: + +let + em = depot.tools.eaglemode; + emSrc = pkgs.srcOnly pkgs.em; +in +(em.buildPlugin { + name = "avif"; + version = "canon"; + src = ./.; + target = "PlAvif"; +}).overrideAttrs + ({ buildInputs ? [ ], nativeBuildInputs ? [ ], ... }: { + buildInputs = buildInputs ++ [ pkgs.libavif ]; + nativeBuildInputs = nativeBuildInputs ++ [ pkgs.pkg-config ]; + }) diff --git a/tools/eaglemode/plugins/avif/etc/emCore/FpPlugins/PlAvif.emFpPlugin b/tools/eaglemode/plugins/avif/etc/emCore/FpPlugins/PlAvif.emFpPlugin new file mode 100644 index 000000000000..61615f9fd391 --- /dev/null +++ b/tools/eaglemode/plugins/avif/etc/emCore/FpPlugins/PlAvif.emFpPlugin @@ -0,0 +1,6 @@ +#%rec:emFpPlugin%# + +FileTypes = { ".avif" } +Priority = 1.0 +Library = "PlAvif" +Function = "PlAvifFpPluginFunc" diff --git a/tools/eaglemode/plugins/avif/makers/PlAvif.maker.pm b/tools/eaglemode/plugins/avif/makers/PlAvif.maker.pm new file mode 100644 index 000000000000..00b927805a72 --- /dev/null +++ b/tools/eaglemode/plugins/avif/makers/PlAvif.maker.pm @@ -0,0 +1,64 @@ +package PlAvif; + +use strict; +use warnings; + +sub GetDependencies +{ + return ('emCore'); +} + +sub IsEssential +{ + return 0; +} + +sub GetFileHandlingrules +{ + return (); +} + +sub GetExtraBuildOptions +{ + return (); +} + +sub Build +{ + shift; + my %options=@_; + + my @libAvifFlags=(); + if ($options{'avif-inc-dir'} eq '' && $options{'avif-lib-dir'} eq '') { + @libAvifFlags=split("\n",readpipe( + "perl \"".$options{'utils'}."/PkgConfig.pl\" libavif" + )); + } + if (!@libAvifFlags) { + if ($options{'avif-inc-dir'} ne '') { + push(@libAvifFlags, "--inc-search-dir", $options{'avif-inc-dir'}); + } + if ($options{'avif-lib-dir'} ne '') { + push(@libAvifFlags, "--lib-search-dir", $options{'avif-lib-dir'}); + } + push(@libAvifFlags, "--link", "avif"); + } + + system( + @{$options{'unicc_call'}}, + "--math", + "--rtti", + "--exceptions", + "--bin-dir" , "bin", + "--lib-dir" , "lib", + "--obj-dir" , "obj", + "--inc-search-dir", "include", + @libAvifFlags, + "--link" , "emCore", + "--type" , "dynlib", + "--name" , "PlAvif", + "src/PlAvif.cpp" + )==0 or return 0; + + return 1; +} diff --git a/tools/eaglemode/plugins/avif/src/PlAvif.cpp b/tools/eaglemode/plugins/avif/src/PlAvif.cpp new file mode 100644 index 000000000000..e4807bacd49a --- /dev/null +++ b/tools/eaglemode/plugins/avif/src/PlAvif.cpp @@ -0,0 +1,190 @@ +#include <emCore/emFpPlugin.h> +#include <emCore/emImageFile.h> + +#include "avif/avif.h" + +class PlAvifImageFileModel : public emImageFileModel +{ +public: + + static emRef<PlAvifImageFileModel> Acquire( + emContext & context, const emString & name, bool common=true + ); + +protected: + PlAvifImageFileModel(emContext & context, const emString & name); + virtual ~PlAvifImageFileModel(); + virtual void TryStartLoading(); + virtual bool TryContinueLoading(); + virtual void QuitLoading(); + virtual void TryStartSaving(); + virtual bool TryContinueSaving(); + virtual void QuitSaving(); + virtual emUInt64 CalcMemoryNeed(); + virtual double CalcFileProgress(); + +private: + struct LoadingState; + LoadingState * L = NULL; +}; + + +struct PlAvifImageFileModel::LoadingState { + avifRGBImage rgb; + avifDecoder * decoder; +}; + + +emRef<PlAvifImageFileModel> PlAvifImageFileModel::Acquire( + emContext & context, const emString & name, bool common +) +{ + EM_IMPL_ACQUIRE(PlAvifImageFileModel, context, name, common) +} + + +PlAvifImageFileModel::PlAvifImageFileModel( + emContext & context, const emString & name +) + : emImageFileModel(context, name) +{ +} + + +PlAvifImageFileModel::~PlAvifImageFileModel() +{ + PlAvifImageFileModel::QuitLoading(); + PlAvifImageFileModel::QuitSaving(); +} + + +void PlAvifImageFileModel::TryStartLoading() +{ + avifResult result; + + L = new LoadingState; + memset(L, 0, sizeof(LoadingState)); + + L->decoder = avifDecoderCreate(); + if (L->decoder == NULL) { + throw emException("failed to create AVIF decoder"); + } + + result = avifDecoderSetIOFile(L->decoder, GetFilePath()); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + result = avifDecoderParse(L->decoder); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + FileFormatInfo = emString::Format( + "AVIF %s %ubpc", + avifPixelFormatToString(L->decoder->image->yuvFormat), + L->decoder->image->depth + ); + + + Signal(ChangeSignal); +} + + +bool PlAvifImageFileModel::TryContinueLoading() +{ + avifResult result; + + if (!Image.GetHeight()) { + Image.Setup( + L->decoder->image->width, + L->decoder->image->height, + L->decoder->alphaPresent ? 4 : 3 + ); + } + + result = avifDecoderNextImage(L->decoder); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + avifRGBImageSetDefaults(&L->rgb, L->decoder->image); + L->rgb.format = L->decoder->alphaPresent ? + AVIF_RGB_FORMAT_RGBA : AVIF_RGB_FORMAT_RGB; + L->rgb.pixels = Image.GetWritableMap(); + L->rgb.width = Image.GetWidth(); + L->rgb.height = Image.GetHeight(); + L->rgb.depth = 8; + L->rgb.rowBytes = Image.GetWidth() * Image.GetChannelCount(); + + result = avifImageYUVToRGB(L->decoder->image, &L->rgb); + if (result != AVIF_RESULT_OK) { + throw emException("%s", avifResultToString(result)); + } + + Signal(ChangeSignal); + return true; +} + + +void PlAvifImageFileModel::QuitLoading() +{ + if (L) { + if (L->decoder) avifDecoderDestroy(L->decoder); + delete L; + L = NULL; + } +} + + +void PlAvifImageFileModel::TryStartSaving() +{ + throw emException("PlAvifImageFileModel: Saving not implemented."); +} + + +bool PlAvifImageFileModel::TryContinueSaving() +{ + return false; +} + + +void PlAvifImageFileModel::QuitSaving() +{ +} + + +emUInt64 PlAvifImageFileModel::CalcMemoryNeed() +{ + return + (emUInt64) + L->decoder->image->width * + L->decoder->image->height * + (L->decoder->alphaPresent ? 4 : 3); +} + + +double PlAvifImageFileModel::CalcFileProgress() +{ + return 0.0; +} + +extern "C" { + emPanel * PlAvifFpPluginFunc( + emPanel::ParentArg parent, const emString & name, + const emString & path, emFpPlugin * plugin, + emString * errorBuf + ) + { + if (plugin->Properties.GetCount()) { + *errorBuf="PlAvifFpPlugin: No properties allowed."; + return NULL; + } + return new emImageFilePanel( + parent, name, + PlAvifImageFileModel::Acquire( + parent.GetRootContext(), path + ) + ); + } +} |