Skip to content
Open
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
2 changes: 1 addition & 1 deletion extras/third_party/libjxl
Submodule libjxl updated 606 files
16 changes: 13 additions & 3 deletions src/JPEGView.Setup/Product.wxs
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,10 @@
<Feature Id="FeatureJXL" Title="JPEG XL Support">
<ComponentRef Id="brotlicommonDLL"/>
<ComponentRef Id="brotlidecDLL"/>
<ComponentRef Id="jxl_decDLL"/>
<ComponentRef Id="brotliencDLL"/>
<ComponentRef Id="jxlDLL"/>
<ComponentRef Id="jxl_threadsDLL"/>
<ComponentRef Id="jxl_cmsDLL"/>
</Feature>
<Feature Id="FeatureHEIF" Title="HEIF/HEIC/AVIF Support">
<ComponentRef Id="dav1dDLL"/>
Expand Down Expand Up @@ -482,6 +484,8 @@
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\SystemFileAssociations\.tif\shell\edit.JPEGView.exe\command" Value="&quot;[APPLICATIONFOLDER]JPEGView.exe&quot; &quot;%1&quot;" Type="string" />
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\SystemFileAssociations\.webp\shell\edit.JPEGView.exe" Value="!(loc.ExplorerMenuEditREG)" Type="string" />
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\SystemFileAssociations\.webp\shell\edit.JPEGView.exe\command" Value="&quot;[APPLICATIONFOLDER]JPEGView.exe&quot; &quot;%1&quot;" Type="string" />
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\SystemFileAssociations\.jxl\shell\edit.JPEGView.exe" Value="!(loc.ExplorerMenuEditREG)" Type="string" />
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\SystemFileAssociations\.jxl\shell\edit.JPEGView.exe\command" Value="&quot;[APPLICATIONFOLDER]JPEGView.exe&quot; &quot;%1&quot;" Type="string" />
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\SystemFileAssociations\.qoi\shell\edit.JPEGView.exe" Value="!(loc.ExplorerMenuEditREG)" Type="string" />
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\SystemFileAssociations\.qoi\shell\edit.JPEGView.exe\command" Value="&quot;[APPLICATIONFOLDER]JPEGView.exe&quot; &quot;%1&quot;" Type="string" />
</Component>
Expand All @@ -493,12 +497,18 @@
<Component Id="brotlidecDLL" Guid="dc648a37-d726-40f9-9098-dfde491dbb44">
<File Id="brotlidec.dll" Name="brotlidec.dll" Source="$(var.JxlDllFolder)\brotlidec.dll" />
</Component>
<Component Id="jxl_decDLL" Guid="a65bca95-9ddf-476c-88b5-5048a3a9bde6">
<File Id="jxl_dec.dll" Name="jxl_dec.dll" Source="$(var.JxlDllFolder)\jxl_dec.dll" />
<Component Id="brotliencDLL" Guid="86874037-d2c4-4d18-ac08-82442006a60e">
<File Id="brotlienc.dll" Name="brotlienc.dll" Source="$(var.JxlDllFolder)\brotlienc.dll" />
</Component>
<Component Id="jxlDLL" Guid="2444593c-141e-4a66-b61e-9f25eb1a9a78">
<File Id="jxl.dll" Name="jxl.dll" Source="$(var.JxlDllFolder)\jxl.dll" />
</Component>
<Component Id="jxl_threadsDLL" Guid="964ed16e-138a-4419-9c4c-8eb45a04d0f6">
<File Id="jxl_threads.dll" Name="jxl_threads.dll" Source="$(var.JxlDllFolder)\jxl_threads.dll" />
</Component>
<Component Id="jxl_cmsDLL" Guid="4c0c5600-5418-4e27-9185-18b926bc91ec">
<File Id="jxl_cms.dll" Name="jxl_cms.dll" Source="$(var.JxlDllFolder)\jxl_cms.dll" />
</Component>


<!-- DLLs required for HEIF/AVIF support -->
Expand Down
5 changes: 4 additions & 1 deletion src/JPEGView/Config/JPEGView.ini
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ DeleteConfirmation=OnlyWhenNoRecycleBin
; * These options control file saving parameters
; *****************************************************************************

; Default format for saving files. Supported formats: jpg, bmp, png, tif, webp
; Default format for saving files. Supported formats: jpg, bmp, png, tif, webp, jxl, qoi
DefaultSaveFormat=jpg

; Quality when saving JPEG files (in 0..100 where 100 is the highest quality)
Expand All @@ -586,6 +586,9 @@ JPEGSaveQuality=85
; Quality when saving WEBP files with lossy compression (in 0..100 where 100 is the highest quality)
WEBPSaveQuality=85

; Quality when saving JXL files with lossy compression (in 0..100 where 100 is the highest quality)
JXLSaveQuality=85

; Set to true to create a parameter DB entry when saving an image with JPEGView to avoid processing it again
CreateParamDBEntryOnSave=true

Expand Down
5 changes: 4 additions & 1 deletion src/JPEGView/Config/JPEGView.ini.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ DeleteConfirmation=OnlyWhenNoRecycleBin
; * These options control file saving parameters
; *****************************************************************************

; Default format for saving files. Supported formats: jpg, bmp, png, tif, webp
; Default format for saving files. Supported formats: jpg, bmp, png, tif, webp, jxl, qoi
DefaultSaveFormat=jpg

; Quality when saving JPEG files (in 0..100 where 100 is the highest quality)
Expand All @@ -556,6 +556,9 @@ JPEGSaveQuality=85
; Quality when saving WEBP files with lossy compression (in 0..100 where 100 is the highest quality)
WEBPSaveQuality=85

; Quality when saving JXL files with lossy compression (in 0..100 where 100 is the highest quality)
JXLSaveQuality=85

; Set to true to create a parameter DB entry when saving an image with JPEGView to avoid processing it again
CreateParamDBEntryOnSave=true

Expand Down
5 changes: 4 additions & 1 deletion src/JPEGView/Config/JPEGView_ru.ini
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ DeleteConfirmation=OnlyWhenNoRecycleBin
; *****************************************************************************

; ������ ���������� ������ �� ���������.
; �������������� �������: jpg, bmp, png, tif, webp.
; �������������� �������: jpg, bmp, png, tif, webp, jxl, qoi.
DefaultSaveFormat=jpg

; �������� ���������� ������ JPEG (0 .. 100, ��� 100 � ��������� ��������).
Expand All @@ -673,6 +673,9 @@ JPEGSaveQuality=85
; �������� ���������� ������ WEBP ��� ������ � �������� (0 .. 100, ��� 100 � ��������� ��������).
WEBPSaveQuality=85

; �������� ���������� ������ JXL ��� ������ � �������� (0 .. 100, ��� 100 � ��������� ��������).
JXLSaveQuality=85

; ���� "true", �� ��� ���������� ����������� � ������� JPEGView �������� ������
; � ���������� � ���� ������ �� ��������� ��������� ��������� ������������ �����.
CreateParamDBEntryOnSave=true
Expand Down
5 changes: 4 additions & 1 deletion src/JPEGView/Config/JPEGView_ru.ini.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ DeleteConfirmation=OnlyWhenNoRecycleBin
; *****************************************************************************

; ������ ���������� ������ �� ���������.
; �������������� �������: jpg, bmp, png, tif, webp.
; �������������� �������: jpg, bmp, png, tif, webp, jxl, qoi.
DefaultSaveFormat=jpg

; �������� ���������� ������ JPEG (0 .. 100, ��� 100 � ��������� ��������).
Expand All @@ -655,6 +655,9 @@ JPEGSaveQuality=85
; �������� ���������� ������ WEBP ��� ������ � �������� (0 .. 100, ��� 100 � ��������� ��������).
WEBPSaveQuality=85

; �������� ���������� ������ JXL ��� ������ � �������� (0 .. 100, ��� 100 � ��������� ��������).
JXLSaveQuality=85

; ���� "true", �� ��� ���������� ����������� � ������� JPEGView �������� ������
; � ���������� � ���� ������ �� ��������� ��������� ��������� ������������ �����.
CreateParamDBEntryOnSave=true
Expand Down
2 changes: 2 additions & 0 deletions src/JPEGView/JPEGView.rc
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@ BEGIN
MENUITEM SEPARATOR
MENUITEM "Mirror horizontally", IDM_MIRROR_H_LOSSLESS
MENUITEM "Mirror vertically", IDM_MIRROR_V_LOSSLESS
MENUITEM SEPARATOR
MENUITEM "Convert to JXL..." IDM_CONVERT_JXL
END
MENUITEM "Auto correction", IDM_AUTO_CORRECTION
MENUITEM "Local density correction", IDM_LDC
Expand Down
16 changes: 8 additions & 8 deletions src/JPEGView/JPEGView.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,14 @@
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>Dbghelp.lib;gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl_dec.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;libraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Dbghelp.lib;gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;libraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>bin\x86\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<DelayLoadDLLs>WICLoader.dll;jxl_dec.dll;jxl_threads.dll;heif.dll;avif.dll;lcms2.dll;libraw.dll</DelayLoadDLLs>
<DelayLoadDLLs>WICLoader.dll;jxl.dll;jxl_threads.dll;heif.dll;avif.dll;lcms2.dll;libraw.dll</DelayLoadDLLs>
<IgnoreSpecificDefaultLibraries>LIBCMT</IgnoreSpecificDefaultLibraries>
<AdditionalOptions>/IGNORE:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
Expand Down Expand Up @@ -170,13 +170,13 @@
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>legacy_stdio_definitions.lib;legacy_stdio_wide_specifiers.lib;Dbghelp.lib;gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl_dec.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;libraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>legacy_stdio_definitions.lib;legacy_stdio_wide_specifiers.lib;Dbghelp.lib;gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;libraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>bin\x64\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ModuleDefinitionFile>
</ModuleDefinitionFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<DelayLoadDLLs>WICLoader.dll;jxl_dec.dll;jxl_threads.dll;heif.dll;avif.dll;lcms2.dll;libraw.dll</DelayLoadDLLs>
<DelayLoadDLLs>WICLoader.dll;jxl.dll;jxl_threads.dll;heif.dll;avif.dll;lcms2.dll;libraw.dll</DelayLoadDLLs>
<IgnoreSpecificDefaultLibraries>LIBCMT</IgnoreSpecificDefaultLibraries>
<AdditionalOptions>/IGNORE:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
Expand Down Expand Up @@ -225,13 +225,13 @@
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl_dec.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;libraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;libraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>bin\x86\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>WICLoader.dll;jxl_dec.dll;jxl_threads.dll;heif.dll;avif.dll;lcms2.dll;libraw.dll</DelayLoadDLLs>
<DelayLoadDLLs>WICLoader.dll;jxl.dll;jxl_threads.dll;heif.dll;avif.dll;lcms2.dll;libraw.dll</DelayLoadDLLs>
<LinkTimeCodeGeneration>UseFastLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<AdditionalOptions>/IGNORE:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
Expand Down Expand Up @@ -279,12 +279,12 @@
<AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>legacy_stdio_definitions.lib;legacy_stdio_wide_specifiers.lib;gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl_dec.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;libraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>legacy_stdio_definitions.lib;legacy_stdio_wide_specifiers.lib;gdiplus.lib;WICLoader.lib;turbojpeg-static.lib;libpng16.lib;zlib.lib;jxl.lib;jxl_threads.lib;heif.lib;libwebp.lib;libwebpdemux.lib;avif.lib;lcms2.lib;libraw.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>bin\x64\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<DelayLoadDLLs>WICLoader.dll;jxl_dec.dll;jxl_threads.dll;heif.dll;avif.dll;lcms2.dll;libraw.dll</DelayLoadDLLs>
<DelayLoadDLLs>WICLoader.dll;jxl.dll;jxl_threads.dll;heif.dll;avif.dll;lcms2.dll;libraw.dll</DelayLoadDLLs>
<LinkTimeCodeGeneration>UseFastLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<AdditionalOptions>/IGNORE:4099 %(AdditionalOptions)</AdditionalOptions>
</Link>
Expand Down
145 changes: 145 additions & 0 deletions src/JPEGView/JXLWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@
#include "JXLWrapper.h"
#include "jxl/decode.h"
#include "jxl/decode_cxx.h"
#include "jxl/encode.h"
#include "jxl/encode_cxx.h"
#include "jxl/thread_parallel_runner.h"
#include "jxl/thread_parallel_runner_cxx.h"
#include "jxl/resizable_parallel_runner.h"
#include "jxl/resizable_parallel_runner_cxx.h"
#include "Helpers.h"
#include "MaxImageDef.h"
#include "ICCProfileTransform.h"

static void* DoCompress(JxlEncoder* enc, size_t& len);

struct JxlReader::jxl_cache {
JxlDecoderPtr decoder;
JxlResizableParallelRunnerPtr runner;
Expand Down Expand Up @@ -236,3 +243,141 @@ void JxlReader::DeleteCache() {
// Setting the decoder and runner to 0 (NULL) will automatically destroy them
cache = { 0 };
}

// based on https://github.com/libjxl/libjxl/blob/main/examples/encode_oneshot.cc
void* JxlReader::Compress(const void* buffer,
int width,
int height,
size_t& len,
int quality,
bool lossless) {

auto enc = JxlEncoderMake(nullptr);
auto runner = JxlThreadParallelRunnerMake(
nullptr,
JxlThreadParallelRunnerDefaultNumWorkerThreads());
if (!enc.get() || !runner.get()) {
return NULL;
}
if (JXL_ENC_SUCCESS != JxlEncoderSetParallelRunner(enc.get(),
JxlThreadParallelRunner,
runner.get())) {
return NULL;
}

JxlPixelFormat pixel_format = { 3, JXL_TYPE_UINT8, JXL_NATIVE_ENDIAN, 4 };

JxlBasicInfo basic_info;
JxlEncoderInitBasicInfo(&basic_info);
basic_info.xsize = width;
basic_info.ysize = height;
basic_info.bits_per_sample = 8;
basic_info.uses_original_profile = lossless;
if (JXL_ENC_SUCCESS != JxlEncoderSetBasicInfo(enc.get(), &basic_info)) {
return NULL;
}

JxlEncoderFrameSettings* frame_settings = JxlEncoderFrameSettingsCreate(enc.get(), NULL);
if (frame_settings == NULL) {
return NULL;
}
if (lossless) {
if (JXL_ENC_SUCCESS != JxlEncoderSetFrameLossless(frame_settings, JXL_TRUE)) {
return NULL;
};
} else {
float distance = JxlEncoderDistanceFromQuality(quality);
distance = max(distance, .1f); // prevent huge file size
if (JXL_ENC_SUCCESS != JxlEncoderSetFrameDistance(frame_settings, distance)) {
return NULL;
};
}

// TODO: remove rgb_buffer once libjxl adds channel order support
int padded_width = Helpers::DoPadding(width * 3, 4);
size_t buffer_size = (size_t)height * padded_width;
uint8_t* rgb_buffer = (uint8_t*)malloc(buffer_size);
if (rgb_buffer == NULL) {
return NULL;
}
memcpy(rgb_buffer, buffer, buffer_size);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
size_t offset = (size_t)i * padded_width + j * 3;
rgb_buffer[offset] = ((const uint8_t*)buffer)[offset+2];
rgb_buffer[offset+2] = ((const uint8_t*)buffer)[offset];
}
}
if (JXL_ENC_SUCCESS !=
JxlEncoderAddImageFrame(frame_settings, &pixel_format,
rgb_buffer,
buffer_size)) {
free(rgb_buffer);
return NULL;
}
JxlEncoderCloseInput(enc.get());
free(rgb_buffer);

return DoCompress(enc.get(), len);
}

void* JxlReader::CompressJPEG(const void* buffer, size_t input_len, size_t& output_len) {
auto enc = JxlEncoderMake(nullptr);
auto runner = JxlThreadParallelRunnerMake(
nullptr,
JxlThreadParallelRunnerDefaultNumWorkerThreads());
if (!enc.get() || !runner.get()) {
return NULL;
}
if (JXL_ENC_SUCCESS != JxlEncoderSetParallelRunner(enc.get(),
JxlThreadParallelRunner,
runner.get())) {
return NULL;
}
JxlEncoderFrameSettings* frame_settings = JxlEncoderFrameSettingsCreate(enc.get(), NULL);
if (frame_settings == NULL) {
return NULL;
}
if (JXL_ENC_SUCCESS != JxlEncoderStoreJPEGMetadata(enc.get(), JXL_TRUE)) {
return NULL;
};
if (JXL_ENC_SUCCESS != JxlEncoderAddJPEGFrame(frame_settings, (const uint8_t*)buffer, input_len)) {
return NULL;
}
JxlEncoderCloseInput(enc.get());

return DoCompress(enc.get(), output_len);
}

static void* DoCompress(JxlEncoder* enc, size_t& len) {
std::vector<uint8_t> compressed;
compressed.resize(4096);
uint8_t* next_out = compressed.data();
size_t avail_out = compressed.size() - (next_out - compressed.data());
JxlEncoderStatus process_result = JXL_ENC_NEED_MORE_OUTPUT;
while (process_result == JXL_ENC_NEED_MORE_OUTPUT) {
process_result = JxlEncoderProcessOutput(enc, &next_out, &avail_out);
if (process_result == JXL_ENC_NEED_MORE_OUTPUT) {
size_t offset = next_out - compressed.data();
compressed.resize(compressed.size() * 2);
next_out = compressed.data() + offset;
avail_out = compressed.size() - offset;
}
}
compressed.resize(next_out - compressed.data());
if (JXL_ENC_SUCCESS != process_result) {
return NULL;
}

len = compressed.size();
void* pOutput = malloc(len);
if (pOutput != NULL) {
memcpy(pOutput, compressed.data(), len);
}

return pOutput;
}

void JxlReader::Free(void* buffer) {
free(buffer);
}
13 changes: 13 additions & 0 deletions src/JPEGView/JXLWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ class JxlReader

static void DeleteCache();

static void* Compress(const void* buffer, // address of image in memory, format must be 3 bytes per pixel BRGBGR with padding to 4 byte boundary
int width, // width of image in pixels
int height, // height of image in pixels.
size_t& len, // returns length of compressed data
int quality, // image quality as a percentage
bool lossless); // use lossless compression if true

static void* CompressJPEG(const void* buffer, // address of JPEG-encoded image in memory
size_t input_len, // Length of input JPEG image
size_t& output_len); // returns length of compressed data

static void Free(void* buffer);

private:
struct jxl_cache;
static jxl_cache cache;
Expand Down
Loading