From 0c391fdbce5a079cf03e483eb6174dd47806163d Mon Sep 17 00:00:00 2001 From: chai Date: Wed, 7 Aug 2019 21:08:47 +0800 Subject: *misc --- Source/modules/asura-core/Image/ImageData.cpp | 62 ++++++++++++ Source/modules/asura-core/Image/ImageData.h | 81 ++++++++++++++++ .../modules/asura-core/Image/ImageDecodeTask.cpp | 17 ++++ Source/modules/asura-core/Image/ImageDecodeTask.h | 35 +++++++ Source/modules/asura-core/Image/ImageDecoder.h | 33 +++++++ Source/modules/asura-core/Image/PngDecoder.cpp | 17 ++++ Source/modules/asura-core/Image/PngDecoder.h | 25 +++++ Source/modules/asura-core/Image/StbDecoder.cpp | 73 ++++++++++++++ Source/modules/asura-core/Image/StbDecoder.h | 26 +++++ .../asura-core/Image/binding/_image_data.cpp | 108 +++++++++++++++++++++ .../Image/binding/_image_decode_task.cpp | 19 ++++ 11 files changed, 496 insertions(+) create mode 100644 Source/modules/asura-core/Image/ImageData.cpp create mode 100644 Source/modules/asura-core/Image/ImageData.h create mode 100644 Source/modules/asura-core/Image/ImageDecodeTask.cpp create mode 100644 Source/modules/asura-core/Image/ImageDecodeTask.h create mode 100644 Source/modules/asura-core/Image/ImageDecoder.h create mode 100644 Source/modules/asura-core/Image/PngDecoder.cpp create mode 100644 Source/modules/asura-core/Image/PngDecoder.h create mode 100644 Source/modules/asura-core/Image/StbDecoder.cpp create mode 100644 Source/modules/asura-core/Image/StbDecoder.h create mode 100644 Source/modules/asura-core/Image/binding/_image_data.cpp create mode 100644 Source/modules/asura-core/Image/binding/_image_decode_task.cpp (limited to 'Source/modules/asura-core/Image') diff --git a/Source/modules/asura-core/Image/ImageData.cpp b/Source/modules/asura-core/Image/ImageData.cpp new file mode 100644 index 0000000..bbfd177 --- /dev/null +++ b/Source/modules/asura-core/Image/ImageData.cpp @@ -0,0 +1,62 @@ +#include "ImageData.h" +#include "PngDecoder.h" +#include "StbDecoder.h" +#include "ImageDecoder.h" + +using namespace std; + +using namespace AEGraphics; + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +// 解析image的decoder,用来作为解析策略。 +list ImageData::ImageDecoders = { + new PNGDecoder(), // png + new STBDecoder() // jpeg, tga, bmp +}; + +ImageData::ImageData() + : pixels(nullptr) + , size(0) + , width(0) + , height(0) + , format(COLOR_FORMAT_UNKNOWN) +{ +} + +ImageData::~ImageData() +{ + if (pixels) + delete[] pixels; +} + +void ImageData::Decode(FileSystem::DataBuffer& buffer) +{ + for (ImageDecoder* decoder : ImageDecoders) + { + if (decoder->CanDecode(buffer)) + { + decoder->Decode(buffer, *this); + return; + } + } +} + +Color ImageData::GetPixel(uint x, uint y) +{ + return Color(); +} + +void ImageData::Lock() +{ + m_Mutex.Lock(); +} + +void ImageData::Unlock() +{ + m_Mutex.Unlock(); +} + +namespace_end +namespace_end \ No newline at end of file diff --git a/Source/modules/asura-core/Image/ImageData.h b/Source/modules/asura-core/Image/ImageData.h new file mode 100644 index 0000000..2d70edc --- /dev/null +++ b/Source/modules/asura-core/Image/ImageData.h @@ -0,0 +1,81 @@ +#ifndef _ASURA_ENGINE_IMAGEDATA_H_ +#define _ASURA_ENGINE_IMAGEDATA_H_ + +#include + +#include +#include +#include +#include +#include + +#include "../Graphics/Texture.h" +#include "../Graphics/Color.h" + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +class ImageDecoder; + +class ImageData ASURA_FINAL + : public Scripting::Portable + , public AEFileSystem::DecodedData +{ +public: + + /// + /// 解析图片数据文件,并构建像素信息,如果解析失败,抛出异常 + /// + ImageData(); + ~ImageData(); + + void Decode(AEFileSystem::DataBuffer& buffer) override; + + void Lock(); + void Unlock(); + + AEGraphics::Color GetPixel(uint x, uint y); + + //----------------------------------------------------------------------------// + + uint width, height; // 像素尺寸 + AEGraphics::ColorFormat format; // 格式 + byte* pixels; // 像素数据 + std::size_t size; // 数据长度 + + //----------------------------------------------------------------------------// + +private: + + /// + /// 在第一次准备image data时构建所有提供的decoder。在几个decoders中间选择解析策略。 + /// + static std::list ImageDecoders; + + /// + /// 写数据的锁。 + /// + AEThreading::Mutex m_Mutex; + +luaxport: + + LUAX_DECL_FACTORY(ImageData); + + LUAX_DECL_METHOD(_New); + LUAX_DECL_METHOD(_GetPixel); + LUAX_DECL_METHOD(_GetSize); + LUAX_DECL_METHOD(_GetWidth); + LUAX_DECL_METHOD(_GetHeight); + LUAX_DECL_METHOD(_GetPixelFormat); + LUAX_DECL_METHOD(_Decode); + LUAX_DECL_METHOD(_DecodeAsync); + LUAX_DECL_METHOD(_IsAvailable); + +}; + +namespace_end +namespace_end + +namespace AEImage = AsuraEngine::Image; + +#endif \ No newline at end of file diff --git a/Source/modules/asura-core/Image/ImageDecodeTask.cpp b/Source/modules/asura-core/Image/ImageDecodeTask.cpp new file mode 100644 index 0000000..16c166e --- /dev/null +++ b/Source/modules/asura-core/Image/ImageDecodeTask.cpp @@ -0,0 +1,17 @@ +#include "ImageDecodeTask.h" + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +bool ImageDecodeTask::Execute() +{ + return false; +} + +void ImageDecodeTask::Invoke(lua_State* invokeThreaad) +{ + +} + +namespace_end +namespace_end \ No newline at end of file diff --git a/Source/modules/asura-core/Image/ImageDecodeTask.h b/Source/modules/asura-core/Image/ImageDecodeTask.h new file mode 100644 index 0000000..194ac3e --- /dev/null +++ b/Source/modules/asura-core/Image/ImageDecodeTask.h @@ -0,0 +1,35 @@ +#ifndef _ASURA_IMAGE_DECODE_TASK_H_ +#define _ASURA_IMAGE_DECODE_TASK_H_ + +#include +#include +#include + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +class ImageDecodeTask + : public AEScripting::Portable +{ +public: + + /// + /// 执行任务,完成后返回true,调用回调函数。 + /// + bool Execute() override; + + /// + /// 调用回调。在invoke thread里面回调。 + /// + void Invoke(lua_State* invokeThreaad) override; + +luaxport: + + LUAX_DECL_FACTORY(ImageDecodeTask, AEThreading::Task); + +}; + +namespace_end +namespace_end + +#endif \ No newline at end of file diff --git a/Source/modules/asura-core/Image/ImageDecoder.h b/Source/modules/asura-core/Image/ImageDecoder.h new file mode 100644 index 0000000..6cea8fd --- /dev/null +++ b/Source/modules/asura-core/Image/ImageDecoder.h @@ -0,0 +1,33 @@ +#ifndef _ASURA_ENGINE_IMAGE_DECODER_H_ +#define _ASURA_ENGINE_IMAGE_DECODER_H_ + +#include + +#include "ImageData.h" + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +ASURA_ABSTRACT class ImageDecoder +{ +public: + + ImageDecoder() {}; + virtual ~ImageDecoder() {}; + + /// + /// 判断内存是否能用本decoder解压 + /// + virtual bool CanDecode(AEFileSystem::DataBuffer& input) = 0; + + /// + /// 输入一个编码后的内存,输出一个解压后的Image data,如果解压失败返回nullptr + /// + virtual void Decode(AEFileSystem::DataBuffer& input, ImageData& target) = 0; + +}; + +namespace_end +namespace_end + +#endif \ No newline at end of file diff --git a/Source/modules/asura-core/Image/PngDecoder.cpp b/Source/modules/asura-core/Image/PngDecoder.cpp new file mode 100644 index 0000000..b314561 --- /dev/null +++ b/Source/modules/asura-core/Image/PngDecoder.cpp @@ -0,0 +1,17 @@ +#include "PngDecoder.h" + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +bool PNGDecoder::CanDecode(AEFileSystem::DataBuffer& buffer) +{ + return false; +} + +void PNGDecoder::Decode(AEFileSystem::DataBuffer& buffer, ImageData& data) +{ + +} + +namespace_end +namespace_end diff --git a/Source/modules/asura-core/Image/PngDecoder.h b/Source/modules/asura-core/Image/PngDecoder.h new file mode 100644 index 0000000..3b2a39c --- /dev/null +++ b/Source/modules/asura-core/Image/PngDecoder.h @@ -0,0 +1,25 @@ +#ifndef _ASURA_ENGINE_PNGDECODER_H_ +#define _ASURA_ENGINE_PNGDECODER_H_ + +#include "ImageDecoder.h" + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +/// +/// 使用lodepng解压png文件 +/// +class PNGDecoder ASURA_FINAL: public ImageDecoder +{ +public: + + bool CanDecode(AEFileSystem::DataBuffer& buffer) override; + + void Decode(AEFileSystem::DataBuffer& buffer, ImageData& data) override; + +}; + +namespace_end +namespace_end + +#endif \ No newline at end of file diff --git a/Source/modules/asura-core/Image/StbDecoder.cpp b/Source/modules/asura-core/Image/StbDecoder.cpp new file mode 100644 index 0000000..101b148 --- /dev/null +++ b/Source/modules/asura-core/Image/StbDecoder.cpp @@ -0,0 +1,73 @@ +#include + +#include "StbDecoder.h" + +#define STB_IMAGE_IMPLEMENTATION +#include + +using namespace AEGraphics; + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +bool STBDecoder::CanDecode(FileSystem::DataBuffer& buffer) +{ + int w = 0; + int h = 0; + int comp = 0; + + int status = stbi_info_from_memory((const stbi_uc*)buffer.GetData(), buffer.GetSize(), &w, &h, &comp); + + return status == 1 && w > 0 && h > 0; +} + +void STBDecoder::Decode(FileSystem::DataBuffer& db, ImageData& imageData) +{ + const stbi_uc *buffer = (const stbi_uc *)db.GetData(); + // databuffer数据长 + int bufferlen = db.GetSize(); + + int width, height; + int comp = 0; + byte* data = nullptr; + ColorFormat format = COLOR_FORMAT_UNKNOWN; + std::size_t size = 0; + + if (stbi_is_hdr_from_memory(buffer, bufferlen)) + { + // 4个channel都是float + data = (byte*)stbi_loadf_from_memory(buffer, bufferlen, &width, &height, &comp, STBI_rgb_alpha); + format = COLOR_FORMAT_RGBA32F; + size = width * height * 4 * sizeof(float); + } + else + { + data = (byte*)stbi_load_from_memory(buffer, bufferlen, &width, &height, &comp, STBI_rgb_alpha); + format = COLOR_FORMAT_RGBA8; + size = width * height * 4; + } + if (data) + { + imageData.Lock(); + + if (imageData.pixels) + free(imageData.pixels); + imageData.pixels = (byte*)data; + imageData.format = format; + imageData.width = width; + imageData.height = height; + imageData.size = size; + + imageData.Unlock(); + } + else + { + const char *err = stbi_failure_reason(); + if (err == nullptr) + err = "unknown error"; + throw Exception("Could not decode image with stb_image (%s).", err); + } +} + +namespace_end +namespace_end \ No newline at end of file diff --git a/Source/modules/asura-core/Image/StbDecoder.h b/Source/modules/asura-core/Image/StbDecoder.h new file mode 100644 index 0000000..23e8c38 --- /dev/null +++ b/Source/modules/asura-core/Image/StbDecoder.h @@ -0,0 +1,26 @@ +#ifndef _ASURA_ENGINE_STBDECODER_H_ +#define _ASURA_ENGINE_STBDECODER_H_ + +#include "ImageDecoder.h" + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +/// +/// 使用stb_image解压JPEG、TGA、BMP文件 +/// +class STBDecoder ASURA_FINAL + : public ImageDecoder +{ +public: + + bool CanDecode(AEFileSystem::DataBuffer& buffer) override; + + void Decode(AEFileSystem::DataBuffer& buffer, ImageData& data) override; + +}; + +namespace_end +namespace_end + +#endif \ No newline at end of file diff --git a/Source/modules/asura-core/Image/binding/_image_data.cpp b/Source/modules/asura-core/Image/binding/_image_data.cpp new file mode 100644 index 0000000..375f854 --- /dev/null +++ b/Source/modules/asura-core/Image/binding/_image_data.cpp @@ -0,0 +1,108 @@ +#include +#include + +#include "../ImageData.h" + +using namespace std; +using namespace AEThreading; +using namespace AEFileSystem; + +namespace_begin(AsuraEngine) +namespace_begin(Image) +LUAX_REGISTRY(ImageData) + { + LUAX_REGISTER_METHODS(state, + { "New", _New }, + { "GetPixel", _GetPixel }, + { "GetSize", _GetSize }, + { "GetWidth", _GetWidth }, + { "GetHeight", _GetHeight }, + { "GetPixelFormat", _GetPixelFormat }, + { "Decode", _Decode }, + { "DecodeAsync", _DecodeAsync }, + { "IsAvailable", _IsAvailable } + ); + } + + LUAX_POSTPROCESS(ImageData) + { + + } + + // ImageData.New() + LUAX_IMPL_METHOD(ImageData, _New) + { + LUAX_STATE(L); + + return 0; + } + + // imagedata:GetPixel() + LUAX_IMPL_METHOD(ImageData, _GetPixel) + { + LUAX_PREPARE(L, ImageData); + + return 0; + } + + // imagedata:GetSize() + LUAX_IMPL_METHOD(ImageData, _GetSize) + { + LUAX_PREPARE(L, ImageData); + + return 0; + } + + // imagedata:GetWidth() + LUAX_IMPL_METHOD(ImageData, _GetWidth) + { + LUAX_PREPARE(L, ImageData); + + return 0; + } + + // imagedata:GetHeight() + LUAX_IMPL_METHOD(ImageData, _GetHeight) + { + LUAX_PREPARE(L, ImageData); + + return 0; + } + + // imagedata:GetPixelFormat() + LUAX_IMPL_METHOD(ImageData, _GetPixelFormat) + { + LUAX_PREPARE(L, ImageData); + + return 0; + } + + // imagedata:Decode() + LUAX_IMPL_METHOD(ImageData, _Decode) + { + LUAX_PREPARE(L, ImageData); + + return 0; + } + + // imagedata:DecodeAsync(thread, databuffer, callback) + LUAX_IMPL_METHOD(ImageData, _DecodeAsync) + { + LUAX_PREPARE(L, ImageData); + + Thread* thread = state.CheckUserdata(2); + DataBuffer* buffer = state.CheckUserdata(3); + + return 0; + } + + // imagedata:IsAvailable() + LUAX_IMPL_METHOD(ImageData, _IsAvailable) + { + LUAX_PREPARE(L, ImageData); + + return 0; + } + + } +} diff --git a/Source/modules/asura-core/Image/binding/_image_decode_task.cpp b/Source/modules/asura-core/Image/binding/_image_decode_task.cpp new file mode 100644 index 0000000..3c8ed4b --- /dev/null +++ b/Source/modules/asura-core/Image/binding/_image_decode_task.cpp @@ -0,0 +1,19 @@ +#include "../ImageDecodeTask.h" + +using namespace std; + +namespace_begin(AsuraEngine) +namespace_begin(Image) + +LUAX_REGISTRY(ImageDecodeTask) +{ + +} + +LUAX_POSTPROCESS(ImageDecodeTask) +{ + +} + +} +} -- cgit v1.1-26-g67d0