@@ -70,6 +70,57 @@ def parse_j2k(buffer):
7070
7171 return param
7272
73+ def parse_codestream_markers (buffer ):
74+ offset = 0
75+ markers = []
76+ while offset < len (buffer ):
77+ symbol_code_bytes = buffer [offset : offset + 2 ]
78+ marker = unpack (">H" , symbol_code_bytes )[0 ]
79+ offset += 2
80+ if marker == 0xFF4F :
81+ markers .append ("SOC" )
82+ elif marker == 0xFF51 :
83+ markers .append ("SIZ" )
84+ length_bytes = buffer [offset : offset + 2 ]
85+ length = unpack (">H" , length_bytes )[0 ]
86+ offset += length
87+ elif marker == 0xFF52 :
88+ markers .append ("COD" )
89+ length_bytes = buffer [offset : offset + 2 ]
90+ length = unpack (">H" , length_bytes )[0 ]
91+ offset += length
92+ elif marker == 0xFF55 :
93+ markers .append ("TLM" )
94+ length_bytes = buffer [offset : offset + 2 ]
95+ length = unpack (">H" , length_bytes )[0 ]
96+ offset += length
97+ elif marker == 0xFF58 :
98+ markers .append ("PLT" )
99+ length_bytes = buffer [offset : offset + 2 ]
100+ length = unpack (">H" , length_bytes )[0 ]
101+ offset += length
102+ elif marker == 0xFF5C :
103+ markers .append ("QCD" )
104+ length_bytes = buffer [offset : offset + 2 ]
105+ length = unpack (">H" , length_bytes )[0 ]
106+ offset += length
107+ elif marker == 0xFF64 :
108+ markers .append ("COM" )
109+ length_bytes = buffer [offset : offset + 2 ]
110+ length = unpack (">H" , length_bytes )[0 ]
111+ offset += length
112+ elif marker == 0xFF90 :
113+ markers .append ("SOT" )
114+ length_bytes = buffer [offset : offset + 2 ]
115+ length = unpack (">H" , length_bytes )[0 ]
116+ offset += length
117+ elif marker == 0xFF93 :
118+ markers .append ("SOD" )
119+ # If we get to here, we have the marker info we need
120+ break
121+ else :
122+ raise Exception (f"unexpected marker: 0x{ marker :04X} " )
123+ return markers
73124
74125class TestEncode :
75126 """Tests for encode_array()"""
@@ -700,7 +751,84 @@ def test_jp2(self):
700751
701752 buffer = encode_array (arr , codec_format = 1 )
702753 assert buffer .startswith (b"\x00 \x00 \x00 \x0c \x6a \x50 \x20 \x20 \x0d \x0a \x87 \x0a " )
754+
755+ def test_no_tlm_or_plt_explicit (self ):
756+ """Test encoding with no TLM or PLT, explicitly disabled"""
757+ rows = 123
758+ cols = 234
759+ bit_depth = 8
760+ maximum = 2 ** bit_depth - 1
761+ dtype = f"u{ math .ceil (bit_depth / 8 )} "
762+ arr = np .random .randint (0 , high = maximum + 1 , size = (rows , cols ), dtype = dtype )
763+ buffer = encode_array (arr , compression_ratios = [4 , 2 , 1 ], add_tlm = False , add_plt = False )
764+ out = decode (buffer )
765+ markers = parse_codestream_markers (buffer )
766+ assert "TLM" not in markers
767+ assert "PLT" not in markers
768+ assert np .allclose (arr , out , atol = 5 )
703769
770+ def test_no_tlm_or_plt_default (self ):
771+ """Test encoding with no TLM or PLT, default options"""
772+ rows = 123
773+ cols = 234
774+ bit_depth = 8
775+ maximum = 2 ** bit_depth - 1
776+ dtype = f"u{ math .ceil (bit_depth / 8 )} "
777+ arr = np .random .randint (0 , high = maximum + 1 , size = (rows , cols ), dtype = dtype )
778+ buffer = encode_array (arr , compression_ratios = [4 , 2 , 1 ])
779+ out = decode (buffer )
780+ markers = parse_codestream_markers (buffer )
781+ assert "TLM" not in markers
782+ assert "PLT" not in markers
783+ assert np .allclose (arr , out , atol = 5 )
784+
785+
786+ def test_tlm (self ):
787+ """Test encoding with TLM"""
788+ rows = 123
789+ cols = 234
790+ bit_depth = 8
791+ maximum = 2 ** bit_depth - 1
792+ dtype = f"u{ math .ceil (bit_depth / 8 )} "
793+ arr = np .random .randint (0 , high = maximum + 1 , size = (rows , cols ), dtype = dtype )
794+ buffer = encode_array (arr , compression_ratios = [4 , 2 , 1 ], add_tlm = True )
795+ out = decode (buffer )
796+ markers = parse_codestream_markers (buffer )
797+ assert "TLM" in markers
798+ assert "PLT" not in markers
799+ assert np .allclose (arr , out , atol = 5 )
800+
801+ def test_plt (self ):
802+ """Test encoding with PLT"""
803+ rows = 123
804+ cols = 234
805+ bit_depth = 8
806+ maximum = 2 ** bit_depth - 1
807+ dtype = f"u{ math .ceil (bit_depth / 8 )} "
808+ arr = np .random .randint (0 , high = maximum + 1 , size = (rows , cols ), dtype = dtype )
809+ buffer = encode_array (arr , compression_ratios = [4 , 2 , 1 ], add_plt = True )
810+ out = decode (buffer )
811+ markers = parse_codestream_markers (buffer )
812+ assert "TLM" not in markers
813+ assert "PLT" in markers
814+ assert np .allclose (arr , out , atol = 5 )
815+
816+ def test_tlm_and_plt (self ):
817+ """Test encoding with both TLM and PLT"""
818+ rows = 123
819+ cols = 234
820+ bit_depth = 8
821+ maximum = 2 ** bit_depth - 1
822+ dtype = f"u{ math .ceil (bit_depth / 8 )} "
823+ arr = np .random .randint (0 , high = maximum + 1 , size = (rows , cols ), dtype = dtype )
824+ buffer = encode_array (arr , compression_ratios = [4 , 2 , 1 ], add_plt = True , add_tlm = True )
825+ out = decode (buffer )
826+ param = parse_j2k (buffer )
827+ assert param ["precision" ] == bit_depth
828+ markers = parse_codestream_markers (buffer )
829+ assert "TLM" in markers
830+ assert "PLT" in markers
831+ assert np .allclose (arr , out , atol = 5 )
704832
705833class TestEncodeBuffer :
706834 """Tests for _openjpeg.encode_buffer"""
0 commit comments