diff --git a/filter/Configuration_filter.mk b/filter/Configuration_filter.mk
index ceafbe860dcf..d881314da19e 100644
--- a/filter/Configuration_filter.mk
+++ b/filter/Configuration_filter.mk
@@ -715,8 +715,9 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_drawgraphics_typ
gif_Graphics_Interchange \
graphic_HTML \
jpg_JPEG \
+ jxl_JPEG_XL \
met_OS2_Metafile \
- mov_MOV \
+ mov_MOV \
pbm_Portable_Bitmap \
pcd_Photo_CD_Base \
pcd_Photo_CD_Base16 \
@@ -750,6 +751,7 @@ $(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_drawgraphics_f
EPS___Encapsulated_PostScript \
GIF___Graphics_Interchange \
JPG___JPEG \
+ JXL___JPEG_XL \
MET___OS_2_Metafile \
mov__MOV \
PBM___Portable_Bitmap \
@@ -801,6 +803,7 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_impressgraphics_
graphic_HTML \
impress_CGM_Computer_Graphics_Metafile \
jpg_JPEG \
+ jxl_JPEG_XL \
met_OS2_Metafile \
pbm_Portable_Bitmap \
pct_Mac_Pict \
@@ -871,8 +874,9 @@ $(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_internalgraphics
eps_Encapsulated_PostScript \
gif_Graphics_Interchange \
jpg_JPEG \
+ jxl_JPEG_XL \
met_OS2_Metafile \
- mov_MOV \
+ mov_MOV \
pbm_Portable_Bitmap \
pcd_Photo_CD_Base \
pcd_Photo_CD_Base16 \
@@ -911,6 +915,7 @@ $(eval $(call filter_Configuration_add_internal_filters,fcfg_langpack,fcfg_inter
gif_Import \
jpg_Export \
jpg_Import \
+ jxl_Import \
met_Import \
pbm_Import \
pcd_Import_Base \
diff --git a/filter/source/config/cache/typedetection.cxx b/filter/source/config/cache/typedetection.cxx
index 007f8a368e90..24f68ff89011 100644
--- a/filter/source/config/cache/typedetection.cxx
+++ b/filter/source/config/cache/typedetection.cxx
@@ -234,6 +234,7 @@ int getFlatTypeRank(std::u16string_view rType)
"psd_Adobe_Photoshop",
"png_Portable_Network_Graphic",
"jpg_JPEG",
+ "jxl_JPEG_XL",
"mov_MOV",
"gif_Graphics_Interchange",
"bmp_MS_Windows",
diff --git a/filter/source/config/fragments/filters/JXL___JPEG_XL.xcu b/filter/source/config/fragments/filters/JXL___JPEG_XL.xcu
new file mode 100644
index 000000000000..cc49099002c6
--- /dev/null
+++ b/filter/source/config/fragments/filters/JXL___JPEG_XL.xcu
@@ -0,0 +1,30 @@
+
+
+ IMPORT ALIEN
+
+
+
+
+ JXL - JPEG XL Image
+
+ 0
+ jxl_JPEG_XL
+
+ com.sun.star.drawing.DrawingDocument
+
diff --git a/filter/source/config/fragments/internalgraphicfilters/jxl_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/jxl_Import.xcu
new file mode 100644
index 000000000000..862f2b599f68
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/jxl_Import.xcu
@@ -0,0 +1,27 @@
+
+
+ jxl_JPEG_XL
+ SVIJXL
+ JXL - JPEG XL
+
+
+ JXL - JPEG XL Image
+
+ IMPORT
+
diff --git a/filter/source/config/fragments/types/jxl_JPEG_XL.xcu b/filter/source/config/fragments/types/jxl_JPEG_XL.xcu
new file mode 100644
index 000000000000..ef884eb9f428
--- /dev/null
+++ b/filter/source/config/fragments/types/jxl_JPEG_XL.xcu
@@ -0,0 +1,29 @@
+
+
+ com.sun.star.comp.draw.FormatDetector
+
+ jxl
+ image/jxl
+ false
+ JXL - JPEG XL
+
+ JXL - JPEG XL Image
+
+
+
diff --git a/include/sal/log-areas.dox b/include/sal/log-areas.dox
index c3cb5e70c137..4c6826bb91c1 100644
--- a/include/sal/log-areas.dox
+++ b/include/sal/log-areas.dox
@@ -501,6 +501,7 @@ certain functionality.
@li @c vcl.emf - EMF/EMF+ processing
@li @c vcl.filter
@li @c vcl.filter.webp
+@li @c vcl.filter.jxl
@li @c vcl.fonts - font-specific code
@li @c vcl.fonts.detail
@li @c vcl.gdi - the GDI part of VCL, devices, bitmaps, etc.
diff --git a/include/svl/inettype.hxx b/include/svl/inettype.hxx
index f57ca1b927ad..24ac527ddd37 100644
--- a/include/svl/inettype.hxx
+++ b/include/svl/inettype.hxx
@@ -166,6 +166,7 @@ enum INetContentType
CONTENT_TYPE_AUDIO_WEBM,
CONTENT_TYPE_IMAGE_GIF,
CONTENT_TYPE_IMAGE_JPEG,
+ CONTENT_TYPE_IMAGE_JXL,
CONTENT_TYPE_IMAGE_PCX,
CONTENT_TYPE_IMAGE_PNG,
CONTENT_TYPE_IMAGE_TIFF,
diff --git a/include/svtools/imagemgr.hxx b/include/svtools/imagemgr.hxx
index 0b2425c24b8d..3e4e2225a923 100644
--- a/include/svtools/imagemgr.hxx
+++ b/include/svtools/imagemgr.hxx
@@ -40,6 +40,7 @@ enum class SvImageId {
HTML = START + 63,
JPG = START + 64,
WEBP = START + 65,
+ JXL = START + 66,
Math = START + 68,
MathTemplate = START + 69,
File = START + 74,
diff --git a/include/svx/strings.hrc b/include/svx/strings.hrc
index dd067b893c9d..e6a38395963c 100644
--- a/include/svx/strings.hrc
+++ b/include/svx/strings.hrc
@@ -1426,6 +1426,7 @@
#define STR_IMAGE_CAPACITY_WITH_REDUCTION NC_("STR_IMAGE_CAPACITY_WITH_REDUCTION", "$(CAPACITY) KiB ($(REDUCTION)% reduction)")
#define STR_IMAGE_GIF NC_("STR_IMAGE_GIF", "GIF image")
#define STR_IMAGE_JPEG NC_("STR_IMAGE_JPEG", "JPEG image")
+#define STR_IMAGE_JXL NC_("STR_IMAGE_JXL", "JPEG XL image")
#define STR_IMAGE_PNG NC_("STR_IMAGE_PNG", "PNG image")
#define STR_IMAGE_TIFF NC_("STR_IMAGE_TIFF", "TIFF image")
#define STR_IMAGE_WMF NC_("STR_IMAGE_WMF", "WMF image")
diff --git a/include/vcl/gfxlink.hxx b/include/vcl/gfxlink.hxx
index 55e294aba70e..a58f3f72f824 100644
--- a/include/vcl/gfxlink.hxx
+++ b/include/vcl/gfxlink.hxx
@@ -48,12 +48,13 @@ enum class GfxLinkType
NativeMov = 10,
NativeBmp = 11,
NativePdf = 12,
- NativeWebp = 13, // If a new type is added, make sure to change NativeLast too
+ NativeWebp = 13,
+ NativeJxl = 14, // If a new type is added, make sure to change NativeLast too
// Alias for when the first native type starts and last native
// type ends.
NativeFirst = NativeGif,
- NativeLast = NativeWebp,
+ NativeLast = NativeJxl,
};
class Graphic;
diff --git a/include/vcl/graphic/GraphicMetadata.hxx b/include/vcl/graphic/GraphicMetadata.hxx
index b01e38c8cfab..63a94c485823 100644
--- a/include/vcl/graphic/GraphicMetadata.hxx
+++ b/include/vcl/graphic/GraphicMetadata.hxx
@@ -38,6 +38,7 @@ enum class GraphicFileFormat
PSD = 0x000f,
EPS = 0x0010,
WEBP = 0x0011,
+ JXL = 0x0012,
MOV = 0x00e0,
PDF = 0x00e1,
DXF = 0x00f1,
diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx
index 26b9ab60479c..6e39e8fe9b8e 100644
--- a/include/vcl/graphicfilter.hxx
+++ b/include/vcl/graphicfilter.hxx
@@ -81,6 +81,7 @@ namespace o3tl
#define IMP_GIF "SVIGIF"
#define IMP_PNG "SVIPNG"
#define IMP_JPEG "SVIJPEG"
+#define IMP_JXL "SVIJXL"
#define IMP_XBM "SVIXBM"
#define IMP_XPM "SVIXPM"
#define IMP_SVG "SVISVG"
@@ -106,6 +107,7 @@ namespace o3tl
#define EXP_EMF "SVEMF"
#define EXP_EMZ "SVEMZ"
#define EXP_JPEG "SVEJPEG"
+#define EXP_JXL "SVEJXL"
#define EXP_SVG "SVESVG"
#define EXP_SVGZ "SVESVGZ"
#define EXP_PDF "SVEPDF"
@@ -120,6 +122,7 @@ namespace o3tl
inline constexpr OUString BMP_SHORTNAME = u"BMP"_ustr;
inline constexpr OUString GIF_SHORTNAME = u"GIF"_ustr;
inline constexpr OUString JPG_SHORTNAME = u"JPG"_ustr;
+inline constexpr OUString JXL_SHORTNAME = u"JXL"_ustr;
inline constexpr OUString MET_SHORTNAME = u"MET"_ustr;
inline constexpr OUString PCT_SHORTNAME = u"PCT"_ustr;
inline constexpr OUString PNG_SHORTNAME = u"PNG"_ustr;
@@ -141,6 +144,7 @@ class VCL_DLLPUBLIC GraphicDescriptor final
SAL_DLLPRIVATE bool ImpDetectBMP( SvStream& rStm, bool bExtendedInfo );
SAL_DLLPRIVATE bool ImpDetectGIF( SvStream& rStm, bool bExtendedInfo );
SAL_DLLPRIVATE bool ImpDetectJPG( SvStream& rStm, bool bExtendedInfo );
+ SAL_DLLPRIVATE bool ImpDetectJXL( SvStream& rStm, bool bExtendedInfo );
SAL_DLLPRIVATE bool ImpDetectPCD( SvStream& rStm, bool bExtendedInfo );
SAL_DLLPRIVATE bool ImpDetectPCX( SvStream& rStm );
SAL_DLLPRIVATE bool ImpDetectPNG( SvStream& rStm, bool bExtendedInfo );
@@ -319,6 +323,7 @@ public:
BinaryDataContainer & rpGraphicContent);
SAL_DLLPRIVATE static ErrCode readJPEG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType,
GraphicFilterImportFlags nImportFlags);
+ SAL_DLLPRIVATE static ErrCode readJXL(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType);
SAL_DLLPRIVATE static ErrCode readSVG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType,
BinaryDataContainer & rpGraphicContent);
SAL_DLLPRIVATE static ErrCode readXBM(SvStream & rStream, Graphic & rGraphic);
diff --git a/include/vcl/salctype.hxx b/include/vcl/salctype.hxx
index c52128aef51d..37a2aefe61f6 100644
--- a/include/vcl/salctype.hxx
+++ b/include/vcl/salctype.hxx
@@ -31,6 +31,7 @@ enum class ConvertDataFormat
BMP,
GIF,
JPG,
+ JXL,
MET,
PCT,
PNG,
diff --git a/scp2/source/draw/registryitem_draw.scp b/scp2/source/draw/registryitem_draw.scp
index e1781c58cf24..d381e8c6960c 100644
--- a/scp2/source/draw/registryitem_draw.scp
+++ b/scp2/source/draw/registryitem_draw.scp
@@ -1079,6 +1079,7 @@ CONDITIONAL_REGISTER_DOC_EXTENSION( Gif, gid_Module_Prg_Draw_Other_Reg, gif, G
CONDITIONAL_REGISTER_DOC_EXTENSION( Jpg, gid_Module_Prg_Draw_Other_Reg, jpg, JPG, JOINT_PHOTOGRAPHIC_EXPERTS_GROUP, 5, sdraw.exe, open, Draw )
CONDITIONAL_REGISTER_DOC_EXTENSION( Jpeg, gid_Module_Prg_Draw_Other_Reg, jpeg, JPEG, JOINT_PHOTOGRAPHIC_EXPERTS_GROUP, 5, sdraw.exe, open, Draw )
CONDITIONAL_REGISTER_DOC_EXTENSION( Jpe, gid_Module_Prg_Draw_Other_Reg, jpe, JPE, JOINT_PHOTOGRAPHIC_EXPERTS_GROUP, 5, sdraw.exe, open, Draw )
+CONDITIONAL_REGISTER_DOC_EXTENSION( Jxl, gid_Module_Prg_Draw_Other_Reg, jxl, JXL, JPEG_XL, 5, sdraw.exe, open, Draw )
CONDITIONAL_REGISTER_DOC_EXTENSION( Pbm, gid_Module_Prg_Draw_Other_Reg, pbm, PBM, PORTABLE_BITMAP_FORMAT, 5, sdraw.exe, open, Draw )
CONDITIONAL_REGISTER_DOC_EXTENSION( Pcx, gid_Module_Prg_Draw_Other_Reg, pcx, PCX, PERSONAL_COMPUTER_EXCHANGE, 5, sdraw.exe, open, Draw )
CONDITIONAL_REGISTER_DOC_EXTENSION( Pgm, gid_Module_Prg_Draw_Other_Reg, pgm, PGM, PORTABLE_GRAYMAP_FORMAT, 5, sdraw.exe, open, Draw )
diff --git a/svx/source/core/graphichelper.cxx b/svx/source/core/graphichelper.cxx
index f92241709984..198f493ca668 100644
--- a/svx/source/core/graphichelper.cxx
+++ b/svx/source/core/graphichelper.cxx
@@ -74,6 +74,7 @@ const auto constGfxTypeToExtension = frozen::make_unordered_map
+
+VCL_DLLPUBLIC bool ImportJxlGraphic(SvStream& rStream, Graphic& rGraphic);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/graphic/GraphicFormatDetector.hxx b/vcl/inc/graphic/GraphicFormatDetector.hxx
index 19c4e2f7e9b1..4569e647f9d3 100644
--- a/vcl/inc/graphic/GraphicFormatDetector.hxx
+++ b/vcl/inc/graphic/GraphicFormatDetector.hxx
@@ -40,6 +40,9 @@ static inline OUString getImportFormatShortName(GraphicFileFormat nFormat)
case GraphicFileFormat::JPG:
aKeyName = u"JPG"_ustr;
break;
+ case GraphicFileFormat::JXL:
+ aKeyName = u"JXL"_ustr;
+ break;
case GraphicFileFormat::PCD:
aKeyName = u"PCD"_ustr;
break;
@@ -165,6 +168,7 @@ public:
bool checkPNG();
bool checkAPNG();
bool checkJPG();
+ bool checkJXL();
SAL_DLLPRIVATE bool checkSVM();
SAL_DLLPRIVATE bool checkPCD();
bool checkPSD();
diff --git a/vcl/inc/graphic/UnoGraphicDescriptor.hxx b/vcl/inc/graphic/UnoGraphicDescriptor.hxx
index 4ac5d17da9ab..8f67b673e016 100644
--- a/vcl/inc/graphic/UnoGraphicDescriptor.hxx
+++ b/vcl/inc/graphic/UnoGraphicDescriptor.hxx
@@ -30,6 +30,7 @@ class SvStream;
inline constexpr OUString MIMETYPE_BMP = u"image/x-MS-bmp"_ustr;
inline constexpr OUString MIMETYPE_GIF = u"image/gif"_ustr;
inline constexpr OUString MIMETYPE_JPG = u"image/jpeg"_ustr;
+inline constexpr OUString MIMETYPE_JXL = u"image/jxl"_ustr;
inline constexpr OUString MIMETYPE_PCD = u"image/x-photo-cd"_ustr;
inline constexpr OUString MIMETYPE_PCX = u"image/x-pcx"_ustr;
inline constexpr OUString MIMETYPE_PNG = u"image/png"_ustr;
diff --git a/vcl/source/filter/FilterConfigCache.cxx b/vcl/source/filter/FilterConfigCache.cxx
index 25411c78c392..caada2535786 100644
--- a/vcl/source/filter/FilterConfigCache.cxx
+++ b/vcl/source/filter/FilterConfigCache.cxx
@@ -42,10 +42,11 @@ using namespace ::com::sun::star::configuration ;
const char* const FilterConfigCache::FilterConfigCacheEntry::InternalPixelFilterNameList[] =
{
- IMP_BMP, IMP_GIF, IMP_PNG, IMP_JPEG, IMP_TIFF, IMP_WEBP,
- IMP_XBM, IMP_XPM, IMP_TGA, IMP_PICT, IMP_MET, IMP_RAS,
- IMP_PCX, IMP_MOV, IMP_PSD, IMP_PCD, IMP_PBM, IMP_DXF,
- EXP_BMP, EXP_GIF, EXP_PNG, EXP_JPEG, EXP_TIFF, EXP_WEBP,
+ IMP_BMP, IMP_GIF, IMP_PNG, IMP_JPEG, IMP_JXL, IMP_TIFF,
+ IMP_WEBP, IMP_XBM, IMP_XPM, IMP_TGA, IMP_PICT, IMP_MET,
+ IMP_RAS, IMP_PCX, IMP_MOV, IMP_PSD, IMP_PCD, IMP_PBM,
+ IMP_DXF,
+ EXP_BMP, EXP_GIF, EXP_PNG, EXP_JPEG, EXP_TIFF, EXP_WEBP,
nullptr
};
@@ -211,6 +212,7 @@ constexpr FilterEntry InternalFilterListForSvxLight[]
{ u"gif"_ustr, 2, u"SVEGIF"_ustr },
{ u"jpg"_ustr, 1, u"SVIJPEG"_ustr },
{ u"jpg"_ustr, 2, u"SVEJPEG"_ustr },
+ { u"jxl"_ustr, 1, u"SVIJXL"_ustr },
{ u"mov"_ustr, 1, u"SVMOV"_ustr },
{ u"mov"_ustr, 2, u"SVMOV"_ustr },
{ u"met"_ustr, 1, u"SVMET"_ustr },
diff --git a/vcl/source/filter/GraphicFormatDetector.cxx b/vcl/source/filter/GraphicFormatDetector.cxx
index 1015e3bbb807..86cc1fc0dbdf 100644
--- a/vcl/source/filter/GraphicFormatDetector.cxx
+++ b/vcl/source/filter/GraphicFormatDetector.cxx
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
#include
#include "igif/gifread.hxx"
#include
@@ -166,6 +167,16 @@ bool peekGraphicFormat(SvStream& rStream, OUString& rFormatExtension, bool bTest
}
}
+ if (!bTest || rFormatExtension.startsWith("JXL"))
+ {
+ bSomethingTested = true;
+ if (aDetector.checkJXL())
+ {
+ rFormatExtension = getImportFormatShortName(aDetector.getMetadata().mnFormat);
+ return true;
+ }
+ }
+
if (!bTest || rFormatExtension.startsWith("SVM"))
{
bSomethingTested = true;
@@ -980,6 +991,20 @@ bool GraphicFormatDetector::checkJPG()
return false;
}
+bool GraphicFormatDetector::checkJXL()
+{
+ if ((maFirstBytes[0] == 0xFF && maFirstBytes[1] == 0x0A)
+ || (maFirstBytes[0] == 0x00 && maFirstBytes[1] == 0x00 && maFirstBytes[2] == 0x00
+ && maFirstBytes[3] == 0x0C && maFirstBytes[4] == 0x4A && maFirstBytes[5] == 0x58
+ && maFirstBytes[6] == 0x4C && maFirstBytes[7] == 0x20 && maFirstBytes[8] == 0x0D
+ && maFirstBytes[9] == 0x0A && maFirstBytes[10] == 0x87 && maFirstBytes[11] == 0x0A))
+ {
+ maMetadata.mnFormat = GraphicFileFormat::JXL;
+ return true;
+ }
+ return false;
+}
+
bool GraphicFormatDetector::checkSVM()
{
sal_uInt32 n32 = 0;
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index 8a9c6763170c..6ab119893282 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -66,6 +66,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -724,6 +725,11 @@ ErrCode prepareImageTypeAndData(SvStream& rStream, sal_uInt32 nStreamLength, Bin
rLinkType = GfxLinkType::NativeJpg;
nStatus = ERRCODE_NONE;
}
+ else if (o3tl::equalsIgnoreAsciiCase(rFilterName, IMP_JXL))
+ {
+ rLinkType = GfxLinkType::NativeJxl;
+ nStatus = ERRCODE_NONE;
+ }
else if (o3tl::equalsIgnoreAsciiCase(rFilterName, IMP_SVG))
{
rStream.Seek(nStreamBegin);
@@ -943,6 +949,17 @@ ErrCode GraphicFilter::readJPEG(SvStream & rStream, Graphic & rGraphic, GfxLinkT
return ERRCODE_NONE;
}
+ErrCode GraphicFilter::readJXL(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType)
+{
+ if (ImportJxlGraphic(rStream, rGraphic))
+ {
+ rLinkType = GfxLinkType::NativeJxl;
+ return ERRCODE_NONE;
+ }
+ else
+ return ERRCODE_GRFILTER_FILTERERROR;
+}
+
ErrCode GraphicFilter::readSVG(SvStream & rStream, Graphic & rGraphic, GfxLinkType & rLinkType, BinaryDataContainer& rpGraphicContent)
{
ErrCode aReturnCode = ERRCODE_NONE;
@@ -1333,6 +1350,10 @@ ErrCode GraphicFilter::ImportGraphic(Graphic& rGraphic, std::u16string_view rPat
{
nStatus = readJPEG(rIStream, rGraphic, eLinkType, nImportFlags);
}
+ else if (aFilterName.equalsIgnoreAsciiCase(IMP_JXL))
+ {
+ nStatus = readJXL(rIStream, rGraphic, eLinkType);
+ }
else if (aFilterName.equalsIgnoreAsciiCase(IMP_SVG) || aFilterName.equalsIgnoreAsciiCase(IMP_SVGZ))
{
nStatus = readSVG(rIStream, rGraphic, eLinkType, aGraphicContent);
@@ -1839,6 +1860,7 @@ IMPL_LINK( GraphicFilter, FilterCallback, ConvertData&, rData, bool )
case ConvertDataFormat::BMP: aShortName = BMP_SHORTNAME; break;
case ConvertDataFormat::GIF: aShortName = GIF_SHORTNAME; break;
case ConvertDataFormat::JPG: aShortName = JPG_SHORTNAME; break;
+ case ConvertDataFormat::JXL: aShortName = JXL_SHORTNAME; break;
case ConvertDataFormat::MET: aShortName = MET_SHORTNAME; break;
case ConvertDataFormat::PCT: aShortName = PCT_SHORTNAME; break;
case ConvertDataFormat::PNG: aShortName = PNG_SHORTNAME; break;
diff --git a/vcl/source/filter/graphicfilter2.cxx b/vcl/source/filter/graphicfilter2.cxx
index 6558deda4597..b0b8f55605f3 100644
--- a/vcl/source/filter/graphicfilter2.cxx
+++ b/vcl/source/filter/graphicfilter2.cxx
@@ -62,6 +62,7 @@ bool GraphicDescriptor::Detect( bool bExtendedInfo )
if ( ImpDetectGIF( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectJPG( rStm, bExtendedInfo ) ) bRet = true;
+ else if ( ImpDetectJXL( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectBMP( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectPNG( rStm, bExtendedInfo ) ) bRet = true;
else if ( ImpDetectTIF( rStm, bExtendedInfo ) ) bRet = true;
@@ -301,6 +302,15 @@ bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm, bool bExtendedInfo )
return bRet;
}
+bool GraphicDescriptor::ImpDetectJXL( SvStream& rStm, bool bExtendedInfo )
+{
+ vcl::GraphicFormatDetector aDetector( rStm, aPathExt, bExtendedInfo );
+ bool bRet = aDetector.detect() && aDetector.checkJXL();
+ if ( bRet )
+ aMetadata = aDetector.getMetadata();
+ return bRet;
+}
+
bool GraphicDescriptor::ImpDetectPCD( SvStream& rStm, bool )
{
vcl::GraphicFormatDetector aDetector( rStm, aPathExt, false /*bExtendedInfo*/ );
diff --git a/vcl/source/filter/jxl/reader.cxx b/vcl/source/filter/jxl/reader.cxx
new file mode 100644
index 000000000000..4393b02bc8d9
--- /dev/null
+++ b/vcl/source/filter/jxl/reader.cxx
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+static bool readJxl(SvStream& stream, Graphic& graphic)
+{
+ std::vector data;
+ std::vector pixels;
+
+ size_t xsize = 0;
+ size_t ysize = 0;
+
+ // Multi-threaded parallel runner.
+ JxlResizableParallelRunnerPtr runner = JxlResizableParallelRunnerMake(nullptr);
+
+ JxlDecoderPtr dec = JxlDecoderMake(nullptr);
+ if (JXL_DEC_SUCCESS
+ != JxlDecoderSubscribeEvents(dec.get(), JXL_DEC_BASIC_INFO | JXL_DEC_COLOR_ENCODING
+ | JXL_DEC_FULL_IMAGE))
+ {
+ SAL_WARN("vcl.filter.jxl", "JxlDecoderSubscribeEvents failed");
+ return false;
+ }
+
+ if (JXL_DEC_SUCCESS
+ != JxlDecoderSetParallelRunner(dec.get(), JxlResizableParallelRunner, runner.get()))
+ {
+ SAL_WARN("vcl.filter.jxl", "JxlDecoderSetParallelRunner failed");
+ return false;
+ }
+
+ JxlBasicInfo info;
+ JxlPixelFormat format = { 4, JXL_TYPE_UINT8, JXL_NATIVE_ENDIAN, 0 };
+
+ size_t chunksize = 4096;
+
+ // Read first chunksize bytes.
+ data.resize(chunksize);
+ sal_Size nBytesRead = stream.ReadBytes(data.data(), chunksize);
+ if (nBytesRead <= 0)
+ return false; // no bytes to read
+ data.resize(nBytesRead);
+
+ if (JXL_DEC_SUCCESS != JxlDecoderSetInput(dec.get(), data.data(), nBytesRead))
+ {
+ SAL_WARN("vcl.filter.jxl", "JxlDecoderSetInput failed");
+ return false;
+ }
+
+ // Try using partially read image if there is an error.
+ bool success = true;
+ for (;;)
+ {
+ JxlDecoderStatus status = JxlDecoderProcessInput(dec.get());
+
+ if (status == JXL_DEC_ERROR)
+ {
+ SAL_WARN("vcl.filter.jxl", "Decoder error");
+ success = false;
+ break;
+ }
+ else if (status == JXL_DEC_NEED_MORE_INPUT || status == JXL_DEC_SUCCESS
+ || status == JXL_DEC_FULL_IMAGE)
+ {
+ JxlDecoderReleaseInput(dec.get());
+ JxlDecoderFlushImage(dec.get());
+
+ // Read 4096 (more) bytes.
+ data.resize(chunksize);
+ nBytesRead = stream.ReadBytes(data.data(), chunksize);
+ if (nBytesRead <= 0)
+ {
+ if (status == JXL_DEC_NEED_MORE_INPUT)
+ {
+ SAL_WARN("vcl.filter.jxl", "Incomplete/truncated file");
+ success = false;
+ break;
+ }
+ else
+ {
+ // Finished decoding complete file.
+ break;
+ }
+ }
+ data.resize(nBytesRead);
+
+ if (JXL_DEC_SUCCESS != JxlDecoderSetInput(dec.get(), data.data(), nBytesRead))
+ {
+ SAL_WARN("vcl.filter.jxl", "JxlDecoderSetInput failed");
+ success = false;
+ break;
+ }
+ }
+ else if (status == JXL_DEC_BASIC_INFO)
+ {
+ if (JXL_DEC_SUCCESS != JxlDecoderGetBasicInfo(dec.get(), &info))
+ {
+ SAL_WARN("vcl.filter.jxl", "JxlDecoderGetBasicInfo failed");
+ success = false;
+ break;
+ }
+ xsize = info.xsize;
+ ysize = info.ysize;
+ JxlResizableParallelRunnerSetThreads(
+ runner.get(), JxlResizableParallelRunnerSuggestThreads(info.xsize, info.ysize));
+ }
+ else if (status == JXL_DEC_NEED_IMAGE_OUT_BUFFER)
+ {
+ size_t buffer_size;
+ if (JXL_DEC_SUCCESS != JxlDecoderImageOutBufferSize(dec.get(), &format, &buffer_size))
+ {
+ SAL_WARN("vcl.filter.jxl", "JxlDecoderImageOutBufferSize failed");
+ success = false;
+ break;
+ }
+ if (buffer_size != xsize * ysize * 4)
+ {
+ SAL_WARN("vcl.filter.jxl", "Invalid out buffer size, expected "
+ << xsize * ysize * 4 << " but got " << buffer_size);
+ success = false;
+ break;
+ }
+ pixels.resize(xsize * ysize * 4);
+ if (JXL_DEC_SUCCESS
+ != JxlDecoderSetImageOutBuffer(dec.get(), &format, pixels.data(), pixels.size()))
+ {
+ SAL_WARN("vcl.filter.jxl", "JxlDecoderSetImageOutBuffer failed");
+ success = false;
+ break;
+ }
+ }
+ else if (status != JXL_DEC_COLOR_ENCODING) // not using color profile
+ {
+ SAL_WARN("vcl.filter.jxl", "Unknown JxlDecoderStatus");
+ success = false;
+ break;
+ }
+ }
+
+ // convert pixels into a bitmap
+
+ Bitmap bitmap(Size(xsize, ysize), vcl::PixelFormat::N32_BPP);
+ BitmapScopedWriteAccess access(bitmap);
+ if (!access)
+ return false;
+
+ for (tools::Long y = 0, nHeight = access->Height(); y < nHeight; ++y)
+ {
+ const unsigned char* src = pixels.data() + xsize * 4 * y;
+ for (tools::Long x = 0, nWidth = access->Width(); x < nWidth; ++x)
+ {
+ sal_uInt8 r = src[0];
+ sal_uInt8 g = src[1];
+ sal_uInt8 b = src[2];
+ sal_uInt8 a = src[3];
+ access->SetPixel(y, x, Color(ColorAlpha, a, r, g, b));
+ src += 4;
+ }
+ }
+
+ access.reset(); // Flush BitmapScopedWriteAccess
+ graphic = bitmap;
+
+ return success;
+}
+
+bool ImportJxlGraphic(SvStream& rStream, Graphic& rGraphic)
+{
+ bool bRetValue = readJxl(rStream, rGraphic);
+ if (!bRetValue)
+ rStream.SetError(SVSTREAM_FILEFORMAT_ERROR);
+ return bRetValue;
+}
diff --git a/vcl/source/gdi/gfxlink.cxx b/vcl/source/gdi/gfxlink.cxx
index aff0e9778980..8a139e582597 100644
--- a/vcl/source/gdi/gfxlink.cxx
+++ b/vcl/source/gdi/gfxlink.cxx
@@ -117,6 +117,7 @@ bool GfxLink::LoadNative(Graphic& rGraphic, sal_Int32 nPageNum) const
{
case GfxLinkType::NativeGif: aShortName = GIF_SHORTNAME; break;
case GfxLinkType::NativeJpg: aShortName = JPG_SHORTNAME; break;
+ case GfxLinkType::NativeJxl: aShortName = JXL_SHORTNAME; break;
case GfxLinkType::NativePng: aShortName = PNG_SHORTNAME; break;
case GfxLinkType::NativeTif: aShortName = TIF_SHORTNAME; break;
case GfxLinkType::NativeWmf: aShortName = WMF_SHORTNAME; break;
diff --git a/vcl/source/gdi/mtfxmldump.cxx b/vcl/source/gdi/mtfxmldump.cxx
index 2807b36a70cb..c973824ddd60 100644
--- a/vcl/source/gdi/mtfxmldump.cxx
+++ b/vcl/source/gdi/mtfxmldump.cxx
@@ -490,6 +490,7 @@ OUString convertGfxLinkTypeToString(GfxLinkType eGfxLinkType)
case GfxLinkType::NativeBmp: return u"NativeBmp"_ustr;
case GfxLinkType::NativeGif: return u"NativeGif"_ustr;
case GfxLinkType::NativeJpg: return u"NativeJpg"_ustr;
+ case GfxLinkType::NativeJxl: return u"NativeJxl"_ustr;
case GfxLinkType::NativeMet: return u"NativeMet"_ustr;
case GfxLinkType::NativeMov: return u"NativeMov"_ustr;
case GfxLinkType::NativePct: return u"NativePct"_ustr;
diff --git a/vcl/source/graphic/UnoGraphicDescriptor.cxx b/vcl/source/graphic/UnoGraphicDescriptor.cxx
index 00330f53946d..9dc31979b311 100644
--- a/vcl/source/graphic/UnoGraphicDescriptor.cxx
+++ b/vcl/source/graphic/UnoGraphicDescriptor.cxx
@@ -116,6 +116,7 @@ void GraphicDescriptor::implCreate( SvStream& rIStm, const OUString& rURL )
case GraphicFileFormat::BMP: aMimeType = MIMETYPE_BMP; cType = graphic::GraphicType::PIXEL; break;
case GraphicFileFormat::GIF: aMimeType = MIMETYPE_GIF; cType = graphic::GraphicType::PIXEL; break;
case GraphicFileFormat::JPG: aMimeType = MIMETYPE_JPG; cType = graphic::GraphicType::PIXEL; break;
+ case GraphicFileFormat::JXL: aMimeType = MIMETYPE_JXL; cType = graphic::GraphicType::PIXEL; break;
case GraphicFileFormat::PCD: aMimeType = MIMETYPE_PCD; cType = graphic::GraphicType::PIXEL; break;
case GraphicFileFormat::PCX: aMimeType = MIMETYPE_PCX; cType = graphic::GraphicType::PIXEL; break;
case GraphicFileFormat::PNG: aMimeType = MIMETYPE_PNG; cType = graphic::GraphicType::PIXEL; break;
@@ -290,6 +291,7 @@ void GraphicDescriptor::_getPropertyValues( const comphelper::PropertyMapEntry**
case GfxLinkType::NativeBmp: aMimeType = MIMETYPE_BMP; break;
case GfxLinkType::NativeJpg: aMimeType = MIMETYPE_JPG; break;
+ case GfxLinkType::NativeJxl: aMimeType = MIMETYPE_JXL; break;
case GfxLinkType::NativePng: aMimeType = MIMETYPE_PNG; break;
case GfxLinkType::NativeTif: aMimeType = MIMETYPE_TIF; break;
case GfxLinkType::NativeWmf: aMimeType = aLink.IsEMF() ? MIMETYPE_EMF : MIMETYPE_WMF; break;
diff --git a/vcl/workben/fftester.cxx b/vcl/workben/fftester.cxx
index 0c10b6bea810..3877a0df7cd5 100644
--- a/vcl/workben/fftester.cxx
+++ b/vcl/workben/fftester.cxx
@@ -48,6 +48,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -147,6 +148,12 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
SvFileStream aFileStream(out, StreamMode::READ);
ret = static_cast(ImportJPEG(aFileStream, aImportOutput, GraphicFilterImportFlags::NONE, nullptr));
}
+ else if (strcmp(argv[2], "jxl") == 0)
+ {
+ Graphic aGraphic;
+ SvFileStream aFileStream(out, StreamMode::READ);
+ ret = static_cast(ImportJxlGraphic(aFileStream, aGraphic));
+ }
else if (strcmp(argv[2], "gif") == 0)
{
ImportOutput aImportOutput;