Compare commits
59 Commits
Author | SHA1 | Date | |
---|---|---|---|
21b3b890ec | |||
aef4bd7e1c | |||
ea1983a7d1 | |||
775b53f1f6 | |||
02cf1502c0 | |||
f6c718a789 | |||
4f2f2425d3 | |||
e6357c22f7 | |||
094177a01c | |||
7420f47c17 | |||
888bca7387 | |||
e3aefd2aa1 | |||
aa8134ee0d | |||
9f09473aa0 | |||
62eb1d28cb | |||
15bece40ec | |||
1b3d2afbe3 | |||
850068c1dc | |||
6bf38ea638 | |||
2adca7c0ca | |||
dd69fdaea9 | |||
ae62ea3dfc | |||
9c47845f15 | |||
7c7fa73020 | |||
92e4271e84 | |||
6f588c6fd3 | |||
a182478e2c | |||
4026f41890 | |||
bef2b9168f | |||
473f5d9847 | |||
9bee29cc01 | |||
cdf3be3af1 | |||
752b18a42c | |||
97a1ea181c | |||
64a43fb04f | |||
6821c29819 | |||
e4d95c03fa | |||
afa8ed1a5d | |||
245c835d92 | |||
b2663d2651 | |||
35ab37c628 | |||
b28baa4a1e | |||
5d2540c135 | |||
25cc8bc262 | |||
7742537f8c | |||
d3386bbf50 | |||
e77986c7e0 | |||
c0261f4926 | |||
e5cf9caac5 | |||
90d4256f3d | |||
bb1c6aab9e | |||
74a734efed | |||
e9fa4b6610 | |||
36a6ef7d78 | |||
9fd6896cec | |||
9b14e752db | |||
90a2e3b412 | |||
b28cf4c352 | |||
b536ec4a5e |
@ -7,5 +7,5 @@ Dependencies:
|
|||||||
Options:
|
Options:
|
||||||
test-before-installing: True
|
test-before-installing: True
|
||||||
require-passing-tests-on: ['Linux', 'FreeBSD', 'Windows']
|
require-passing-tests-on: ['Linux', 'FreeBSD', 'Windows']
|
||||||
cmake-options: "-DKIMAGEFORMATS_DDS=ON -DKIMAGEFORMATS_JXR=ON"
|
cmake-options: "-DKIMAGEFORMATS_DDS=ON -DKIMAGEFORMATS_JXR=ON -DKIMAGEFORMATS_HEIF=ON"
|
||||||
per-test-timeout: 90
|
per-test-timeout: 90
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
set(KF_VERSION "6.11.0") # handled by release scripts
|
set(KF_VERSION "6.17.0") # handled by release scripts
|
||||||
set(KF_DEP_VERSION "6.11.0") # handled by release scripts
|
set(KF_DEP_VERSION "6.16.0") # handled by release scripts
|
||||||
project(KImageFormats VERSION ${KF_VERSION})
|
project(KImageFormats VERSION ${KF_VERSION})
|
||||||
|
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
find_package(ECM 6.11.0 NO_MODULE)
|
find_package(ECM 6.16.0 NO_MODULE)
|
||||||
set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules")
|
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)
|
feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ include(ECMDeprecationSettings)
|
|||||||
include(CheckIncludeFiles)
|
include(CheckIncludeFiles)
|
||||||
include(FindPkgConfig)
|
include(FindPkgConfig)
|
||||||
|
|
||||||
set(REQUIRED_QT_VERSION 6.6.0)
|
set(REQUIRED_QT_VERSION 6.7.0)
|
||||||
find_package(Qt6Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
find_package(Qt6Gui ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
|
||||||
|
|
||||||
find_package(KF6Archive ${KF_DEP_VERSION})
|
find_package(KF6Archive ${KF_DEP_VERSION})
|
||||||
@ -99,8 +99,8 @@ endif()
|
|||||||
add_feature_info(LibJXR LibJXR_FOUND "required for the QImage plugin for JPEG XR images")
|
add_feature_info(LibJXR LibJXR_FOUND "required for the QImage plugin for JPEG XR images")
|
||||||
|
|
||||||
ecm_set_disabled_deprecation_versions(
|
ecm_set_disabled_deprecation_versions(
|
||||||
QT 6.8.0
|
QT 6.9.0
|
||||||
KF 6.10.0
|
KF 6.13.0
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
@ -109,6 +109,28 @@ if (BUILD_TESTING)
|
|||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF6ImageFormats")
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
|
||||||
|
write_basic_package_version_file(
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/KF6ImageFormatsConfigVersion.cmake"
|
||||||
|
VERSION ${PROJECT_VERSION}
|
||||||
|
COMPATIBILITY AnyNewerVersion
|
||||||
|
)
|
||||||
|
|
||||||
|
configure_package_config_file(
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/KF6ImageFormatsConfig.cmake.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/KF6ImageFormatsConfig.cmake"
|
||||||
|
INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
|
||||||
|
)
|
||||||
|
|
||||||
|
install(FILES
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/KF6ImageFormatsConfig.cmake"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/KF6ImageFormatsConfigVersion.cmake"
|
||||||
|
DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
|
||||||
|
COMPONENT Devel
|
||||||
|
)
|
||||||
|
|
||||||
include(ECMFeatureSummary)
|
include(ECMFeatureSummary)
|
||||||
ecm_feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
ecm_feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||||
|
|
||||||
|
5
KF6ImageFormatsConfig.cmake.in
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2025 Xaver Hugl <xaver.hugl@gmail.com>
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
|
@PACKAGE_INIT@
|
||||||
|
# empty, because this is plugins for Qt instead of a library to link against
|
24
README.md
@ -17,6 +17,7 @@ The following image formats have read-only support:
|
|||||||
- Animated Windows cursors (ani)
|
- Animated Windows cursors (ani)
|
||||||
- Camera RAW images (arw, cr2, cr3, dcs, dng, ...)
|
- Camera RAW images (arw, cr2, cr3, dcs, dng, ...)
|
||||||
- Gimp (xcf)
|
- Gimp (xcf)
|
||||||
|
- Interchange Format Files (IFF)
|
||||||
- Krita (kra)
|
- Krita (kra)
|
||||||
- OpenRaster (ora)
|
- OpenRaster (ora)
|
||||||
- Pixar raster (pxr)
|
- Pixar raster (pxr)
|
||||||
@ -53,8 +54,10 @@ willing to sign the Qt Project contributor agreement, it may be better to
|
|||||||
submit the plugin directly to the Qt Project.
|
submit the plugin directly to the Qt Project.
|
||||||
|
|
||||||
To be accepted, contributions must:
|
To be accepted, contributions must:
|
||||||
- Contain the test images needed to verify that the changes work correctly
|
- Contain the test images needed to verify that the changes work correctly.
|
||||||
- Pass the tests successfully
|
- Pass the tests successfully.
|
||||||
|
|
||||||
|
For more info about tests, see also [Autotests README](autotests/README.md).
|
||||||
|
|
||||||
## Duplicated Plugins
|
## Duplicated Plugins
|
||||||
|
|
||||||
@ -125,9 +128,12 @@ About the image:
|
|||||||
example a verbal description of the image.
|
example a verbal description of the image.
|
||||||
- `Copyright`: Copyright notice of the person or organization that claims
|
- `Copyright`: Copyright notice of the person or organization that claims
|
||||||
the copyright to the image.
|
the copyright to the image.
|
||||||
- `CreationDate`: Creation date and time in ISO 8601 format without
|
- `CreationDate`: When the image was created or captured. Date and time in
|
||||||
milliseconds (e.g. 2024-03-23T15:30:43).
|
ISO 8601 format without milliseconds (e.g. 2024-03-23T15:30:43). This value
|
||||||
|
should be kept unchanged when present.
|
||||||
- `Description`: A string that describes the subject of the image.
|
- `Description`: A string that describes the subject of the image.
|
||||||
|
- `Direction`: Floating-point number indicating the direction of the image
|
||||||
|
when it was captured in degrees (e.g. 123.3).
|
||||||
- `DocumentName`: The name of the document from which this image was
|
- `DocumentName`: The name of the document from which this image was
|
||||||
scanned.
|
scanned.
|
||||||
- `HostComputer`: The computer and/or operating system in use at the time
|
- `HostComputer`: The computer and/or operating system in use at the time
|
||||||
@ -136,6 +142,9 @@ About the image:
|
|||||||
north of the equator (e.g. 27.717).
|
north of the equator (e.g. 27.717).
|
||||||
- `Longitude`: Floating-point number indicating the longitude in degrees
|
- `Longitude`: Floating-point number indicating the longitude in degrees
|
||||||
east of Greenwich (e.g. 85.317).
|
east of Greenwich (e.g. 85.317).
|
||||||
|
- `ModificationDate`: Last modification date and time in ISO 8601 format
|
||||||
|
without milliseconds (e.g. 2024-03-23T15:30:43). This value should be
|
||||||
|
updated every time the image is saved.
|
||||||
- `Owner`: Name of the owner of the image.
|
- `Owner`: Name of the owner of the image.
|
||||||
- `Software`: Name and version number of the software package(s) used to
|
- `Software`: Name and version number of the software package(s) used to
|
||||||
create the image.
|
create the image.
|
||||||
@ -189,6 +198,7 @@ are created automatically:
|
|||||||
- `Software`: Created using `applicationName` and `applicationVersion` methods
|
- `Software`: Created using `applicationName` and `applicationVersion` methods
|
||||||
of [`QCoreApplication`](https://doc.qt.io/qt-6/qcoreapplication.html).
|
of [`QCoreApplication`](https://doc.qt.io/qt-6/qcoreapplication.html).
|
||||||
- `CreationDate`: Set to current time and date.
|
- `CreationDate`: Set to current time and date.
|
||||||
|
- `ModificationDate`: Set to current time and date.
|
||||||
|
|
||||||
### ICC profile support
|
### ICC profile support
|
||||||
|
|
||||||
@ -213,7 +223,8 @@ plugin ('n/a' means no limit, i.e. the limit depends on the format encoding).
|
|||||||
- EPS: n/a
|
- EPS: n/a
|
||||||
- HDR: n/a (large image)
|
- HDR: n/a (large image)
|
||||||
- HEIF: n/a
|
- HEIF: n/a
|
||||||
- JP2: 300,000 x 300,000 pixels
|
- IFF: 65,535 x 65,535 pixels
|
||||||
|
- JP2: 300,000 x 300,000 pixels, in any case no larger than 2 gigapixels
|
||||||
- JXL: 262,144 x 262,144 pixels, in any case no larger than 256 megapixels
|
- JXL: 262,144 x 262,144 pixels, in any case no larger than 256 megapixels
|
||||||
- JXR: n/a, in any case no larger than 4 GB
|
- JXR: n/a, in any case no larger than 4 GB
|
||||||
- KRA: same size as Qt's PNG plugin
|
- KRA: same size as Qt's PNG plugin
|
||||||
@ -258,7 +269,7 @@ been used or the maximum size of the image that can be saved has been limited.
|
|||||||
PSD plugin loads CMYK, Lab and Multichannel images and converts them to RGB
|
PSD plugin loads CMYK, Lab and Multichannel images and converts them to RGB
|
||||||
without using the ICC profile.
|
without using the ICC profile.
|
||||||
|
|
||||||
JP2, JXR, PSD and SCT plugins natively support 4-channel CMYK images when
|
JP2, JXL, JXR, PSD and SCT plugins natively support 4-channel CMYK images when
|
||||||
compiled with Qt 6.8+.
|
compiled with Qt 6.8+.
|
||||||
|
|
||||||
### The DDS plugin
|
### The DDS plugin
|
||||||
@ -314,6 +325,7 @@ in your cmake options.**
|
|||||||
JP2 plugin has the following limitations due to the lack of support by OpenJPEG:
|
JP2 plugin has the following limitations due to the lack of support by OpenJPEG:
|
||||||
- Metadata are not supported.
|
- Metadata are not supported.
|
||||||
- Image resolution is not supported.
|
- Image resolution is not supported.
|
||||||
|
- To write ICC profiles you need OpenJPEG V2.5.4 or higher
|
||||||
|
|
||||||
### The JXL plugin
|
### The JXL plugin
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@ endmacro()
|
|||||||
# result against the data read from the corresponding png file
|
# result against the data read from the corresponding png file
|
||||||
kimageformats_read_tests(
|
kimageformats_read_tests(
|
||||||
hdr
|
hdr
|
||||||
|
iff
|
||||||
pcx
|
pcx
|
||||||
pfm
|
pfm
|
||||||
psd
|
psd
|
||||||
@ -122,9 +123,12 @@ if (LibHeif_FOUND)
|
|||||||
kimageformats_read_tests(FUZZ 1
|
kimageformats_read_tests(FUZZ 1
|
||||||
hej2
|
hej2
|
||||||
)
|
)
|
||||||
|
kimageformats_write_tests(FUZZ 1
|
||||||
|
hej2-nodatacheck-lossless
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (LibHeif_VERSION VERSION_GREATER_EQUAL "1.19.0")
|
if (LibHeif_VERSION VERSION_GREATER_EQUAL "1.19.6")
|
||||||
kimageformats_read_tests(FUZZ 4
|
kimageformats_read_tests(FUZZ 4
|
||||||
avci
|
avci
|
||||||
)
|
)
|
||||||
|
253
autotests/README.md
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
# Autotests
|
||||||
|
|
||||||
|
Automated testing for plugins to allow
|
||||||
|
[`QImage`](https://doc.qt.io/qt-6/qimage.html) to support
|
||||||
|
extra file formats.
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
The testing part is essential for the correct functioning of the plugins.
|
||||||
|
There are generic read/write tests and specific tests for the plugins that
|
||||||
|
require them.
|
||||||
|
|
||||||
|
## Read tests
|
||||||
|
|
||||||
|
The generic reading tests are contained in the `read` folder. Inside the
|
||||||
|
`read` folder, there are one or more folders for each plugin to be tested.
|
||||||
|
A plugin can support multiple image file types, and if you need different
|
||||||
|
parameters for each type, you need to create a folder for each type supported
|
||||||
|
by the plugin (see e.g. HEIF plugin). If all formats supported by the plugin
|
||||||
|
do not require different parameters, a single folder approach is simpler (see
|
||||||
|
e.g. PSD plugin).
|
||||||
|
|
||||||
|
The reading tests are mainly based on comparing the image read by the plugin
|
||||||
|
with a template in a known and working format. For this reason, the template
|
||||||
|
formats chosen are those distributed by the Qt project: PNG in the first
|
||||||
|
instance and TIFF for image formats not supported by PNG (e.g. CMYK images).
|
||||||
|
|
||||||
|
Some image options such as `QImageIOHandler::Size`,
|
||||||
|
`QImageIOHandler::ImageFormat` and `QImageIOHandler::ImageTransformation` are
|
||||||
|
also checked. If supported by the plugin, the resulting image is checked to
|
||||||
|
see if it is compatible with the option's specification.
|
||||||
|
|
||||||
|
Optionally, for each image, you can also create a JSON file to modify the test
|
||||||
|
behavior and/or verify data other than image pixels, such as metadata.
|
||||||
|
|
||||||
|
Finally, two tests are run for each test case:
|
||||||
|
- On a random access device: this test must not fail.
|
||||||
|
- On a sequential access device: a plugin may not support sequential operation.
|
||||||
|
In this case, the test is skipped. However, if an image is returned, the test
|
||||||
|
must succeed.
|
||||||
|
|
||||||
|
### The readtest command
|
||||||
|
|
||||||
|
To start a test, run the `readtest` command with the format to test as an
|
||||||
|
argument. The format is one of those supported by plugins and a folder with
|
||||||
|
the name of the format must be present inside the `read` folder.
|
||||||
|
Depending on the format, you can specify the following additional options.
|
||||||
|
|
||||||
|
- `--help`: Displays help on commandline options.
|
||||||
|
- `--fuzz <max>`: The fuzziness. Used to add some deviation in ARGB data
|
||||||
|
(nornally used on lossy codec).
|
||||||
|
- `--perceptive-fuzz`: Used to scale dynamically the fuzziness based on
|
||||||
|
the alpha channel value. This is useful on images with pre-multiplied and
|
||||||
|
small alphas. Qt can use different roundings based on optimizations resulting
|
||||||
|
in very different RGB values. Since the alpha is small visually there is no
|
||||||
|
difference (so it is not considered an error).
|
||||||
|
- `--skip-optional-tests`: Used to skip the optional test such as metadata
|
||||||
|
and resolution tests.
|
||||||
|
|
||||||
|
Note that some tests may fail if the correct options are not used. The correct
|
||||||
|
options for each test are defined in [CMakeLists.txt](CMakeLists.txt).
|
||||||
|
See also [Add a test to CMakeLists.txt](#add-a-test-to-cmakeliststxt).
|
||||||
|
|
||||||
|
### Test image nomenclature
|
||||||
|
|
||||||
|
Each test consists of the image to test, the verification image(s) (template)
|
||||||
|
and, optionally, the additional JSON file.
|
||||||
|
To be a test, the names of these files must be the same (except for
|
||||||
|
the extension). A test for a JXL image would be, for example, composed like
|
||||||
|
this:
|
||||||
|
- `testRGB.jxl`: The image to test.
|
||||||
|
- `testRGB.jxl.json`: The test behavior modifier (note that it must contain
|
||||||
|
the double extension).
|
||||||
|
- `testRGB.png`: How the image should look (template). The template name
|
||||||
|
can be different if specified in the JSON file.
|
||||||
|
|
||||||
|
Although there is no precise rule for the name of a test, it is good to have
|
||||||
|
a name that is explanatory.
|
||||||
|
|
||||||
|
### JSON behavior file
|
||||||
|
|
||||||
|
The behavior file was initially introduced to solve compatibility issues
|
||||||
|
between different versions of Qt supported by the framework. It was later
|
||||||
|
extended to also check image metadata.
|
||||||
|
|
||||||
|
The JSON file consists of an array of JSON objects. The objects in the array
|
||||||
|
are iterated sequentially and the first object that matches the requirements
|
||||||
|
is used for testing (successes are ignored).
|
||||||
|
|
||||||
|
Supported values for JSON objects:
|
||||||
|
- `comment`: Type string. A string shown by the test when a condition occurs.
|
||||||
|
- `description`: Type string. A description of the object. Not used by the
|
||||||
|
test.
|
||||||
|
- `disableAutoTransform`: Type boolean. By default, tests are run with
|
||||||
|
autotransform enabled (i.e. rotation is applied if the plugin supports it).
|
||||||
|
Set to `true` to disable autotransform.
|
||||||
|
- `filename`: Type string. Name of the template file to use. E.g.
|
||||||
|
"testRGB_Qt_6_2.png".
|
||||||
|
- `fuzziness`: Type integer. Set the fuzziness only if not already set on the
|
||||||
|
command line. The value set on the command line wins over the one in the JSON
|
||||||
|
file.
|
||||||
|
- `maxQtVersion`: Type string. Maximum Qt version this object is compatible
|
||||||
|
with (if not set means all). E.g. "6.2.99".
|
||||||
|
- `metadata`: Type Array. An array of key/value objects (string type)
|
||||||
|
containing the image metadata as returned by `QImage::text`.
|
||||||
|
- `minQtVersion`: Type string. Minimum Qt version this object is compatible
|
||||||
|
with (if not set means all). E.g. "6.2.0".
|
||||||
|
- `perceptiveFuzziness` Type boolean. Set the perceptive fuzziness only if not
|
||||||
|
already set on the command line. The value set on the command line wins over
|
||||||
|
the one in the JSON file.
|
||||||
|
- `resolution`: Type object. An object with the `dotsPerMeterX` and
|
||||||
|
`dotsPerMeterY` (integer) values of the image.
|
||||||
|
- `seeAlso`: Type string. More info about the object. Normally used to point
|
||||||
|
to bug reports. Not used by the test.
|
||||||
|
- `unsupportedFormat`: Type `boolean`. When true, the test is skipped.
|
||||||
|
|
||||||
|
Some examples:
|
||||||
|
- Example 1: [Runs only on Qt without alpha bug on float formats](read/jxl/testcard_rgba_fp16.jxl.json)
|
||||||
|
- Example 2: [Rotation disabled](read/jxl/orientation6_notranfs.jxl.json)
|
||||||
|
- Example 3: [Metadata](read/psd/metadata.psd.json)
|
||||||
|
- Example 4: [Check Qt version, resolution and metadata](read/psd/mch-16bits.psd.json)
|
||||||
|
- Example 5: [Fuzziness setting](read/xcf/birthday16.xcf.json)
|
||||||
|
|
||||||
|
These are just a few examples. More examples can be found in the test folders.
|
||||||
|
|
||||||
|
## Write tests
|
||||||
|
|
||||||
|
The generic writing tests are contained in the `write/basic` and
|
||||||
|
`write/format` folders. Similar to the read tests, they verify the written
|
||||||
|
(and then reread) image with a template.
|
||||||
|
|
||||||
|
The write test is composed of several phases:
|
||||||
|
- Basic test: Uses the `write/basic` folder and checks the most common images
|
||||||
|
and, optionally, metadata and resolution via a JSON properties file.
|
||||||
|
- Format test: Uses the `write/format` folder and checks that all QImage image
|
||||||
|
formats are written correctly.
|
||||||
|
- Dimensional test: Uses the `write/format` folder and check images of
|
||||||
|
different sizes (odd numbers, prime numbers, etc.) to verify internal
|
||||||
|
alignments.
|
||||||
|
- Null device test: Verify that there are no crashes if the device is null.
|
||||||
|
|
||||||
|
### The writetest command
|
||||||
|
|
||||||
|
To start a test, run the `writetest` command with the format to test as an
|
||||||
|
argument. The format is one of those supported by plugins, a folder with
|
||||||
|
the name of the format must be present inside the `write/format` folder and
|
||||||
|
may need a template image in `write/basic`.
|
||||||
|
Depending on the format, you can specify the following additional options.
|
||||||
|
|
||||||
|
- `--help`: Displays help on commandline options.
|
||||||
|
- `--create-format-templates`: Create template images for all formats
|
||||||
|
supported by the QImage in `write/format`. Command to simplify the creation of
|
||||||
|
format test images when adding a new plugin or modifying an old one. This
|
||||||
|
command is not intended to be used from the CMakeLists file as it must be used
|
||||||
|
manually and the generated images must be verified one by one.
|
||||||
|
- `--fuzz <max>`: The fuzziness. Used to add some deviation in ARGB data
|
||||||
|
(nornally used on lossy codec).
|
||||||
|
- `--lossless`: Check that reading back the data gives the same image.
|
||||||
|
- `--no-data-check`: Don't check that write data is exactly the same.
|
||||||
|
- `--skip-optional-tests`: Skip optional data tests (metadata, resolution,
|
||||||
|
etc...).
|
||||||
|
|
||||||
|
Note that some tests may fail if the correct options are not used. The correct
|
||||||
|
options for each test are defined in [CMakeLists.txt](CMakeLists.txt).
|
||||||
|
See also [Add a test to CMakeLists.txt](#add-a-test-to-cmakeliststxt).
|
||||||
|
|
||||||
|
### JSON properties file
|
||||||
|
|
||||||
|
The properties file must be located in `write/basic` and must have the name
|
||||||
|
of the file format (e.g. jxl.json). It is a JSON object composed of the
|
||||||
|
following values:
|
||||||
|
- `format`: Type string. The format tested.
|
||||||
|
- `metadata`: Type Array. An array of key/value objects (string type)
|
||||||
|
containing the image metadata as returned by `QImage::text`.
|
||||||
|
- `resolution`: Type object. An object with the `dotsPerMeterX` and `
|
||||||
|
dotsPerMeterY` (integer) values of the image.
|
||||||
|
|
||||||
|
[This is an example](write/basic/jxl.json) of property file.
|
||||||
|
|
||||||
|
|
||||||
|
## Custom tests
|
||||||
|
|
||||||
|
If the generic read/write tests do not meet the requirements of a plugin,
|
||||||
|
it is possible to write a custom test.
|
||||||
|
In general it makes sense to write a dedicated test for a format if and
|
||||||
|
only if you are testing unique features not present in other plugins.
|
||||||
|
|
||||||
|
### The PIC test
|
||||||
|
|
||||||
|
The PIC test is generated using Qt Test class. For more information
|
||||||
|
see [Qt Test](https://doc.qt.io/qt-6/qttest-index.html).
|
||||||
|
|
||||||
|
### The ANI test
|
||||||
|
|
||||||
|
The ANI test is generated using Qt Test class. For more information
|
||||||
|
see [Qt Test](https://doc.qt.io/qt-6/qttest-index.html).
|
||||||
|
|
||||||
|
|
||||||
|
## Add a test to CMakeLists.txt
|
||||||
|
|
||||||
|
To add a test to CMake use the `kimageformats_read_tests` and
|
||||||
|
`kimageformats_write_tests` functions. For example, to add the read
|
||||||
|
tests for the PSD you just write `kimageformats_read_tests(psd)`.
|
||||||
|
|
||||||
|
It is also possible to pass command line arguments to the test by
|
||||||
|
appropriately composing the string passed to the test functions.
|
||||||
|
For boolean parameters you need to add a string starting with '-'
|
||||||
|
after the image format. For example, to pass `--skip-optional-tests`
|
||||||
|
to the PSD plugin write `kimageformats_read_tests(psd-skipoptional)`.
|
||||||
|
|
||||||
|
To add a fuzziness of 4, you must first set it as follows:
|
||||||
|
`kimageformats_read_tests(FUZZ 4 psd-skipoptional)`.
|
||||||
|
|
||||||
|
The possible modifiers for `kimageformats_read_tests` are as follows:
|
||||||
|
- `-skipoptional`: Add the `--skip-optional-tests` command line parameter.
|
||||||
|
|
||||||
|
The possible modifiers for `kimageformats_write_tests` are as follows:
|
||||||
|
- `-lossless`: Add the `--lossless` command line parameter.
|
||||||
|
- `-nodatacheck`: Add the `--no-data-check` command line parameter.
|
||||||
|
- `-skipoptional`: Add the `--skip-optional-tests` command line parameter.
|
||||||
|
|
||||||
|
To set multiple parameters, you can enter multiple modifiers. For example:
|
||||||
|
```
|
||||||
|
kimageformats_write_tests(FUZZ 1
|
||||||
|
hej2-nodatacheck-lossless
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## OSS-Fuzz
|
||||||
|
|
||||||
|
Plugins are also tested with [OSS-Fuzz](https://google.github.io/oss-fuzz/)
|
||||||
|
project to identify possible security issues. When adding a new plugin it is
|
||||||
|
also necessary to add it to the test in the [kimageformats
|
||||||
|
project](https://github.com/google/oss-fuzz/tree/master/projects/kimageformats)
|
||||||
|
on OSS-Fuzz.
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
List of tests not implemented or only partially implemented.
|
||||||
|
|
||||||
|
### Color Profiles Test
|
||||||
|
|
||||||
|
Many plugins support color profiles via [`QColorSpace`](https://doc.qt.io/qt-6/qcolorspace.html).
|
||||||
|
Checking for correct color management is increasingly necessary especially now
|
||||||
|
that monitors are HDR and other than RGB color spaces have been added to Qt.
|
||||||
|
|
||||||
|
Furthermore, lossy plugins often have different color management behaviors
|
||||||
|
depending on how the image is saved.
|
||||||
|
|
||||||
|
### Animations Test
|
||||||
|
|
||||||
|
Few plugins support animations. There are currently no plans for
|
||||||
|
implementation.
|
BIN
autotests/read/avif/metadata.avif
Normal file
After Width: | Height: | Size: 18 KiB |
59
autotests/read/avif/metadata.avif.json
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fileName" : "metadata.png",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "ModificationDate",
|
||||||
|
"value" : "2025-02-19T08:27:22+01:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "GIMP 3.0.0-RC3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Altitude",
|
||||||
|
"value" : "34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Author",
|
||||||
|
"value" : "KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Copyright",
|
||||||
|
"value" : "@2025 KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Description",
|
||||||
|
"value" : "TV broadcast test image."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Latitude",
|
||||||
|
"value" : "44.6478"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensManufacturer",
|
||||||
|
"value" : "KDE Glasses"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensModel",
|
||||||
|
"value" : "A1234"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Longitude",
|
||||||
|
"value" : "10.9254"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Manufacturer",
|
||||||
|
"value" : "KFramework"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Model",
|
||||||
|
"value" : "KImageFormats"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resolution" : {
|
||||||
|
"dotsPerMeterX" : 11811,
|
||||||
|
"dotsPerMeterY" : 5905
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
BIN
autotests/read/avif/metadata.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
autotests/read/heif/metadata.heif
Normal file
59
autotests/read/heif/metadata.heif.json
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fileName" : "metadata.png",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "ModificationDate",
|
||||||
|
"value" : "2025-02-26T16:52:06Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "LIFE Pro 2.18.10 (Linux)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Altitude",
|
||||||
|
"value" : "34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Author",
|
||||||
|
"value" : "KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Copyright",
|
||||||
|
"value" : "@2025 KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Description",
|
||||||
|
"value" : "TV broadcast test image."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Latitude",
|
||||||
|
"value" : "44.6478"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensManufacturer",
|
||||||
|
"value" : "KDE Glasses"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensModel",
|
||||||
|
"value" : "A1234"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Longitude",
|
||||||
|
"value" : "10.9254"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Manufacturer",
|
||||||
|
"value" : "KFramework"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Model",
|
||||||
|
"value" : "KImageFormats"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resolution" : {
|
||||||
|
"dotsPerMeterX" : 11811,
|
||||||
|
"dotsPerMeterY" : 5905
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
BIN
autotests/read/heif/metadata.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
autotests/read/iff/blue_noise_rgba16.iff
Normal file
BIN
autotests/read/iff/blue_noise_rgba16.png
Normal file
After Width: | Height: | Size: 103 KiB |
BIN
autotests/read/iff/blue_noise_rgba8.iff
Normal file
BIN
autotests/read/iff/blue_noise_rgba8.png
Normal file
After Width: | Height: | Size: 53 KiB |
BIN
autotests/read/iff/flag_ham6.iff
Normal file
BIN
autotests/read/iff/flag_ham6.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
autotests/read/iff/ps_testcard_bitmap_amiga.iff
Normal file
BIN
autotests/read/iff/ps_testcard_bitmap_amiga.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
autotests/read/iff/ps_testcard_gray_amiga.iff
Normal file
BIN
autotests/read/iff/ps_testcard_gray_amiga.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
autotests/read/iff/ps_testcard_indexed_amiga.iff
Normal file
BIN
autotests/read/iff/ps_testcard_indexed_amiga.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
autotests/read/iff/ps_testcard_rgb16_maya.iff
Normal file
BIN
autotests/read/iff/ps_testcard_rgb16_maya.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
autotests/read/iff/ps_testcard_rgb_amiga.iff
Normal file
BIN
autotests/read/iff/ps_testcard_rgb_amiga.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
autotests/read/iff/ps_testcard_rgb_maya.iff
Normal file
BIN
autotests/read/iff/ps_testcard_rgb_maya.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
autotests/read/iff/ps_testcard_rgba16_maya.iff
Normal file
BIN
autotests/read/iff/ps_testcard_rgba16_maya.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
autotests/read/iff/ps_testcard_rgba_maya.iff
Normal file
BIN
autotests/read/iff/ps_testcard_rgba_maya.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
autotests/read/iff/testcard_indexed2_amiga.iff
Normal file
BIN
autotests/read/iff/testcard_indexed2_amiga.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
autotests/read/iff/testcard_indexed3_amiga.iff
Normal file
BIN
autotests/read/iff/testcard_indexed3_amiga.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
autotests/read/iff/testcard_indexed4_amiga.iff
Normal file
BIN
autotests/read/iff/testcard_indexed4_amiga.png
Normal file
After Width: | Height: | Size: 9.3 KiB |
@ -3,7 +3,7 @@
|
|||||||
"fileName" : "gimp_exif.png",
|
"fileName" : "gimp_exif.png",
|
||||||
"metadata" : [
|
"metadata" : [
|
||||||
{
|
{
|
||||||
"key" : "CreationDate",
|
"key" : "ModificationDate",
|
||||||
"value" : "2025-01-05T10:18:16"
|
"value" : "2025-01-05T10:18:16"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
BIN
autotests/read/jxr/metadata.jxr
Normal file
59
autotests/read/jxr/metadata.jxr.json
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fileName" : "metadata.png",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "CreationDate",
|
||||||
|
"value" : "2025-01-14T10:34:51Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "LIFE Pro 2.18.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Altitude",
|
||||||
|
"value" : "34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Author",
|
||||||
|
"value" : "KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Copyright",
|
||||||
|
"value" : "@2025 KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Description",
|
||||||
|
"value" : "TV broadcast test image."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Latitude",
|
||||||
|
"value" : "44.6478"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensManufacturer",
|
||||||
|
"value" : "KDE Glasses"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensModel",
|
||||||
|
"value" : "A1234"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Longitude",
|
||||||
|
"value" : "10.9254"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Manufacturer",
|
||||||
|
"value" : "KFramework"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Model",
|
||||||
|
"value" : "KImageFormats"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resolution" : {
|
||||||
|
"dotsPerMeterX" : 11811,
|
||||||
|
"dotsPerMeterY" : 5906
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
BIN
autotests/read/jxr/metadata.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
autotests/read/jxr/orientation1.jxr
Normal file
11
autotests/read/jxr/orientation1.jxr.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fileName" : "orientation_all.png",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "LIFE Pro 2.18.10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
autotests/read/jxr/orientation2.jxr
Normal file
11
autotests/read/jxr/orientation2.jxr.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fileName" : "orientation_all.png",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "LIFE Pro 2.18.10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
autotests/read/jxr/orientation3.jxr
Normal file
11
autotests/read/jxr/orientation3.jxr.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fileName" : "orientation_all.png",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "LIFE Pro 2.18.10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
autotests/read/jxr/orientation4.jxr
Normal file
11
autotests/read/jxr/orientation4.jxr.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fileName" : "orientation_all.png",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "LIFE Pro 2.18.10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
autotests/read/jxr/orientation5.jxr
Normal file
11
autotests/read/jxr/orientation5.jxr.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fileName" : "orientation_all.png",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "LIFE Pro 2.18.10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
autotests/read/jxr/orientation6.jxr
Normal file
11
autotests/read/jxr/orientation6.jxr.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fileName" : "orientation_all.png",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "LIFE Pro 2.18.10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
autotests/read/jxr/orientation7.jxr
Normal file
11
autotests/read/jxr/orientation7.jxr.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fileName" : "orientation_all.png",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "LIFE Pro 2.18.10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
autotests/read/jxr/orientation8.jxr
Normal file
11
autotests/read/jxr/orientation8.jxr.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"fileName" : "orientation_all.png",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "LIFE Pro 2.18.10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
BIN
autotests/read/jxr/orientation_all.png
Normal file
After Width: | Height: | Size: 18 KiB |
@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"metadata" : [
|
"metadata" : [
|
||||||
{
|
{
|
||||||
"key" : "CreationDate",
|
"key" : "ModificationDate",
|
||||||
"value" : "2022-11-11T14:27:52"
|
"value" : "2022-11-11T14:27:52"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"metadata" : [
|
"metadata" : [
|
||||||
{
|
{
|
||||||
"key" : "CreationDate",
|
"key" : "ModificationDate",
|
||||||
"value" : "2022-11-11T14:27:39"
|
"value" : "2022-11-11T14:27:39"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"fileName" : "metadata.png",
|
"fileName" : "metadata.png",
|
||||||
"metadata" : [
|
"metadata" : [
|
||||||
{
|
{
|
||||||
"key" : "CreationDate",
|
"key" : "ModificationDate",
|
||||||
"value" : "2025-01-14T13:53:32+01:00"
|
"value" : "2025-01-14T13:53:32+01:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
BIN
autotests/read/tga/colormapped.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
autotests/read/tga/colormapped.tga
Normal file
@ -258,6 +258,15 @@ int main(int argc, char **argv)
|
|||||||
});
|
});
|
||||||
QTextStream(stdout) << "QImageReader::supportedImageFormats: " << formatStrings.join(", ") << "\n";
|
QTextStream(stdout) << "QImageReader::supportedImageFormats: " << formatStrings.join(", ") << "\n";
|
||||||
|
|
||||||
|
if (!formats.contains(format)) {
|
||||||
|
if (format == "avci" || format == "heif" || format == "hej2") {
|
||||||
|
QTextStream(stdout) << "WARNING : " << suffix << " is not supported with current libheif configuration!\n"
|
||||||
|
<< "********* "
|
||||||
|
<< "Finished basic read tests for " << suffix << " images *********\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const QFileInfoList lstImgDir = imgdir.entryInfoList();
|
const QFileInfoList lstImgDir = imgdir.entryInfoList();
|
||||||
// Launch 2 runs for each test: first run on a random access device, second run on a sequential access device
|
// Launch 2 runs for each test: first run on a random access device, second run on a sequential access device
|
||||||
for (int seq = 0; seq < 2; ++seq) {
|
for (int seq = 0; seq < 2; ++seq) {
|
||||||
@ -323,7 +332,12 @@ int main(int argc, char **argv)
|
|||||||
OptionTest optionTest;
|
OptionTest optionTest;
|
||||||
if (!optionTest.store(&inputReader)) {
|
if (!optionTest.store(&inputReader)) {
|
||||||
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": error while reading options\n";
|
QTextStream(stdout) << "FAIL : " << fi.fileName() << ": error while reading options\n";
|
||||||
++failed;
|
if (format == "heif") {
|
||||||
|
// libheif + ffmpeg decoder is unable to load all HEIF files.
|
||||||
|
++skipped;
|
||||||
|
} else {
|
||||||
|
++failed;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
65
autotests/write/basic/avif.json
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"format" : "avif",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "CreationDate",
|
||||||
|
"value" : "2025-01-14T13:53:32+01:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Direction",
|
||||||
|
"value" : "123.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "ModificationDate",
|
||||||
|
"value" : "2025-02-14T15:58:44+01:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "Adobe Photoshop 26.2 (Windows)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Altitude",
|
||||||
|
"value" : "34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Author",
|
||||||
|
"value" : "KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Copyright",
|
||||||
|
"value" : "@2025 KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Description",
|
||||||
|
"value" : "テレビ放送テスト映像。(TV broadcast test image.)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Latitude",
|
||||||
|
"value" : "44.6478"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensManufacturer",
|
||||||
|
"value" : "KDE Glasses"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensModel",
|
||||||
|
"value" : "A1234"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Longitude",
|
||||||
|
"value" : "10.9254"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Manufacturer",
|
||||||
|
"value" : "KFramework"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Model",
|
||||||
|
"value" : "KImageFormats"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resolution" : {
|
||||||
|
"dotsPerMeterX" : 11811,
|
||||||
|
"dotsPerMeterY" : 11812
|
||||||
|
}
|
||||||
|
}
|
65
autotests/write/basic/heif.json
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"format" : "heif",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "CreationDate",
|
||||||
|
"value" : "2025-01-14T13:53:32+01:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Direction",
|
||||||
|
"value" : "123.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "ModificationDate",
|
||||||
|
"value" : "2025-02-14T15:58:44+01:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "Adobe Photoshop 26.2 (Windows)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Altitude",
|
||||||
|
"value" : "34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Author",
|
||||||
|
"value" : "KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Copyright",
|
||||||
|
"value" : "@2025 KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Description",
|
||||||
|
"value" : "テレビ放送テスト映像。(TV broadcast test image.)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Latitude",
|
||||||
|
"value" : "44.6478"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensManufacturer",
|
||||||
|
"value" : "KDE Glasses"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensModel",
|
||||||
|
"value" : "A1234"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Longitude",
|
||||||
|
"value" : "10.9254"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Manufacturer",
|
||||||
|
"value" : "KFramework"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Model",
|
||||||
|
"value" : "KImageFormats"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resolution" : {
|
||||||
|
"dotsPerMeterX" : 11811,
|
||||||
|
"dotsPerMeterY" : 11812
|
||||||
|
}
|
||||||
|
}
|
65
autotests/write/basic/hej2.json
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"format" : "hej2",
|
||||||
|
"metadata" : [
|
||||||
|
{
|
||||||
|
"key" : "CreationDate",
|
||||||
|
"value" : "2025-01-14T13:53:32+01:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Direction",
|
||||||
|
"value" : "123.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "ModificationDate",
|
||||||
|
"value" : "2025-02-14T15:58:44+01:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Software" ,
|
||||||
|
"value" : "Adobe Photoshop 26.2 (Windows)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Altitude",
|
||||||
|
"value" : "34"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Author",
|
||||||
|
"value" : "KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Copyright",
|
||||||
|
"value" : "@2025 KDE Project"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Description",
|
||||||
|
"value" : "TV broadcast test image."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Latitude",
|
||||||
|
"value" : "44.6478"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensManufacturer",
|
||||||
|
"value" : "KDE Glasses"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensModel",
|
||||||
|
"value" : "A1234"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Longitude",
|
||||||
|
"value" : "10.9254"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Manufacturer",
|
||||||
|
"value" : "KFramework"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Model",
|
||||||
|
"value" : "KImageFormats"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"resolution" : {
|
||||||
|
"dotsPerMeterX" : 11811,
|
||||||
|
"dotsPerMeterY" : 11812
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,14 @@
|
|||||||
"key" : "CreationDate",
|
"key" : "CreationDate",
|
||||||
"value" : "2025-01-14T13:53:32+01:00"
|
"value" : "2025-01-14T13:53:32+01:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key" : "Direction",
|
||||||
|
"value" : "123.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "ModificationDate",
|
||||||
|
"value" : "2025-02-14T15:58:44+01:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key" : "Software" ,
|
"key" : "Software" ,
|
||||||
"value" : "Adobe Photoshop 26.2 (Windows)"
|
"value" : "Adobe Photoshop 26.2 (Windows)"
|
||||||
@ -23,7 +31,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key" : "Description",
|
"key" : "Description",
|
||||||
"value" : "TV broadcast test image."
|
"value" : "テレビ放送テスト映像。(TV broadcast test image.)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key" : "Latitude",
|
"key" : "Latitude",
|
||||||
|
@ -5,6 +5,18 @@
|
|||||||
"key" : "CreationDate",
|
"key" : "CreationDate",
|
||||||
"value" : "2025-01-14T13:53:32+01:00"
|
"value" : "2025-01-14T13:53:32+01:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key" : "Direction",
|
||||||
|
"value" : "123.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "ModificationDate",
|
||||||
|
"value" : "2025-02-14T15:58:44+01:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Altitude",
|
||||||
|
"value" : "34"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key" : "Author",
|
"key" : "Author",
|
||||||
"value" : "KDE Project"
|
"value" : "KDE Project"
|
||||||
@ -17,6 +29,22 @@
|
|||||||
"key" : "Description",
|
"key" : "Description",
|
||||||
"value" : "TV broadcast test image."
|
"value" : "TV broadcast test image."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key" : "Latitude",
|
||||||
|
"value" : "44.6478"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensManufacturer",
|
||||||
|
"value" : "KDE Glasses"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "LensModel",
|
||||||
|
"value" : "A1234"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key" : "Longitude",
|
||||||
|
"value" : "10.9254"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key" : "Manufacturer",
|
"key" : "Manufacturer",
|
||||||
"value" : "KFramework"
|
"value" : "KFramework"
|
||||||
|