Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/2026.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ <h5>New features</h5>
<li>SVE2 optimizations of class SynetQuantizedConvolutionNhwcDepthwiseV3.</li>
<li>NEON, SVE2 optimizations of class SynetQuantizedConvolutionNhwcGemmV0.</li>
<li>NEON, SVE2 optimizations of class SynetQuantizedConvolutionNhwcSpecV0.</li>
<li>SVE2 optimizations of class ImagePgmTxtSaver.</li>
<li>SVE2 optimizations of class ImagePgmBinSaver.</li>
<li>SVE2 optimizations of class ImagePpmTxtSaver.</li>
<li>SVE2 optimizations of class ImagePpmBinSaver.</li>
<li>C++ wrapper Simd::SynetAdd16b.</li>
<li>C++ wrapper Simd::SynetQuantizedAdd.</li>
<li>C++ wrapper Simd::SynetQuantizedMul.</li>
Expand Down Expand Up @@ -137,6 +141,13 @@ <h5>Removing</h5>
</ul>

<h4>Test framework</h4>
<h5>New features</h5>
<ul>
<li>Tests for verifying functionality of SVE2 optimizations of class ImagePgmTxtSaver.</li>
<li>Tests for verifying functionality of SVE2 optimizations of class ImagePgmBinSaver.</li>
<li>Tests for verifying functionality of SVE2 optimizations of class ImagePpmTxtSaver.</li>
<li>Tests for verifying functionality of SVE2 optimizations of class ImagePpmBinSaver.</li>
</ul>
<h5>Removing</h5>
<ul>
<li>Tests for verifying functionality of function FillFrame.</li>
Expand Down
1 change: 1 addition & 0 deletions prj/vs2022/Sve2.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<ClCompile Include="..\..\src\Simd\SimdSve2InterleaveUv.cpp" />
<ClCompile Include="..\..\src\Simd\SimdSve2Histogram.cpp" />
<ClCompile Include="..\..\src\Simd\SimdSve2Hog.cpp" />
<ClCompile Include="..\..\src\Simd\SimdSve2ImageSave.cpp" />
<ClCompile Include="..\..\src\Simd\SimdSve2Laplace.cpp" />
<ClCompile Include="..\..\src\Simd\SimdSve2Lbp.cpp" />
<ClCompile Include="..\..\src\Simd\SimdSve2MaxFilter.cpp" />
Expand Down
3 changes: 3 additions & 0 deletions prj/vs2022/Sve2.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@
<ClCompile Include="..\..\src\Simd\SimdSve2Hog.cpp">
<Filter>Sve2\Legacy</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Simd\SimdSve2ImageSave.cpp">
<Filter>Sve2\Image</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Simd\SimdSve2Laplace.cpp">
<Filter>Sve2\Filter</Filter>
</ClCompile>
Expand Down
33 changes: 33 additions & 0 deletions src/Simd/SimdImageSave.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions src/Simd/SimdLib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3427,15 +3427,15 @@ 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);
}

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);
}
Expand Down
135 changes: 135 additions & 0 deletions src/Simd/SimdSve2ImageSave.cpp
Original file line number Diff line number Diff line change
@@ -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 <memory>

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<ImageSaver> saver(CreateImageSaver(param));
if (saver)
{
if (saver->ToStream(src, stride))
return saver->Release(size);
}
}
return NULL;
}
}
#endif
}
5 changes: 5 additions & 0 deletions src/Test/TestImageIO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down