mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-02-10 18:05:41 +08:00
Add heif decode and encode
This commit is contained in:
@ -38,6 +38,7 @@
|
||||
#define CXIMAGE_SUPPORT_PNM 1
|
||||
#define CXIMAGE_SUPPORT_RAS 1
|
||||
#define CXIMAGE_SUPPORT_PIC 1
|
||||
#define CXIMAGE_SUPPORT_HEIF 1
|
||||
|
||||
#define CXIMAGE_SUPPORT_JBG 0 // GPL'd see ../jbig/copying.txt & ../jbig/patents.htm
|
||||
|
||||
|
||||
@ -133,13 +133,17 @@ CXIMAGE_FORMAT_PSD = 20,
|
||||
#if CXIMAGE_SUPPORT_PIC
|
||||
CXIMAGE_FORMAR_PIC = 25,
|
||||
#endif
|
||||
#if CXIMAGE_SUPPORT_HEIF
|
||||
CXIMAGE_FORMAT_HEIF = 26,
|
||||
#endif
|
||||
CMAX_IMAGE_FORMATS = CXIMAGE_SUPPORT_BMP + CXIMAGE_SUPPORT_GIF + CXIMAGE_SUPPORT_JPG +
|
||||
CXIMAGE_SUPPORT_PNG + CXIMAGE_SUPPORT_MNG + CXIMAGE_SUPPORT_ICO +
|
||||
CXIMAGE_SUPPORT_TIF + CXIMAGE_SUPPORT_TGA + CXIMAGE_SUPPORT_PCX +
|
||||
CXIMAGE_SUPPORT_WBMP+ CXIMAGE_SUPPORT_WMF + CXIMAGE_SUPPORT_PIC +
|
||||
CXIMAGE_SUPPORT_JBG + CXIMAGE_SUPPORT_JP2 + CXIMAGE_SUPPORT_JPC +
|
||||
CXIMAGE_SUPPORT_PGX + CXIMAGE_SUPPORT_PNM + CXIMAGE_SUPPORT_RAS +
|
||||
CXIMAGE_SUPPORT_SKA + CXIMAGE_SUPPORT_RAW + CXIMAGE_SUPPORT_PSD + 1
|
||||
CXIMAGE_SUPPORT_SKA + CXIMAGE_SUPPORT_RAW + CXIMAGE_SUPPORT_PSD +
|
||||
CXIMAGE_SUPPORT_HEIF + 1
|
||||
};
|
||||
|
||||
#if CXIMAGE_SUPPORT_EXIF
|
||||
|
||||
@ -23,14 +23,14 @@
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma warning (disable : 4550)
|
||||
|
||||
#pragma warning (disable : 4550)
|
||||
|
||||
/*
|
||||
* TIFF Library
|
||||
*
|
||||
* Read and return a packed RGBA image.
|
||||
*/
|
||||
*/
|
||||
#include "tiffiop.h"
|
||||
#include <stdio.h>
|
||||
|
||||
@ -828,11 +828,12 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
|
||||
nrowsub = nrow;
|
||||
if ((nrowsub%subsamplingver)!=0)
|
||||
nrowsub+=subsamplingver-nrowsub%subsamplingver;
|
||||
|
||||
if (TIFFReadEncodedStrip(tif,
|
||||
TIFFComputeStrip(tif,row+img->row_offset, 0),
|
||||
buf,
|
||||
((row + img->row_offset)%rowsperstrip + nrowsub) * scanline) < 0
|
||||
&& img->stoponerr)
|
||||
((row + img->row_offset)%rowsperstrip + nrowsub) * scanline) < 0
|
||||
&& img->stoponerr)
|
||||
{
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
@ -39,7 +39,8 @@ core_android {
|
||||
INCLUDEPATH += \
|
||||
$$LIB_GRAPHICS_PRI_PATH/cximage/jasper/include \
|
||||
$$LIB_GRAPHICS_PRI_PATH/cximage/jpeg \
|
||||
$$LIB_GRAPHICS_PRI_PATH/cximage/png
|
||||
$$LIB_GRAPHICS_PRI_PATH/cximage/png \
|
||||
$$LIB_GRAPHICS_PRI_PATH/../Common/3dParty/heif/libheif/libheif/api \
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/../../graphics/Image.h \
|
||||
@ -285,6 +286,9 @@ SOURCES += \
|
||||
$$LIB_GRAPHICS_PRI_PATH/raster/PICT/PICFile.cpp \
|
||||
$$LIB_GRAPHICS_PRI_PATH/raster/PICT/pic.cpp
|
||||
|
||||
SOURCES += \
|
||||
$$LIB_GRAPHICS_PRI_PATH/raster/heif/heif.cpp
|
||||
|
||||
SOURCES += \
|
||||
$$LIB_GRAPHICS_PRI_PATH/cximage/jasper/base/jas_cm.c \
|
||||
$$LIB_GRAPHICS_PRI_PATH/cximage/jasper/base/jas_debug.c \
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
122
DesktopEditor/raster/heif/heif.cpp
Normal file
122
DesktopEditor/raster/heif/heif.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
15
DesktopEditor/raster/heif/heif.h
Normal file
15
DesktopEditor/raster/heif/heif.h
Normal 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);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user