openpreserve / jpylyzer

JP2 (JPEG 2000 Part 1) validator and properties extractor. Jpylyzer was specifically created to check that a JP2 file really conforms to the format's specifications. Additionally jpylyzer is able to extract technical characteristics.
http://jpylyzer.openpreservation.org/
Other
69 stars 28 forks source link

Improve reporting on precincts (COD, COC marker) #124

Closed bitsgalore closed 5 years ago

bitsgalore commented 5 years ago

Currently reporting on precinct info is not completely accurate. By default, encoders use a default precinct size of 15 pixels, unless a user-specified value was given; however jpylyzer's output suggests that precincts aren't used at all in the former case. Fix:

  1. Rename precincts to userDefinedPrecincts or something similar.
  2. If userDefinedPrecincts is false (0), report precinctSizeX / precinctSizeY with value 15.

This applies to the validate_cod and validate_coc functions. E.g. something like this:

if userDefinedPrecincts == 1:

    # Precinct size for each resolution level (=decomposition levels +1)
    # Order: low to high (lowest first)

    offset += 1

    for i in range(levels + 1):
        # Precinct byte
        precinctByte = bc.bytesToUnsignedChar(
            self.boxContents[offset:offset + 1])

        # Precinct width exponent: least significant 4 bytes (apply bit
        # mask)
        ppx = precinctByte & 15
        precinctSizeX = 2 ** ppx
        self.addCharacteristic("precinctSizeX", precinctSizeX)

        # Precinct size of 1 (exponent 0) only allowed for lowest
        # resolution level
        if i != 0:
            precinctSizeXIsValid = precinctSizeX >= 2
        else:
            precinctSizeXIsValid = True

        self.testFor("precinctSizeXIsValid", precinctSizeXIsValid)

        # Precinct height exponent: most significant 4 bytes (shift 4
        # to right and apply bit mask)
        ppy = (precinctByte >> 4) & 15
        precinctSizeY = 2 ** ppy
        self.addCharacteristic("precinctSizeY", precinctSizeY)

        # Precinct size of 1 (exponent 0) only allowed for lowest
        # resolution level
        if i != 0:
            precinctSizeYIsValid = precinctSizeY >= 2
        else:
            precinctSizeYIsValid = True

        self.testFor("precinctSizeYIsValid", precinctSizeYIsValid)
        offset += 1
else:
        for i in range(levels + 1):
            precinctSizeX = 2 ** 15
            self.addCharacteristic("precinctSizeX", precinctSizeX)
            precinctSizeY = 2 ** 15
            self.addCharacteristic("precinctSizeY", precinctSizeY)

Also needs changes to XSD schema, so best to do this before the 2.0 release (but make sure to report in the old format if --legacyout is used!).

bitsgalore commented 5 years ago

Implemented a slightly more elegant solution here https://github.com/openpreserve/jpylyzer/commit/0d746c88f83316c9014c7f0af988f4be7a00c7b8:

  1. This keeps the existing precincts element, but using values "default" and "user defined" (this means no changes to the schema are needed)
  2. If --legacyout option is used the old "yes"/"no" values are reported
  3. Precinct sizes are now also reported for the "default" case.