Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL
4 : * Purpose: OPENJPEG driver
5 : * Author: Even Rouault, <even.rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2023, Even Rouault, <even.rouault at spatialys.com>
9 : *
10 : * Permission is hereby granted, free of charge, to any person obtaining a
11 : * copy of this software and associated documentation files (the "Software"),
12 : * to deal in the Software without restriction, including without limitation
13 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 : * and/or sell copies of the Software, and to permit persons to whom the
15 : * Software is furnished to do so, subject to the following conditions:
16 : *
17 : * The above copyright notice and this permission notice shall be included
18 : * in all copies or substantial portions of the Software.
19 : *
20 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 : * DEALINGS IN THE SOFTWARE.
27 : ****************************************************************************/
28 :
29 : #include "openjpegdrivercore.h"
30 :
31 : /* This file is to be used with openjpeg 2.1 or later */
32 : #ifdef __clang__
33 : #pragma clang diagnostic push
34 : #pragma clang diagnostic ignored "-Wunknown-pragmas"
35 : #pragma clang diagnostic ignored "-Wdocumentation"
36 : #endif
37 :
38 : #include <openjpeg.h>
39 : #include <opj_config.h>
40 :
41 : #ifdef __clang__
42 : #pragma clang diagnostic pop
43 : #endif
44 :
45 : #define IS_OPENJPEG_OR_LATER(major, minor, patch) \
46 : ((OPJ_VERSION_MAJOR * 10000 + OPJ_VERSION_MINOR * 100 + \
47 : OPJ_VERSION_BUILD) >= ((major)*10000 + (minor)*100 + (patch)))
48 :
49 : /************************************************************************/
50 : /* Identify() */
51 : /************************************************************************/
52 :
53 : #ifndef jpc_header_defined
54 : #define jpc_header_defined
55 : static const unsigned char jpc_header[] = {0xff, 0x4f, 0xff,
56 : 0x51}; // SOC + RSIZ markers
57 : static const unsigned char jp2_box_jp[] = {0x6a, 0x50, 0x20, 0x20}; /* 'jP ' */
58 : #endif
59 :
60 56899 : static int Identify(GDALOpenInfo *poOpenInfo)
61 :
62 : {
63 56899 : if (poOpenInfo->nHeaderBytes >= 16 &&
64 9377 : (memcmp(poOpenInfo->pabyHeader, jpc_header, sizeof(jpc_header)) == 0 ||
65 9338 : memcmp(poOpenInfo->pabyHeader + 4, jp2_box_jp, sizeof(jp2_box_jp)) ==
66 : 0))
67 523 : return TRUE;
68 :
69 : else
70 56376 : return FALSE;
71 : }
72 :
73 : /************************************************************************/
74 : /* OPENJPEGDriverSetCommonMetadata() */
75 : /************************************************************************/
76 :
77 1227 : void OPENJPEGDriverSetCommonMetadata(GDALDriver *poDriver)
78 : {
79 1227 : poDriver->SetDescription(DRIVER_NAME);
80 1227 : poDriver->SetMetadataItem(GDAL_DCAP_RASTER, "YES");
81 1227 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
82 1227 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME,
83 1227 : "JPEG-2000 driver based on JP2OpenJPEG library");
84 :
85 1227 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
86 1227 : "drivers/raster/jp2openjpeg.html");
87 1227 : poDriver->SetMetadataItem(GDAL_DMD_MIMETYPE, "image/jp2");
88 1227 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "jp2");
89 1227 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSIONS, "jp2 j2k");
90 1227 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONDATATYPES,
91 1227 : "Byte Int16 UInt16 Int32 UInt32");
92 :
93 1227 : poDriver->SetMetadataItem(GDAL_DCAP_VIRTUALIO, "YES");
94 :
95 1227 : poDriver->SetMetadataItem(
96 : GDAL_DMD_OPENOPTIONLIST,
97 : "<OpenOptionList>"
98 : #if IS_OPENJPEG_OR_LATER(2, 5, 0)
99 : " <Option name='STRICT' type='boolean' description='Whether "
100 : "strict/pedantic decoding should be adopted. Set to NO to allow "
101 : "decoding broken files' default='YES'/>"
102 : #endif
103 : " <Option name='1BIT_ALPHA_PROMOTION' type='boolean' "
104 : "description='Whether a 1-bit alpha channel should be promoted to "
105 : "8-bit' default='YES'/>"
106 : " <Option name='OPEN_REMOTE_GML' type='boolean' "
107 : "description='Whether "
108 : "to load remote vector layers referenced by a link in a GMLJP2 v2 "
109 : "box' "
110 : "default='NO'/>"
111 : " <Option name='GEOREF_SOURCES' type='string' description='Comma "
112 : "separated list made with values "
113 : "INTERNAL/GMLJP2/GEOJP2/WORLDFILE/PAM/NONE that describe the "
114 : "priority "
115 : "order for georeferencing' default='PAM,GEOJP2,GMLJP2,WORLDFILE'/>"
116 : " <Option name='USE_TILE_AS_BLOCK' type='boolean' "
117 : "description='Whether to always use the JPEG-2000 block size as "
118 : "the "
119 : "GDAL block size' default='NO'/>"
120 1227 : "</OpenOptionList>");
121 :
122 1227 : poDriver->SetMetadataItem(
123 : GDAL_DMD_CREATIONOPTIONLIST,
124 : "<CreationOptionList>"
125 : " <Option name='CODEC' type='string-select' default='according "
126 : "to "
127 : "file extension. If unknown, default to J2K'>"
128 : " <Value>JP2</Value>"
129 : " <Value>J2K</Value>"
130 : " </Option>"
131 : " <Option name='GeoJP2' type='boolean' description='Whether to "
132 : "emit "
133 : "a GeoJP2 box' default='YES'/>"
134 : " <Option name='GMLJP2' type='boolean' description='Whether to "
135 : "emit "
136 : "a GMLJP2 v1 box' default='YES'/>"
137 : " <Option name='GMLJP2V2_DEF' type='string' "
138 : "description='Definition "
139 : "file to describe how a GMLJP2 v2 box should be generated. If set "
140 : "to "
141 : "YES, a minimal instance will be created'/>"
142 : " <Option name='QUALITY' type='string' description='Single "
143 : "quality "
144 : "value or comma separated list of increasing quality values for "
145 : "several layers, each in the 0-100 range' default='25'/>"
146 : " <Option name='REVERSIBLE' type='boolean' description='True if "
147 : "the "
148 : "compression is reversible' default='false'/>"
149 : " <Option name='RESOLUTIONS' type='int' description='Number of "
150 : "resolutions.' min='1' max='30'/>"
151 : " <Option name='BLOCKXSIZE' type='int' description='Tile Width' "
152 : "default='1024'/>"
153 : " <Option name='BLOCKYSIZE' type='int' description='Tile Height' "
154 : "default='1024'/>"
155 : " <Option name='PROGRESSION' type='string-select' default='LRCP'>"
156 : " <Value>LRCP</Value>"
157 : " <Value>RLCP</Value>"
158 : " <Value>RPCL</Value>"
159 : " <Value>PCRL</Value>"
160 : " <Value>CPRL</Value>"
161 : " </Option>"
162 : " <Option name='SOP' type='boolean' description='True to insert "
163 : "SOP "
164 : "markers' default='false'/>"
165 : " <Option name='EPH' type='boolean' description='True to insert "
166 : "EPH "
167 : "markers' default='false'/>"
168 : " <Option name='YCBCR420' type='boolean' description='if RGB "
169 : "must be "
170 : "resampled to YCbCr 4:2:0' default='false'/>"
171 : " <Option name='YCC' type='boolean' description='if RGB must be "
172 : "transformed to YCC color space (lossless MCT transform)' "
173 : "default='YES'/>"
174 : " <Option name='NBITS' type='int' description='Bits (precision) "
175 : "for "
176 : "sub-byte files (1-7), sub-uint16 (9-15), sub-uint32 (17-31)'/>"
177 : " <Option name='1BIT_ALPHA' type='boolean' description='Whether "
178 : "to "
179 : "encode the alpha channel as a 1-bit channel' default='NO'/>"
180 : " <Option name='ALPHA' type='boolean' description='Whether to "
181 : "force "
182 : "encoding last channel as alpha channel' default='NO'/>"
183 : " <Option name='PROFILE' type='string-select' description='Which "
184 : "codestream profile to use' default='AUTO'>"
185 : " <Value>AUTO</Value>"
186 : " <Value>UNRESTRICTED</Value>"
187 : " <Value>PROFILE_1</Value>"
188 : " </Option>"
189 : " <Option name='INSPIRE_TG' type='boolean' description='Whether "
190 : "to "
191 : "use features that comply with Inspire Orthoimagery Technical "
192 : "Guidelines' default='NO'/>"
193 : " <Option name='JPX' type='boolean' description='Whether to "
194 : "advertise JPX features when a GMLJP2 box is written (or use JPX "
195 : "branding if GMLJP2 v2)' default='YES'/>"
196 : " <Option name='GEOBOXES_AFTER_JP2C' type='boolean' "
197 : "description='Whether to place GeoJP2/GMLJP2 boxes after the "
198 : "code-stream' default='NO'/>"
199 : " <Option name='PRECINCTS' type='string' description='Precincts "
200 : "size "
201 : "as a string of the form {w,h},{w,h},... with power-of-two "
202 : "values'/>"
203 : " <Option name='TILEPARTS' type='string-select' "
204 : "description='Whether "
205 : "to generate tile-parts and according to which criterion' "
206 : "default='DISABLED'>"
207 : " <Value>DISABLED</Value>"
208 : " <Value>RESOLUTIONS</Value>"
209 : " <Value>LAYERS</Value>"
210 : " <Value>COMPONENTS</Value>"
211 : " </Option>"
212 : " <Option name='CODEBLOCK_WIDTH' type='int' "
213 : "description='Codeblock "
214 : "width' default='64' min='4' max='1024'/>"
215 : " <Option name='CODEBLOCK_HEIGHT' type='int' "
216 : "description='Codeblock "
217 : "height' default='64' min='4' max='1024'/>"
218 : " <Option name='CT_COMPONENTS' type='int' min='3' max='4' "
219 : "description='If there is one color table, number of color table "
220 : "components to write. Autodetected if not specified.'/>"
221 : " <Option name='WRITE_METADATA' type='boolean' "
222 : "description='Whether "
223 : "metadata should be written, in a dedicated JP2 XML box' "
224 : "default='NO'/>"
225 : " <Option name='MAIN_MD_DOMAIN_ONLY' type='boolean' "
226 : "description='(Only if WRITE_METADATA=YES) Whether only metadata "
227 : "from "
228 : "the main domain should be written' default='NO'/>"
229 : " <Option name='USE_SRC_CODESTREAM' type='boolean' "
230 : "description='When "
231 : "source dataset is JPEG2000, whether to reuse the codestream of "
232 : "the "
233 : "source dataset unmodified' default='NO'/>"
234 : " <Option name='CODEBLOCK_STYLE' type='string' "
235 : "description='Comma-separated combination of BYPASS, RESET, "
236 : "TERMALL, "
237 : "VSC, PREDICTABLE, SEGSYM or value between 0 and 63'/>"
238 : #if IS_OPENJPEG_OR_LATER(2, 4, 0)
239 : " <Option name='PLT' type='boolean' description='True to insert "
240 : "PLT "
241 : "marker segments' default='false'/>"
242 : #endif
243 : #if IS_OPENJPEG_OR_LATER(2, 5, 0)
244 : " <Option name='TLM' type='boolean' description='True to insert "
245 : "TLM "
246 : "marker segments' default='false'/>"
247 : #endif
248 : " <Option name='COMMENT' type='string' description='Content of "
249 : "the "
250 : "comment (COM) marker'/>"
251 1227 : "</CreationOptionList>");
252 :
253 1227 : poDriver->pfnIdentify = Identify;
254 1227 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
255 1227 : poDriver->SetMetadataItem(GDAL_DCAP_CREATECOPY, "YES");
256 1227 : }
257 :
258 : /************************************************************************/
259 : /* DeclareDeferredOPENJPEGPlugin() */
260 : /************************************************************************/
261 :
262 : #ifdef PLUGIN_FILENAME
263 1520 : void DeclareDeferredOPENJPEGPlugin()
264 : {
265 1520 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
266 : {
267 301 : return;
268 : }
269 1219 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
270 : #ifdef PLUGIN_INSTALLATION_MESSAGE
271 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
272 : PLUGIN_INSTALLATION_MESSAGE);
273 : #endif
274 1219 : OPENJPEGDriverSetCommonMetadata(poDriver);
275 1219 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
276 : }
277 : #endif
|