WriteJPEGToMem is the only JPEG code in the tree (encode only, no decoding), and libjpeg-turbo came in as an ExternalProject whose imported target passed its include dir as -isystem. Any other jpeglib.h on the include path (conda, the distribution, the CUDA directory) could then win, and a build failed with "Wrong JPEG library version: library is 62, caller expects 80". stb_image_write v1.16 (commit 31c1ad3) is vendored in preview/stb/ and compiled into JFJochJPEG.cpp alone with STB_IMAGE_WRITE_STATIC and STBI_WRITE_NO_STDIO, so no JPEG symbol or header leaves that file. Output is baseline JPEG (it was progressive); the API is unchanged. Size limits are checked up front (JPEG's 65535 per side, stb's int pixel index) and an encoder failure throws JFJochException. Quality is clamped to 1-100. stb encodes an 18 Mpx frame in ~350 ms against ~210 ms for the scalar libjpeg-turbo we built; accepted. Removed: the ExternalProject and JPEG::JPEG target in preview/, nasm from the Docker images, licenses/libjpeg-turbo.txt and its manifest row, and the CI check that counted libjpeg-turbo copies in the viewer (the Qt JPEG/TIFF plugin check stays, as does the viewer's plugin exclusion). Licence: MIT OR Unlicense, recorded in licenses/ and THIRD_PARTY_NOTICES.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HVeDQqrcrEZy6XBUCMZvyT
59 lines
2.2 KiB
C++
59 lines
2.2 KiB
C++
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
#include <algorithm>
|
|
#include <climits>
|
|
#include <cstdint>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "../common/JFJochException.h"
|
|
#include "../common/CompressedImage.h"
|
|
#include "JFJochJPEG.h"
|
|
|
|
// The encoder is the vendored stb_image_write, compiled into this file only and with static linkage,
|
|
// so no JPEG symbol or header leaves it. File output is compiled out - the image goes to memory.
|
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
#define STB_IMAGE_WRITE_STATIC
|
|
#define STBI_WRITE_NO_STDIO
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(push)
|
|
#pragma warning(disable: 4244 4505)
|
|
#elif defined(__GNUC__)
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
|
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
|
#endif
|
|
#include "stb/stb_image_write.h"
|
|
#if defined(_MSC_VER)
|
|
#pragma warning(pop)
|
|
#elif defined(__GNUC__)
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
static void AppendToString(void *context, void *data, int size) {
|
|
static_cast<std::string *>(context)->append(static_cast<const char *>(data), size);
|
|
}
|
|
|
|
std::string WriteJPEGToMem(const CompressedImage& image, int quality) {
|
|
if (image.GetMode() != CompressedImageMode::RGB)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Only RGB images allowed for JPEG saving");
|
|
|
|
// 65535 is the JPEG format's limit; stb also indexes the pixels with an int.
|
|
const int64_t width = image.GetWidth();
|
|
const int64_t height = image.GetHeight();
|
|
if (width <= 0 || height <= 0 || width > 65535 || height > 65535 || width * height * 3 > INT_MAX)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid,
|
|
"Image size not supported by JPEG encoder");
|
|
|
|
std::vector<uint8_t> buffer;
|
|
image.GetUncompressed(buffer);
|
|
|
|
std::string ret;
|
|
if (stbi_write_jpg_to_func(AppendToString, &ret, static_cast<int>(width), static_cast<int>(height), 3,
|
|
buffer.data(), std::clamp(quality, 1, 100)) == 0)
|
|
throw JFJochException(JFJochExceptionCategory::InputParameterInvalid, "JPEG encoding failed");
|
|
return ret;
|
|
}
|