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