Leptonica  1.77.0
Image processing and image analysis suite
jp2kheader.c
Go to the documentation of this file.
1 /*====================================================================*
2  - Copyright (C) 2001 Leptonica. All rights reserved.
3  -
4  - Redistribution and use in source and binary forms, with or without
5  - modification, are permitted provided that the following conditions
6  - are met:
7  - 1. Redistributions of source code must retain the above copyright
8  - notice, this list of conditions and the following disclaimer.
9  - 2. Redistributions in binary form must reproduce the above
10  - copyright notice, this list of conditions and the following
11  - disclaimer in the documentation and/or other materials
12  - provided with the distribution.
13  -
14  - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15  - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16  - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17  - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18  - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23  - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *====================================================================*/
26 
45 #include <string.h>
46 #include <math.h>
47 #include "allheaders.h"
48 
49 #ifndef NO_CONSOLE_IO
50 #define DEBUG_IHDR 0
51 #endif /* ~NO_CONSOLE_IO */
52 
53 /* --------------------------------------------*/
54 #if USE_JP2KHEADER /* defined in environ.h */
55 /* --------------------------------------------*/
56 
57  /* a sanity check on the size read from file */
58 static const l_int32 MAX_JP2K_WIDTH = 100000;
59 static const l_int32 MAX_JP2K_HEIGHT = 100000;
60 
61 /*--------------------------------------------------------------------*
62  * Stream interface *
63  *--------------------------------------------------------------------*/
74 l_ok
75 readHeaderJp2k(const char *filename,
76  l_int32 *pw,
77  l_int32 *ph,
78  l_int32 *pbps,
79  l_int32 *pspp)
80 {
81 l_int32 ret;
82 FILE *fp;
83 
84  PROCNAME("readHeaderJp2k");
85 
86  if (pw) *pw = 0;
87  if (ph) *ph = 0;
88  if (pbps) *pbps = 0;
89  if (pspp) *pspp = 0;
90  if (!filename)
91  return ERROR_INT("filename not defined", procName, 1);
92 
93  if ((fp = fopenReadStream(filename)) == NULL)
94  return ERROR_INT("image file not found", procName, 1);
95  ret = freadHeaderJp2k(fp, pw, ph, pbps, pspp);
96  fclose(fp);
97  return ret;
98 }
99 
100 
111 l_ok
113  l_int32 *pw,
114  l_int32 *ph,
115  l_int32 *pbps,
116  l_int32 *pspp)
117 {
118 l_uint8 buf[80]; /* just need the first 80 bytes */
119 l_int32 nread;
120 
121  PROCNAME("freadHeaderJp2k");
122 
123  if (pw) *pw = 0;
124  if (ph) *ph = 0;
125  if (pbps) *pbps = 0;
126  if (pspp) *pspp = 0;
127  if (!fp)
128  return ERROR_INT("fp not defined", procName, 1);
129 
130  rewind(fp);
131  nread = fread(buf, 1, sizeof(buf), fp);
132  if (nread != sizeof(buf))
133  return ERROR_INT("read failure", procName, 1);
134 
135  readHeaderMemJp2k(buf, sizeof(buf), pw, ph, pbps, pspp);
136  rewind(fp);
137  return 0;
138 }
139 
140 
166 l_ok
167 readHeaderMemJp2k(const l_uint8 *data,
168  size_t size,
169  l_int32 *pw,
170  l_int32 *ph,
171  l_int32 *pbps,
172  l_int32 *pspp)
173 {
174 l_int32 format, val, w, h, bps, spp, loc, found, windex;
175 l_uint8 ihdr[4] = {0x69, 0x68, 0x64, 0x72}; /* 'ihdr' */
176 
177  PROCNAME("readHeaderMemJp2k");
178 
179  if (pw) *pw = 0;
180  if (ph) *ph = 0;
181  if (pbps) *pbps = 0;
182  if (pspp) *pspp = 0;
183  if (!data)
184  return ERROR_INT("data not defined", procName, 1);
185  if (size < 80)
186  return ERROR_INT("size < 80", procName, 1);
187  findFileFormatBuffer(data, &format);
188  if (format != IFF_JP2)
189  return ERROR_INT("not jp2 file", procName, 1);
190 
191  /* Search for beginning of the Image Header Box: 'ihdr' */
192  arrayFindSequence(data, size, ihdr, 4, &loc, &found);
193  if (!found)
194  return ERROR_INT("image parameters not found", procName, 1);
195 #if DEBUG_IHDR
196  if (loc != 44)
197  L_INFO("Beginning of ihdr is at byte %d\n", procName, loc);
198 #endif /* DEBUG_IHDR */
199 
200  windex = loc / 4 + 1;
201  if (4 * (windex + 2) + 2 >= size)
202  return ERROR_INT("image parameters end are outside of header",
203  procName, 1);
204  val = *((l_uint32 *)data + windex);
205  h = convertOnLittleEnd32(val);
206  val = *((l_uint32 *)data + windex + 1);
207  w = convertOnLittleEnd32(val);
208  val = *((l_uint16 *)data + 2 * (windex + 2));
209  spp = convertOnLittleEnd16(val);
210  bps = *(data + 4 * (windex + 2) + 2) + 1;
211  if (w > MAX_JP2K_WIDTH || h > MAX_JP2K_HEIGHT)
212  return ERROR_INT("unrealistically large sizes", procName, 1);
213  if (pw) *pw = w;
214  if (ph) *ph = h;
215  if (pbps) *pbps = bps;
216  if (pspp) *pspp = spp;
217  return 0;
218 }
219 
220 
221 /*
222  * fgetJp2kResolution()
223  *
224  * Input: fp (file stream opened for read)
225  * &xres, &yres (<return> resolution in ppi)
226  * Return: 0 if found; 1 if not found or on error
227  *
228  * Notes:
229  * (1) If the capture resolution field is not set, this is not an error;
230  * the returned resolution values are 0 (designating 'unknown').
231  * (2) Side-effect: this rewinds the stream.
232  * (3) The capture resolution box is optional in the jp2 spec, and
233  * it is usually not written.
234  * (4) The big-endian data fields that follow the 4 bytes of 'resc' are:
235  * ynum: 2 bytes
236  * ydenom: 2 bytes
237  * xnum: 2 bytes
238  * xdenom: 2 bytes
239  * yexp: 1 byte
240  * xexp: 1 byte
241  */
242 l_int32
243 fgetJp2kResolution(FILE *fp,
244  l_int32 *pxres,
245  l_int32 *pyres)
246 {
247 l_uint8 xexp, yexp;
248 l_uint8 *data;
249 l_uint16 xnum, ynum, xdenom, ydenom; /* these jp2k fields are 2-byte */
250 l_int32 loc, found;
251 l_uint8 resc[4] = {0x72, 0x65, 0x73, 0x63}; /* 'resc' */
252 size_t nbytes;
253 l_float64 xres, yres;
254 
255  PROCNAME("fgetJp2kResolution");
256 
257  if (pxres) *pxres = 0;
258  if (pyres) *pyres = 0;
259  if (!pxres || !pyres)
260  return ERROR_INT("&xres and &yres not both defined", procName, 1);
261  if (!fp)
262  return ERROR_INT("stream not opened", procName, 1);
263 
264  rewind(fp);
265  data = l_binaryReadStream(fp, &nbytes);
266  rewind(fp);
267 
268  /* Search for the start of the first capture resolution box: 'resc' */
269  arrayFindSequence(data, nbytes, resc, 4, &loc, &found);
270  if (!found) {
271  L_WARNING("image resolution not found\n", procName);
272  LEPT_FREE(data);
273  return 1;
274  }
275 
276  /* Extract the fields and calculate the resolution in pixels/meter.
277  * See section 1.5.3.7.1 of JPEG 2000 ISO/IEC 15444-1 spec. */
278  ynum = data[loc + 5] << 8 | data[loc + 4];
279  ynum = convertOnLittleEnd16(ynum);
280  ydenom = data[loc + 7] << 8 | data[loc + 6];
281  ydenom = convertOnLittleEnd16(ydenom);
282  xnum = data[loc + 9] << 8 | data[loc + 8];
283  xnum = convertOnLittleEnd16(xnum);
284  xdenom = data[loc + 11] << 8 | data[loc + 10];
285  xdenom = convertOnLittleEnd16(xdenom);
286  yexp = data[loc + 12];
287  xexp = data[loc + 13];
288  yres = ((l_float64)ynum / (l_float64)ydenom) * pow(10.0, (l_float64)yexp);
289  xres = ((l_float64)xnum / (l_float64)xdenom) * pow(10.0, (l_float64)xexp);
290 
291  /* Convert from pixels/meter to ppi */
292  yres *= (300.0 / 11811.0);
293  xres *= (300.0 / 11811.0);
294  *pyres = (l_int32)(yres + 0.5);
295  *pxres = (l_int32)(xres + 0.5);
296 
297  LEPT_FREE(data);
298  return 0;
299 }
300 
301 /* --------------------------------------------*/
302 #endif /* USE_JP2KHEADER */
l_ok readHeaderMemJp2k(const l_uint8 *data, size_t size, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp)
readHeaderMemJp2k()
Definition: jp2kheader.c:167
l_ok freadHeaderJp2k(FILE *fp, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp)
freadHeaderJp2k()
Definition: jp2kheader.c:112
l_ok findFileFormatBuffer(const l_uint8 *buf, l_int32 *pformat)
findFileFormatBuffer()
Definition: readfile.c:666
l_int32 w
Definition: jbclass.h:108
FILE * fopenReadStream(const char *filename)
fopenReadStream()
Definition: utils2.c:1657
l_uint8 * l_binaryReadStream(FILE *fp, size_t *pnbytes)
l_binaryReadStream()
Definition: utils2.c:1262
l_int32 h
Definition: jbclass.h:109
l_ok readHeaderJp2k(const char *filename, l_int32 *pw, l_int32 *ph, l_int32 *pbps, l_int32 *pspp)
readHeaderJp2k()
Definition: jp2kheader.c:75
l_ok arrayFindSequence(const l_uint8 *data, size_t datalen, const l_uint8 *sequence, size_t seqlen, l_int32 *poffset, l_int32 *pfound)
arrayFindSequence()
Definition: utils2.c:1092