Add heif decode and encode

This commit is contained in:
Prokhorov Kirill
2025-06-29 10:08:51 +03:00
parent 03463ee0e4
commit d3aae6dfcb
9 changed files with 198 additions and 12 deletions

View File

@ -44,6 +44,10 @@
#include "PICT/PICFile.h"
#endif
#if CXIMAGE_SUPPORT_HEIF
#include "heif/heif.h"
#endif
#include <cmath>
#define BGRA_FRAME_CXIMAGE_MAX_MEMORY 67108864 // 256Mb (*4 channel)
@ -444,11 +448,18 @@ bool CBgraFrame::OpenFile(const std::wstring& strFileName, unsigned int nFileTyp
#endif
#if CXIMAGE_SUPPORT_PIC
if (CXIMAGE_FORMAR_PIC == m_nFileType)
{
PICT::CPictFile PIC;
return PIC.Open(this, strFileName, !m_bIsRGBA);
}
if (CXIMAGE_FORMAR_PIC == m_nFileType)
{
PICT::CPictFile PIC;
return PIC.Open(this, strFileName, !m_bIsRGBA);
}
#endif
#if CXIMAGE_SUPPORT_HEIF
if (CXIMAGE_FORMAT_HEIF == m_nFileType)
{
return NSHeif::CHeifFile::Open(this, strFileName, !m_bIsRGBA);
}
#endif
NSFile::CFileBinary oFile;
@ -534,6 +545,13 @@ bool CBgraFrame::Decode(BYTE* pBuffer, int nSize, unsigned int nFileType)
}
#endif
#if CXIMAGE_SUPPORT_HEIF
if (CXIMAGE_FORMAT_HEIF == m_nFileType)
{
return NSHeif::CHeifFile::Open(this, pBuffer, nSize, !m_bIsRGBA);
}
#endif
CxImage img;
if (!img.Decode(pBuffer, nSize, m_nFileType))

View File

@ -32,6 +32,7 @@
#include "ImageFileFormatChecker.h"
#include "../common/File.h"
#include "../cximage/CxImage/ximacfg.h"
#include "heif/heif.h"
#ifndef IMAGE_CHECKER_DISABLE_XML
#include "../xml/include/xmlutils.h"
@ -432,6 +433,11 @@ bool CImageFileFormatChecker::isPicFile(BYTE *pBuffer, DWORD dwBytes)
return false;
}
bool CImageFileFormatChecker::isHeifFile(BYTE* pBuffer, DWORD dwBytes)
{
return NSHeif::CHeifFile::isHeif(pBuffer, dwBytes);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool CImageFileFormatChecker::isImageFile(const std::wstring& fileName)
{
@ -554,6 +560,10 @@ bool CImageFileFormatChecker::isImageFile(const std::wstring& fileName)
{
eFileType = _CXIMAGE_FORMAT_PIC;
}
else if (isHeifFile(fileName))
{
eFileType = _CXIMAGE_FORMAT_HEIF;
}
///////////////////////////////////////////////////////////////////////
delete [] buffer;
@ -669,6 +679,10 @@ bool CImageFileFormatChecker::isImageFile(BYTE* buffer, DWORD sizeRead)
{
eFileType = _CXIMAGE_FORMAT_PIC;
}
if (isHeifFile(buffer, sizeRead))
{
eFileType = _CXIMAGE_FORMAT_HEIF;
}
///////////////////////////////////////////////////////////////////////
if (eFileType) return true;
return false;
@ -786,6 +800,10 @@ bool CImageFileFormatChecker::isSvgFile(const std::wstring& fileName)
return bFind;
#endif
}
bool CImageFileFormatChecker::isHeifFile(const std::wstring& fileName)
{
return NSHeif::CHeifFile::isHeif(fileName);
}
std::wstring CImageFileFormatChecker::DetectFormatByData(BYTE *Data, int DataSize)
{

View File

@ -63,6 +63,7 @@ enum __ENUM_CXIMAGE_FORMATS
_CXIMAGE_FORMAT_SVM = 23,
_CXIMAGE_FORMAT_SVG = 24,
_CXIMAGE_FORMAT_PIC = 25,
_CXIMAGE_FORMAT_HEIF = 26,
};
class GRAPHICS_DECL CImageFileFormatChecker
@ -82,6 +83,7 @@ public:
bool isRawFile(const std::wstring& fileName);
bool isSvgFile(const std::wstring& fileName);
bool isHeifFile(const std::wstring& fileName);
bool isImageFile(BYTE* pBuffer,DWORD dwBytes);
bool isBmpFile(BYTE* pBuffer,DWORD dwBytes);
@ -111,6 +113,7 @@ public:
bool isSvgFile(BYTE* pBuffer,DWORD dwBytes);
bool isRawFile(BYTE* pBuffer,DWORD dwBytes);
bool isPicFile(BYTE* pBuffer,DWORD dwBytes);
bool isHeifFile(BYTE* pBuffer, DWORD dwBytes);
std::wstring DetectFormatByData(BYTE *Data, int DataSize);

View File

@ -0,0 +1,122 @@
#include "heif.h"
#include "../../Common/3dParty/heif/libheif/libheif/api/libheif/heif.h"
#include "../../UnicodeConverter/UnicodeConverter.h"
#include "../../common/File.h"
namespace NSHeif {
bool CHeifFile::isHeif(const std::wstring& fileName)
{
NSUnicodeConverter::CUnicodeConverter converter;
heif_context* ctx = heif_context_alloc();
bool status = heif_context_read_from_file(ctx, converter.fromUnicode(fileName, "UTF-8").c_str(), nullptr).code == heif_error_Ok;
heif_context_free(ctx);
return status;
}
bool CHeifFile::isHeif(BYTE* buffer, size_t size)
{
NSFile::CFileBinary file;
std::wstring tmp_file = NSFile::CFileBinary::CreateTempFileWithUniqueName(NSFile::CFileBinary::GetTempPath(), L"heif");
if (!file.CreateFile(tmp_file))
return false;
file.WriteFile(buffer, size);
file.CloseFile();
return isHeif(tmp_file);
}
bool CHeifFile::Open(CBgraFrame *frame, const std::wstring& fileName, bool isRGBA)
{
NSUnicodeConverter::CUnicodeConverter converter;
heif_context* ctx = heif_context_alloc();
if (heif_context_read_from_file(ctx, converter.fromUnicode(fileName, "UTF-8").c_str(), nullptr).code != heif_error_Ok)
return false;
heif_image_handle* handle;
if (heif_context_get_primary_image_handle(ctx, &handle).code != heif_error_Ok)
return false;
heif_image* img;
if (heif_decode_image(handle, &img, heif_colorspace_RGB, heif_chroma_interleaved_RGB, nullptr).code != heif_error_Ok)
return false;
int width = heif_image_get_primary_width(img);
int height = heif_image_get_primary_height(img);
int stride;
const BYTE* source = heif_image_get_plane_readonly(img, heif_channel_interleaved, &stride);
if (stride == 0 || source == nullptr)
return false;
BYTE* data = new BYTE[stride * height];
frame->put_Width(width);
frame->put_Height(height);
frame->put_Stride(stride);
frame->put_Data(data);
frame->put_IsRGBA(isRGBA);
memcpy(data, source, stride * height);
heif_image_release(img);
heif_image_handle_release(handle);
heif_context_free(ctx);
return true;
}
bool CHeifFile::Open(CBgraFrame *frame, BYTE* buffer, size_t size, bool isRGBA)
{
NSFile::CFileBinary file;
std::wstring tmp_file = NSFile::CFileBinary::CreateTempFileWithUniqueName(NSFile::CFileBinary::GetTempPath(), L"heif");
if (!file.CreateFile(tmp_file))
return false;
file.WriteFile(buffer, size);
file.CloseFile();
bool status = false;
if (Open(frame, tmp_file, isRGBA))
status = true;
if (NSFile::CFileBinary::Exists(tmp_file))
NSFile::CFileBinary::Remove(tmp_file);
return status;
}
bool CHeifFile::Save(CBgraFrame *frame, const std::wstring& dstPath)
{
if (!frame)
return false;
heif_context* ctx = heif_context_alloc();
heif_encoder* encoder;
if (heif_context_get_encoder_for_format(ctx, heif_compression_HEVC, &encoder).code != heif_error_Ok)
return false;
if (heif_encoder_set_lossy_quality(encoder, 50).code != heif_error_Ok)
return false;
heif_image* img;
if (heif_context_encode_image(ctx, img, encoder, nullptr, nullptr).code != heif_error_Ok)
return false;
heif_encoder_release(encoder);
NSUnicodeConverter::CUnicodeConverter converter;
if (heif_context_write_to_file(ctx, converter.fromUnicode(dstPath, "UTF-8").c_str()).code != heif_error_Ok)
return false;
heif_context_free(ctx);
return true;
}
}

View File

@ -0,0 +1,15 @@
#include "../BgraFrame.h"
namespace NSHeif {
class GRAPHICS_DECL CHeifFile {
private:
CHeifFile() = delete;
public:
static bool isHeif(const std::wstring& fileName);
static bool isHeif(BYTE* buffer, size_t size);
static bool Open(CBgraFrame* frame, const std::wstring& fileName, bool isRGBA);
static bool Open(CBgraFrame* frame, BYTE* buffer, size_t size, bool isRGBA);
static bool Save(CBgraFrame* frame, const std::wstring& dstPath);
};
}