Compare commits
52 Commits
v5.107.0
...
work/fuf/r
Author | SHA1 | Date | |
---|---|---|---|
485e084fa9 | |||
75e1280073 | |||
0a6fbd88e9 | |||
fbf60f8bbb | |||
2799382c21 | |||
adc7da4f41 | |||
ac808679cd | |||
2aea982e9e | |||
9173f02ea3 | |||
4badb3088e | |||
8dc685df26 | |||
4bd9d5baec | |||
79e8e183eb | |||
7d63a1d8fa | |||
c11c5eff4f | |||
c02bf3dbcc | |||
6254529d2d | |||
35ff3efbbc | |||
7a0d95af92 | |||
4c3ade04dd | |||
b209e54b6f | |||
4dc2099fa4 | |||
491b223c15 | |||
6559bf8994 | |||
34ed3bad27 | |||
9c579fc1f8 | |||
93adb22632 | |||
d57ff91f8b | |||
edd6adcbac | |||
d787c12727 | |||
c9fec5e408 | |||
e60dfd4968 | |||
f5a9dd46d2 | |||
41f0411b62 | |||
e1a3751936 | |||
402dfb5de3 | |||
a3f7c03b61 | |||
20cec27ae8 | |||
d34c1668aa | |||
560d0483ae | |||
085c9c4841 | |||
b654f20ece | |||
21211cd63b | |||
5cc7a2b45c | |||
4451737d2f | |||
01ab0876f1 | |||
a67dcac7d1 | |||
cef8d08ad4 | |||
a4b9dd9400 | |||
6e6c1ab5f4 | |||
f205adf2e0 | |||
14742cb502 |
@ -2,13 +2,7 @@
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
include:
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-static.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android-qt6.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows-static.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd-qt6.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows-qt6.yml
|
||||
|
@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.16)
|
||||
project(KImageFormats)
|
||||
|
||||
include(FeatureSummary)
|
||||
find_package(ECM 5.107.0 NO_MODULE)
|
||||
find_package(ECM 5.240.0 NO_MODULE)
|
||||
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules")
|
||||
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||
|
||||
@ -19,11 +19,11 @@ include(ECMDeprecationSettings)
|
||||
include(CheckIncludeFiles)
|
||||
include(FindPkgConfig)
|
||||
|
||||
set(REQUIRED_QT_VERSION 5.15.2)
|
||||
find_package(Qt${QT_MAJOR_VERSION}Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
||||
set(REQUIRED_QT_VERSION 6.5.0)
|
||||
find_package(Qt6Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
||||
|
||||
find_package(KF5Archive)
|
||||
set_package_properties(KF5Archive PROPERTIES
|
||||
find_package(KF6Archive)
|
||||
set_package_properties(KF6Archive PROPERTIES
|
||||
TYPE OPTIONAL
|
||||
PURPOSE "Required for the QImage plugin for Krita and OpenRaster images"
|
||||
)
|
||||
@ -32,12 +32,12 @@ set_package_properties(KF5Archive PROPERTIES
|
||||
# this available in PATH
|
||||
set(BUILD_EPS_PLUGIN FALSE)
|
||||
if (UNIX)
|
||||
find_package(Qt${QT_MAJOR_VERSION}PrintSupport ${REQUIRED_QT_VERSION} NO_MODULE)
|
||||
set_package_properties(Qt${QT_MAJOR_VERSION}PrintSupport PROPERTIES
|
||||
find_package(Qt6PrintSupport ${REQUIRED_QT_VERSION} NO_MODULE)
|
||||
set_package_properties(Qt6PrintSupport PROPERTIES
|
||||
PURPOSE "Required for the QImage plugin for EPS images"
|
||||
TYPE OPTIONAL
|
||||
)
|
||||
if (TARGET Qt${QT_MAJOR_VERSION}::PrintSupport)
|
||||
if (TARGET Qt6::PrintSupport)
|
||||
set(BUILD_EPS_PLUGIN TRUE)
|
||||
endif()
|
||||
endif()
|
||||
@ -51,7 +51,10 @@ set_package_properties(OpenEXR PROPERTIES
|
||||
PURPOSE "Required for the QImage plugin for OpenEXR images"
|
||||
)
|
||||
|
||||
find_package(libavif 0.8.2 CONFIG)
|
||||
find_package(libavif 0.8.2 CONFIG QUIET)
|
||||
if(NOT libavif_FOUND)
|
||||
find_package(libavif 1 CONFIG)
|
||||
endif()
|
||||
set_package_properties(libavif PROPERTIES
|
||||
TYPE OPTIONAL
|
||||
PURPOSE "Required for the QImage plugin for AVIF images"
|
||||
@ -65,8 +68,8 @@ add_feature_info(LibHeif LibHeif_FOUND "required for the QImage plugin for HEIF/
|
||||
|
||||
option(KIMAGEFORMATS_JXL "Enable plugin for JPEG XL format" ON)
|
||||
if(KIMAGEFORMATS_JXL)
|
||||
pkg_check_modules(LibJXL IMPORTED_TARGET libjxl>=0.6.1)
|
||||
pkg_check_modules(LibJXLThreads IMPORTED_TARGET libjxl_threads>=0.6.1)
|
||||
pkg_check_modules(LibJXL IMPORTED_TARGET libjxl>=0.7.0)
|
||||
pkg_check_modules(LibJXLThreads IMPORTED_TARGET libjxl_threads>=0.7.0)
|
||||
endif()
|
||||
add_feature_info(LibJXL LibJXL_FOUND "required for the QImage plugin for JPEG XL images")
|
||||
|
||||
@ -78,8 +81,8 @@ set_package_properties(LibRaw PROPERTIES
|
||||
)
|
||||
|
||||
ecm_set_disabled_deprecation_versions(
|
||||
QT 5.15.2
|
||||
KF 5.95
|
||||
QT 6.4
|
||||
KF 5.102
|
||||
)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
14
README.md
@ -14,22 +14,26 @@ image formats.
|
||||
The following image formats have read-only support:
|
||||
|
||||
- Animated Windows cursors (ani)
|
||||
- Gimp (xcf)
|
||||
- OpenEXR (exr)
|
||||
- Photoshop documents (psd, psb, pdd, psdt)
|
||||
- Sun Raster (ras)
|
||||
- Camera RAW images (arw, cr2, cr3, dcs, dng, ...)
|
||||
- Gimp (xcf)
|
||||
- Krita (kra)
|
||||
- OpenEXR (exr)
|
||||
- OpenRaster (ora)
|
||||
- Photoshop documents (psd, psb, pdd, psdt)
|
||||
- Radiance HDR (hdr)
|
||||
- Sun Raster (im1, im8, im24, im32, ras, sun)
|
||||
|
||||
The following image formats have read and write support:
|
||||
|
||||
- AV1 Image File Format (AVIF)
|
||||
- Encapsulated PostScript (eps)
|
||||
- High Efficiency Image File Format (heif). Can be enabled with the KIMAGEFORMATS_HEIF build option.
|
||||
- JPEG XL (jxl)
|
||||
- Personal Computer Exchange (pcx)
|
||||
- Quite OK Image format (qoi)
|
||||
- SGI images (rgb, rgba, sgi, bw)
|
||||
- Softimage PIC (pic)
|
||||
- Targa (tga): supports more formats than Qt's version
|
||||
- XView (xv)
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@ -1,7 +1,4 @@
|
||||
#find_package(Qt5Test ${REQUIRED_QT_VERSION} NO_MODULE)
|
||||
|
||||
include(ECMMarkAsTest)
|
||||
include(CMakeParseArguments)
|
||||
|
||||
add_definitions(-DPLUGIN_DIR="${CMAKE_CURRENT_BINARY_DIR}/../bin")
|
||||
remove_definitions(-DQT_NO_CAST_FROM_ASCII)
|
||||
@ -15,7 +12,7 @@ macro(kimageformats_read_tests)
|
||||
|
||||
if (NOT TARGET readtest)
|
||||
add_executable(readtest readtest.cpp)
|
||||
target_link_libraries(readtest Qt${QT_MAJOR_VERSION}::Gui)
|
||||
target_link_libraries(readtest Qt6::Gui)
|
||||
target_compile_definitions(readtest
|
||||
PRIVATE IMAGEDIR="${CMAKE_CURRENT_SOURCE_DIR}/read")
|
||||
ecm_mark_as_test(readtest)
|
||||
@ -38,7 +35,7 @@ macro(kimageformats_write_tests)
|
||||
|
||||
if (NOT TARGET writetest)
|
||||
add_executable(writetest writetest.cpp)
|
||||
target_link_libraries(writetest Qt${QT_MAJOR_VERSION}::Gui)
|
||||
target_link_libraries(writetest Qt6::Gui)
|
||||
target_compile_definitions(writetest
|
||||
PRIVATE IMAGEDIR="${CMAKE_CURRENT_SOURCE_DIR}/write")
|
||||
ecm_mark_as_test(writetest)
|
||||
@ -70,12 +67,13 @@ kimageformats_read_tests(
|
||||
hdr
|
||||
pcx
|
||||
psd
|
||||
qoi
|
||||
ras
|
||||
rgb
|
||||
tga
|
||||
)
|
||||
|
||||
if (KF5Archive_FOUND)
|
||||
if (KF6Archive_FOUND)
|
||||
kimageformats_read_tests(
|
||||
kra
|
||||
ora
|
||||
@ -125,6 +123,7 @@ kimageformats_read_tests(FUZZ 1
|
||||
kimageformats_write_tests(
|
||||
pcx-lossless
|
||||
pic-lossless
|
||||
qoi-lossless
|
||||
rgb-lossless
|
||||
tga # fixme: the alpha images appear not to be written properly
|
||||
)
|
||||
@ -147,19 +146,19 @@ if (LibRaw_FOUND)
|
||||
)
|
||||
endif()
|
||||
|
||||
find_package(Qt${QT_MAJOR_VERSION}Test ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
find_package(Qt6Test ${REQUIRED_QT_VERSION} CONFIG QUIET)
|
||||
|
||||
if(NOT TARGET Qt${QT_MAJOR_VERSION}::Test)
|
||||
message(STATUS "Qt${QT_MAJOR_VERSION}Test not found, some autotests will not be built.")
|
||||
if(NOT TARGET Qt6::Test)
|
||||
message(STATUS "Qt6Test not found, some autotests will not be built.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
add_executable(pictest pictest.cpp)
|
||||
target_link_libraries(pictest Qt${QT_MAJOR_VERSION}::Gui Qt${QT_MAJOR_VERSION}::Test)
|
||||
target_link_libraries(pictest Qt6::Gui Qt6::Test)
|
||||
ecm_mark_as_test(pictest)
|
||||
add_test(NAME kimageformats-pic COMMAND pictest)
|
||||
|
||||
add_executable(anitest anitest.cpp)
|
||||
target_link_libraries(anitest Qt${QT_MAJOR_VERSION}::Gui Qt${QT_MAJOR_VERSION}::Test)
|
||||
target_link_libraries(anitest Qt6::Gui Qt6::Test)
|
||||
ecm_mark_as_test(anitest)
|
||||
add_test(NAME kimageformats-ani COMMAND anitest)
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
BIN
autotests/read/hdr/fake_earth.hdr
Normal file
BIN
autotests/read/hdr/fake_earth.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 189 KiB |
BIN
autotests/read/psd/mch3-16bits.png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
autotests/read/psd/mch3-16bits.psb
Normal file
BIN
autotests/read/psd/mch3-8bits.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
autotests/read/psd/mch3-8bits.psb
Normal file
BIN
autotests/read/qoi/1px.png
Normal file
After Width: | Height: | Size: 551 B |
BIN
autotests/read/qoi/1px.qoi
Normal file
BIN
autotests/read/qoi/2px.png
Normal file
After Width: | Height: | Size: 561 B |
BIN
autotests/read/qoi/2px.qoi
Normal file
BIN
autotests/read/qoi/bnm_rgb.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
autotests/read/qoi/bnm_rgb.qoi
Normal file
BIN
autotests/read/qoi/bnm_rgba.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
autotests/read/qoi/bnm_rgba.qoi
Normal file
BIN
autotests/read/qoi/testcard.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
autotests/read/qoi/testcard.qoi
Normal file
BIN
autotests/read/qoi/testcard_rgba.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
autotests/read/qoi/testcard_rgba.qoi
Normal file
BIN
autotests/read/ras/rgb-gimp-2.10-1bit.png
Normal file
After Width: | Height: | Size: 192 B |
BIN
autotests/read/ras/rgb-gimp-2.10-1bit.ras
Normal file
BIN
autotests/read/ras/rgb-gimp-2.10-gray.png
Normal file
After Width: | Height: | Size: 470 B |
BIN
autotests/read/ras/rgb-gimp-2.10-gray.ras
Normal file
BIN
autotests/read/ras/rgb-gimp-2.10-pal16.png
Normal file
After Width: | Height: | Size: 338 B |
BIN
autotests/read/ras/rgb-gimp-2.10-pal16.ras
Normal file
BIN
autotests/read/ras/rgb24.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
autotests/read/ras/rgb24.ras
Normal file
BIN
autotests/read/ras/rle_1bit.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
autotests/read/ras/rle_1bit.ras
Normal file
BIN
autotests/read/ras/rle_24bit.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
autotests/read/ras/rle_24bit.ras
Normal file
BIN
autotests/read/ras/rle_pal8bit.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
autotests/read/ras/rle_pal8bit.ras
Normal file
BIN
autotests/read/xcf/birthday.png
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
autotests/read/xcf/birthday.xcf
Normal file
BIN
autotests/read/xcf/birthday16.png
Normal file
After Width: | Height: | Size: 91 KiB |
BIN
autotests/read/xcf/birthday16.xcf
Normal file
BIN
autotests/read/xcf/birthday16_gray.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
autotests/read/xcf/birthday16_gray.xcf
Normal file
BIN
autotests/read/xcf/birthday16_grayA.png
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
autotests/read/xcf/birthday16_grayA.xcf
Normal file
BIN
autotests/read/xcf/birthday16fp.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
autotests/read/xcf/birthday16fp.xcf
Normal file
BIN
autotests/read/xcf/birthday16fp_gray.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
autotests/read/xcf/birthday16fp_gray.xcf
Normal file
BIN
autotests/read/xcf/birthday16fp_grayA.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
autotests/read/xcf/birthday16fp_grayA.xcf
Normal file
BIN
autotests/read/xcf/birthday32.png
Normal file
After Width: | Height: | Size: 91 KiB |
BIN
autotests/read/xcf/birthday32.xcf
Normal file
BIN
autotests/read/xcf/birthday32_gray.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
autotests/read/xcf/birthday32_gray.xcf
Normal file
BIN
autotests/read/xcf/birthday32_grayA.png
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
autotests/read/xcf/birthday32_grayA.xcf
Normal file
BIN
autotests/read/xcf/birthday32fp.png
Normal file
After Width: | Height: | Size: 82 KiB |
BIN
autotests/read/xcf/birthday32fp.xcf
Normal file
BIN
autotests/read/xcf/birthday32fp_gray.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
autotests/read/xcf/birthday32fp_gray.xcf
Normal file
BIN
autotests/read/xcf/birthday32fp_grayA.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
autotests/read/xcf/birthday32fp_grayA.xcf
Normal file
BIN
autotests/read/xcf/birthday_grayA.png
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
autotests/read/xcf/birthday_grayA.xcf
Normal file
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 115 KiB |
BIN
autotests/read/xcf/fruktpilot16_icc.png
Normal file
After Width: | Height: | Size: 115 KiB |
BIN
autotests/read/xcf/fruktpilot16_icc.xcf
Normal file
BIN
autotests/read/xcf/fruktpilot16fplin_icc.png
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
autotests/read/xcf/fruktpilot16fplin_icc.xcf
Normal file
BIN
autotests/read/xcf/fruktpilot32_icc.png
Normal file
After Width: | Height: | Size: 115 KiB |
BIN
autotests/read/xcf/fruktpilot32_icc.xcf
Normal file
BIN
autotests/read/xcf/fruktpilot32fplin_icc.png
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
autotests/read/xcf/fruktpilot32fplin_icc.xcf
Normal file
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 115 KiB |
@ -162,13 +162,13 @@ int main(int argc, char **argv)
|
||||
if (!fi.suffix().compare("png", Qt::CaseInsensitive) || !fi.suffix().compare("tif", Qt::CaseInsensitive)) {
|
||||
continue;
|
||||
}
|
||||
int suffixPos = fi.filePath().count() - suffix.count();
|
||||
int suffixPos = fi.filePath().size() - suffix.size();
|
||||
QString inputfile = fi.filePath();
|
||||
QString fmt = QStringLiteral("png");
|
||||
QString expfile = fi.filePath().replace(suffixPos, suffix.count(), fmt);
|
||||
QString expfile = fi.filePath().replace(suffixPos, suffix.size(), fmt);
|
||||
if (!QFile::exists(expfile)) { // try with tiff
|
||||
fmt = QStringLiteral("tif");
|
||||
expfile = fi.filePath().replace(suffixPos, suffix.count(), fmt);
|
||||
expfile = fi.filePath().replace(suffixPos, suffix.size(), fmt);
|
||||
}
|
||||
QString expfilename = QFileInfo(expfile).fileName();
|
||||
|
||||
|
BIN
autotests/write/rgb.qoi
Normal file
BIN
autotests/write/rgba.qoi
Normal file
@ -85,8 +85,8 @@ int main(int argc, char **argv)
|
||||
if (parser.isSet(ignoreDataCheck)) {
|
||||
pngfile = fi.filePath();
|
||||
} else {
|
||||
int suffixPos = fi.filePath().count() - suffix.count();
|
||||
pngfile = fi.filePath().replace(suffixPos, suffix.count(), QStringLiteral("png"));
|
||||
int suffixPos = fi.filePath().size() - suffix.size();
|
||||
pngfile = fi.filePath().replace(suffixPos, suffix.size(), QStringLiteral("png"));
|
||||
}
|
||||
QString pngfilename = QFileInfo(pngfile).fileName();
|
||||
|
||||
|
@ -12,3 +12,4 @@ Ignacio Castaño <castano@ludicon.com> -- DDS and PDS format reader.
|
||||
Christoph Hormann <chris_hormann@gmx.de> -- HDR format read support.
|
||||
Michael Ritzert <kde@ritzert.de> -- JPEG 2000 format read/write support
|
||||
Troy Unrau <troy@kde.org> -- Sun RASter read support
|
||||
Ernest Gupik <ernestgupik@wp.pl> -- QOI format read support
|
||||
|
@ -11,9 +11,10 @@ function(kimageformats_add_plugin plugin)
|
||||
message(FATAL_ERROR "kimageformats_add_plugin called without SOURCES parameter")
|
||||
endif()
|
||||
|
||||
add_library(${plugin} MODULE ${KIF_ADD_PLUGIN_SOURCES})
|
||||
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/imageformats")
|
||||
target_link_libraries(${plugin} Qt${QT_MAJOR_VERSION}::Gui)
|
||||
qt_add_plugin(${plugin} PLUGIN_TYPE imageformats)
|
||||
target_sources(${plugin} PRIVATE ${KIF_ADD_PLUGIN_SOURCES})
|
||||
set_target_properties(${plugin} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/imageformats)
|
||||
target_link_libraries(${plugin} PRIVATE Qt6::Gui)
|
||||
install(TARGETS ${plugin} DESTINATION ${KDE_INSTALL_QTPLUGINDIR}/imageformats)
|
||||
endfunction()
|
||||
|
||||
@ -21,172 +22,105 @@ endfunction()
|
||||
|
||||
kimageformats_add_plugin(kimg_ani SOURCES ani.cpp)
|
||||
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES ani.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
if (TARGET avif)
|
||||
kimageformats_add_plugin(kimg_avif SOURCES "avif.cpp")
|
||||
target_link_libraries(kimg_avif "avif")
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES avif.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES dds-qt.desktop RENAME dds.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
target_link_libraries(kimg_avif PRIVATE "avif")
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
if (BUILD_EPS_PLUGIN)
|
||||
if (TARGET Qt${QT_MAJOR_VERSION}::PrintSupport)
|
||||
if (TARGET Qt6::PrintSupport)
|
||||
kimageformats_add_plugin(kimg_eps SOURCES eps.cpp)
|
||||
target_link_libraries(kimg_eps Qt${QT_MAJOR_VERSION}::PrintSupport)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES eps.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
target_link_libraries(kimg_eps PRIVATE Qt6::PrintSupport)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
# need this for Qt's version of the plugin
|
||||
install(FILES jp2.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
if(OpenEXR_FOUND)
|
||||
kimageformats_add_plugin(kimg_exr SOURCES exr.cpp)
|
||||
if(TARGET OpenEXR::OpenEXR)
|
||||
target_link_libraries(kimg_exr OpenEXR::OpenEXR)
|
||||
target_link_libraries(kimg_exr PRIVATE OpenEXR::OpenEXR)
|
||||
else()
|
||||
if(OpenEXR_VERSION_STRING VERSION_LESS 2.3.0)
|
||||
# Older OpenEXR versions use dynamic exception specifications, so
|
||||
# cannot use C++17 with them
|
||||
set_target_properties(kimg_exr PROPERTIES CXX_STANDARD 14)
|
||||
endif()
|
||||
target_link_libraries(kimg_exr OpenEXR::IlmImf)
|
||||
target_link_libraries(kimg_exr PRIVATE OpenEXR::IlmImf)
|
||||
endif()
|
||||
kde_target_enable_exceptions(kimg_exr PRIVATE)
|
||||
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES exr.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
kimageformats_add_plugin(kimg_hdr SOURCES hdr.cpp)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES hdr.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
if (LibHeif_FOUND)
|
||||
kimageformats_add_plugin(kimg_heif SOURCES heif.cpp)
|
||||
target_link_libraries(kimg_heif PkgConfig::LibHeif)
|
||||
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES heif.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
target_link_libraries(kimg_heif PRIVATE PkgConfig::LibHeif)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
if (LibJXL_FOUND AND LibJXLThreads_FOUND)
|
||||
kimageformats_add_plugin(kimg_jxl SOURCES jxl.cpp)
|
||||
target_link_libraries(kimg_jxl PkgConfig::LibJXL PkgConfig::LibJXLThreads)
|
||||
if (LibJXL_VERSION VERSION_GREATER_EQUAL "0.7.0")
|
||||
target_compile_definitions(kimg_jxl PRIVATE KIMG_JXL_API_VERSION=70)
|
||||
endif()
|
||||
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES jxl.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
target_link_libraries(kimg_jxl PRIVATE PkgConfig::LibJXL PkgConfig::LibJXLThreads)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
kimageformats_add_plugin(kimg_pcx SOURCES pcx.cpp)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES pcx.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
kimageformats_add_plugin(kimg_pic SOURCES pic.cpp)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES pic.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
kimageformats_add_plugin(kimg_psd SOURCES psd.cpp)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES psd.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
kimageformats_add_plugin(kimg_qoi SOURCES qoi.cpp scanlineconverter.cpp)
|
||||
|
||||
##################################
|
||||
|
||||
kimageformats_add_plugin(kimg_ras SOURCES ras.cpp)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES ras.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
kimageformats_add_plugin(kimg_rgb SOURCES rgb.cpp)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES rgb.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
kimageformats_add_plugin(kimg_tga SOURCES tga.cpp)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES tga.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
kimageformats_add_plugin(kimg_xcf SOURCES xcf.cpp)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES xcf.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
if (LibRaw_FOUND)
|
||||
kimageformats_add_plugin(kimg_raw SOURCES raw.cpp)
|
||||
kde_enable_exceptions()
|
||||
target_link_libraries(kimg_raw LibRaw::LibRaw)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES raw.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
target_link_libraries(kimg_raw PRIVATE LibRaw::LibRaw)
|
||||
endif()
|
||||
|
||||
##################################
|
||||
|
||||
if (KF5Archive_FOUND)
|
||||
if (KF6Archive_FOUND)
|
||||
|
||||
kimageformats_add_plugin(kimg_kra SOURCES kra.cpp)
|
||||
target_link_libraries(kimg_kra KF5::Archive)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES kra.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
target_link_libraries(kimg_kra PRIVATE KF6::Archive)
|
||||
|
||||
kimageformats_add_plugin(kimg_ora SOURCES ora.cpp)
|
||||
target_link_libraries(kimg_ora KF5::Archive)
|
||||
if (QT_MAJOR_VERSION STREQUAL "5")
|
||||
install(FILES ora.desktop DESTINATION ${KDE_INSTALL_KSERVICESDIR}/qimageioplugins/)
|
||||
endif()
|
||||
target_link_libraries(kimg_ora PRIVATE KF6::Archive)
|
||||
|
||||
endif()
|
||||
|
@ -90,7 +90,7 @@ bool ANIHandler::read(QImage *outImage)
|
||||
}
|
||||
|
||||
const QByteArray frameSizeData = device()->read(sizeof(quint32_le));
|
||||
if (frameSizeData.count() != sizeof(quint32_le)) {
|
||||
if (frameSizeData.size() != sizeof(quint32_le)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -384,7 +384,7 @@ bool ANIHandler::ensureScanned() const
|
||||
// TODO should we check that the number of rate entries matches nSteps?
|
||||
auto *dataPtr = data.data();
|
||||
QVector<int> list;
|
||||
for (int i = 0; i < data.count(); i += sizeof(quint32_le)) {
|
||||
for (int i = 0; i < data.size(); i += sizeof(quint32_le)) {
|
||||
const auto entry = *(reinterpret_cast<const quint32_le *>(dataPtr + i));
|
||||
list.append(entry);
|
||||
}
|
||||
@ -570,3 +570,5 @@ QImageIOHandler *ANIPlugin::create(QIODevice *device, const QByteArray &format)
|
||||
handler->setFormat(format);
|
||||
return handler;
|
||||
}
|
||||
|
||||
#include "moc_ani_p.cpp"
|
||||
|
@ -1,7 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=QImageIOPlugins
|
||||
X-KDE-ImageFormat=ani
|
||||
X-KDE-MimeType=application/x-navi-animation
|
||||
X-KDE-Read=true
|
||||
X-KDE-Write=false
|
@ -424,7 +424,7 @@ bool QAVIFHandler::decode_one_frame()
|
||||
}
|
||||
|
||||
if (m_decoder->image->transformFlags & AVIF_TRANSFORM_IMIR) {
|
||||
#if AVIF_VERSION > 90100
|
||||
#if AVIF_VERSION > 90100 && AVIF_VERSION < 1000000
|
||||
switch (m_decoder->image->imir.mode) {
|
||||
#else
|
||||
switch (m_decoder->image->imir.axis) {
|
||||
@ -714,9 +714,9 @@ bool QAVIFHandler::write(const QImage &image)
|
||||
if (save_depth == 8) {
|
||||
save_depth = 10;
|
||||
if (tmpcolorimage.hasAlphaChannel()) {
|
||||
tmpcolorimage = tmpcolorimage.convertToFormat(QImage::Format_RGBA64);
|
||||
tmpcolorimage.convertTo(QImage::Format_RGBA64);
|
||||
} else {
|
||||
tmpcolorimage = tmpcolorimage.convertToFormat(QImage::Format_RGBX64);
|
||||
tmpcolorimage.convertTo(QImage::Format_RGBX64);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1103,3 +1103,5 @@ QImageIOHandler *QAVIFPlugin::create(QIODevice *device, const QByteArray &format
|
||||
handler->setFormat(format);
|
||||
return handler;
|
||||
}
|
||||
|
||||
#include "moc_avif_p.cpp"
|
||||
|
@ -1,7 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=QImageIOPlugins
|
||||
X-KDE-ImageFormat=avif
|
||||
X-KDE-MimeType=image/avif
|
||||
X-KDE-Read=true
|
||||
X-KDE-Write=true
|
@ -1,7 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=QImageIOPlugins
|
||||
X-KDE-ImageFormat=dds
|
||||
X-KDE-MimeType=image/x-dds
|
||||
X-KDE-Read=true
|
||||
X-KDE-Write=true
|
@ -365,3 +365,5 @@ QImageIOHandler *EPSPlugin::create(QIODevice *device, const QByteArray &format)
|
||||
handler->setFormat(format);
|
||||
return handler;
|
||||
}
|
||||
|
||||
#include "moc_eps_p.cpp"
|
||||
|
@ -1,7 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=QImageIOPlugins
|
||||
X-KDE-ImageFormat=eps,epsi,epsf
|
||||
X-KDE-MimeType=image/x-eps
|
||||
X-KDE-Read=true
|
||||
X-KDE-Write=true
|
@ -3,10 +3,27 @@
|
||||
in the high dynamic range EXR format.
|
||||
|
||||
SPDX-FileCopyrightText: 2003 Brad Hards <bradh@frogmouth.net>
|
||||
SPDX-FileCopyrightText: 2023 Mirco Miranda <mircomir@outlook.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/* *** EXR_USE_LEGACY_CONVERSIONS ***
|
||||
* If defined, the result image is an 8-bit RGB(A) converted
|
||||
* without icc profiles. Otherwise, a 16-bit images is generated.
|
||||
* NOTE: The use of legacy conversions are discouraged due to
|
||||
* imprecise image result.
|
||||
*/
|
||||
//#define EXR_USE_LEGACY_CONVERSIONS // default commented -> you should define it in your cmake file
|
||||
|
||||
/* *** EXR_ALLOW_LINEAR_COLORSPACE ***
|
||||
* If defined, the linear data is kept and it is the display program that
|
||||
* must convert to the monitor profile. Otherwise the data is converted to sRGB
|
||||
* to accommodate programs that do not support color profiles.
|
||||
* NOTE: If EXR_USE_LEGACY_CONVERSIONS is active, this is ignored.
|
||||
*/
|
||||
//#define EXR_ALLOW_LINEAR_COLORSPACE // default: commented -> you should define it in your cmake file
|
||||
|
||||
#include "exr_p.h"
|
||||
#include "util_p.h"
|
||||
|
||||
@ -30,11 +47,22 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QColorSpace>
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
#include <QFloat16>
|
||||
#include <QImage>
|
||||
#include <QImageIOPlugin>
|
||||
|
||||
#include <QTimeZone>
|
||||
|
||||
// Allow the code to works on all QT versions supported by KDE
|
||||
// project (Qt 5.15 and Qt 6.x) to easy backports fixes.
|
||||
#if (QT_VERSION_MAJOR >= 6) && !defined(EXR_USE_LEGACY_CONVERSIONS)
|
||||
// If uncommented, the image is rendered in a float16 format, the result is very precise
|
||||
#define EXR_USE_QT6_FLOAT_IMAGE // default uncommented
|
||||
#endif
|
||||
|
||||
class K_IStream : public Imf::IStream
|
||||
{
|
||||
public:
|
||||
@ -94,77 +122,21 @@ void K_IStream::clear()
|
||||
// TODO
|
||||
}
|
||||
|
||||
/* this does a conversion from the ILM Half (equal to Nvidia Half)
|
||||
* format into the normal 32 bit pixel format. Process is from the
|
||||
* ILM code.
|
||||
*/
|
||||
QRgb RgbaToQrgba(struct Imf::Rgba &imagePixel)
|
||||
#ifdef EXR_USE_LEGACY_CONVERSIONS
|
||||
// source: https://openexr.com/en/latest/ReadingAndWritingImageFiles.html
|
||||
inline unsigned char gamma(float x)
|
||||
{
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
float a;
|
||||
|
||||
// 1) Compensate for fogging by subtracting defog
|
||||
// from the raw pixel values.
|
||||
// Response: We work with defog of 0.0, so this is a no-op
|
||||
|
||||
// 2) Multiply the defogged pixel values by
|
||||
// 2^(exposure + 2.47393).
|
||||
// Response: We work with exposure of 0.0.
|
||||
// (2^2.47393) is 5.55555
|
||||
r = imagePixel.r * 5.55555;
|
||||
g = imagePixel.g * 5.55555;
|
||||
b = imagePixel.b * 5.55555;
|
||||
a = imagePixel.a * 5.55555;
|
||||
|
||||
// 3) Values, which are now 1.0, are called "middle gray".
|
||||
// If defog and exposure are both set to 0.0, then
|
||||
// middle gray corresponds to a raw pixel value of 0.18.
|
||||
// In step 6, middle gray values will be mapped to an
|
||||
// intensity 3.5 f-stops below the display's maximum
|
||||
// intensity.
|
||||
// Response: no apparent content.
|
||||
|
||||
// 4) Apply a knee function. The knee function has two
|
||||
// parameters, kneeLow and kneeHigh. Pixel values
|
||||
// below 2^kneeLow are not changed by the knee
|
||||
// function. Pixel values above kneeLow are lowered
|
||||
// according to a logarithmic curve, such that the
|
||||
// value 2^kneeHigh is mapped to 2^3.5 (in step 6,
|
||||
// this value will be mapped to the display's
|
||||
// maximum intensity).
|
||||
// Response: kneeLow = 0.0 (2^0.0 => 1); kneeHigh = 5.0 (2^5 =>32)
|
||||
if (r > 1.0) {
|
||||
r = 1.0 + std::log((r - 1.0) * 0.184874 + 1) / 0.184874;
|
||||
}
|
||||
if (g > 1.0) {
|
||||
g = 1.0 + std::log((g - 1.0) * 0.184874 + 1) / 0.184874;
|
||||
}
|
||||
if (b > 1.0) {
|
||||
b = 1.0 + std::log((b - 1.0) * 0.184874 + 1) / 0.184874;
|
||||
}
|
||||
if (a > 1.0) {
|
||||
a = 1.0 + std::log((a - 1.0) * 0.184874 + 1) / 0.184874;
|
||||
}
|
||||
//
|
||||
// 5) Gamma-correct the pixel values, assuming that the
|
||||
// screen's gamma is 0.4545 (or 1/2.2).
|
||||
r = std::pow(r, 0.4545);
|
||||
g = std::pow(g, 0.4545);
|
||||
b = std::pow(b, 0.4545);
|
||||
a = std::pow(a, 0.4545);
|
||||
|
||||
// 6) Scale the values such that pixels middle gray
|
||||
// pixels are mapped to 84.66 (or 3.5 f-stops below
|
||||
// the display's maximum intensity).
|
||||
//
|
||||
// 7) Clamp the values to [0, 255].
|
||||
return qRgba((unsigned char)(Imath::clamp(r * 84.66f, 0.f, 255.f)),
|
||||
(unsigned char)(Imath::clamp(g * 84.66f, 0.f, 255.f)),
|
||||
(unsigned char)(Imath::clamp(b * 84.66f, 0.f, 255.f)),
|
||||
(unsigned char)(Imath::clamp(a * 84.66f, 0.f, 255.f)));
|
||||
x = std::pow(5.5555f * std::max(0.f, x), 0.4545f) * 84.66f;
|
||||
return (unsigned char)qBound(0.f, x, 255.f);
|
||||
}
|
||||
inline QRgb RgbaToQrgba(struct Imf::Rgba &imagePixel)
|
||||
{
|
||||
return qRgba(gamma(float(imagePixel.r)),
|
||||
gamma(float(imagePixel.g)),
|
||||
gamma(float(imagePixel.b)),
|
||||
(unsigned char)(qBound(0.f, imagePixel.a * 255.f, 255.f) + 0.5f));
|
||||
}
|
||||
#endif
|
||||
|
||||
EXRHandler::EXRHandler()
|
||||
{
|
||||
@ -188,31 +160,96 @@ bool EXRHandler::read(QImage *outImage)
|
||||
K_IStream istr(device(), QByteArray());
|
||||
Imf::RgbaInputFile file(istr);
|
||||
Imath::Box2i dw = file.dataWindow();
|
||||
bool isRgba = file.channels() & Imf::RgbaChannels::WRITE_A;
|
||||
|
||||
width = dw.max.x - dw.min.x + 1;
|
||||
height = dw.max.y - dw.min.y + 1;
|
||||
|
||||
QImage image = imageAlloc(width, height, QImage::Format_RGB32);
|
||||
#if defined(EXR_USE_LEGACY_CONVERSIONS)
|
||||
QImage image = imageAlloc(width, height, isRgba ? QImage::Format_ARGB32 : QImage::Format_RGB32);
|
||||
#elif defined(EXR_USE_QT6_FLOAT_IMAGE)
|
||||
QImage image = imageAlloc(width, height, isRgba ? QImage::Format_RGBA16FPx4 : QImage::Format_RGBX16FPx4);
|
||||
#else
|
||||
QImage image = imageAlloc(width, height, isRgba ? QImage::Format_RGBA64 : QImage::Format_RGBX64);
|
||||
#endif
|
||||
if (image.isNull()) {
|
||||
qWarning() << "Failed to allocate image, invalid size?" << QSize(width, height);
|
||||
return false;
|
||||
}
|
||||
|
||||
Imf::Array2D<Imf::Rgba> pixels;
|
||||
pixels.resizeErase(height, width);
|
||||
// set some useful metadata
|
||||
auto &&h = file.header();
|
||||
if (auto comments = h.findTypedAttribute<Imf::StringAttribute>("comments")) {
|
||||
image.setText(QStringLiteral("Comment"), QString::fromStdString(comments->value()));
|
||||
}
|
||||
if (auto owner = h.findTypedAttribute<Imf::StringAttribute>("owner")) {
|
||||
image.setText(QStringLiteral("Owner"), QString::fromStdString(owner->value()));
|
||||
}
|
||||
if (auto capDate = h.findTypedAttribute<Imf::StringAttribute>("capDate")) {
|
||||
float off = 0;
|
||||
if (auto utcOffset = h.findTypedAttribute<Imf::FloatAttribute>("utcOffset")) {
|
||||
off = utcOffset->value();
|
||||
}
|
||||
auto dateTime = QDateTime::fromString(QString::fromStdString(capDate->value()), QStringLiteral("yyyy:MM:dd HH:mm:ss"));
|
||||
if (dateTime.isValid()) {
|
||||
dateTime.setTimeZone(QTimeZone::fromSecondsAheadOfUtc(off));
|
||||
image.setText(QStringLiteral("Date"), dateTime.toString(Qt::ISODate));
|
||||
}
|
||||
}
|
||||
if (auto xDensity = h.findTypedAttribute<Imf::FloatAttribute>("xDensity")) {
|
||||
float par = 1;
|
||||
if (auto pixelAspectRatio = h.findTypedAttribute<Imf::FloatAttribute>("pixelAspectRatio")) {
|
||||
par = pixelAspectRatio->value();
|
||||
}
|
||||
image.setDotsPerMeterX(qRound(xDensity->value() * 100.0 / 2.54));
|
||||
image.setDotsPerMeterY(qRound(xDensity->value() * par * 100.0 / 2.54));
|
||||
}
|
||||
|
||||
file.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width);
|
||||
file.readPixels(dw.min.y, dw.max.y);
|
||||
Imf::Array<Imf::Rgba> pixels;
|
||||
pixels.resizeErase(width);
|
||||
|
||||
// somehow copy pixels into image
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
// copy pixels(x,y) into image(x,y)
|
||||
image.setPixel(x, y, RgbaToQrgba(pixels[y][x]));
|
||||
for (int y = 0; y < height; ++y) {
|
||||
auto my = dw.min.y + y;
|
||||
if (my <= dw.max.y) { // paranoia check
|
||||
file.setFrameBuffer(&pixels[0] - dw.min.x - qint64(my) * width, 1, width);
|
||||
file.readPixels(my, my);
|
||||
|
||||
#if defined(EXR_USE_LEGACY_CONVERSIONS)
|
||||
auto scanLine = reinterpret_cast<QRgb *>(image.scanLine(y));
|
||||
for (int x = 0; x < width; ++x) {
|
||||
*(scanLine + x) = RgbaToQrgba(pixels[x]);
|
||||
}
|
||||
#elif defined(EXR_USE_QT6_FLOAT_IMAGE)
|
||||
auto scanLine = reinterpret_cast<qfloat16 *>(image.scanLine(y));
|
||||
for (int x = 0; x < width; ++x) {
|
||||
auto xcs = x * 4;
|
||||
*(scanLine + xcs) = qfloat16(qBound(0.f, float(pixels[x].r), 1.f));
|
||||
*(scanLine + xcs + 1) = qfloat16(qBound(0.f, float(pixels[x].g), 1.f));
|
||||
*(scanLine + xcs + 2) = qfloat16(qBound(0.f, float(pixels[x].b), 1.f));
|
||||
*(scanLine + xcs + 3) = qfloat16(isRgba ? qBound(0.f, float(pixels[x].a), 1.f) : 1.f);
|
||||
}
|
||||
#else
|
||||
auto scanLine = reinterpret_cast<QRgba64 *>(image.scanLine(y));
|
||||
for (int x = 0; x < width; ++x) {
|
||||
*(scanLine + x) = QRgba64::fromRgba64(quint16(qBound(0.f, float(pixels[x].r) * 65535.f + 0.5f, 65535.f)),
|
||||
quint16(qBound(0.f, float(pixels[x].g) * 65535.f + 0.5f, 65535.f)),
|
||||
quint16(qBound(0.f, float(pixels[x].b) * 65535.f + 0.5f, 65535.f)),
|
||||
isRgba ? quint16(qBound(0.f, float(pixels[x].a) * 65535.f + 0.5f, 65535.f)) : quint16(65535));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
*outImage = image;
|
||||
// final color operations
|
||||
#ifndef EXR_USE_LEGACY_CONVERSIONS
|
||||
image.setColorSpace(QColorSpace(QColorSpace::SRgbLinear));
|
||||
#ifndef EXR_ALLOW_LINEAR_COLORSPACE
|
||||
image.convertToColorSpace(QColorSpace(QColorSpace::SRgb));
|
||||
#endif // !EXR_ALLOW_LINEAR_COLORSPACE
|
||||
#endif // !EXR_USE_LEGACY_CONVERSIONS
|
||||
|
||||
*outImage = std::move(image);
|
||||
|
||||
return true;
|
||||
} catch (const std::exception &exc) {
|
||||
@ -259,3 +296,5 @@ QImageIOHandler *EXRPlugin::create(QIODevice *device, const QByteArray &format)
|
||||
handler->setFormat(format);
|
||||
return handler;
|
||||
}
|
||||
|
||||
#include "moc_exr_p.cpp"
|
||||
|
@ -1,7 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=QImageIOPlugins
|
||||
X-KDE-ImageFormat=exr
|
||||
X-KDE-MimeType=image/x-exr
|
||||
X-KDE-Read=true
|
||||
X-KDE-Write=false
|
@ -46,33 +46,6 @@ typedef enum {
|
||||
|
||||
// From GIMP "libgimp/gimpenums.h" v2.4
|
||||
|
||||
//! Effect to apply when layers are merged together.
|
||||
|
||||
typedef enum {
|
||||
NORMAL_MODE,
|
||||
DISSOLVE_MODE,
|
||||
BEHIND_MODE,
|
||||
MULTIPLY_MODE,
|
||||
SCREEN_MODE,
|
||||
OVERLAY_MODE,
|
||||
DIFFERENCE_MODE,
|
||||
ADDITION_MODE,
|
||||
SUBTRACT_MODE,
|
||||
DARKEN_ONLY_MODE,
|
||||
LIGHTEN_ONLY_MODE,
|
||||
HUE_MODE,
|
||||
SATURATION_MODE,
|
||||
COLOR_MODE,
|
||||
VALUE_MODE,
|
||||
DIVIDE_MODE,
|
||||
DODGE_MODE,
|
||||
BURN_MODE,
|
||||
HARDLIGHT_MODE,
|
||||
SOFTLIGHT_MODE,
|
||||
GRAIN_EXTRACT_MODE,
|
||||
GRAIN_MERGE_MODE
|
||||
} LayerModeEffects;
|
||||
|
||||
// From GIMP "paint_funcs.c" v1.2
|
||||
|
||||
/*!
|
||||
|
@ -9,13 +9,20 @@
|
||||
#include "hdr_p.h"
|
||||
#include "util_p.h"
|
||||
|
||||
#include <QColorSpace>
|
||||
#include <QDataStream>
|
||||
#include <QFloat16>
|
||||
#include <QImage>
|
||||
#include <QLoggingCategory>
|
||||
#include <QRegularExpressionMatch>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
/* *** HDR_HALF_QUALITY ***
|
||||
* If defined, a 16-bits float image is created, otherwise a 32-bits float ones (default).
|
||||
*/
|
||||
//#define HDR_HALF_QUALITY // default commented -> you should define it in your cmake file
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
||||
Q_LOGGING_CATEGORY(HDRPLUGIN, "kf.imageformats.plugins.hdr", QtWarningMsg)
|
||||
@ -26,15 +33,6 @@ namespace // Private.
|
||||
#define MINELEN 8 // minimum scanline length for encoding
|
||||
#define MAXELEN 0x7fff // maximum scanline length for encoding
|
||||
|
||||
static inline uchar ClipToByte(float value)
|
||||
{
|
||||
if (value > 255.0f) {
|
||||
return 255;
|
||||
}
|
||||
// else if (value < 0.0f) return 0; // we know value is positive.
|
||||
return uchar(value);
|
||||
}
|
||||
|
||||
// read an old style line from the hdr image file
|
||||
// if 'first' is true the first byte is already read
|
||||
static bool Read_Old_Line(uchar *image, int width, QDataStream &s)
|
||||
@ -42,6 +40,7 @@ static bool Read_Old_Line(uchar *image, int width, QDataStream &s)
|
||||
int rshift = 0;
|
||||
int i;
|
||||
|
||||
uchar *start = image;
|
||||
while (width > 0) {
|
||||
s >> image[0];
|
||||
s >> image[1];
|
||||
@ -53,7 +52,14 @@ static bool Read_Old_Line(uchar *image, int width, QDataStream &s)
|
||||
}
|
||||
|
||||
if ((image[0] == 1) && (image[1] == 1) && (image[2] == 1)) {
|
||||
for (i = image[3] << rshift; i > 0; i--) {
|
||||
// NOTE: we don't have an image sample that cover this code
|
||||
if (rshift > 31) {
|
||||
return false;
|
||||
}
|
||||
for (i = image[3] << rshift; i > 0 && width > 0; i--) {
|
||||
if (image == start) {
|
||||
return false; // you cannot be here at the first run
|
||||
}
|
||||
// memcpy(image, image-4, 4);
|
||||
(uint &)image[0] = (uint &)image[0 - 4];
|
||||
image += 4;
|
||||
@ -69,24 +75,38 @@ static bool Read_Old_Line(uchar *image, int width, QDataStream &s)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void RGBE_To_QRgbLine(uchar *image, QRgb *scanline, int width)
|
||||
template<class float_T>
|
||||
void RGBE_To_QRgbLine(uchar *image, float_T *scanline, int width)
|
||||
{
|
||||
for (int j = 0; j < width; j++) {
|
||||
// v = ldexp(1.0, int(image[3]) - 128);
|
||||
float v;
|
||||
int e = int(image[3]) - 128;
|
||||
int e = qBound(-31, int(image[3]) - 128, 31);
|
||||
if (e > 0) {
|
||||
v = float(1 << e);
|
||||
} else {
|
||||
v = 1.0f / float(1 << -e);
|
||||
}
|
||||
|
||||
scanline[j] = qRgb(ClipToByte(float(image[0]) * v), ClipToByte(float(image[1]) * v), ClipToByte(float(image[2]) * v));
|
||||
|
||||
auto j4 = j * 4;
|
||||
auto vn = v / 255.0f;
|
||||
scanline[j4] = float_T(std::min(float(image[0]) * vn, 1.0f));
|
||||
scanline[j4 + 1] = float_T(std::min(float(image[1]) * vn, 1.0f));
|
||||
scanline[j4 + 2] = float_T(std::min(float(image[2]) * vn, 1.0f));
|
||||
scanline[j4 + 3] = float_T(1.0f);
|
||||
image += 4;
|
||||
}
|
||||
}
|
||||
|
||||
QImage::Format imageFormat()
|
||||
{
|
||||
#ifdef HDR_HALF_QUALITY
|
||||
return QImage::Format_RGBX16FPx4;
|
||||
#else
|
||||
return QImage::Format_RGBX32FPx4;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Load the HDR image.
|
||||
static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &img)
|
||||
{
|
||||
@ -94,7 +114,7 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
||||
uchar code;
|
||||
|
||||
// Create dst image.
|
||||
img = imageAlloc(width, height, QImage::Format_RGB32);
|
||||
img = imageAlloc(width, height, imageFormat());
|
||||
if (img.isNull()) {
|
||||
qCDebug(HDRPLUGIN) << "Couldn't create image with size" << width << height << "and format RGB32";
|
||||
return false;
|
||||
@ -102,10 +122,14 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
||||
|
||||
QByteArray lineArray;
|
||||
lineArray.resize(4 * width);
|
||||
uchar *image = (uchar *)lineArray.data();
|
||||
uchar *image = reinterpret_cast<uchar *>(lineArray.data());
|
||||
|
||||
for (int cline = 0; cline < height; cline++) {
|
||||
QRgb *scanline = (QRgb *)img.scanLine(cline);
|
||||
#ifdef HDR_HALF_QUALITY
|
||||
auto scanline = reinterpret_cast<qfloat16 *>(img.scanLine(cline));
|
||||
#else
|
||||
auto scanline = reinterpret_cast<float *>(img.scanLine(cline));
|
||||
#endif
|
||||
|
||||
// determine scanline type
|
||||
if ((width < MINELEN) || (MAXELEN < width)) {
|
||||
@ -148,7 +172,7 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
||||
}
|
||||
|
||||
// read each component
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int i = 0, len = int(lineArray.size()); i < 4; i++) {
|
||||
for (int j = 0; j < width;) {
|
||||
s >> code;
|
||||
if (s.atEnd()) {
|
||||
@ -160,14 +184,20 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
||||
code &= 127;
|
||||
s >> val;
|
||||
while (code != 0) {
|
||||
image[i + j * 4] = val;
|
||||
auto idx = i + j * 4;
|
||||
if (idx < len) {
|
||||
image[idx] = val;
|
||||
}
|
||||
j++;
|
||||
code--;
|
||||
}
|
||||
} else {
|
||||
// non-run
|
||||
while (code != 0) {
|
||||
s >> image[i + j * 4];
|
||||
auto idx = i + j * 4;
|
||||
if (idx < len) {
|
||||
s >> image[idx];
|
||||
}
|
||||
j++;
|
||||
code--;
|
||||
}
|
||||
@ -181,9 +211,7 @@ static bool LoadHDR(QDataStream &s, const int width, const int height, QImage &i
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool HDRHandler::read(QImage *outImage)
|
||||
static QSize readHeaderSize(QIODevice *device)
|
||||
{
|
||||
int len;
|
||||
QByteArray line(MAXLINE + 1, Qt::Uninitialized);
|
||||
@ -191,7 +219,7 @@ bool HDRHandler::read(QImage *outImage)
|
||||
|
||||
// Parse header
|
||||
do {
|
||||
len = device()->readLine(line.data(), MAXLINE);
|
||||
len = device->readLine(line.data(), MAXLINE);
|
||||
|
||||
if (line.startsWith("FORMAT=")) {
|
||||
format = line.mid(7, len - 7 - 1 /*\n*/);
|
||||
@ -201,10 +229,10 @@ bool HDRHandler::read(QImage *outImage)
|
||||
|
||||
if (format != "32-bit_rle_rgbe") {
|
||||
qCDebug(HDRPLUGIN) << "Unknown HDR format:" << format;
|
||||
return false;
|
||||
return QSize();
|
||||
}
|
||||
|
||||
len = device()->readLine(line.data(), MAXLINE);
|
||||
len = device->readLine(line.data(), MAXLINE);
|
||||
line.resize(len);
|
||||
|
||||
/*
|
||||
@ -224,29 +252,75 @@ bool HDRHandler::read(QImage *outImage)
|
||||
QRegularExpressionMatch match = resolutionRegExp.match(QString::fromLatin1(line));
|
||||
if (!match.hasMatch()) {
|
||||
qCDebug(HDRPLUGIN) << "Invalid HDR file, the first line after the header didn't have the expected format:" << line;
|
||||
return false;
|
||||
return QSize();
|
||||
}
|
||||
|
||||
if ((match.captured(1).at(1) != u'Y') || (match.captured(3).at(1) != u'X')) {
|
||||
qCDebug(HDRPLUGIN) << "Unsupported image orientation in HDR file.";
|
||||
return QSize();
|
||||
}
|
||||
|
||||
return QSize(match.captured(4).toInt(), match.captured(2).toInt());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool HDRHandler::read(QImage *outImage)
|
||||
{
|
||||
QDataStream s(device());
|
||||
|
||||
QSize size = readHeaderSize(s.device());
|
||||
if (!size.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int width = match.captured(4).toInt();
|
||||
const int height = match.captured(2).toInt();
|
||||
|
||||
QDataStream s(device());
|
||||
|
||||
QImage img;
|
||||
if (!LoadHDR(s, width, height, img)) {
|
||||
if (!LoadHDR(s, size.width(), size.height(), img)) {
|
||||
// qDebug() << "Error loading HDR file.";
|
||||
return false;
|
||||
}
|
||||
// The images read by Gimp and Photoshop (including those of the tests) are interpreted with linear color space.
|
||||
// By setting the linear color space, programs that support profiles display HDR files as in GIMP and Photoshop.
|
||||
img.setColorSpace(QColorSpace(QColorSpace::SRgbLinear));
|
||||
|
||||
*outImage = img;
|
||||
*outImage = std::move(img);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HDRHandler::supportsOption(ImageOption option) const
|
||||
{
|
||||
if (option == QImageIOHandler::Size) {
|
||||
return true;
|
||||
}
|
||||
if (option == QImageIOHandler::ImageFormat) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant HDRHandler::option(ImageOption option) const
|
||||
{
|
||||
QVariant v;
|
||||
|
||||
if (option == QImageIOHandler::Size) {
|
||||
if (auto d = device()) {
|
||||
// transactions works on both random and sequential devices
|
||||
d->startTransaction();
|
||||
auto size = readHeaderSize(d);
|
||||
d->rollbackTransaction();
|
||||
if (size.isValid()) {
|
||||
v = QVariant::fromValue(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (option == QImageIOHandler::ImageFormat) {
|
||||
v = QVariant::fromValue(imageFormat());
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
HDRHandler::HDRHandler()
|
||||
{
|
||||
}
|
||||
@ -267,7 +341,20 @@ bool HDRHandler::canRead(QIODevice *device)
|
||||
return false;
|
||||
}
|
||||
|
||||
return device->peek(11) == "#?RADIANCE\n" || device->peek(7) == "#?RGBE\n";
|
||||
// the .pic taken from official test cases does not start with this string but can be loaded.
|
||||
if(device->peek(11) == "#?RADIANCE\n" || device->peek(7) == "#?RGBE\n") {
|
||||
return true;
|
||||
}
|
||||
|
||||
// allow to load offical test cases: https://radsite.lbl.gov/radiance/framed.html
|
||||
device->startTransaction();
|
||||
QSize size = readHeaderSize(device);
|
||||
device->rollbackTransaction();
|
||||
if (size.isValid()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QImageIOPlugin::Capabilities HDRPlugin::capabilities(QIODevice *device, const QByteArray &format) const
|
||||
@ -296,3 +383,5 @@ QImageIOHandler *HDRPlugin::create(QIODevice *device, const QByteArray &format)
|
||||
handler->setFormat(format);
|
||||
return handler;
|
||||
}
|
||||
|
||||
#include "moc_hdr_p.cpp"
|
||||
|
@ -1,7 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=QImageIOPlugins
|
||||
X-KDE-ImageFormat=hdr
|
||||
X-KDE-MimeType=image/x-hdr
|
||||
X-KDE-Read=true
|
||||
X-KDE-Write=false
|
@ -18,6 +18,9 @@ public:
|
||||
bool canRead() const override;
|
||||
bool read(QImage *outImage) override;
|
||||
|
||||
bool supportsOption(QImageIOHandler::ImageOption option) const override;
|
||||
QVariant option(QImageIOHandler::ImageOption option) const override;
|
||||
|
||||
static bool canRead(QIODevice *device);
|
||||
};
|
||||
|
||||
|
@ -926,3 +926,5 @@ QImageIOHandler *HEIFPlugin::create(QIODevice *device, const QByteArray &format)
|
||||
handler->setFormat(format);
|
||||
return handler;
|
||||
}
|
||||
|
||||
#include "moc_heif_p.cpp"
|
||||
|
@ -1,7 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=QImageIOPlugins
|
||||
X-KDE-ImageFormat=heif
|
||||
X-KDE-MimeType=image/heif
|
||||
X-KDE-Read=true
|
||||
X-KDE-Write=true
|