Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jpeg: add encodingProcess and numColorComponents SOF members (backport #2874) #2887

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/on_PR_linux_special_builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jobs:

- name: install dependencies
run: |
sudo apt-get install -y libxml2-dev libxslt-dev python3-dev
python3 -m pip install conan==1.59.0 gcovr ninja

- name: Conan common config
Expand Down
15 changes: 15 additions & 0 deletions include/exiv2/jpgimage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ class EXIV2API JpegBase : public Image {
virtual int writeHeader(BasicIo& oIo) const = 0;
//@}

int num_color_components_{-1}; //!< image number of color components
std::string sof_encoding_process_; //!< image encoding process

private:
//! @name Manipulators
//@{
Expand Down Expand Up @@ -153,6 +156,18 @@ class EXIV2API JpegImage : public JpegBase {
//! @name Accessors
//@{
[[nodiscard]] std::string mimeType() const override;
/*!
@brief Get the number of color components of the JPEG Image
*/
[[nodiscard]] int numColorComponents() const {
return num_color_components_;
}
/*!
@brief Get the encoding process of the JPEG Image derived from the Start of Frame (SOF) markers
*/
[[nodiscard]] std::string encodingProcess() const {
return sof_encoding_process_;
}
//@}

protected:
Expand Down
33 changes: 33 additions & 0 deletions samples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# CMakeLists.txt for exiv2 library sample applications

<<<<<<< HEAD
set( SAMPLES
addmoddel.cpp
convert-test.cpp
Expand Down Expand Up @@ -29,6 +30,38 @@ set( SAMPLES
xmpprint.cpp
xmpsample.cpp
xmpdump.cpp
=======
set(SAMPLES
addmoddel.cpp
convert-test.cpp
easyaccess-test.cpp
exifcomment.cpp
exifdata-test.cpp
exifdata.cpp
exifprint.cpp
exifvalue.cpp
ini-test.cpp
iotest.cpp
iptceasy.cpp
iptcprint.cpp
iptctest.cpp
jpegparsetest.cpp
key-test.cpp
largeiptc-test.cpp
mmap-test.cpp
mrwthumb.cpp
prevtest.cpp
stringto-test.cpp
taglist.cpp
tiff-test.cpp
write-test.cpp
write2-test.cpp
xmpparse.cpp
xmpparser-test.cpp
xmpprint.cpp
xmpsample.cpp
xmpdump.cpp
>>>>>>> 6b5cb9841 (Add test to validate jpeg parse)
)

##
Expand Down
28 changes: 28 additions & 0 deletions samples/jpegparsetest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Sample program to parse jpeg files and obtain its specific metadata

#include <exiv2/exiv2.hpp>
#include <exiv2/image_types.hpp>
#include <iostream>

int main(int argc, char* const argv[]) {
try {
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " file\n";
return EXIT_FAILURE;
}

auto image = Exiv2::ImageFactory::open(argv[1]);
if (image->imageType() == Exiv2::ImageType::jpeg) {
auto jpegImage = dynamic_cast<Exiv2::JpegImage*>(image.get());
jpegImage->readMetadata();
std::cout << "Number of color components: " << jpegImage->numColorComponents() << "\n";
std::cout << "Encoding process: " << jpegImage->encodingProcess() << "\n";
}

return EXIT_SUCCESS;
} catch (Exiv2::Error& e) {
std::cout << "Caught Exiv2 exception '" << e << "'\n";
return EXIT_FAILURE;
}
}
35 changes: 35 additions & 0 deletions src/jpgimage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
#include "error.hpp"
#include "futils.hpp"
#include "helper_functions.hpp"
#include "i18n.h" // NLS support.
#include "image_int.hpp"
#include "jpgimage.hpp"
#include "photoshop.hpp"
#include "safe_op.hpp"
#include "tags_int.hpp"
#include "utils.hpp"

#ifdef _WIN32
Expand Down Expand Up @@ -49,14 +51,40 @@ constexpr byte rst1_ = 0xd0; //!< JPEG Restart 0 Marker (from 0xD0 to 0xD7 ther

// Start of Frame markers, nondifferential Huffman-coding frames
constexpr byte sof0_ = 0xc0; //!< JPEG Start-Of-Frame marker
constexpr byte sof1_ = 0xc1; //!< JPEG Start-Of-Frame marker
constexpr byte sof2_ = 0xc2; //!< JPEG Start-Of-Frame marker
constexpr byte sof3_ = 0xc3; //!< JPEG Start-Of-Frame marker

// Start of Frame markers, differential Huffman-coding frames
constexpr byte sof5_ = 0xc5; //!< JPEG Start-Of-Frame marker
constexpr byte sof6_ = 0xc6; //!< JPEG Start-Of-Frame marker
constexpr byte sof7_ = 0xc6; //!< JPEG Start-Of-Frame marker

// Start of Frame markers, differential arithmetic-coding frames
constexpr byte sof9_ = 0xc9; //!< JPEG Start-Of-Frame marker
constexpr byte sof10_ = 0xca; //!< JPEG Start-Of-Frame marker
constexpr byte sof11_ = 0xcb; //!< JPEG Start-Of-Frame marker
constexpr byte sof13_ = 0xcd; //!< JPEG Start-Of-Frame marker
constexpr byte sof14_ = 0xce; //!< JPEG Start-Of-Frame marker
constexpr byte sof15_ = 0xcf; //!< JPEG Start-Of-Frame marker

// JPEG process SOF markers
constexpr Internal::TagDetails jpegProcessMarkerTags[] = {
{sof0_, N_("Baseline DCT, Huffman coding")},
{sof1_, N_("Extended sequential DCT, Huffman coding")},
{sof2_, N_("Progressive DCT, Huffman coding")},
{sof3_, N_("Lossless, Huffman coding")},
{sof5_, N_("Sequential DCT, differential Huffman coding")},
{sof6_, N_("Progressive DCT, differential Huffman coding")},
{sof7_, N_("Lossless, Differential Huffman coding")},
{sof9_, N_("Extended sequential DCT, arithmetic coding")},
{sof10_, N_("Progressive DCT, arithmetic coding")},
{sof11_, N_("Lossless, arithmetic coding")},
{sof13_, N_("Sequential DCT, differential arithmetic coding")},
{sof14_, N_("Progressive DCT, differential arithmetic coding")},
{sof15_, N_("Lossless, differential arithmetic coding")},
};

constexpr auto exifId_ = "Exif\0\0"; //!< Exif identifier
// constexpr auto jfifId_ = "JFIF\0"; //!< JFIF identifier
constexpr auto xmpId_ = "http://ns.adobe.com/xap/1.0/\0"; //!< XMP packet identifier
Expand Down Expand Up @@ -159,6 +187,13 @@ void JpegBase::readMetadata() {
std::copy(sizebuf.begin(), sizebuf.end(), buf.begin());
}

if (auto itSofMarker = Exiv2::find(jpegProcessMarkerTags, marker)) {
sof_encoding_process_ = itSofMarker->label_;
if (size >= 7 && buf.c_data(7)) {
num_color_components_ = *buf.c_data(7);
}
}

if (!foundExifData && marker == app1_ && size >= 8 // prevent out-of-bounds read in memcmp on next line
&& buf.cmpBytes(2, exifId_, 6) == 0) {
ByteOrder bo = ExifParser::decode(exifData_, buf.c_data(8), size - 8);
Expand Down
13 changes: 13 additions & 0 deletions tests/bash_tests/test_jpegparse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-

import system_tests

class TestJpegParse(metaclass=system_tests.CaseMeta):
url = "https://github.com/Exiv2/exiv2/pull/2874"

# Test extraction of jpeg specific metadata
filename = "$data_path/exiv2-fujifilm-finepix-s2pro.jpg"
commands = ["$jpegparsetest $filename"]
stderr = [""] * len(commands)
stdout = ["""Number of color components: 3\nEncoding process: Baseline DCT, Huffman coding\n"""]
retval = [0] * len(commands)
1 change: 1 addition & 0 deletions tests/suite.conf
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ tiff_test: ${ENV:exiv2_path}/tiff-test
largeiptc_test: ${ENV:exiv2_path}/largeiptc-test
easyaccess_test: ${ENV:exiv2_path}/easyaccess-test
taglist: ${ENV:exiv2_path}/taglist
jpegparsetest: ${ENV:exiv2_path}/jpegparsetest

[variables]
kerOffsetOutOfRange: Offset out of range
Expand Down
Loading