Compare commits

...

19 Commits

Author SHA1 Message Date
fcd7818675 Add test for heif 2025-08-04 12:51:33 +03:00
6d707ebae2 Fix decode 2025-07-28 13:28:20 +03:00
41dc23ce53 Add Release/Debug libs 2025-07-24 12:10:26 +03:00
a817cd54d5 Fix static build 2025-07-17 20:11:46 +03:00
f5ddf8c6ce Fix build 2025-07-10 18:27:15 +03:00
29355d337b Fix encode 2025-07-07 18:01:25 +03:00
8c6a26895b Add read from memory 2025-07-02 13:22:30 +03:00
0154543b01 Remove temp file 2025-06-30 16:25:28 +03:00
3e2dee5719 Fix heif encode 2025-06-30 16:13:03 +03:00
c25f8cc204 Fix heif image convert 2025-06-30 13:51:05 +03:00
d3aae6dfcb Add heif decode and encode 2025-06-29 10:08:51 +03:00
03463ee0e4 Merge remote-tracking branch 'origin/release/v9.0.0' into develop 2025-05-29 12:34:25 +03:00
c964ed7d58 Merge branch hotfix/v8.3.3 into develop 2025-04-21 09:03:54 +00:00
21028c2ca5 Merge pull request 'hotfix/v8.3.3' (#276) from hotfix/v8.3.3 into develop
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/core/pulls/276
2025-04-07 11:58:23 +00:00
3c2fd33c7a Merge pull request 'FIx bug #73451' (#272) from fix/bug73451 into develop
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/core/pulls/272
2025-04-04 10:44:44 +00:00
f9062d7d38 Merge pull request 'Fix bug #73585' (#271) from fix/bug73585 into develop
Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/core/pulls/271
2025-04-04 10:44:33 +00:00
cafdb1d2a5 Merge branch hotfix/v8.3.2 into develop 2025-04-01 08:34:19 +00:00
7857106d76 Fix bug #73585 2025-03-21 13:43:19 +05:00
64c74192c7 FIx bug #73451 2025-03-20 16:09:36 +05:00
13 changed files with 312 additions and 33 deletions

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -1,4 +1,6 @@
LIB_GRAPHICS_PRI_PATH=$$PWD/../..
LIB_3DPARTY_PRI_PATH=$$LIB_GRAPHICS_PRI_PATH/../Common/3dParty/heif/lib/Debug
!core_debug:LIB_3DPARTY_PRI_PATH=$$LIB_GRAPHICS_PRI_PATH/../Common/3dParty/heif/lib/Release
DEFINES -= UNICODE
DEFINES -= _UNICODE
@ -12,15 +14,24 @@ DEFINES += \
MNG_SUPPORT_WRITE \
MNG_ACCESS_CHUNKS \
MNG_STORE_CHUNKS\
MNG_ERROR_TELLTALE
MNG_ERROR_TELLTALE\
LIBHEIF_STATIC_BUILD
core_linux {
DEFINES += HAVE_UNISTD_H HAVE_FCNTL_H
QMAKE_CXXFLAGS += -Wno-narrowing
LIBS += -L$$LIB_3DPARTY_PRI_PATH \
-lheif \
-lde265 \
-lx265
}
core_linux_clang {
QMAKE_CFLAGS += -Wno-incompatible-function-pointer-types
QMAKE_CFLAGS += -Wno-incompatible-function-pointer-types
LIBS += -L$$LIB_3DPARTY_PRI_PATH \
-lheif \
-lde265 \
-lx265
}
core_mac {
@ -30,6 +41,10 @@ core_mac {
core_windows {
DEFINES += JAS_WIN_MSVC_BUILD NOMINMAX
LIBS += -lUser32
LIBS += -L$$LIB_3DPARTY_PRI_PATH \
-lheif \
-llibde265 \
-lx265-static
}
core_android {
@ -39,7 +54,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 +301,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 \

View File

@ -0,0 +1,9 @@
#include "../../pro/Graphics.h"
int main(int argc, char *argv[])
{
Aggplus::CImage img(L"C:\\Users\\KProkhorov\\Work\\core\\DesktopEditor\\graphics\\tests\\testHeic\\image1.heic");
img.SaveFile(L"C:\\Users\\KProkhorov\\Work\\core\\DesktopEditor\\graphics\\tests\\testHeic\\image1.bmp", 1);
return 0;
}

View File

@ -0,0 +1,23 @@
QT -= core
QT -= gui
TARGET = test
CONFIG += console
TEMPLATE = app
CORE_ROOT_DIR = $$PWD/../../../..
PWD_ROOT_DIR = $$PWD
include($$CORE_ROOT_DIR/Common/base.pri)
include($$CORE_ROOT_DIR/Common/3dParty/icu/icu.pri)
ADD_DEPENDENCY(kernel, graphics, UnicodeConverter)
GRAPHICS_AGG_PATH = $$PWD/../../../agg-2.4
INCLUDEPATH += \
$$GRAPHICS_AGG_PATH/include
SOURCES += main.cpp
DESTDIR = $$PWD_ROOT_DIR/build/$$CORE_BUILDS_PLATFORM_PREFIX/$$CORE_BUILDS_CONFIGURATION_PREFIX

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);
}
#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);
}
#endif
CxImage img;
if (!img.Decode(pBuffer, nSize, m_nFileType))
@ -562,28 +580,32 @@ bool CBgraFrame::SaveFile(const std::wstring& strFileName, unsigned int nFileTyp
return res;
}
else
#endif
#if CXIMAGE_SUPPORT_HEIF
if (CXIMAGE_FORMAT_HEIF == nFileType)
{
NSFile::CFileBinary oFile;
if (!oFile.CreateFileW(strFileName))
return false;
CxImage img;
if (!img.CreateFromArray(m_pData, m_lWidth, m_lHeight, lBitsPerPixel * 8, lStride, (m_lStride >= 0) ? true : false, !m_bIsRGBA))
return false;
if (m_pPalette)
{
img.SetPalette((RGBQUAD*)m_pPalette, m_lPaletteColors);
}
if (!img.Encode(oFile.GetFileNative(), nFileType))
return false;
oFile.CloseFile();
return NSHeif::CHeifFile::Save(m_pData, m_lWidth, m_lHeight, m_lStride, strFileName);
}
#endif
NSFile::CFileBinary oFile;
if (!oFile.CreateFileW(strFileName))
return false;
CxImage img;
if (!img.CreateFromArray(m_pData, m_lWidth, m_lHeight, lBitsPerPixel * 8, lStride, (m_lStride >= 0) ? true : false, !m_bIsRGBA))
return false;
if (m_pPalette)
{
img.SetPalette((RGBQUAD*)m_pPalette, m_lPaletteColors);
}
if (!img.Encode(oFile.GetFileNative(), nFileType))
return false;
oFile.CloseFile();
return true;
}
bool CBgraFrame::Encode(BYTE*& pBuffer, int& nSize, unsigned int 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,152 @@
#include "heif.h"
#include "../../common/File.h"
#include <functional>
#define CONCAT_IMPL(x, y) x##y
#define CONCAT(x, y) CONCAT_IMPL(x, y)
#define defer(code) Defer CONCAT(_defer_, __COUNTER__)([&](){code;})
class Defer {
std::function<void()> func;
public:
explicit Defer(std::function<void()> func) : func(func) {}
~Defer() { func(); }
};
namespace NSHeif {
bool CHeifFile::isHeif(const std::wstring& fileName)
{
heif_context* ctx = heif_context_alloc();
defer(heif_context_free(ctx););
return !IsError(heif_context_read_from_file(ctx, m_oConverter.fromUnicode(fileName, "UTF-8").c_str(), nullptr));
}
bool CHeifFile::isHeif(BYTE* buffer, DWORD size)
{
heif_context* ctx = heif_context_alloc();
defer(heif_context_free(ctx););
return !IsError(heif_context_read_from_memory_without_copy(ctx, buffer, size, nullptr));
}
bool CHeifFile::Open(CBgraFrame *frame, const std::wstring& fileName)
{
heif_context* ctx = heif_context_alloc();
defer(heif_context_free(ctx););
if (IsError(heif_context_read_from_file(ctx, m_oConverter.fromUnicode(fileName, "UTF-8").c_str(), nullptr)))
return false;
return Decode(ctx, frame);
}
bool CHeifFile::Open(CBgraFrame *frame, BYTE* buffer, DWORD size)
{
heif_context* ctx = heif_context_alloc();
defer(heif_context_free(ctx););
if (IsError(heif_context_read_from_memory_without_copy(ctx, buffer, size, nullptr)))
return false;
return Decode(ctx, frame);
}
bool CHeifFile::Save(const BYTE* source, int width, int height, int sourceStride, const std::wstring& dstPath)
{
if (!source)
return false;
heif_image* img;
defer(heif_image_release(img););
if (IsError(heif_image_create(width, height, heif_colorspace_RGB, heif_chroma_interleaved_RGB, &img)))
return false;
if (IsError(heif_image_add_plane(img, heif_channel_interleaved, width, height, 24)))
return false;
int stride;
BYTE* data = heif_image_get_plane(img, heif_channel_interleaved, &stride);
if (!data || stride == 0)
return false;
for (size_t i = 0; i < height; ++i)
{
const BYTE* row = source + (height - i - 1) * (sourceStride < 0 ? -sourceStride : sourceStride);
for (size_t j = 0; j < width; ++j)
{
data[(i * width + j) * 3 + 0] = row[(width - j - 1) * 4 + 2];
data[(i * width + j) * 3 + 1] = row[(width - j - 1) * 4 + 1];
data[(i * width + j) * 3 + 2] = row[(width - j - 1) * 4 + 0];
}
}
heif_context* ctx = heif_context_alloc();
defer(heif_context_free(ctx););
heif_encoder* encoder;
defer(heif_encoder_release(encoder););
if (IsError(heif_context_get_encoder_for_format(ctx, heif_compression_HEVC, &encoder)))
return false;
if (IsError(heif_context_encode_image(ctx, img, encoder, nullptr, nullptr)))
return false;
if (IsError(heif_context_write_to_file(ctx, m_oConverter.fromUnicode(dstPath, "UTF-8").c_str())))
return false;
return true;
}
inline bool CHeifFile::IsError(heif_error err)
{
return err.code != heif_error_Ok;
}
inline bool CHeifFile::Decode(heif_context* ctx, CBgraFrame* frame)
{
heif_image_handle* handle;
defer(heif_image_handle_release(handle););
if (IsError(heif_context_get_primary_image_handle(ctx, &handle)))
return false;
heif_image* img;
defer(heif_image_release(img););
if (IsError(heif_decode_image(handle, &img, heif_colorspace_RGB, heif_chroma_444, nullptr)))
return false;
int width = heif_image_get_primary_width(img);
int height = heif_image_get_primary_height(img);
int stride_R, stride_G, stride_B;
const BYTE* source_R = heif_image_get_plane_readonly(img, heif_channel_R, &stride_R);
const BYTE* source_G = heif_image_get_plane_readonly(img, heif_channel_G, &stride_G);
const BYTE* source_B = heif_image_get_plane_readonly(img, heif_channel_B, &stride_B);
if (stride_R == 0 || !source_R)
return false;
BYTE* data = new BYTE[4 * width * height];
frame->put_Width(width);
frame->put_Height(height);
frame->put_Stride(4 * width);
frame->put_Data(data);
for (size_t i = 0; i < height; ++i)
{
const BYTE* row_R = source_R + i * stride_R;
const BYTE* row_G = source_G + i * stride_G;
const BYTE* row_B = source_B + i * stride_B;
for (size_t j = 0; j < width; ++j)
{
data[(i * width + j) * 4 + 0] = row_B[j];
data[(i * width + j) * 4 + 1] = row_G[j];
data[(i * width + j) * 4 + 2] = row_R[j];
data[(i * width + j) * 4 + 3] = 255;
}
}
return true;
}
}

View File

@ -0,0 +1,22 @@
#include "../BgraFrame.h"
#include "../../Common/3dParty/heif/libheif/libheif/api/libheif/heif.h"
#include "../../UnicodeConverter/UnicodeConverter.h"
namespace NSHeif {
class GRAPHICS_DECL CHeifFile {
private:
CHeifFile() = delete;
public:
static bool isHeif(const std::wstring& fileName);
static bool isHeif(BYTE* buffer, DWORD size);
static bool Open(CBgraFrame* frame, const std::wstring& fileName);
static bool Open(CBgraFrame* frame, BYTE* buffer, DWORD size);
static bool Save(const BYTE* source, int width, int height, int sourceStride, const std::wstring& dstPath);
private:
static inline bool IsError(heif_error err);
static inline bool Decode(heif_context* ctx, CBgraFrame* frame);
static inline NSUnicodeConverter::CUnicodeConverter m_oConverter{};
};
}

View File

@ -1615,6 +1615,9 @@ void DocxConverter::convert(OOX::Logic::CParagraphProperty *oox_paragraph_pr,
convert(oox_paragraph_pr->m_oJc.GetPointer(), paragraph_properties->fo_text_align_);
if (!oox_paragraph_pr->m_oJc.GetPointer() && oox_paragraph_pr->m_oBidi.IsInit())
paragraph_properties->fo_text_align_ = odf_types::text_align(odf_types::text_align::End);
if (oox_paragraph_pr->m_oTextAlignment.IsInit() && oox_paragraph_pr->m_oTextAlignment->m_oVal.IsInit())
{
//switch(oox_paragraph_pr->m_oTextAlignment->m_oVal->GetValue())

View File

@ -637,6 +637,8 @@ void odf_drawing_context::end_drawing()
draw->common_draw_attlists_.shape_with_text_and_styles_.common_shape_draw_attlist_.drawooo_display_ = L"printer"; // L"none" ???
if (!impl_->current_drawing_state_.xml_id_.empty())
draw->xml_id_ = impl_->current_drawing_state_.xml_id_;
if (impl_->anchor_settings_.style_wrap_)
impl_->current_graphic_properties->style_wrap_ = *impl_->anchor_settings_.style_wrap_;
std::wstring strTransform;