Line data Source code
1 : /*
2 : Copyright 2021 Esri
3 : Licensed under the Apache License, Version 2.0 (the "License");
4 : you may not use this file except in compliance with the License.
5 : You may obtain a copy of the License at
6 : http://www.apache.org/licenses/LICENSE-2.0
7 : Unless required by applicable law or agreed to in writing, software
8 : distributed under the License is distributed on an "AS IS" BASIS,
9 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 : See the License for the specific language governing permissions and
11 : limitations under the License.
12 :
13 : QB3 band implementation
14 : QB3 page compression and decompression functions
15 :
16 : Authors: Lucian Plesea
17 : */
18 : #include "marfa.h"
19 : #include <QB3.h>
20 :
21 : NAMESPACE_MRF_START
22 13 : CPLErr QB3_Band::Compress(buf_mgr &dst, buf_mgr &src)
23 : {
24 13 : auto bands = static_cast<size_t>(img.pagesize.c);
25 13 : encsp pQB3 = nullptr;
26 : #define CREATE_QB3(T) \
27 : qb3_create_encoder(img.pagesize.x, img.pagesize.y, bands, qb3_dtype::T)
28 :
29 13 : switch (img.dt)
30 : {
31 8 : case (GDT_Byte):
32 8 : pQB3 = CREATE_QB3(QB3_U8);
33 8 : break;
34 1 : case (GDT_Int16):
35 1 : pQB3 = CREATE_QB3(QB3_I16);
36 1 : break;
37 1 : case (GDT_UInt16):
38 1 : pQB3 = CREATE_QB3(QB3_U16);
39 1 : break;
40 1 : case (GDT_Int32):
41 1 : pQB3 = CREATE_QB3(QB3_I32);
42 1 : break;
43 1 : case (GDT_UInt32):
44 1 : pQB3 = CREATE_QB3(QB3_U32);
45 1 : break;
46 1 : case (GDT_Int64):
47 1 : pQB3 = CREATE_QB3(QB3_I64);
48 1 : break;
49 0 : case (GDT_UInt64):
50 0 : pQB3 = CREATE_QB3(QB3_U64);
51 0 : break;
52 0 : default:
53 0 : CPLError(CE_Failure, CPLE_AssertionFailed,
54 : "MRF:QB3 Data type not supported");
55 0 : return CE_Failure;
56 : }
57 : #undef CREATE_QB3
58 :
59 13 : if (nullptr == pQB3)
60 : {
61 0 : CPLError(CE_Failure, CPLE_AssertionFailed,
62 : "MRF:QB3 Cannot create encoder");
63 0 : return CE_Failure;
64 : }
65 :
66 13 : CPLErr status = CE_None;
67 : try
68 : {
69 13 : if (dst.size < qb3_max_encoded_size(pQB3))
70 : {
71 0 : CPLError(CE_Failure, CPLE_AssertionFailed,
72 : "MRF:QB3 encoded buffer size too small");
73 0 : throw CE_Failure;
74 : }
75 :
76 : // Use independent band compression when by default band 1 is core band
77 14 : if ((3 == bands || 4 == bands) &&
78 1 : EQUAL(poMRFDS->GetPhotometricInterpretation(), "MULTISPECTRAL"))
79 : {
80 0 : size_t corebands[] = {0, 1, 2, 3}; // Identity, no core bands
81 0 : qb3_set_encoder_coreband(pQB3, bands, corebands);
82 : }
83 :
84 : // Quality of 90 and above trigger the better encoding
85 13 : qb3_set_encoder_mode(pQB3, (img.quality > 90) ? QB3M_BEST : QB3M_BASE);
86 :
87 : #if defined(QB3_HAS_FTL)
88 : // Quality below 5 triggers the faster encoding, when available
89 13 : if (img.quality < 5)
90 0 : qb3_set_encoder_mode(pQB3, QB3M_FTL);
91 : #endif
92 :
93 13 : dst.size = qb3_encode(pQB3, src.buffer, dst.buffer);
94 13 : if (0 == dst.size)
95 : {
96 0 : CPLError(CE_Failure, CPLE_AssertionFailed,
97 : "MRF:QB3 encoding failed");
98 0 : throw CE_Failure;
99 : }
100 :
101 : // Never happens if qb3_max_encoded doesn't lie
102 13 : if (dst.size > qb3_max_encoded_size(pQB3))
103 : {
104 0 : CPLError(CE_Failure, CPLE_AssertionFailed,
105 : "MRF:QB3 encoded size exceeds limit, check QB3 library");
106 0 : throw CE_Failure;
107 : }
108 : }
109 0 : catch (CPLErr error)
110 : {
111 0 : status = error;
112 : }
113 13 : qb3_destroy_encoder(pQB3);
114 13 : return status;
115 : }
116 :
117 9 : CPLErr QB3_Band::Decompress(buf_mgr &dst, buf_mgr &src)
118 : {
119 : size_t img_size[3];
120 9 : auto pdQB3 = qb3_read_start(src.buffer, src.size, img_size);
121 9 : if (nullptr == pdQB3)
122 : {
123 0 : CPLError(CE_Failure, CPLE_AppDefined,
124 : "MRF: QB3 can't create decoder, is it a valid QB3 stream?");
125 0 : return CE_Failure;
126 : }
127 :
128 9 : CPLErr status = CE_None;
129 : try
130 : {
131 9 : if (img_size[0] != static_cast<size_t>(img.pagesize.x) ||
132 9 : img_size[1] != static_cast<size_t>(img.pagesize.y) ||
133 9 : img_size[2] != static_cast<size_t>(img.pagesize.c))
134 : {
135 0 : CPLError(CE_Failure, CPLE_AppDefined,
136 : "MRF: QB Page has invalid size");
137 0 : throw CE_Failure;
138 : }
139 :
140 9 : if (!qb3_read_info(pdQB3))
141 : {
142 0 : CPLError(CE_Failure, CPLE_AppDefined,
143 : "MRF: QB3 metadata read failure");
144 0 : throw CE_Failure;
145 : }
146 :
147 9 : if (static_cast<size_t>(img.pageSizeBytes) != qb3_decoded_size(pdQB3))
148 : {
149 0 : CPLError(CE_Failure, CPLE_AppDefined,
150 : "MRF: QB3 incorrect decoded tile size");
151 0 : throw CE_Failure;
152 : }
153 :
154 9 : dst.size = qb3_read_data(pdQB3, dst.buffer);
155 9 : if (static_cast<size_t>(img.pageSizeBytes) != dst.size)
156 : {
157 0 : CPLError(CE_Failure, CPLE_AppDefined, "MRF: QB3 decoding error");
158 0 : throw CE_Failure;
159 : }
160 : }
161 0 : catch (CPLErr error)
162 : {
163 0 : status = error;
164 : }
165 9 : qb3_destroy_decoder(pdQB3);
166 9 : return status;
167 : }
168 :
169 44 : QB3_Band::QB3_Band(MRFDataset *pDS, const ILImage &image, int b, int level)
170 44 : : MRFRasterBand(pDS, image, b, level)
171 : {
172 : static_assert(CPL_IS_LSB,
173 : "QB3 is only implemented for little endian architectures");
174 44 : if (image.pageSizeBytes > INT_MAX / 4)
175 : {
176 0 : CPLError(CE_Failure, CPLE_AppDefined, "QB3 page too large");
177 0 : return;
178 : }
179 :
180 44 : if (0 != nBlockXSize % 4 || 0 != nBlockYSize % 4)
181 : {
182 0 : CPLError(CE_Failure, CPLE_NotSupported,
183 : "QB3 page size has to be a multiple of 4");
184 0 : return;
185 : }
186 :
187 44 : if (image.dt != GDT_Byte && image.dt != GDT_Int16 &&
188 11 : image.dt != GDT_UInt16 && image.dt != GDT_Int32 &&
189 5 : image.dt != GDT_UInt32 && image.dt != GDT_Int64 &&
190 0 : image.dt != GDT_UInt64)
191 : {
192 0 : CPLError(CE_Failure, CPLE_NotSupported,
193 : "Data type not supported by QB3 compression");
194 0 : return;
195 : }
196 :
197 : // Should use qb3_max_encoded_size();
198 :
199 : // Enlarge the page buffer, QB3 may expand data.
200 44 : pDS->SetPBufferSize(2 * image.pageSizeBytes);
201 : }
202 :
203 : NAMESPACE_MRF_END
|