mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-03-05 05:47:44 +00:00
Image: Swap stb for libpng/libjpeg
This commit is contained in:
parent
e9c4416272
commit
c854b8f85e
|
@ -358,6 +358,78 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<h3>libjpeg - <a href="https://ijg.org/">https://ijg.org/</a></h3>
|
||||||
|
<pre>
|
||||||
|
The authors make NO WARRANTY or representation, either express or implied,
|
||||||
|
with respect to this software, its quality, accuracy, merchantability, or
|
||||||
|
fitness for a particular purpose. This software is provided "AS IS", and you,
|
||||||
|
its user, assume the entire risk as to its quality and accuracy.
|
||||||
|
|
||||||
|
This software is copyright (C) 1991-2024, Thomas G. Lane, Guido Vollbeding.
|
||||||
|
All Rights Reserved except as specified below.
|
||||||
|
|
||||||
|
Permission is hereby granted to use, copy, modify, and distribute this
|
||||||
|
software (or portions thereof) for any purpose, without fee, subject to these
|
||||||
|
conditions:
|
||||||
|
(1) If any part of the source code for this software is distributed, then this
|
||||||
|
README file must be included, with this copyright and no-warranty notice
|
||||||
|
unaltered; and any additions, deletions, or changes to the original files
|
||||||
|
must be clearly indicated in accompanying documentation.
|
||||||
|
(2) If only executable code is distributed, then the accompanying
|
||||||
|
documentation must state that "this software is based in part on the work of
|
||||||
|
the Independent JPEG Group".
|
||||||
|
(3) Permission for use of this software is granted only if the user accepts
|
||||||
|
full responsibility for any undesirable consequences; the authors accept
|
||||||
|
NO LIABILITY for damages of any kind.
|
||||||
|
|
||||||
|
These conditions apply to any software derived from or based on the IJG code,
|
||||||
|
not just to the unmodified library. If you use our work, you ought to
|
||||||
|
acknowledge us.
|
||||||
|
|
||||||
|
Permission is NOT granted for the use of any IJG author's name or company name
|
||||||
|
in advertising or publicity relating to this software or products derived from
|
||||||
|
it. This software may be referred to only as "the Independent JPEG Group's
|
||||||
|
software".
|
||||||
|
|
||||||
|
We specifically permit and encourage the use of this software as the basis of
|
||||||
|
commercial products, provided that all warranty or liability claims are
|
||||||
|
assumed by the product vendor.
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h3>libpng - <a href="http://www.libpng.org/pub/png/libpng.html">http://www.libpng.org/pub/png/libpng.html</a></h3>
|
||||||
|
<pre>
|
||||||
|
* Copyright (c) 1995-2024 The PNG Reference Library Authors.
|
||||||
|
* Copyright (c) 2018-2024 Cosmin Truta.
|
||||||
|
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
|
||||||
|
* Copyright (c) 1996-1997 Andreas Dilger.
|
||||||
|
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
|
||||||
|
|
||||||
|
The software is supplied "as is", without warranty of any kind,
|
||||||
|
express or implied, including, without limitation, the warranties
|
||||||
|
of merchantability, fitness for a particular purpose, title, and
|
||||||
|
non-infringement. In no event shall the Copyright owners, or
|
||||||
|
anyone distributing the software, be liable for any damages or
|
||||||
|
other liability, whether in contract, tort or otherwise, arising
|
||||||
|
from, out of, or in connection with the software, or the use or
|
||||||
|
other dealings in the software, even if advised of the possibility
|
||||||
|
of such damage.
|
||||||
|
|
||||||
|
Permission is hereby granted to use, copy, modify, and distribute
|
||||||
|
this software, or portions hereof, for any purpose, without fee,
|
||||||
|
subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you
|
||||||
|
must not claim that you wrote the original software. If you
|
||||||
|
use this software in a product, an acknowledgment in the product
|
||||||
|
documentation would be appreciated, but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and must
|
||||||
|
not be misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This Copyright notice may not be removed or altered from any
|
||||||
|
source or altered source distribution.
|
||||||
|
</pre>
|
||||||
|
|
||||||
<h3>LLVM - <a href="https://github.com/llvm/llvm-project">https://github.com/llvm/llvm-project</a></h3>
|
<h3>LLVM - <a href="https://github.com/llvm/llvm-project">https://github.com/llvm/llvm-project</a></h3>
|
||||||
<pre>
|
<pre>
|
||||||
Apache License
|
Apache License
|
||||||
|
@ -1580,11 +1652,6 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<h3>stb libraries - <a href="https://github.com/nothings/stb">https://github.com/nothings/stb</a></h3>
|
|
||||||
These libraries are in the public domain. You can do anything you want with them. You have no legal obligation to do anything else, although I appreciate attribution.
|
|
||||||
|
|
||||||
They are also licensed under the MIT open source license, if you have lawyers who are unhappy with public domain. Every source file includes an explicit dual-license for you to choose from.
|
|
||||||
|
|
||||||
<h3>vixl - <a href="https://git.linaro.org/arm/vixl.git">https://git.linaro.org/arm/vixl.git</a></h3>
|
<h3>vixl - <a href="https://git.linaro.org/arm/vixl.git">https://git.linaro.org/arm/vixl.git</a></h3>
|
||||||
<pre>
|
<pre>
|
||||||
LICENCE
|
LICENCE
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
set(FMT_INSTALL OFF CACHE BOOL "")
|
set(FMT_INSTALL OFF CACHE BOOL "")
|
||||||
add_subdirectory(fmt EXCLUDE_FROM_ALL)
|
add_subdirectory(fmt EXCLUDE_FROM_ALL)
|
||||||
disable_compiler_warnings_for_target(fmt)
|
disable_compiler_warnings_for_target(fmt)
|
||||||
add_subdirectory(stb EXCLUDE_FROM_ALL)
|
|
||||||
disable_compiler_warnings_for_target(stb)
|
|
||||||
add_subdirectory(minizip EXCLUDE_FROM_ALL)
|
add_subdirectory(minizip EXCLUDE_FROM_ALL)
|
||||||
disable_compiler_warnings_for_target(minizip)
|
disable_compiler_warnings_for_target(minizip)
|
||||||
add_subdirectory(lzma EXCLUDE_FROM_ALL)
|
add_subdirectory(lzma EXCLUDE_FROM_ALL)
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
set(SRCS
|
|
||||||
include/stb_image.h
|
|
||||||
include/stb_image_resize.h
|
|
||||||
include/stb_image_write.h
|
|
||||||
src/stb_image.c
|
|
||||||
src/stb_image_resize.c
|
|
||||||
src/stb_image_write.c
|
|
||||||
)
|
|
||||||
|
|
||||||
add_library(stb ${SRCS})
|
|
||||||
target_include_directories(stb PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
|
||||||
target_include_directories(stb INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
|
||||||
target_link_libraries(stb ZLIB::ZLIB Threads::Threads "${CMAKE_DL_LIBS}")
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,2 +0,0 @@
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
|
||||||
#include "stb_image.h"
|
|
|
@ -1,2 +0,0 @@
|
||||||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
|
||||||
#include "stb_image_resize.h"
|
|
|
@ -1,28 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "zlib.h"
|
|
||||||
|
|
||||||
// https://github.com/nothings/stb/issues/113
|
|
||||||
static unsigned char* compress_for_stbiw(unsigned char* data, int data_len, int* out_len, int quality)
|
|
||||||
{
|
|
||||||
uLongf buf_size = compressBound(data_len);
|
|
||||||
|
|
||||||
// note that buf will be free'd by stb_image_write.h
|
|
||||||
// with STBIW_FREE() (plain free() by default)
|
|
||||||
unsigned char* buf = malloc(buf_size);
|
|
||||||
if (buf == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (compress2(buf, &buf_size, data, data_len, quality) != Z_OK)
|
|
||||||
{
|
|
||||||
free(buf);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
*out_len = buf_size;
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define STBIW_ZLIB_COMPRESS compress_for_stbiw
|
|
||||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
||||||
#include "stb_image_write.h"
|
|
|
@ -1,30 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<Import Project="..\msvc\vsprops\Configurations.props" />
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="src\stb_image.c" />
|
|
||||||
<ClCompile Include="src\stb_image_resize.c" />
|
|
||||||
<ClCompile Include="src\stb_image_write.c" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="include\stb_image.h" />
|
|
||||||
<ClInclude Include="include\stb_image_resize.h" />
|
|
||||||
<ClInclude Include="include\stb_image_write.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>{ED601289-AC1A-46B8-A8ED-17DB9EB73423}</ProjectGuid>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<Import Project="..\msvc\vsprops\StaticLibrary.props" />
|
|
||||||
|
|
||||||
<ItemDefinitionGroup>
|
|
||||||
<ClCompile>
|
|
||||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)dep\zlib\include;$(ProjectDir)include;$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
|
||||||
</ClCompile>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
|
|
||||||
<Import Project="..\msvc\vsprops\Targets.props" />
|
|
||||||
</Project>
|
|
|
@ -1,13 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<ItemGroup>
|
|
||||||
<ClCompile Include="src\stb_image_write.c" />
|
|
||||||
<ClCompile Include="src\stb_image_resize.c" />
|
|
||||||
<ClCompile Include="src\stb_image.c" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<ClInclude Include="include\stb_image_write.h" />
|
|
||||||
<ClInclude Include="include\stb_image_resize.h" />
|
|
||||||
<ClInclude Include="include\stb_image.h" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
|
@ -13,8 +13,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "src\common\common
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "src\core\core.vcxproj", "{868B98C8-65A1-494B-8346-250A73A48C0A}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "src\core\core.vcxproj", "{868B98C8-65A1-494B-8346-250A73A48C0A}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "stb", "dep\stb\stb.vcxproj", "{ED601289-AC1A-46B8-A8ED-17DB9EB73423}"
|
|
||||||
EndProject
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simpleini", "dep\simpleini\simpleini.vcxproj", "{3773F4CC-614E-4028-8595-22E08CA649E3}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simpleini", "dep\simpleini\simpleini.vcxproj", "{3773F4CC-614E-4028-8595-22E08CA649E3}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "duckstation-qt", "src\duckstation-qt\duckstation-qt.vcxproj", "{28F14272-0EC4-41BB-849F-182ADB81AF70}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "duckstation-qt", "src\duckstation-qt\duckstation-qt.vcxproj", "{28F14272-0EC4-41BB-849F-182ADB81AF70}"
|
||||||
|
@ -223,38 +221,6 @@ Global
|
||||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.ReleaseLTCG-Clang|ARM64.Build.0 = ReleaseLTCG-Clang|ARM64
|
{868B98C8-65A1-494B-8346-250A73A48C0A}.ReleaseLTCG-Clang|ARM64.Build.0 = ReleaseLTCG-Clang|ARM64
|
||||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.ReleaseLTCG-Clang|x64.ActiveCfg = ReleaseLTCG-Clang|x64
|
{868B98C8-65A1-494B-8346-250A73A48C0A}.ReleaseLTCG-Clang|x64.ActiveCfg = ReleaseLTCG-Clang|x64
|
||||||
{868B98C8-65A1-494B-8346-250A73A48C0A}.ReleaseLTCG-Clang|x64.Build.0 = ReleaseLTCG-Clang|x64
|
{868B98C8-65A1-494B-8346-250A73A48C0A}.ReleaseLTCG-Clang|x64.Build.0 = ReleaseLTCG-Clang|x64
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Debug|ARM64.Build.0 = Debug|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Debug|x64.ActiveCfg = Debug|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Debug-Clang|ARM64.ActiveCfg = Debug-Clang|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Debug-Clang|ARM64.Build.0 = Debug-Clang|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Debug-Clang|x64.ActiveCfg = Debug-Clang|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Debug-Clang|x64.Build.0 = Debug-Clang|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.DebugFast|ARM64.ActiveCfg = DebugFast|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.DebugFast|ARM64.Build.0 = DebugFast|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.DebugFast|x64.Build.0 = DebugFast|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.DebugFast-Clang|ARM64.ActiveCfg = DebugFast-Clang|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.DebugFast-Clang|ARM64.Build.0 = DebugFast-Clang|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.DebugFast-Clang|x64.ActiveCfg = DebugFast-Clang|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.DebugFast-Clang|x64.Build.0 = DebugFast-Clang|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Release|ARM64.ActiveCfg = Release|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Release|ARM64.Build.0 = Release|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Release|x64.ActiveCfg = Release|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Release|x64.Build.0 = Release|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Release-Clang|ARM64.ActiveCfg = Release-Clang|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Release-Clang|ARM64.Build.0 = Release-Clang|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Release-Clang|x64.ActiveCfg = Release-Clang|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.Release-Clang|x64.Build.0 = Release-Clang|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.ReleaseLTCG|ARM64.ActiveCfg = ReleaseLTCG|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.ReleaseLTCG|ARM64.Build.0 = ReleaseLTCG|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.ReleaseLTCG|x64.ActiveCfg = ReleaseLTCG|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.ReleaseLTCG|x64.Build.0 = ReleaseLTCG|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.ReleaseLTCG-Clang|ARM64.ActiveCfg = ReleaseLTCG-Clang|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.ReleaseLTCG-Clang|ARM64.Build.0 = ReleaseLTCG-Clang|ARM64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.ReleaseLTCG-Clang|x64.ActiveCfg = ReleaseLTCG-Clang|x64
|
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423}.ReleaseLTCG-Clang|x64.Build.0 = ReleaseLTCG-Clang|x64
|
|
||||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
{3773F4CC-614E-4028-8595-22E08CA649E3}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Debug|ARM64.Build.0 = Debug|ARM64
|
{3773F4CC-614E-4028-8595-22E08CA649E3}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
{3773F4CC-614E-4028-8595-22E08CA649E3}.Debug|x64.ActiveCfg = Debug|x64
|
{3773F4CC-614E-4028-8595-22E08CA649E3}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
@ -1140,7 +1106,6 @@ Global
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{43540154-9E1E-409C-834F-B84BE5621388} = {BA490C0E-497D-4634-A21E-E65012006385}
|
{43540154-9E1E-409C-834F-B84BE5621388} = {BA490C0E-497D-4634-A21E-E65012006385}
|
||||||
{BB08260F-6FBC-46AF-8924-090EE71360C6} = {BA490C0E-497D-4634-A21E-E65012006385}
|
{BB08260F-6FBC-46AF-8924-090EE71360C6} = {BA490C0E-497D-4634-A21E-E65012006385}
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423} = {BA490C0E-497D-4634-A21E-E65012006385}
|
|
||||||
{3773F4CC-614E-4028-8595-22E08CA649E3} = {BA490C0E-497D-4634-A21E-E65012006385}
|
{3773F4CC-614E-4028-8595-22E08CA649E3} = {BA490C0E-497D-4634-A21E-E65012006385}
|
||||||
{72F9423C-91EE-4487-AAC6-555ED6F61AA1} = {BA490C0E-497D-4634-A21E-E65012006385}
|
{72F9423C-91EE-4487-AAC6-555ED6F61AA1} = {BA490C0E-497D-4634-A21E-E65012006385}
|
||||||
{8BDA439C-6358-45FB-9994-2FF083BABE06} = {BA490C0E-497D-4634-A21E-E65012006385}
|
{8BDA439C-6358-45FB-9994-2FF083BABE06} = {BA490C0E-497D-4634-A21E-E65012006385}
|
||||||
|
|
|
@ -131,7 +131,7 @@ target_precompile_headers(core PRIVATE "pch.h")
|
||||||
target_include_directories(core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
target_include_directories(core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
||||||
target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
||||||
target_link_libraries(core PUBLIC Threads::Threads common util ZLIB::ZLIB)
|
target_link_libraries(core PUBLIC Threads::Threads common util ZLIB::ZLIB)
|
||||||
target_link_libraries(core PRIVATE stb xxhash imgui rapidyaml rcheevos)
|
target_link_libraries(core PRIVATE xxhash imgui rapidyaml rcheevos)
|
||||||
|
|
||||||
if(CPU_ARCH_X64)
|
if(CPU_ARCH_X64)
|
||||||
target_compile_definitions(core PUBLIC "ENABLE_RECOMPILER=1" "ENABLE_NEWREC=1" "ENABLE_MMAP_FASTMEM=1")
|
target_compile_definitions(core PUBLIC "ENABLE_RECOMPILER=1" "ENABLE_NEWREC=1" "ENABLE_MMAP_FASTMEM=1")
|
||||||
|
|
|
@ -178,9 +178,6 @@
|
||||||
<ProjectReference Include="..\..\dep\rcheevos\rcheevos.vcxproj">
|
<ProjectReference Include="..\..\dep\rcheevos\rcheevos.vcxproj">
|
||||||
<Project>{4ba0a6d4-3ae1-42b2-9347-096fd023ff64}</Project>
|
<Project>{4ba0a6d4-3ae1-42b2-9347-096fd023ff64}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\..\dep\stb\stb.vcxproj">
|
|
||||||
<Project>{ed601289-ac1a-46b8-a8ed-17db9eb73423}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\..\dep\vixl\vixl.vcxproj" Condition="'$(Platform)'=='ARM64'">
|
<ProjectReference Include="..\..\dep\vixl\vixl.vcxproj" Condition="'$(Platform)'=='ARM64'">
|
||||||
<Project>{8906836e-f06e-46e8-b11a-74e5e8c7b8fb}</Project>
|
<Project>{8906836e-f06e-46e8-b11a-74e5e8c7b8fb}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
|
|
@ -77,7 +77,7 @@ target_precompile_headers(util PRIVATE "pch.h")
|
||||||
target_include_directories(util PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
target_include_directories(util PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
||||||
target_include_directories(util PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
target_include_directories(util PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
||||||
target_link_libraries(util PUBLIC common simpleini imgui)
|
target_link_libraries(util PUBLIC common simpleini imgui)
|
||||||
target_link_libraries(util PRIVATE stb libchdr ZLIB::ZLIB soundtouch xxhash Zstd::Zstd reshadefx)
|
target_link_libraries(util PRIVATE libchdr JPEG::JPEG PNG::PNG ZLIB::ZLIB soundtouch xxhash Zstd::Zstd reshadefx)
|
||||||
|
|
||||||
if(ENABLE_CUBEB)
|
if(ENABLE_CUBEB)
|
||||||
target_sources(util PRIVATE
|
target_sources(util PRIVATE
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
|
||||||
|
#include "common/bitutils.h"
|
||||||
#include "common/byte_stream.h"
|
#include "common/byte_stream.h"
|
||||||
#include "common/file_system.h"
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
|
@ -10,50 +11,41 @@
|
||||||
#include "common/scoped_guard.h"
|
#include "common/scoped_guard.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
|
|
||||||
#include "stb_image.h"
|
#include <jpeglib.h>
|
||||||
#include "stb_image_resize.h"
|
#include <png.h>
|
||||||
#include "stb_image_write.h"
|
|
||||||
|
// clang-format off
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
|
||||||
|
#pragma warning(disable : 4324) // warning C4324: '`anonymous-namespace'::JPEGErrorHandler': structure was padded due to alignment specifier
|
||||||
|
#endif
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
Log_SetChannel(Image);
|
Log_SetChannel(Image);
|
||||||
|
|
||||||
#if 0
|
|
||||||
static bool PNGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size);
|
static bool PNGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size);
|
||||||
static bool PNGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, int quality);
|
static bool PNGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, u8 quality);
|
||||||
static bool PNGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp);
|
static bool PNGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp);
|
||||||
static bool PNGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality);
|
static bool PNGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, u8 quality);
|
||||||
|
|
||||||
static bool JPEGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size);
|
static bool JPEGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size);
|
||||||
static bool JPEGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, int quality);
|
static bool JPEGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, u8 quality);
|
||||||
static bool JPEGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp);
|
static bool JPEGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp);
|
||||||
static bool JPEGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality);
|
static bool JPEGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, u8 quality);
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool STBBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size);
|
|
||||||
static bool STBFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp);
|
|
||||||
static bool STBBufferSaverPNG(const RGBA8Image& image, std::vector<u8>* buffer, int quality);
|
|
||||||
static bool STBBufferSaverJPEG(const RGBA8Image& image, std::vector<u8>* buffer, int quality);
|
|
||||||
static bool STBFileSaverPNG(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality);
|
|
||||||
static bool STBFileSaverJPEG(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality);
|
|
||||||
|
|
||||||
struct FormatHandler
|
struct FormatHandler
|
||||||
{
|
{
|
||||||
const char* extension;
|
const char* extension;
|
||||||
bool (*buffer_loader)(RGBA8Image*, const void*, size_t);
|
bool (*buffer_loader)(RGBA8Image*, const void*, size_t);
|
||||||
bool (*buffer_saver)(const RGBA8Image&, std::vector<u8>*, int);
|
bool (*buffer_saver)(const RGBA8Image&, std::vector<u8>*, u8);
|
||||||
bool (*file_loader)(RGBA8Image*, const char*, std::FILE*);
|
bool (*file_loader)(RGBA8Image*, const char*, std::FILE*);
|
||||||
bool (*file_saver)(const RGBA8Image&, const char*, std::FILE*, int);
|
bool (*file_saver)(const RGBA8Image&, const char*, std::FILE*, u8);
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr FormatHandler s_format_handlers[] = {
|
static constexpr FormatHandler s_format_handlers[] = {
|
||||||
#if 0
|
|
||||||
{"png", PNGBufferLoader, PNGBufferSaver, PNGFileLoader, PNGFileSaver},
|
{"png", PNGBufferLoader, PNGBufferSaver, PNGFileLoader, PNGFileSaver},
|
||||||
{"jpg", JPEGBufferLoader, JPEGBufferSaver, JPEGFileLoader, JPEGFileSaver},
|
{"jpg", JPEGBufferLoader, JPEGBufferSaver, JPEGFileLoader, JPEGFileSaver},
|
||||||
{"jpeg", JPEGBufferLoader, JPEGBufferSaver, JPEGFileLoader, JPEGFileSaver},
|
{"jpeg", JPEGBufferLoader, JPEGBufferSaver, JPEGFileLoader, JPEGFileSaver},
|
||||||
#else
|
|
||||||
{"png", STBBufferLoader, STBBufferSaverPNG, STBFileLoader, STBFileSaverPNG},
|
|
||||||
{"jpg", STBBufferLoader, STBBufferSaverJPEG, STBFileLoader, STBFileSaverJPEG},
|
|
||||||
{"jpeg", STBBufferLoader, STBBufferSaverJPEG, STBFileLoader, STBFileSaverJPEG},
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const FormatHandler* GetFormatHandler(const std::string_view& extension)
|
static const FormatHandler* GetFormatHandler(const std::string_view& extension)
|
||||||
|
@ -110,7 +102,7 @@ bool RGBA8Image::LoadFromFile(const char* filename)
|
||||||
return LoadFromFile(filename, fp.get());
|
return LoadFromFile(filename, fp.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RGBA8Image::SaveToFile(const char* filename, int quality) const
|
bool RGBA8Image::SaveToFile(const char* filename, u8 quality) const
|
||||||
{
|
{
|
||||||
auto fp = FileSystem::OpenManagedCFile(filename, "wb");
|
auto fp = FileSystem::OpenManagedCFile(filename, "wb");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
|
@ -151,7 +143,7 @@ bool RGBA8Image::LoadFromBuffer(const char* filename, const void* buffer, size_t
|
||||||
return handler->buffer_loader(this, buffer, buffer_size);
|
return handler->buffer_loader(this, buffer, buffer_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RGBA8Image::SaveToFile(const char* filename, std::FILE* fp, int quality) const
|
bool RGBA8Image::SaveToFile(const char* filename, std::FILE* fp, u8 quality) const
|
||||||
{
|
{
|
||||||
const std::string_view extension(Path::GetExtension(filename));
|
const std::string_view extension(Path::GetExtension(filename));
|
||||||
const FormatHandler* handler = GetFormatHandler(extension);
|
const FormatHandler* handler = GetFormatHandler(extension);
|
||||||
|
@ -167,7 +159,7 @@ bool RGBA8Image::SaveToFile(const char* filename, std::FILE* fp, int quality) co
|
||||||
return (std::fflush(fp) == 0);
|
return (std::fflush(fp) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::vector<u8>> RGBA8Image::SaveToBuffer(const char* filename, int quality) const
|
std::optional<std::vector<u8>> RGBA8Image::SaveToBuffer(const char* filename, u8 quality) const
|
||||||
{
|
{
|
||||||
std::optional<std::vector<u8>> ret;
|
std::optional<std::vector<u8>> ret;
|
||||||
|
|
||||||
|
@ -186,6 +178,8 @@ std::optional<std::vector<u8>> RGBA8Image::SaveToBuffer(const char* filename, in
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
void RGBA8Image::Resize(u32 new_width, u32 new_height)
|
void RGBA8Image::Resize(u32 new_width, u32 new_height)
|
||||||
{
|
{
|
||||||
if (m_width == new_width && m_height == new_height)
|
if (m_width == new_width && m_height == new_height)
|
||||||
|
@ -222,7 +216,7 @@ void RGBA8Image::Resize(const RGBA8Image* src_image, u32 new_width, u32 new_heig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#endif
|
||||||
|
|
||||||
static bool PNGCommonLoader(RGBA8Image* image, png_structp png_ptr, png_infop info_ptr, std::vector<u32>& new_data,
|
static bool PNGCommonLoader(RGBA8Image* image, png_structp png_ptr, png_infop info_ptr, std::vector<u32>& new_data,
|
||||||
std::vector<png_bytep>& row_pointers)
|
std::vector<png_bytep>& row_pointers)
|
||||||
|
@ -336,7 +330,7 @@ bool PNGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size)
|
||||||
return PNGCommonLoader(image, png_ptr, info_ptr, new_data, row_pointers);
|
return PNGCommonLoader(image, png_ptr, info_ptr, new_data, row_pointers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PNGSaveCommon(const RGBA8Image& image, png_structp png_ptr, png_infop info_ptr, int quality)
|
static void PNGSaveCommon(const RGBA8Image& image, png_structp png_ptr, png_infop info_ptr, u8 quality)
|
||||||
{
|
{
|
||||||
png_set_compression_level(png_ptr, std::clamp(quality / 10, 0, 9));
|
png_set_compression_level(png_ptr, std::clamp(quality / 10, 0, 9));
|
||||||
png_set_IHDR(png_ptr, info_ptr, image.GetWidth(), image.GetHeight(), 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
|
png_set_IHDR(png_ptr, info_ptr, image.GetWidth(), image.GetHeight(), 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
|
||||||
|
@ -349,7 +343,7 @@ static void PNGSaveCommon(const RGBA8Image& image, png_structp png_ptr, png_info
|
||||||
png_write_end(png_ptr, nullptr);
|
png_write_end(png_ptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PNGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality)
|
bool PNGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, u8 quality)
|
||||||
{
|
{
|
||||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||||
png_infop info_ptr = nullptr;
|
png_infop info_ptr = nullptr;
|
||||||
|
@ -380,7 +374,7 @@ bool PNGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PNGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, int quality)
|
bool PNGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, u8 quality)
|
||||||
{
|
{
|
||||||
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||||
png_infop info_ptr = nullptr;
|
png_infop info_ptr = nullptr;
|
||||||
|
@ -415,245 +409,200 @@ bool PNGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, int qualit
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JPEGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size)
|
namespace {
|
||||||
|
struct JPEGErrorHandler
|
||||||
{
|
{
|
||||||
int width, height, file_comps;
|
jpeg_error_mgr err;
|
||||||
u8* data = jpgd::decompress_jpeg_image_from_memory(static_cast<const u8*>(buffer), static_cast<int>(buffer_size),
|
jmp_buf jbuf;
|
||||||
&width, &height, &file_comps, 4, 0);
|
};
|
||||||
if (!data)
|
} // namespace
|
||||||
|
|
||||||
|
static bool HandleJPEGError(JPEGErrorHandler* eh)
|
||||||
|
{
|
||||||
|
jpeg_std_error(&eh->err);
|
||||||
|
|
||||||
|
eh->err.error_exit = [](j_common_ptr cinfo) {
|
||||||
|
JPEGErrorHandler* eh = (JPEGErrorHandler*)cinfo->err;
|
||||||
|
char msg[JMSG_LENGTH_MAX];
|
||||||
|
eh->err.format_message(cinfo, msg);
|
||||||
|
Log_ErrorFmt("libjpeg fatal error: {}", msg);
|
||||||
|
longjmp(eh->jbuf, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (setjmp(eh->jbuf) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static bool WrapJPEGDecompress(RGBA8Image* image, T setup_func)
|
||||||
|
{
|
||||||
|
std::vector<u8> scanline;
|
||||||
|
|
||||||
|
JPEGErrorHandler err;
|
||||||
|
if (!HandleJPEGError(&err))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
jpeg_decompress_struct info;
|
||||||
|
info.err = &err.err;
|
||||||
|
jpeg_create_decompress(&info);
|
||||||
|
setup_func(info);
|
||||||
|
|
||||||
|
const int herr = jpeg_read_header(&info, TRUE);
|
||||||
|
if (herr != JPEG_HEADER_OK)
|
||||||
{
|
{
|
||||||
Console.Error("jpgd::decompress_jpeg_image_from_memory() failed");
|
Log_ErrorFmt("jpeg_read_header() returned {}", herr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
image->SetPixels(static_cast<u32>(width), static_cast<u32>(height), reinterpret_cast<const u32*>(data));
|
if (info.image_width == 0 || info.image_height == 0 || info.num_components < 3)
|
||||||
std::free(data);
|
{
|
||||||
return true;
|
Log_ErrorFmt("Invalid image dimensions: {}x{}x{}", info.image_width, info.image_height, info.num_components);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.out_color_space = JCS_RGB;
|
||||||
|
info.out_color_components = 3;
|
||||||
|
|
||||||
|
if (!jpeg_start_decompress(&info))
|
||||||
|
{
|
||||||
|
Log_ErrorFmt("jpeg_start_decompress() returned failure");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
image->SetSize(info.image_width, info.image_height);
|
||||||
|
scanline.resize(info.image_width * 3);
|
||||||
|
|
||||||
|
u8* scanline_buffer[1] = {scanline.data()};
|
||||||
|
bool result = true;
|
||||||
|
for (u32 y = 0; y < info.image_height; y++)
|
||||||
|
{
|
||||||
|
if (jpeg_read_scanlines(&info, scanline_buffer, 1) != 1)
|
||||||
|
{
|
||||||
|
Log_ErrorFmt("jpeg_read_scanlines() failed at row {}", y);
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RGB -> RGBA
|
||||||
|
const u8* src_ptr = scanline.data();
|
||||||
|
u32* dst_ptr = image->GetRowPixels(y);
|
||||||
|
for (u32 x = 0; x < info.image_width; x++)
|
||||||
|
{
|
||||||
|
*(dst_ptr) =
|
||||||
|
(ZeroExtend32(src_ptr[0]) | (ZeroExtend32(src_ptr[1]) << 8) | (ZeroExtend32(src_ptr[2]) << 16) | 0xFF000000u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jpeg_finish_decompress(&info);
|
||||||
|
jpeg_destroy_decompress(&info);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JPEGBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size)
|
||||||
|
{
|
||||||
|
return WrapJPEGDecompress(image, [buffer, buffer_size](jpeg_decompress_struct& info) {
|
||||||
|
jpeg_mem_src(&info, static_cast<const unsigned char*>(buffer), buffer_size);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JPEGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp)
|
bool JPEGFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp)
|
||||||
{
|
{
|
||||||
class FileStream : public jpgd::jpeg_decoder_stream
|
return WrapJPEGDecompress(image, [fp](jpeg_decompress_struct& info) { jpeg_stdio_src(&info, fp); });
|
||||||
{
|
|
||||||
std::FILE* m_fp;
|
|
||||||
bool m_error_flag = false;
|
|
||||||
bool m_eof_flag = false;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FileStream(std::FILE* fp_) : m_fp(fp_) {}
|
|
||||||
|
|
||||||
int read(jpgd::uint8* pBuf, int max_bytes_to_read, bool* pEOF_flag) override
|
|
||||||
{
|
|
||||||
if (m_eof_flag)
|
|
||||||
{
|
|
||||||
*pEOF_flag = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_error_flag)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
int bytes_read = static_cast<int>(std::fread(pBuf, 1, max_bytes_to_read, m_fp));
|
|
||||||
if (bytes_read < max_bytes_to_read)
|
|
||||||
{
|
|
||||||
if (std::ferror(m_fp))
|
|
||||||
{
|
|
||||||
m_error_flag = true;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_eof_flag = true;
|
|
||||||
*pEOF_flag = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytes_read;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
FileStream stream(fp);
|
|
||||||
int width, height, file_comps;
|
|
||||||
u8* data = jpgd::decompress_jpeg_image_from_stream(&stream, &width, &height, &file_comps, 4, 0);
|
|
||||||
if (!data)
|
|
||||||
{
|
|
||||||
Console.Error("jpgd::decompress_jpeg_image_from_stream() failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
image->SetPixels(static_cast<u32>(width), static_cast<u32>(height), reinterpret_cast<const u32*>(data));
|
|
||||||
std::free(data);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool JPEGCommonSaver(const RGBA8Image& image, jpge::output_stream& stream, int quality)
|
template<typename T>
|
||||||
|
static bool WrapJPEGCompress(const RGBA8Image& image, u8 quality, T setup_func)
|
||||||
{
|
{
|
||||||
jpge::params params;
|
std::vector<u8> scanline;
|
||||||
params.m_quality = quality;
|
|
||||||
|
|
||||||
jpge::jpeg_encoder dst_image;
|
JPEGErrorHandler err;
|
||||||
if (!dst_image.init(&stream, image.GetWidth(), image.GetHeight(), 3, params))
|
if (!HandleJPEGError(&err))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// for RGBA->RGB
|
jpeg_compress_struct info;
|
||||||
std::vector<u8> row;
|
info.err = &err.err;
|
||||||
row.resize(image.GetWidth() * 3);
|
jpeg_create_compress(&info);
|
||||||
|
setup_func(info);
|
||||||
|
|
||||||
for (uint pass_index = 0; pass_index < dst_image.get_total_passes(); pass_index++)
|
info.image_width = image.GetWidth();
|
||||||
|
info.image_height = image.GetHeight();
|
||||||
|
info.in_color_space = JCS_RGB;
|
||||||
|
info.input_components = 3;
|
||||||
|
|
||||||
|
jpeg_set_defaults(&info);
|
||||||
|
jpeg_set_quality(&info, quality, TRUE);
|
||||||
|
jpeg_start_compress(&info, TRUE);
|
||||||
|
|
||||||
|
scanline.resize(image.GetWidth() * 3);
|
||||||
|
u8* scanline_buffer[1] = {scanline.data()};
|
||||||
|
bool result = true;
|
||||||
|
for (u32 y = 0; y < info.image_height; y++)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < image.GetHeight(); i++)
|
// RGBA -> RGB
|
||||||
|
u8* dst_ptr = scanline.data();
|
||||||
|
const u32* src_ptr = image.GetRowPixels(y);
|
||||||
|
for (u32 x = 0; x < info.image_width; x++)
|
||||||
{
|
{
|
||||||
const u8* row_in = reinterpret_cast<const u8*>(image.GetRowPixels(i));
|
const u32 rgba = *(src_ptr++);
|
||||||
u8* row_out = row.data();
|
*(dst_ptr++) = Truncate8(rgba);
|
||||||
for (u32 j = 0; j < image.GetWidth(); j++)
|
*(dst_ptr++) = Truncate8(rgba >> 8);
|
||||||
{
|
*(dst_ptr++) = Truncate8(rgba >> 16);
|
||||||
*(row_out++) = *(row_in++);
|
}
|
||||||
*(row_out++) = *(row_in++);
|
|
||||||
*(row_out++) = *(row_in++);
|
if (jpeg_write_scanlines(&info, scanline_buffer, 1) != 1)
|
||||||
row_in++;
|
{
|
||||||
}
|
Log_ErrorFmt("jpeg_write_scanlines() failed at row {}", y);
|
||||||
|
result = false;
|
||||||
if (!dst_image.process_scanline(row.data()))
|
break;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (!dst_image.process_scanline(NULL))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dst_image.deinit();
|
jpeg_finish_compress(&info);
|
||||||
|
jpeg_destroy_compress(&info);
|
||||||
return true;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JPEGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, int quality)
|
bool JPEGBufferSaver(const RGBA8Image& image, std::vector<u8>* buffer, u8 quality)
|
||||||
{
|
{
|
||||||
class BufferStream : public jpge::output_stream
|
|
||||||
{
|
|
||||||
std::vector<u8>* buffer;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit BufferStream(std::vector<u8>* buffer_) : buffer(buffer_) {}
|
|
||||||
|
|
||||||
bool put_buf(const void* Pbuf, int len) override
|
|
||||||
{
|
|
||||||
const size_t old_size = buffer->size();
|
|
||||||
buffer->resize(buffer->size() + static_cast<size_t>(len));
|
|
||||||
std::memcpy(buffer->data() + old_size, Pbuf, static_cast<size_t>(len));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// give enough space to avoid reallocs
|
// give enough space to avoid reallocs
|
||||||
buffer->reserve(image.GetWidth() * image.GetHeight() * 2);
|
buffer->resize(image.GetWidth() * image.GetHeight() * 2);
|
||||||
|
|
||||||
BufferStream stream(buffer);
|
struct MemCallback
|
||||||
return JPEGCommonSaver(image, stream, quality);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool JPEGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality)
|
|
||||||
{
|
|
||||||
class FileStream : public jpge::output_stream
|
|
||||||
{
|
{
|
||||||
std::FILE* m_fp;
|
jpeg_destination_mgr mgr;
|
||||||
bool m_error_flag = false;
|
std::vector<u8>* buffer;
|
||||||
|
size_t buffer_used;
|
||||||
public:
|
|
||||||
explicit FileStream(std::FILE* fp_) : m_fp(fp_) {}
|
|
||||||
|
|
||||||
bool put_buf(const void* Pbuf, int len) override
|
|
||||||
{
|
|
||||||
if (m_error_flag)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (std::fwrite(Pbuf, len, 1, m_fp) != 1)
|
|
||||||
{
|
|
||||||
m_error_flag = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FileStream stream(fp);
|
MemCallback cb;
|
||||||
return JPEGCommonSaver(image, stream, quality);
|
cb.buffer = buffer;
|
||||||
}
|
cb.buffer_used = 0;
|
||||||
|
cb.mgr.next_output_byte = buffer->data();
|
||||||
|
cb.mgr.free_in_buffer = buffer->size();
|
||||||
|
cb.mgr.init_destination = [](j_compress_ptr cinfo) {};
|
||||||
|
cb.mgr.empty_output_buffer = [](j_compress_ptr cinfo) -> boolean {
|
||||||
|
MemCallback* cb = (MemCallback*)cinfo->dest;
|
||||||
|
|
||||||
#endif
|
// double size
|
||||||
|
cb->buffer_used = cb->buffer->size();
|
||||||
|
cb->buffer->resize(cb->buffer->size() * 2);
|
||||||
|
cb->mgr.next_output_byte = cb->buffer->data() + cb->buffer_used;
|
||||||
|
cb->mgr.free_in_buffer = cb->buffer->size() - cb->buffer_used;
|
||||||
|
return TRUE;
|
||||||
|
};
|
||||||
|
cb.mgr.term_destination = [](j_compress_ptr cinfo) {
|
||||||
|
MemCallback* cb = (MemCallback*)cinfo->dest;
|
||||||
|
|
||||||
bool STBBufferLoader(RGBA8Image* image, const void* buffer, size_t buffer_size)
|
// get final size
|
||||||
{
|
cb->buffer->resize(cb->buffer->size() - cb->mgr.free_in_buffer);
|
||||||
int width, height, file_channels;
|
|
||||||
u8* pixel_data = stbi_load_from_memory(static_cast<const stbi_uc*>(buffer), static_cast<int>(buffer_size), &width,
|
|
||||||
&height, &file_channels, 4);
|
|
||||||
if (!pixel_data)
|
|
||||||
{
|
|
||||||
const char* error_reason = stbi_failure_reason();
|
|
||||||
Log_ErrorPrintf("Failed to load image from memory: %s", error_reason ? error_reason : "unknown error");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
image->SetPixels(static_cast<u32>(width), static_cast<u32>(height), reinterpret_cast<const u32*>(pixel_data));
|
|
||||||
stbi_image_free(pixel_data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool STBFileLoader(RGBA8Image* image, const char* filename, std::FILE* fp)
|
|
||||||
{
|
|
||||||
int width, height, file_channels;
|
|
||||||
u8* pixel_data = stbi_load_from_file(fp, &width, &height, &file_channels, 4);
|
|
||||||
if (!pixel_data)
|
|
||||||
{
|
|
||||||
const char* error_reason = stbi_failure_reason();
|
|
||||||
Log_ErrorPrintf("Failed to load image from memory: %s", error_reason ? error_reason : "unknown error");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
image->SetPixels(static_cast<u32>(width), static_cast<u32>(height), reinterpret_cast<const u32*>(pixel_data));
|
|
||||||
stbi_image_free(pixel_data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool STBBufferSaverPNG(const RGBA8Image& image, std::vector<u8>* buffer, int quality)
|
|
||||||
{
|
|
||||||
const auto write_func = [](void* context, void* data, int size) {
|
|
||||||
std::vector<u8>* buffer = reinterpret_cast<std::vector<u8>*>(data);
|
|
||||||
const u32 len = static_cast<u32>(size);
|
|
||||||
buffer->resize(buffer->size() + len);
|
|
||||||
std::memcpy(buffer->data(), data, len);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (stbi_write_png_to_func(write_func, buffer, image.GetWidth(), image.GetHeight(), 4, image.GetPixels(),
|
return WrapJPEGCompress(image, quality, [&cb](jpeg_compress_struct& info) { info.dest = &cb.mgr; });
|
||||||
image.GetPitch()) != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool STBBufferSaverJPEG(const RGBA8Image& image, std::vector<u8>* buffer, int quality)
|
bool JPEGFileSaver(const RGBA8Image& image, const char* filename, std::FILE* fp, u8 quality)
|
||||||
{
|
{
|
||||||
const auto write_func = [](void* context, void* data, int size) {
|
return WrapJPEGCompress(image, quality, [fp](jpeg_compress_struct& info) { jpeg_stdio_dest(&info, fp); });
|
||||||
std::vector<u8>* buffer = reinterpret_cast<std::vector<u8>*>(data);
|
|
||||||
const u32 len = static_cast<u32>(size);
|
|
||||||
buffer->resize(buffer->size() + len);
|
|
||||||
std::memcpy(buffer->data(), data, len);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (stbi_write_jpg_to_func(write_func, buffer, image.GetWidth(), image.GetHeight(), 4, image.GetPixels(),
|
|
||||||
quality) != 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool STBFileSaverPNG(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality)
|
|
||||||
{
|
|
||||||
const auto write_func = [](void* context, void* data, int size) {
|
|
||||||
std::fwrite(data, 1, size, static_cast<std::FILE*>(context));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (stbi_write_png_to_func(write_func, fp, image.GetWidth(), image.GetHeight(), 4, image.GetPixels(),
|
|
||||||
image.GetPitch()) != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool STBFileSaverJPEG(const RGBA8Image& image, const char* filename, std::FILE* fp, int quality)
|
|
||||||
{
|
|
||||||
const auto write_func = [](void* context, void* data, int size) {
|
|
||||||
std::fwrite(data, 1, size, static_cast<std::FILE*>(context));
|
|
||||||
};
|
|
||||||
|
|
||||||
return (stbi_write_jpg_to_func(write_func, fp, image.GetWidth(), image.GetHeight(), 4, image.GetPixels(), quality) !=
|
|
||||||
0);
|
|
||||||
}
|
|
|
@ -114,7 +114,7 @@ protected:
|
||||||
class RGBA8Image : public Image<u32>
|
class RGBA8Image : public Image<u32>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static constexpr int DEFAULT_SAVE_QUALITY = 85;
|
static constexpr u8 DEFAULT_SAVE_QUALITY = 85;
|
||||||
|
|
||||||
RGBA8Image();
|
RGBA8Image();
|
||||||
RGBA8Image(u32 width, u32 height);
|
RGBA8Image(u32 width, u32 height);
|
||||||
|
@ -130,10 +130,7 @@ public:
|
||||||
bool LoadFromFile(const char* filename, std::FILE* fp);
|
bool LoadFromFile(const char* filename, std::FILE* fp);
|
||||||
bool LoadFromBuffer(const char* filename, const void* buffer, size_t buffer_size);
|
bool LoadFromBuffer(const char* filename, const void* buffer, size_t buffer_size);
|
||||||
|
|
||||||
bool SaveToFile(const char* filename, int quality = DEFAULT_SAVE_QUALITY) const;
|
bool SaveToFile(const char* filename, u8 quality = DEFAULT_SAVE_QUALITY) const;
|
||||||
bool SaveToFile(const char* filename, std::FILE* fp, int quality = DEFAULT_SAVE_QUALITY) const;
|
bool SaveToFile(const char* filename, std::FILE* fp, u8 quality = DEFAULT_SAVE_QUALITY) const;
|
||||||
std::optional<std::vector<u8>> SaveToBuffer(const char* filename, int quality = DEFAULT_SAVE_QUALITY) const;
|
std::optional<std::vector<u8>> SaveToBuffer(const char* filename, u8 quality = DEFAULT_SAVE_QUALITY) const;
|
||||||
|
|
||||||
void Resize(u32 new_width, u32 new_height);
|
|
||||||
void Resize(const RGBA8Image* src_image, u32 new_width, u32 new_height);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<PreprocessorDefinitions>ENABLE_CUBEB=1;ENABLE_SDL2=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>ENABLE_CUBEB=1;ENABLE_SDL2=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PreprocessorDefinitions Condition="'$(Platform)'!='ARM64'">%(PreprocessorDefinitions);ENABLE_OPENGL=1;ENABLE_VULKAN=1</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="'$(Platform)'!='ARM64'">%(PreprocessorDefinitions);ENABLE_OPENGL=1;ENABLE_VULKAN=1</PreprocessorDefinitions>
|
||||||
<PreprocessorDefinitions Condition="'$(Platform)'=='ARM64'">%(PreprocessorDefinitions);SOUNDTOUCH_USE_NEON</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="'$(Platform)'=='ARM64'">%(PreprocessorDefinitions);SOUNDTOUCH_USE_NEON</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\soundtouch\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\simpleini\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\d3d12ma\include;$(SolutionDir)dep\zstd\lib;$(SolutionDir)dep\stb\include</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\soundtouch\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\simpleini\include;$(SolutionDir)dep\libchdr\include;$(SolutionDir)dep\cubeb\include;$(SolutionDir)dep\d3d12ma\include;$(SolutionDir)dep\zstd\lib;$(SolutionDir)dep\libpng\include;$(SolutionDir)dep\libjpeg\include</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories Condition="'$(Platform)'!='ARM64'">%(AdditionalIncludeDirectories);$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan\include;$(SolutionDir)dep\glslang</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories Condition="'$(Platform)'!='ARM64'">%(AdditionalIncludeDirectories);$(SolutionDir)dep\glad\include;$(SolutionDir)dep\vulkan\include;$(SolutionDir)dep\glslang</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
|
|
@ -253,6 +253,12 @@
|
||||||
<ProjectReference Include="..\..\dep\libchdr\libchdr.vcxproj">
|
<ProjectReference Include="..\..\dep\libchdr\libchdr.vcxproj">
|
||||||
<Project>{425d6c99-d1c8-43c2-b8ac-4d7b1d941017}</Project>
|
<Project>{425d6c99-d1c8-43c2-b8ac-4d7b1d941017}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\dep\libjpeg\libjpeg.vcxproj">
|
||||||
|
<Project>{ec3b6685-0b6e-4767-84ab-39b75eead2e2}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\dep\libpng\libpng.vcxproj">
|
||||||
|
<Project>{9fd2abcd-2dcd-4302-be5c-df0ba8431fa5}</Project>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\..\dep\reshadefx\reshadefx.vcxproj">
|
<ProjectReference Include="..\..\dep\reshadefx\reshadefx.vcxproj">
|
||||||
<Project>{27b8d4bb-4f01-4432-bc14-9bf6ca458eee}</Project>
|
<Project>{27b8d4bb-4f01-4432-bc14-9bf6ca458eee}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
@ -265,9 +271,6 @@
|
||||||
<ProjectReference Include="..\..\dep\glslang\glslang.vcxproj" Condition="'$(Platform)'!='ARM64'">
|
<ProjectReference Include="..\..\dep\glslang\glslang.vcxproj" Condition="'$(Platform)'!='ARM64'">
|
||||||
<Project>{7f909e29-4808-4bd9-a60c-56c51a3aaec2}</Project>
|
<Project>{7f909e29-4808-4bd9-a60c-56c51a3aaec2}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\..\dep\stb\stb.vcxproj">
|
|
||||||
<Project>{ed601289-ac1a-46b8-a8ed-17db9eb73423}</Project>
|
|
||||||
</ProjectReference>
|
|
||||||
<ProjectReference Include="..\..\dep\zstd\zstd.vcxproj">
|
<ProjectReference Include="..\..\dep\zstd\zstd.vcxproj">
|
||||||
<Project>{73ee0c55-6ffe-44e7-9c12-baa52434a797}</Project>
|
<Project>{73ee0c55-6ffe-44e7-9c12-baa52434a797}</Project>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
|
Loading…
Reference in a new issue