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

Patch to read GML geo metadata and other associated data for inclusio… #1110

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

HWiman
Copy link

@HWiman HWiman commented Mar 22, 2018

Referring to Issue #1109, this is the requested pull request.

We need the GML meta data stored in some JP2 files as described here.

There was no reader for ASOC, LBL or XML boxes so I have added that (v2.3.0). I hope you will consider adding these changes to future versions of openjpeg.Please let me know if I can assist in getting this into openjpeg.

The patches add a new opj_jp2_asoc_t type. An opj_jp2 decoder has numasoc number of such instances in asoc. For retrieval on client side, these data are copied to opj_codestream_info_v2_t for direct access and can be dumped using opj_dump_associated_data( opj_codestream_info_v2_t cstr_info, FILE *output_stream ).

@HWiman
Copy link
Author

HWiman commented Mar 22, 2018

Sample image file with GML XML data as defined in the GML standard.
T33VWD_20170127T102301_B10.zip

Result of opj_dump -i T33VWD_20170127T102301_B10.jp2

dump.txt

@@ -10442,6 +10442,9 @@ opj_codestream_info_v2_t* j2k_get_cstr_info(opj_j2k_t* p_j2k)
if (!cstr_info) {
return NULL;
}

cstr_info->nbasoc = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation issue. Please build with cmake -DWITH_ASTYLE=ON and run scripts/prepare-commit.sh

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just did that, but with no effect. Is the prepare-commit.sh Windows-compatible?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum probably not... Maybe under Cygwin ? Anyway on already committed code, this has no effect. You can use scripts/astyle.sh your.c to fix an existing committed file

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not find an exact match of astyle in Code::Blocks. The closest I got was Kernighan&Ritchie but had to make small edits in source files manually. I guess the
build system checks if this will pass?
astyle_kr

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Latest push clearly changed everything. My attempt with astyle failed completely.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am afraid I need your assistance to format the committed six files since it can not be done on Windows. I compiled on a remote Linux machine WITH_ASTYLE, but it does not have C++11 and I am not authorized to install gcc. Can you please run astyle.sh on the commited files?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I've run astyle. Please pull from rouault:associated_data_support to get rouault@713e131

assert(jp2 != 00);
assert(p_header_data != 00);
assert(p_manager != 00);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should check p_header_size is at least 8 bytes long here

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

asoc = &(jp2->asoc[jp2->numasoc-1]);
asoc->level = jp2->numasoc-1; /* TODO: This is not correct if a parent asoc contains multiple child asocs! */
asoc->label_length = asoc_size;
asoc->label = opj_malloc(asoc_size);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be safer for users to allocate asoc_size + 1 and nul terminate asoc->label[asoc_size]

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

asoc = &(jp2->asoc[jp2->numasoc-1]);
asoc->level = jp2->numasoc-1; /* TODO: This is not correct if a parent asoc contains multiple child asocs! */
asoc->label_length = asoc_size;
asoc->label = opj_malloc(asoc_size);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should check asoc->label is not null

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

asoc->label is always uninitialized since it is created a few lines above.

p_header_data += asoc_size;
p_header_size -= asoc_size;

opj_read_bytes(p_header_data,&asoc_tag,4);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ypi sjpimd check that there's at least 4 remaining bytes

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

/* Copy the unknown data for external handling.
NOTE: This is not tested, but does the same as if an XML tag was found.*/
asoc->xml_len = p_header_size;
asoc->xml_buf = opj_malloc(p_header_size);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

to_asoc->level = asoc->level;
to_asoc->label_length = asoc->label_length;
to_asoc->xml_len = asoc->xml_len;
to_asoc->label = opj_malloc( to_asoc->label_length );
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null pointer checks needed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@@ -1049,7 +1093,12 @@ opj_stream_t* OPJ_CALLCONV opj_stream_create_file_stream(

return l_stream;
}


OPJ_OFF_T opj_stream_skip_api(opj_stream_t * p_stream, OPJ_OFF_T p_size)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is unrelated to this pull request AFAICS. Better put that in another one

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, sorry! Some files (like NITF) encapsulate JP2 in a file, so we need to offset the start of file reading. I did not find any way to do that so added this method.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit self-promotion, but you are probably aware of the GDAL library (http://gdal.org/) that takes care of all this geo stuff already and deals with NITF.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that´s an impressing and complete library! We do all our software in Java so it would require a lot of JNI bindings and we have implemented almost all image and sensor support we need already, this GML parsing being one of few missing parts.

@@ -1314,9 +1345,6 @@ OPJ_API OPJ_BOOL OPJ_CALLCONV opj_setup_decoder(opj_codec_t *p_codec,
* number, or "ALL_CPUS". If OPJ_NUM_THREADS is set and this function is called,
* this function will override the behaviour of the environment variable.
*
* Currently this function must be called after opj_setup_decoder() and
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why has this comment been removed ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unintentional mistake. Re-inserted.

@@ -943,6 +959,12 @@ typedef struct opj_codestream_info_v2 {
/** information regarding tiles inside image */
opj_tile_info_v2_t *tile_info; /* FIXME not used for the moment */

/** Number of associated data boxes*/
OPJ_UINT32 nbasoc;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

technically GMLJP2 boxes are JP2 level info, not codestream-level, so it is a bit weird to put them there. @detonin any better idea of a more appropriate structure ?

@HWiman
Copy link
Author

HWiman commented Mar 23, 2018

I get fails that I do not understand:

The following tests FAILED:
1401 - NR-DEC-issue226.j2k-74-decode (Failed)
1402 - NR-DEC-issue226.j2k-74-decode-md5 (Failed)
and:
1012.2
Compiler: clang-3.8 C++ OPJ_CI_CC=clang-3.8 OPJ_CI_CXX=clang-3.8 OPJ_CI_CHECK_STYLE=1 OPJ_CI_SKIP_TESTS=1 5 min 4 sec
1012.11
Compiler: g++-4.8 C++ OPJ_CI_CC=gcc-4.8 OPJ_CI_CXX=g++-4.8 OPJ_CI_ABI_CHECK=1 2 min 32 sec

What action should I take for these?

@HWiman
Copy link
Author

HWiman commented Mar 23, 2018

Except from fails and the potential move of associated data from code stream structure, I think the review is finished. Thanks a lot for taking the time!

@rouault
Copy link
Collaborator

rouault commented Apr 7, 2018

@HWiman Can you pull from from rouault:associated_data_support to get rouault/openjpeg@713e131 which should fix indentation issues ?

@HWiman
Copy link
Author

HWiman commented Apr 11, 2018

Accepted pull request from @rouault .

@rouault
Copy link
Collaborator

rouault commented Apr 11, 2018

@detonin Are you OK with the addition of the new members at the bottom of opj_codestream_info_v2_t ?

+    /** Number of associated data boxes*/
+    OPJ_UINT32 nbasoc;
+
+    /** Associated data, e.g. GML geoinformation */
+    opj_jp2_asoc_t *asoc_info;
+

I had a semantic observation that GMLJP2 boxes are at the JP2 level and not the codestream one, but I'm not sure of a better place where that could be stored ?
Or perhaps add a dedicated function opj_get_jp2_asoc_boxes() ? On the reflexion that might be the best solution. @HWiman would you be willing to do such change ?

@HWiman
Copy link
Author

HWiman commented Apr 11, 2018

@rouault I can change to a opj_get_jp2_asoc_boxes() function if that is preferred. I'll wait for @detonin and your decision, though.

@detonin
Copy link
Contributor

detonin commented Apr 11, 2018

@rouault Indeed this kind of geoinformation needs to be at JP2 level and certainly not in the J2K codestream. The dedicated function you propose seems to be a good option. I guess it means that we will have to bump the minor version in the next release (as we add function in the API).

@HWiman
Copy link
Author

HWiman commented Apr 12, 2018

There is an unused opj_jp2_metadata struct. Would you prefer that I put the asoc boxes there and implement the declared opj_get_jp2_metadata or would you prefer that I create a specific OPJ_API opj_jp2_asoc_t* OPJ_CALLCONV opj_get_jp2_asoc_boxes( opj_codec_t *p_codec, OPJ_UINT32 *num_asoc );?

@rouault
Copy link
Collaborator

rouault commented Apr 18, 2018

I'm fine with you implementing opj_get_jp2_metadata() and using opj_jp2_metadata. Could you add a comment in the doc of the opj_jp2_metadata struct to mention that it should never be allocated by calling code, and only used as the return of opj_get_jp2_metadata() (so we can add fields without breaking the ABI). There will probably be a need for a cleanup function to release allocated memory ?

@HWiman
Copy link
Author

HWiman commented May 28, 2018 via email

@rouault
Copy link
Collaborator

rouault commented Jun 16, 2018

@HWiman I've run astyle on your changes and committed the reformat in rouault@14fd14e
I'm wnodering why they are failures on NR-DEC-issue226.j2k-74-decode test specifically on Windows builds though

@rouault
Copy link
Collaborator

rouault commented Jun 16, 2018

I've also fixed memory leaks per rouault@e984dfc

@rouault
Copy link
Collaborator

rouault commented Aug 3, 2018

@HWiman Can you pull my changes from https://github.com/rouault/openjpeg/tree/associated_data_support to update this PR ?

@emiax
Copy link

emiax commented Oct 4, 2019

Hi @HWiman and @rouault,
This seems like a great addition to the openjpeg, and I'd love to use it in our open source project. I see that there has not been any update here since Aug 2018. Are there any plans to continue this work? Is there anything I can do to help? Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants