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