IIIF / htj2k

A project to evaluate htj2k for IIIF
12 stars 1 forks source link

jp2 kakadu recipe #1

Open glenrobson opened 2 years ago

glenrobson commented 2 years ago

Issue to discuss the best jp2 recipe for both the jp2hk jp2 and the control jp2. In @scossu's document he uses the following command:

kdu_compress -i $in_path -o $out_path Clevels=6 Clayers=6 \
"Cprecincts={256,256},{256,256},{128,128}" "Stiles={512,512}" Corder=RPCL \
ORGgen_plt=yes ORGtparts=R "Cblk={64,64}" -jp2_space sRGB Cuse_sop=yes \
Cuse_eph=yes -flush_period 1024 -rate 3
ruven commented 2 years ago

These are the Kakadu encoding parameters I recommend on the IIPImage website:

kdu_compress -i input.tif -o output.jp2 -rate 2.5 Clayers=1 Clevels=7 "Cprecincts={256,256}" "Corder=RPCL" "Cblk={64,64}" Cuse_sop=yes

These settings are designed to optimize the image in terms of fast random access decoding for use with IIIF servers such as IIPImage or Loris etc. These settings were derived from some experiments I did a number of years ago looking at different combinations of code block size, precinct size and tile size and how they affect things like file size, encoding and decoding speed. There's a presentation I did about this at the time presentation I did about this at the time (scroll to near the end of the presentation to see these results). It would probably be a good idea to redo this with the latest versions Kakadu and OpenJPEG and compare them to HTJ2K.

scossu commented 2 years ago

I see that some usage examples for kdu_compress are here, however a more comprehensive breakdown of the command line parameters would be nice.

irv commented 2 years ago

kdu_compress -usage

michaeldsmith commented 2 years ago

To experiment with HTJ2K encoding using Kakadu version 8.0 (and later versions) just add the Cmodes=HT parameter to any existing kdu_compress command-line you are already using. To enable the accelerated HTJ2K encoding for lossy compression, you can also add Cplex={6,EST,0.25,-1} that will speed up lossy HTJ2K encoding.

michaeldsmith commented 2 years ago

@scossu I'm working as a consultant for Kakadu and so I certainly can try to answer any questions you have on kdu_compress, or anything else Kakadu or JPEG2000 related. As you know, there are a lot of kakadu sdk parameters. Is there a specific question or a list of parameters you want more info about?

ruven commented 2 years ago

To help testing, I've added code to detect and log HTJ2K streams when using OpenJPEG (https://github.com/ruven/iipsrv/commit/00b69c0c699d2bc748d253362e77ae215fa4d77e). @michaeldsmith, is there a way in the SDK to do this with Kakadu also? I can't find anything in the library documentation.

michaeldsmith commented 2 years ago

@ruven you can use kdu_codestream.get_ht_usage() in kakadu SDK to determine if a J2C file uses HT. See sample code below:

int
main(int argc, char* argv[])
{
  const char *filename = "C:\\temp\\part15.j2c";
  //const char* filename = "C:\\temp\\part1.j2c";

  kdu_simple_file_source file_src;
  file_src.open(filename);
  kdu_compressed_source* compressed_source = NULL;
  compressed_source = &file_src;
  kdu_codestream codestream;
  codestream.create(compressed_source);
  const int ht_usage = codestream.get_ht_usage();
  switch (ht_usage)
  {
  case 2:
    printf("kdu_codestream.get_ht_usage() = 2 means that both HT and non - HT block coding technologies may be used in tiles encountered so far.\n");
    break;
  case 1:
    printf("kdu_codestream.get_ht_usage() = 1 means that HT block coding technology is used in tiles encountered so far, or it is certain that only HT block coding technology will be used.\n");
    break;
  case 0:
    printf("kdu_codestream.get_ht_usage() = 0 means that HT block coding technology may be used in the codestream, but we have not seen any tiles that indicate its use or its possible use.\n");
    break;
  case -1:
    printf("kdu_codestream.get_ht_usage() = -1 means that HT block coding technology is definitely not used in the codestream, because the codestream does not conform to JPEG 2000 Part - 15 (HTJ2K).\n");
    break;
  }
}
michaeldsmith commented 2 years ago

@ruven you can also access the Scap parameter which returns the Pcap field in the CAP marker if it is present. The Pcap field in the CAP marker will have its 14th bit set to 1 if the codestream contains Part-15 (HTJ2K) capabilities. Here some sample code that uses this approach:

int
main(int argc, char* argv[])
{
  const char* filename = "C:\\temp\\part15.j2c";
  //const char* filename = "C:\\temp\\part1.j2c";

  kdu_simple_file_source file_src;
  file_src.open(filename);
  kdu_compressed_source* compressed_source = NULL;
  compressed_source = &file_src;
  kdu_codestream codestream;
  codestream.create(compressed_source);
  siz_params *siz = codestream.access_siz();
  int pcap_value = 0;
  siz->get(Scap, 0, 0, pcap_value);
  if (pcap_value & 0x00020000)
    printf("JPEG2000 Part-15 (HTJ2K) capabilities are present in codestream %s\n", filename);
  else
    printf("JPEG2000 Part-15 (HTJ2K) capabilities are not present in codestream %s\n", filename);

}
michaeldsmith commented 2 years ago

The specific signalling used by the HTJ2K standard to indicate that HTJ2K is used within a codestream appears in Annex A of the HTJ2K standard and includes the specific signalling necessary within the SIZ, CAP and COD/COC marker segments.

The HTJ2K standard is currently available-free-of-charge here [1].

[1] https://www.itu.int/rec/T-REC-T.814-201906-I/en

ruven commented 2 years ago

Thanks @michaeldsmith, I've now also added HTJ2K detection when using Kakadu (https://github.com/ruven/iipsrv/commit/4db9fff42dc2c07d871bca508b2f33a4cf376185)