diff --git a/docs/2026.html b/docs/2026.html
index 940986a59c..85babbad78 100644
--- a/docs/2026.html
+++ b/docs/2026.html
@@ -73,6 +73,10 @@
New features
SVE2 optimizations of class SynetQuantizedConvolutionNhwcDepthwiseV3.
NEON, SVE2 optimizations of class SynetQuantizedConvolutionNhwcGemmV0.
NEON, SVE2 optimizations of class SynetQuantizedConvolutionNhwcSpecV0.
+ SVE2 optimizations of class ImagePgmTxtSaver.
+ SVE2 optimizations of class ImagePgmBinSaver.
+ SVE2 optimizations of class ImagePpmTxtSaver.
+ SVE2 optimizations of class ImagePpmBinSaver.
C++ wrapper Simd::SynetAdd16b.
C++ wrapper Simd::SynetQuantizedAdd.
C++ wrapper Simd::SynetQuantizedMul.
@@ -137,6 +141,13 @@ Removing
Test framework
+New features
+
+ - Tests for verifying functionality of SVE2 optimizations of class ImagePgmTxtSaver.
+ - Tests for verifying functionality of SVE2 optimizations of class ImagePgmBinSaver.
+ - Tests for verifying functionality of SVE2 optimizations of class ImagePpmTxtSaver.
+ - Tests for verifying functionality of SVE2 optimizations of class ImagePpmBinSaver.
+
Removing
- Tests for verifying functionality of function FillFrame.
diff --git a/prj/vs2022/Sve2.vcxproj b/prj/vs2022/Sve2.vcxproj
index 63f2fb43ef..7c92773673 100644
--- a/prj/vs2022/Sve2.vcxproj
+++ b/prj/vs2022/Sve2.vcxproj
@@ -70,6 +70,7 @@
+
diff --git a/prj/vs2022/Sve2.vcxproj.filters b/prj/vs2022/Sve2.vcxproj.filters
index 36a4c75b67..bff68fdd00 100644
--- a/prj/vs2022/Sve2.vcxproj.filters
+++ b/prj/vs2022/Sve2.vcxproj.filters
@@ -308,6 +308,9 @@
Sve2\Legacy
+
+ Sve2\Image
+
Sve2\Filter
diff --git a/src/Simd/SimdImageSave.h b/src/Simd/SimdImageSave.h
index 2a98aba665..d1faf8a6fc 100644
--- a/src/Simd/SimdImageSave.h
+++ b/src/Simd/SimdImageSave.h
@@ -491,6 +491,39 @@ namespace Simd
uint8_t* Yuv420pSaveAsJpegToMemory(const uint8_t* y, size_t yStride, const uint8_t* u, size_t uStride, const uint8_t* v, size_t vStride, size_t width, size_t height, SimdYuvType yuvType, int quality, size_t* size);
}
#endif
+
+#ifdef SIMD_SVE2_ENABLE
+ namespace Sve2
+ {
+ class ImagePgmTxtSaver : public Neon::ImagePgmTxtSaver
+ {
+ public:
+ ImagePgmTxtSaver(const ImageSaverParam& param);
+ };
+
+ class ImagePgmBinSaver : public Neon::ImagePgmBinSaver
+ {
+ public:
+ ImagePgmBinSaver(const ImageSaverParam& param);
+ };
+
+ class ImagePpmTxtSaver : public Neon::ImagePpmTxtSaver
+ {
+ public:
+ ImagePpmTxtSaver(const ImageSaverParam& param);
+ };
+
+ class ImagePpmBinSaver : public Neon::ImagePpmBinSaver
+ {
+ public:
+ ImagePpmBinSaver(const ImageSaverParam& param);
+ };
+
+ //-------------------------------------------------------------------------------------------------
+
+ uint8_t* ImageSaveToMemory(const uint8_t* src, size_t stride, size_t width, size_t height, SimdPixelFormatType format, SimdImageFileType file, int quality, size_t* size);
+ }
+#endif
}
#endif
diff --git a/src/Simd/SimdLib.cpp b/src/Simd/SimdLib.cpp
index 37734b9adc..dac00508f2 100644
--- a/src/Simd/SimdLib.cpp
+++ b/src/Simd/SimdLib.cpp
@@ -3427,7 +3427,7 @@ SIMD_API void SimdHogFilterSeparable(const float * src, size_t srcStride, size_t
SIMD_API uint8_t* SimdImageSaveToMemory(const uint8_t* src, size_t stride, size_t width, size_t height, SimdPixelFormatType format, SimdImageFileType file, int quality, size_t* size)
{
SIMD_EMPTY();
- const static Simd::ImageSaveToMemoryPtr imageSaveToMemory = SIMD_FUNC4(ImageSaveToMemory, SIMD_AVX512BW_FUNC, SIMD_AVX2_FUNC, SIMD_SSE41_FUNC, SIMD_NEON_FUNC);
+ const static Simd::ImageSaveToMemoryPtr imageSaveToMemory = SIMD_FUNC5(ImageSaveToMemory, SIMD_AVX512BW_FUNC, SIMD_AVX2_FUNC, SIMD_SSE41_FUNC, SIMD_SVE2_FUNC, SIMD_NEON_FUNC);
return imageSaveToMemory(src, stride, width, height, format, file, quality, size);
}
@@ -3435,7 +3435,7 @@ SIMD_API uint8_t* SimdImageSaveToMemory(const uint8_t* src, size_t stride, size_
SIMD_API SimdBool SimdImageSaveToFile(const uint8_t* src, size_t stride, size_t width, size_t height, SimdPixelFormatType format, SimdImageFileType file, int quality, const char* path)
{
SIMD_EMPTY();
- const static Simd::ImageSaveToMemoryPtr imageSaveToMemory = SIMD_FUNC4(ImageSaveToMemory, SIMD_AVX512BW_FUNC, SIMD_AVX2_FUNC, SIMD_SSE41_FUNC, SIMD_NEON_FUNC);
+ const static Simd::ImageSaveToMemoryPtr imageSaveToMemory = SIMD_FUNC5(ImageSaveToMemory, SIMD_AVX512BW_FUNC, SIMD_AVX2_FUNC, SIMD_SSE41_FUNC, SIMD_SVE2_FUNC, SIMD_NEON_FUNC);
return ImageSaveToFile(imageSaveToMemory, src, stride, width, height, format, file, quality, path);
}
diff --git a/src/Simd/SimdSve2ImageSave.cpp b/src/Simd/SimdSve2ImageSave.cpp
new file mode 100644
index 0000000000..b0a8fae1bd
--- /dev/null
+++ b/src/Simd/SimdSve2ImageSave.cpp
@@ -0,0 +1,135 @@
+/*
+* Simd Library (http://ermig1979.github.io/Simd).
+*
+* Copyright (c) 2011-2026 Yermalayeu Ihar.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*/
+#include "Simd/SimdMemory.h"
+#include "Simd/SimdImageSave.h"
+#include "Simd/SimdSve2.h"
+
+#include
+
+namespace Simd
+{
+#ifdef SIMD_SVE2_ENABLE
+ namespace Sve2
+ {
+ ImagePgmTxtSaver::ImagePgmTxtSaver(const ImageSaverParam& param)
+ : Neon::ImagePgmTxtSaver(param)
+ {
+ if (_param.width >= svcntb())
+ {
+ switch (_param.format)
+ {
+ case SimdPixelFormatBgr24: _convert = Sve2::BgrToGray; break;
+ case SimdPixelFormatBgra32: _convert = Sve2::BgraToGray; break;
+ case SimdPixelFormatRgb24: _convert = Sve2::RgbToGray; break;
+ case SimdPixelFormatRgba32: _convert = Sve2::RgbaToGray; break;
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+
+ ImagePgmBinSaver::ImagePgmBinSaver(const ImageSaverParam& param)
+ : Neon::ImagePgmBinSaver(param)
+ {
+ if (_param.width >= svcntb())
+ {
+ switch (_param.format)
+ {
+ case SimdPixelFormatBgr24: _convert = Sve2::BgrToGray; break;
+ case SimdPixelFormatBgra32: _convert = Sve2::BgraToGray; break;
+ case SimdPixelFormatRgb24: _convert = Sve2::RgbToGray; break;
+ case SimdPixelFormatRgba32: _convert = Sve2::RgbaToGray; break;
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+
+ ImagePpmTxtSaver::ImagePpmTxtSaver(const ImageSaverParam& param)
+ : Neon::ImagePpmTxtSaver(param)
+ {
+ if (_param.width >= svcntb())
+ {
+ switch (_param.format)
+ {
+ case SimdPixelFormatGray8: _convert = Sve2::GrayToBgr; break;
+ case SimdPixelFormatBgr24: _convert = Sve2::BgrToRgb; break;
+ case SimdPixelFormatBgra32: _convert = Sve2::BgraToRgb; break;
+ case SimdPixelFormatRgba32: _convert = Sve2::BgraToBgr; break;
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+
+ ImagePpmBinSaver::ImagePpmBinSaver(const ImageSaverParam& param)
+ : Neon::ImagePpmBinSaver(param)
+ {
+ if (_param.width >= svcntb())
+ {
+ switch (_param.format)
+ {
+ case SimdPixelFormatGray8: _convert = Sve2::GrayToBgr; break;
+ case SimdPixelFormatBgr24: _convert = Sve2::BgrToRgb; break;
+ case SimdPixelFormatBgra32: _convert = Sve2::BgraToRgb; break;
+ case SimdPixelFormatRgba32: _convert = Sve2::BgraToBgr; break;
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------------------------------
+
+ ImageSaver* CreateImageSaver(const ImageSaverParam& param)
+ {
+ switch (param.file)
+ {
+ case SimdImageFilePgmTxt: return new ImagePgmTxtSaver(param);
+ case SimdImageFilePgmBin: return new ImagePgmBinSaver(param);
+ case SimdImageFilePpmTxt: return new ImagePpmTxtSaver(param);
+ case SimdImageFilePpmBin: return new ImagePpmBinSaver(param);
+ case SimdImageFilePng: return new Neon::ImagePngSaver(param);
+ case SimdImageFileJpeg: return new Neon::ImageJpegSaver(param);
+ case SimdImageFileBmp: return new Neon::ImageBmpSaver(param);
+ default:
+ return NULL;
+ }
+ }
+
+ uint8_t* ImageSaveToMemory(const uint8_t* src, size_t stride, size_t width, size_t height, SimdPixelFormatType format, SimdImageFileType file, int quality, size_t* size)
+ {
+ ImageSaverParam param(width, height, format, file, quality);
+ if (param.Validate())
+ {
+ Holder saver(CreateImageSaver(param));
+ if (saver)
+ {
+ if (saver->ToStream(src, stride))
+ return saver->Release(size);
+ }
+ }
+ return NULL;
+ }
+ }
+#endif
+}
diff --git a/src/Test/TestImageIO.cpp b/src/Test/TestImageIO.cpp
index 1cc574cc00..bcbdebe1de 100644
--- a/src/Test/TestImageIO.cpp
+++ b/src/Test/TestImageIO.cpp
@@ -254,6 +254,11 @@ namespace Test
result = result && ImageSaveToMemoryAutoTest(FUNC_SM(Simd::Avx512bw::ImageSaveToMemory), FUNC_SM(SimdImageSaveToMemory));
#endif
+#ifdef SIMD_SVE2_ENABLE
+ if (Simd::Sve2::Enable && TestSve2(options))
+ result = result && ImageSaveToMemoryAutoTest(FUNC_SM(Simd::Sve2::ImageSaveToMemory), FUNC_SM(SimdImageSaveToMemory));
+#endif
+
#ifdef SIMD_NEON_ENABLE
if (Simd::Neon::Enable && TestNeon(options))
result = result && ImageSaveToMemoryAutoTest(FUNC_SM(Simd::Neon::ImageSaveToMemory), FUNC_SM(SimdImageSaveToMemory));