aous72 / OpenJPH

Open-source implementation of JPEG2000 Part-15 (or JPH or HTJ2K)
BSD 2-Clause "Simplified" License
196 stars 46 forks source link

Support decode/expand a j2c file with just tilepart bytes #122

Closed smithago closed 7 months ago

smithago commented 8 months ago

I was able compress a raw using the ojph_compress tool with tile_parts and tile markers. Lets assume the original resolution was 512x512. And the lowest decomposition I had was 64x64.

Ideally I would like to store these files in the cloud and download only the required resoultion tile bytes. Right now the entire file(headers) is expected for the ojph_expand to decode to specific resolution.

Can we get

  1. Tile markers byte offset as part of ojph_compress? I can mitigate this by looking for SOT bytes.
  2. How can I expand/decode with just the tilepart without headers?
aous72 commented 7 months ago

Hi Smitha,

I suspect this is a common question.

Let me give a typical usage scenario. Here I assume you control the creation of the file -- I suspect, because of the way DICOM Recommendation 235 works, you will always have this byte sequence arrangement. Also for this to make sense, you need access to JPEG2000 Part 1 document. ISO 15444-1, or ITU T.800.

Most of the information about the file structure is in the first 1K bytes, but let's say 2K.
At first the client connect to the server and ask for bytes 0-1999 from the file -- the first 2K. Then, using a script you have to write, you would parse those bytes. You look for (SOC or 0xFF4F) marker; this is the start of the codestream. SOC is followed by many marker segments, but they all have the same format, a two bytes marker segment code, followed by 2 or 4 byte segment length (some markers have no length like the previously mentioned SOC). Examples include COD and SIZ. You skip all marker segments, except for the following two.

  1. TLM 0xFF55, which carries the tile-part lengths -- the first length is for the first tile-part or the coarsest resolution, second is for second and so.
  2. SOD or 0xFF90 or start of tile-part. Additionally, the first length starts from this location until the end of the first tile part, whose length you already know from TLM. The first tile-part is immediately followed by SOT of the next tile-part which carries the second coarsest resolution data. The following SOT should help you know that you are in the correct location. OpenJPH parses most of the segments in ojph_codestream_local.cpp in codestream::read_headers, so that might inspire you.

You parse the header, decide how many bytes to retrieve to have the complete tile parts that you are interested in. Say you need in total 20000 bytes, so you retrieve from byte 2000-19999. Then you concatenate these to the 0-1999 that you already have. Then you give these 20000 bytes to OpenJPH to decode them. You need to set resilience in OpenJPH, if not you would get an error that the file is not complete.

That's the outline of what you should do.
If there are difficulties, please let me know.

Kind regards, Aous.

smithago commented 7 months ago

Thanks Aous. This was very usefull. I was able to parse the header and understand the bytes to read.