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

openjph: HT-J2K encoder #1072

Merged
merged 2 commits into from
Jan 16, 2024
Merged
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
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