Skip to content

Commit

Permalink
Merge pull request #1072 from bradh/openjph
Browse files Browse the repository at this point in the history
openjph: HT-J2K encoder
  • Loading branch information
farindk authored Jan 16, 2024
2 parents e4ddcc6 + d621840 commit d7e3fa8
Show file tree
Hide file tree
Showing 18 changed files with 1,089 additions and 12 deletions.
28 changes: 23 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,14 @@ if (WITH_FFMPEG_DECODER)
find_package(FFMPEG COMPONENTS avcodec)
endif ()

# openjph

plugin_option(OPENJPH_ENCODER "OpenJPH HT-J2K encoder" OFF ON)
# plugin_option(OPENJPH_DECODER "OpenJPH HT-J2K decoder" OFF ON)
if (WITH_OPENJPH_ENCODER OR WITH_OPENJPH_DECODER)
find_package(OPENJPH)
endif()

# uncompressed

option(WITH_UNCOMPRESSED_CODEC " Support internal ISO/IEC 23001-17 uncompressed codec (experimental) " OFF)
Expand All @@ -206,7 +214,8 @@ plugin_compilation_info(JPEG_DECODER JPEG "JPEG decoder")
plugin_compilation_info(JPEG_ENCODER JPEG "JPEG encoder")
plugin_compilation_info(OpenJPEG_DECODER OpenJPEG "OpenJPEG J2K decoder")
plugin_compilation_info(OpenJPEG_ENCODER OpenJPEG "OpenJPEG J2K encoder")

# plugin_compilation_info(OPENJPH_DECODER OPENJPH "OpenJPH HT-J2K decoder")
plugin_compilation_info(OPENJPH_ENCODER OPENJPH "OpenJPH HT-J2K encoder")

# --- show summary which formats are supported

Expand All @@ -224,9 +233,9 @@ macro(format_compilation_info formatName decoding_supported encoding_supported)
endif()

string(LENGTH "${formatName}" len)
math(EXPR fill "10 - ${len}")
math(EXPR fill "12 - ${len}")
string(SUBSTRING " " 0 ${fill} filler)
message("${formatName}${filler} ${decoding} ${encoding}")
message("${formatName}${filler} ${decoding} ${encoding}")
unset(msg)
endmacro()

Expand All @@ -251,22 +260,31 @@ if (JPEG_FOUND AND WITH_JPEG_ENCODER)
endif()
if (OpenJPEG_FOUND AND WITH_OpenJPEG_DECODER)
set(SUPPORTS_J2K_DECODING TRUE)
set(SUPPORTS_J2K_HT_DECODING TRUE)
endif()
if (OpenJPEG_FOUND AND WITH_OpenJPEG_ENCODER)
set(SUPPORTS_J2K_ENCODING TRUE)
endif()
if (OPENJPH_FOUND AND WITH_OPENJPH_ENCODER)
set(SUPPORTS_J2K_HT_ENCODING TRUE)
endif()
if (OPENJPH_FOUND AND WITH_OPENJPH_DECODER)
set(SUPPORTS_J2K_HT_ENCODING TRUE)
endif()

if (WITH_UNCOMPRESSED_CODEC)
set(SUPPORTS_UNCOMPRESSED_DECODING TRUE)
set(SUPPORTS_UNCOMPRESSED_ENCODING TRUE)
endif()

message("\n=== Supported formats ===")
message("format decoding encoding")
message("format decoding encoding")
format_compilation_info("HEIC" SUPPORTS_HEIC_DECODING SUPPORTS_HEIC_ENCODING)
format_compilation_info("AVIF" SUPPORTS_AVIF_DECODING SUPPORTS_AVIF_ENCODING)
format_compilation_info("JPEG" SUPPORTS_JPEG_DECODING SUPPORTS_JPEG_ENCODING)
format_compilation_info("JPEG2000" SUPPORTS_J2K_DECODING SUPPORTS_J2K_ENCODING)
format_compilation_info("Uncompr." SUPPORTS_UNCOMPRESSED_DECODING SUPPORTS_UNCOMPRESSED_ENCODING)
format_compilation_info("JPEG2000-HT" SUPPORTS_J2K_HT_DECODING SUPPORTS_J2K_HT_ENCODING)
format_compilation_info("Uncompressed" SUPPORTS_UNCOMPRESSED_DECODING SUPPORTS_UNCOMPRESSED_ENCODING)
message("")

# --- Libsharpyuv color space transforms
Expand Down
3 changes: 2 additions & 1 deletion CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"WITH_OpenJPEG_ENCODER" : "ON",
"WITH_OpenJPEG_ENCODER_PLUGIN" : "ON",
"WITH_FFMPEG_DECODER" : "ON",
"WITH_FFMPEG_DECODER_PLUGIN" : "ON"
"WITH_FFMPEG_DECODER_PLUGIN" : "ON",
}
},
{
Expand All @@ -63,6 +63,7 @@
"WITH_KVAZAAR" : "ON",
"WITH_OpenJPEG_DECODER" : "ON",
"WITH_OpenJPEG_ENCODER" : "ON",
"WITH_OPENJPH_ENCODER" : "ON",
"WITH_FFMPEG_DECODER" : "ON",
"WITH_REDUCED_VISIBILITY" : "OFF",
"WITH_DEFLATE_HEADER_COMPRESSION" : "ON",
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ For each codec, there are two configuration variables:
* `WITH_{codec}_PLUGIN`: when enabled, the codec is compiled as a separate plugin.

In order to use dynamic plugins, also make sure that `ENABLE_PLUGIN_LOADING` is enabled.
The placeholder `{codec}` can have these values: `LIBDE265`, `X265`, `AOM_DECODER`, `AOM_ENCODER`, `SvtEnc`, `DAV1D`, `FFMPEG_DECODER`, `JPEG_DECODER`, `JPEG_ENCODER`, `KVAZAAR`, `OpenJPEG_DECODER`, `OpenJPEG_ENCODER`.
The placeholder `{codec}` can have these values: `LIBDE265`, `X265`, `AOM_DECODER`, `AOM_ENCODER`, `SvtEnc`, `DAV1D`, `FFMPEG_DECODER`, `JPEG_DECODER`, `JPEG_ENCODER`, `KVAZAAR`, `OpenJPEG_DECODER`, `OpenJPEG_ENCODER`, `OPENJPH_ENCODER`

Further options are:

Expand Down
24 changes: 24 additions & 0 deletions cmake/modules/FindOPENJPH.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
include(LibFindMacros)
libfind_pkg_check_modules(OPENJPH_PKGCONF openjph)

find_path(OPENJPH_INCLUDE_DIR
NAMES openjph/ojph_version.h
HINTS ${OPENJPH_PKGCONF_INCLUDE_DIRS} ${OPENJPH_PKGCONF_INCLUDEDIR}
PATH_SUFFIXES OPENJPH
)

find_library(OPENJPH_LIBRARY
NAMES libopenjph openjph
HINTS ${OPENJPH_PKGCONF_LIBRARY_DIRS} ${OPENJPH_PKGCONF_LIBDIR}
)

set(OPENJPH_PROCESS_LIBS OPENJPH_LIBRARY)
set(OPENJPH_PROCESS_INCLUDES OPENJPH_INCLUDE_DIR)
libfind_process(OPENJPH)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OPENJPH
REQUIRED_VARS
OPENJPH_INCLUDE_DIR
OPENJPH_LIBRARY
)
3 changes: 3 additions & 0 deletions examples/heif_convert.cc
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ void list_all_decoders()
std::cout << "JPEG 2000 decoders:\n";
list_decoders(heif_compression_JPEG2000);

std::cout << "HT-J2K decoders:\n";
list_decoders(heif_compression_HTJ2K);

#if WITH_UNCOMPRESSED_CODEC
std::cout << "uncompressed: yes\n";
#else
Expand Down
18 changes: 17 additions & 1 deletion examples/heif_enc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ const int OPTION_PITM_DESCRIPTION = 1005;
const int OPTION_USE_JPEG_COMPRESSION = 1006;
const int OPTION_USE_JPEG2000_COMPRESSION = 1007;
const int OPTION_VERBOSE = 1008;
const int OPTION_USE_HTJ2K_COMPRESSION = 1009;


static struct option long_options[] = {
Expand All @@ -115,6 +116,7 @@ static struct option long_options[] = {
{(char* const) "avif", no_argument, 0, 'A'},
{(char* const) "jpeg", no_argument, 0, OPTION_USE_JPEG_COMPRESSION},
{(char* const) "jpeg2000", no_argument, 0, OPTION_USE_JPEG2000_COMPRESSION},
{(char* const) "htj2k", no_argument, 0, OPTION_USE_HTJ2K_COMPRESSION},
#if WITH_UNCOMPRESSED_CODEC
{(char* const) "uncompressed", no_argument, 0, 'U'},
#endif
Expand Down Expand Up @@ -162,6 +164,7 @@ void show_help(const char* argv0)
<< " -A, --avif encode as AVIF (not needed if output filename with .avif suffix is provided)\n"
<< " --jpeg encode as JPEG\n"
<< " --jpeg2000 encode as JPEG 2000 (experimental)\n"
<< " --htj2k encode as High Throughput JPEG 2000 (experimental)\n"
#if WITH_UNCOMPRESSED_CODEC
<< " -U, --uncompressed encode as uncompressed image (according to ISO 23001-17) (EXPERIMENTAL)\n"
#endif
Expand Down Expand Up @@ -359,6 +362,9 @@ static const char* get_compression_format_name(heif_compression_format format)
case heif_compression_JPEG2000:
return "JPEG 2000";
break;
case heif_compression_HTJ2K:
return "HT-J2K";
break;
case heif_compression_uncompressed:
return "Uncompressed";
break;
Expand All @@ -370,7 +376,7 @@ static const char* get_compression_format_name(heif_compression_format format)

static void show_list_of_all_encoders()
{
for (auto compression_format : {heif_compression_HEVC, heif_compression_AV1, heif_compression_JPEG, heif_compression_JPEG2000
for (auto compression_format : {heif_compression_HEVC, heif_compression_AV1, heif_compression_JPEG, heif_compression_JPEG2000, heif_compression_HTJ2K
#if WITH_UNCOMPRESSED_CODEC
, heif_compression_uncompressed
#endif
Expand All @@ -389,6 +395,9 @@ static void show_list_of_all_encoders()
case heif_compression_JPEG2000:
std::cout << "JPEG 2000";
break;
case heif_compression_HTJ2K:
std::cout << "HT-J2K";
break;
case heif_compression_uncompressed:
std::cout << "Uncompressed";
break;
Expand Down Expand Up @@ -477,6 +486,7 @@ int main(int argc, char** argv)
bool force_enc_uncompressed = false;
bool force_enc_jpeg = false;
bool force_enc_jpeg2000 = false;
bool force_enc_htj2k = false;
bool crop_to_even_size = false;

std::vector<std::string> raw_params;
Expand Down Expand Up @@ -558,6 +568,9 @@ int main(int argc, char** argv)
case OPTION_USE_JPEG2000_COMPRESSION:
force_enc_jpeg2000 = true;
break;
case OPTION_USE_HTJ2K_COMPRESSION:
force_enc_htj2k = true;
break;
case OPTION_PLUGIN_DIRECTORY: {
int nPlugins;
heif_error error = heif_load_plugins(optarg, nullptr, &nPlugins, 0);
Expand Down Expand Up @@ -653,6 +666,9 @@ int main(int argc, char** argv)
else if (force_enc_jpeg2000) {
compressionFormat = heif_compression_JPEG2000;
}
else if (force_enc_htj2k) {
compressionFormat = heif_compression_HTJ2K;
}
else {
compressionFormat = guess_compression_format_from_filename(output_filename);
}
Expand Down
1 change: 1 addition & 0 deletions go/heif/heif.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const (
CompressionEVC = C.heif_compression_EVC
CompressionUncompressed = C.heif_compression_uncompressed
CompressionMask = C.heif_compression_mask
CompressionHTJ2K = C.heif_compression_HTJ2K
)

type Chroma C.enum_heif_chroma
Expand Down
3 changes: 2 additions & 1 deletion libheif/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2272,7 +2272,8 @@ Error HeifContext::encode_image(const std::shared_ptr<HeifPixelImage>& pixel_ima
out_image);
}
break;
case heif_compression_JPEG2000: {
case heif_compression_JPEG2000:
case heif_compression_HTJ2K: {
error = encode_image_as_jpeg2000(pixel_image,
encoder,
options,
Expand Down
1 change: 1 addition & 0 deletions libheif/file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ void HeifFile::set_brand(heif_compression_format format, bool miaf_compatible)
break;

case heif_compression_JPEG2000:
case heif_compression_HTJ2K:
m_ftyp_box->set_major_brand(fourcc("j2ki"));
m_ftyp_box->set_minor_version(0);
m_ftyp_box->add_compatible_brand(fourcc("mif1"));
Expand Down
2 changes: 1 addition & 1 deletion libheif/heif.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2026,7 +2026,7 @@ int heif_get_decoder_descriptors(enum heif_compression_format format_filter,
std::vector<decoder_with_priority> plugins;
std::vector<heif_compression_format> formats;
if (format_filter == heif_compression_undefined) {
formats = {heif_compression_HEVC, heif_compression_AV1, heif_compression_JPEG, heif_compression_JPEG2000, heif_compression_VVC};
formats = {heif_compression_HEVC, heif_compression_AV1, heif_compression_JPEG, heif_compression_JPEG2000, heif_compression_HTJ2K, heif_compression_VVC};
}
else {
formats.emplace_back(format_filter);
Expand Down
9 changes: 8 additions & 1 deletion libheif/heif.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,14 @@ enum heif_compression_format
*
* See ISO/IEC 23008-12:2022 Section 6.10.2
*/
heif_compression_mask = 9
heif_compression_mask = 9,
/**
* High Throughput JPEG 2000 (HT-J2K) compression.
*
* The encapsulation of HT-J2K is specified in ISO/IEC 15444-16:2021.
* The core encoding is defined in ISO/IEC 15444-15, or ITU-T T.814.
*/
heif_compression_HTJ2K = 10
};

enum heif_chroma
Expand Down
3 changes: 2 additions & 1 deletion libheif/heif_emscripten.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,8 @@ EMSCRIPTEN_BINDINGS(libheif) {
.value("heif_compression_EVC", heif_compression_EVC)
.value("heif_compression_JPEG2000", heif_compression_JPEG2000)
.value("heif_compression_uncompressed", heif_compression_uncompressed)
.value("heif_compression_mask", heif_compression_mask);
.value("heif_compression_mask", heif_compression_mask)
.value("heif_compression_HTJ2K", heif_compression_HTJ2K);
emscripten::enum_<heif_chroma>("heif_chroma")
.value("heif_chroma_undefined", heif_chroma_undefined)
.value("heif_chroma_monochrome", heif_chroma_monochrome)
Expand Down
8 changes: 8 additions & 0 deletions libheif/plugin_registry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@

#include "libheif/plugins/encoder_mask.h"

#if HAVE_OPENJPH_ENCODER
#include "libheif/plugins/encoder_openjph.h"
#endif

std::set<const struct heif_decoder_plugin*> s_decoder_plugins;

std::multiset<std::unique_ptr<struct heif_encoder_descriptor>,
Expand Down Expand Up @@ -171,6 +175,10 @@ void register_default_plugins()
register_decoder(get_decoder_plugin_openjpeg());
#endif

#if HAVE_OPENJPH_ENCODER
register_encoder(get_encoder_plugin_openjph());
#endif

#if WITH_UNCOMPRESSED_CODEC
register_encoder(get_encoder_plugin_uncompressed());
#endif
Expand Down
4 changes: 4 additions & 0 deletions libheif/plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ set(FFMPEG_DECODER_sources decoder_ffmpeg.cc decoder_ffmpeg.h)
set(FFMPEG_DECODER_extra_plugin_sources ../error.cc)
plugin_compilation(ffmpegdec FFMPEG FFMPEG_FOUND FFMPEG_DECODER FFMPEG_DECODER)

set(OPENJPH_ENCODER_sources encoder_openjph.cc encoder_openjph.h)
set(OPENJPH_ENCODER_extra_plugin_sources)
plugin_compilation(jphenc OPENJPH OPENJPH_FOUND OPENJPH_ENCODER OPENJPH_ENCODER)

target_sources(heif PRIVATE
encoder_mask.h
encoder_mask.cc)
Expand Down
Loading

0 comments on commit d7e3fa8

Please sign in to comment.