about summary refs log tree commit diff
path: root/tools/eaglemode/plugins/avif/src/PlAvif.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/eaglemode/plugins/avif/src/PlAvif.cpp')
-rw-r--r--tools/eaglemode/plugins/avif/src/PlAvif.cpp190
1 files changed, 190 insertions, 0 deletions
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
+			)
+		);
+	}
+}