1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of HDF. The full HDF copyright notice, including *
* terms governing use, modification, and redistribution, is contained in *
* the COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "hdf_priv.h"
/* Size of the file buffer to copy through */
#define MAX_FILE_BUF 16384
typedef enum { /* JPEG marker codes */
M_SOF0 = 0xc0,
M_SOF1 = 0xc1,
M_SOF2 = 0xc2,
M_SOF3 = 0xc3,
M_SOF5 = 0xc5,
M_SOF6 = 0xc6,
M_SOF7 = 0xc7,
M_JPG = 0xc8,
M_SOF9 = 0xc9,
M_SOF10 = 0xca,
M_SOF11 = 0xcb,
M_SOF13 = 0xcd,
M_SOF14 = 0xce,
M_SOF15 = 0xcf,
M_DHT = 0xc4,
M_DAC = 0xcc,
M_RST0 = 0xd0,
M_RST1 = 0xd1,
M_RST2 = 0xd2,
M_RST3 = 0xd3,
M_RST4 = 0xd4,
M_RST5 = 0xd5,
M_RST6 = 0xd6,
M_RST7 = 0xd7,
M_SOI = 0xd8,
M_EOI = 0xd9,
M_SOS = 0xda,
M_DQT = 0xdb,
M_DNL = 0xdc,
M_DRI = 0xdd,
M_DHP = 0xde,
M_EXP = 0xdf,
M_APP0 = 0xe0,
M_APP15 = 0xef,
M_JPG0 = 0xf0,
M_JPG13 = 0xfd,
M_COM = 0xfe,
M_TEM = 0x01,
M_ERROR = 0x100
} JPEG_MARKER;
static int32 num_bytes; /* number of bytes until the SOS code. */
static int32 image_width = 0; /* width of the JPEG image in pixels */
static int32 image_height = 0; /* height of the JPEG image in pixels */
static intn num_components = 0; /* number of components in the JPEG image */
static uint8 file_buf[MAX_FILE_BUF]; /* size of the buffer to copy through */
/*
* Routines to parse JPEG markers & save away the useful info.
*/
static intn
jgetc(FILE *f)
/* Get a 2-byte unsigned integer (e.g., a marker parameter length field) */
{
intn a;
a = fgetc(f);
if (a != EOF)
num_bytes++;
return (a);
}
static int32
get_2bytes(FILE *f)
/* Get a 2-byte unsigned integer (e.g., a marker parameter length field) */
{
int32 a;
a = jgetc(f);
return (a << 8) + jgetc(f);
}
static void
get_sof(FILE *f)
/* Process a SOFn marker */
{
short ci;
(void)get_2bytes(f);
jgetc(f); /* data_precision */
image_height = get_2bytes(f);
image_width = get_2bytes(f);
num_components = jgetc(f);
for (ci = 0; ci < num_components; ci++) {
jgetc(f);
jgetc(f);
jgetc(f);
}
}
static void
skip_variable(FILE *f)
/* Skip over an unknown or uninteresting variable-length marker */
{
int32 length;
length = get_2bytes(f);
for (length -= 2; length > 0; length--)
(void)jgetc(f);
}
static intn
next_marker(FILE *f)
/* Find the next JPEG marker */
/* Note that the output might not be a valid marker code, */
/* but it will never be 0 or FF */
{
intn c, nbytes;
nbytes = 0;
do {
do { /* skip any non-FF bytes */
nbytes++;
c = jgetc(f);
} while (c != 0xFF);
do { /* skip any duplicate FFs */
nbytes++;
c = jgetc(f);
} while (c == 0xFF);
} while (c == 0); /* repeat if it was a stuffed FF/00 */
return c;
}
static JPEG_MARKER
process_tables(FILE *f)
/* Scan and process JPEG markers that can appear in any order */
/* Return when an SOI, EOI, SOFn, or SOS is found */
{
int c;
while (TRUE) {
c = next_marker(f);
switch (c) {
case M_EOI:
return ((JPEG_MARKER)c);
case M_SOF0:
case M_SOF1:
case M_SOF9:
get_sof(f);
return ((JPEG_MARKER)c);
case M_RST0: /* these are all parameterless */
case M_RST1:
case M_RST2:
case M_RST3:
case M_RST4:
case M_RST5:
case M_RST6:
case M_RST7:
case M_TEM:
break;
default: /* must be DNL, DHP, EXP, APPn, JPGn, COM, or RESn */
skip_variable(f);
break;
}
}
}
/*
* Initialize and read the file header (everything through the SOF marker).
*/
static int32
read_file_header(FILE *f)
{
int c;
num_bytes = 0; /* reset the number of bytes into the file we are */
/* Demand an SOI marker at the start of the file --- otherwise it's
* probably not a JPEG file at all. If the user interface wants to support
* nonstandard headers in front of the SOI, it must skip over them itself
* before calling jpeg_decompress().
*/
if (jgetc(f) != 0xFF || jgetc(f) != M_SOI)
return (0);
/* Process markers until SOF */
c = (int)process_tables(f);
switch (c) {
case M_SOF0: /* ok, now we know the correct number of bytes to grab */
case M_SOF1:
case M_SOF9:
return (num_bytes);
default:
return (0);
}
}
/*-----------------------------------------------------------------------------
* Name: DFJPEGaddrig
* Purpose: Write RIG struct for the new JPEG image out to HDF file
* Inputs: file_id: HDF file pointer
* ref: ref to write RIG with
* Returns: 0 on success, -1 on failure with DFerror set
* Users: hopefully only routines in this utility
* Invokes: DFdistart, DFdiadd, DFdiend, DFputelement
* Remarks: another really, really, nasty hack brought to you by QAK in the
* interest of not decompressing the JPEG image before stuffing it
* into the HDF file...
*---------------------------------------------------------------------------*/
static intn
DFJPEGaddrig(int32 file_id, uint16 ref, uint16 ctag)
{
uint8 ntstring[4];
int32 GroupID;
uint8 *p;
ntstring[0] = DFNT_VERSION; /* version */
ntstring[1] = DFNT_UCHAR; /* type */
ntstring[2] = 8; /* width: RIG data is 8-bit chars */
ntstring[3] = DFNTC_BYTE; /* class: data are numeric values */
if (Hputelement(file_id, DFTAG_NT, ref, (uint8 *)ntstring, (int32)4) == FAIL)
return FAIL;
p = file_buf;
INT32ENCODE(p, image_width); /* width */
INT32ENCODE(p, image_height); /* height */
UINT16ENCODE(p, DFTAG_NT); /* number type */
UINT16ENCODE(p, ref);
INT16ENCODE(p, num_components); /* number of components */
INT16ENCODE(p, 0); /* interlace scheme */
UINT16ENCODE(p, ctag); /* compression type */
UINT16ENCODE(p, ref);
if (Hputelement(file_id, DFTAG_ID, ref, file_buf, (int32)(p - file_buf)) == FAIL)
return FAIL;
/* prepare to start writing rig */
/* ### NOTE: the parameter to this call may go away */
if ((GroupID = DFdisetup(10)) == FAIL)
return FAIL; /* max 10 tag/refs in set */
/* add tag/ref to RIG - image description, image and lookup table */
if (DFdiput(GroupID, DFTAG_ID, ref) == FAIL)
return FAIL;
if (DFdiput(GroupID, DFTAG_CI, ref) == FAIL)
return FAIL;
/* write out RIG */
return (DFdiwrite(file_id, GroupID, DFTAG_RIG, ref));
}
static void
usage(void)
{
printf("USAGE: jpeg2hdf <input JPEG file> <output HDF file>\n");
printf(" <input JPEG file> : JPEG file containing input image \n");
printf(" <output HDF file> : HDF file to store the image\n");
exit(1);
} /* end usage() */
int
main(int argc, char *argv[])
{
int32 off_image; /* offset of the JPEG image in the JFIF file */
int32 file_len; /* total length of the JPEG file */
FILE *jfif_file; /* file handle of the JFIF image */
int32 file_id; /* HDF file ID of the file to write */
uint16 wtag; /* tag number to use for the image */
uint16 wref; /* reference number to use for the image */
uint16 ctag; /* tag for the compression to do */
int32 aid; /* access ID for the JPEG image to stuff */
if (argc != 3)
usage();
if (argv[1][0] == '-' || argv[1][0] == '/') /* check command line */
usage();
jfif_file = fopen(argv[1], "rb");
if (jfif_file == NULL) {
printf("Error opening JPEG file: %s\n", argv[1]);
exit(1);
} /* end if */
off_image = read_file_header(jfif_file);
if (off_image == 0 || image_width <= 0 || image_height <= 0 || num_components <= 0) {
printf("Error reading JPEG file: %s, could not find a JFIF header\n", argv[1]);
exit(1);
} /* end if */
if (!fseek(jfif_file, 0, SEEK_END)) {
file_len = (int32)ftell(jfif_file);
fseek(jfif_file, 0, SEEK_SET); /* go back to beginning of JFIF file */
} /* end if */
else {
printf("Error, cannot fseek in %s(?!)\n", argv[1]);
exit(1);
} /* end else */
if ((file_id = Hopen(argv[2], DFACC_RDWR, 0)) != FAIL) {
wref = Hnewref(file_id);
if (!wref) {
printf("Error getting a reference number for HDF file: %s\n", argv[2]);
Hclose(file_id);
exit(1);
} /* end if */
wtag = DFTAG_CI; /* yes, this is a compressed image */
if (num_components == 1)
ctag = DFTAG_GREYJPEG5;
else if (num_components == 3)
ctag = DFTAG_JPEG5;
else {
printf("Error, cannot support JPEG file containing %d components\n", num_components);
Hclose(file_id);
exit(1);
} /* end else */
if ((aid = Hstartwrite(file_id, ctag, wref, 0)) == FAIL) {
printf("Error writing JPEG header to HDF file: %s\n", argv[2]);
exit(1);
} /* end if */
Hendaccess(aid);
if ((aid = Hstartwrite(file_id, wtag, wref, file_len)) == FAIL) {
printf("Error from Hstartwrite() for JPEG image data\n");
exit(1);
} /* end if */
while (file_len > MAX_FILE_BUF) {
if (fread(file_buf, sizeof(uint8), MAX_FILE_BUF, jfif_file) != MAX_FILE_BUF) {
printf("Error reading JFIF image data from %s\n", argv[1]);
exit(1);
} /* end if */
if (Hwrite(aid, MAX_FILE_BUF, file_buf) != (int32)(MAX_FILE_BUF)) {
printf("Error writing JPEG image data to HDF file\n");
exit(1);
} /* end if */
file_len -= MAX_FILE_BUF;
} /* end while */
if (file_len > 0) {
if (fread(file_buf, sizeof(uint8), (size_t)file_len, jfif_file) != (size_t)file_len) {
printf("Error reading JFIF image data from %s\n", argv[1]);
exit(1);
} /* end if */
if (Hwrite(aid, file_len, file_buf) != (int32)(file_len)) {
printf("Error writing last of JPEG image data to HDF file\n");
exit(1);
} /* end if */
} /* end if */
Hendaccess(aid); /* done with JPEG data, create RIG */
if (DFJPEGaddrig(file_id, wref, ctag) == FAIL) {
printf("Error writing JPEG RIG information\n");
exit(1);
} /* end if */
Hclose(file_id);
} /* end if */
else {
printf("Error opening HDF file: %s\b", argv[2]);
exit(1);
} /* end else */
return (0);
} /* end jpeg2hdf */
|