1
#include "file_manager.h"
12
#define EOC_MARKER 0xFFD9
13
#define SOC_MARKER 0xFF4F
14
#define SIZ_MARKER 0xFF51
15
#define COD_MARKER 0xFF52
16
#define SOT_MARKER 0xFF90
17
#define PLT_MARKER 0xFF58
18
#define SOD_MARKER 0xFF93
20
#define JP2C_BOX_ID 0x6A703263
21
#define XML__BOX_ID 0x786D6C20
22
#define ASOC_BOX_ID 0x61736F63
23
#define NLST_BOX_ID 0x6E6C7374
24
#define JPCH_BOX_ID 0x6A706368
25
#define FTBL_BOX_ID 0x6674626C
26
#define DBTL_BOX_ID 0x6474626C
27
#define URL__BOX_ID 0x75726C20
28
#define FLST_BOX_ID 0x666C7374
31
string FileManager::GetCacheFileName(const string& path_image_file)
33
string name_cache_file;
36
while (!isalpha(path_image_file[begin_pos]))
39
name_cache_file=path_image_file.substr(begin_pos,path_image_file.size()-begin_pos);
41
// Replace "." with "_"
42
for (size_t j; (j = name_cache_file.find(".")) != string::npos;)
43
name_cache_file.replace(j, 1, "_");
45
// Replace "/" with "_"
46
for (size_t j; (j = name_cache_file.find("/")) != string::npos;)
47
name_cache_file.replace(j, 1, "_");
49
// Add the file extension ".cache"
50
//name_cache_file+=".cache";
52
return name_cache_file;
55
bool FileManager::ExistCacheImage(const string& path_image_file, string *path_cache_file)
57
// Get the path cache file
58
*path_cache_file = cache_dir_ + GetCacheFileName(path_image_file) + ".cache";
60
struct stat cache_att;
63
if (stat(path_cache_file->c_str(), &cache_att) == 0)
65
// Get last modification dates of image and cache files
67
stat(path_image_file.c_str(), &file_att);
69
// Check if last modification date of image file is lower than
70
// last modification date of cache file
71
if (file_att.st_mtime < cache_att.st_mtime) return true;
77
bool FileManager::ReadImage(const string& name_image_file, ImageInfo *image_info)
80
string path_cache_file;
82
// Cache file does not exist or it is not updated
83
if (!ExistCacheImage(name_image_file, &path_cache_file))
87
string extension = "";
88
size_t pos = name_image_file.find_last_of(".");
89
if (pos != string::npos) extension = name_image_file.substr(pos);
92
if (extension.compare(".j2c") == 0)
94
image_info->codestreams.push_back(CodestreamIndex());
96
CodingParameters *cp = &image_info->coding_parameters;
97
CodestreamIndex *ci = &image_info->codestreams.back();
98
if (!f.OpenForReading(name_image_file.c_str()))
100
ERROR("Impossible to open file: '" << name_image_file << "'...");
103
res = res && ReadCodestream(f, cp, ci);
107
else if (extension.compare(".jp2") == 0)
109
image_info->codestreams.push_back(CodestreamIndex());
111
if (!f.OpenForReading(name_image_file.c_str()))
113
ERROR("Impossible to open file: '" << name_image_file << "'...");
116
res = res && ReadJP2(f, image_info);
120
else if (extension.compare(".jpx") == 0)
122
if (!f.OpenForReading(name_image_file.c_str()))
124
ERROR("Impossible to open file: '" << name_image_file << "'...");
127
res = res && ReadJPX(f, image_info);
132
ERROR("File type not supported...");
135
// Serialize the info of the image in a cache file
136
struct stat cache_dir_stat;
137
if (stat(cache_dir_.c_str(), &cache_dir_stat)==0) res = res && OutputStream().Open(path_cache_file.c_str()).Serialize(*image_info);
139
// Cache file is updated
142
// Get info of the image
143
res = res && InputStream().Open(path_cache_file.c_str()).Serialize(*image_info);
149
bool FileManager::ReadCodestream(const File& file, CodingParameters *params, CodestreamIndex *index)
157
while (res = res && file.ReadReverse(&value), res && (value != EOC_MARKER))
162
TRACE("SOC marker...");
163
index->header.offset = file.GetOffset() - 2;
167
TRACE("SIZ marker...");
168
res = res && ReadSIZMarker(file, params);
172
TRACE("COD marker...");
173
res = res && ReadCODMarker(file, params);
177
TRACE("SOT marker...");
178
res = res && ReadSOTMarker(file, index);
182
TRACE("PLT marker...");
183
res = res && ReadPLTMarker(file, index);
184
if (res) plts = true;
188
TRACE("SOD marker...");
189
res = res && ReadSODMarker(file, index);
193
res = res && file.ReadReverse(&value) && file.Seek(value - 2, SEEK_CUR);
197
// Check if the image has been read in a right way
198
if (value == EOC_MARKER)
200
// Check if the image has PLT marker
201
if (plts) return true;
204
ERROR("The code-stream does not include any PLT marker");
210
ERROR("The code-stream does not end with an EOC marker");
215
bool FileManager::ReadSIZMarker(const File& file, CodingParameters *params)
219
res = res && file.Seek(4, SEEK_CUR);
220
// Get image height and width
222
for (int i = 0; i < 4; i++)
223
res = res && file.ReadReverse(&FE[i]);
226
params->size = Size(FE[0] - FE[2], FE[1] - FE[3]);
227
// Get T2, T1, omegaT2, omegaT1
229
for (int i = 0; i < 4; i++)
230
res = res && file.ReadReverse(&tiling[i]);
231
// Get number of components
232
uint16_t num_components;
233
res = res && file.ReadReverse(&num_components);
234
params->num_components = num_components;
235
// To jump to the end of the marker
236
res = res && file.Seek(3 * num_components, SEEK_CUR);
241
bool FileManager::ReadCODMarker(const File& file, CodingParameters *params)
246
res = res && file.Seek(2, SEEK_CUR) && file.ReadReverse(&cs_buf);
247
// Get progression order
249
res = res && file.ReadReverse(&progression);
250
params->progression = progression;
251
// Get number of quality layers
252
uint16_t quality_layers;
254
res = res && file.ReadReverse(&quality_layers) && file.Seek(1, SEEK_CUR);
255
params->num_layers = quality_layers;
256
// Get transform levels
257
uint8_t transform_levels;
258
// To jump 4 bytes (ECB2,ECB1,MS,WT)
259
res = res && file.ReadReverse(&transform_levels) && file.Seek(4, SEEK_CUR);
260
params->num_levels = transform_levels;
261
// Get precint sizes for each resolution
263
uint8_t size_precinct;
264
params->precinct_size.clear();
265
for (int i = 0; i <= params->num_levels; i++)
269
res = res && file.ReadReverse(&size_precinct);
270
height = 1L << ((size_precinct & 0xF0) >> 4);
271
width = 1L << (size_precinct & 0x0F);
272
params->precinct_size.push_back(Size(width, height));
276
height = ceil((double) params->size.y / (1L << i));
277
width = ceil((double) params->size.x / (1L << i));
278
params->precinct_size.insert(params->precinct_size.begin(), Size(width, height));
284
bool FileManager::ReadSOTMarker(const File& file, CodestreamIndex *index)
287
// Get offset of the codestream header
288
if (index->header.length == 0) index->header.length = file.GetOffset() - 2 - index->header.offset;
291
// To jump Lsot, it, itp, ntp
292
res = res && file.Seek(4, SEEK_CUR) && file.ReadReverse(<p) && file.Seek(2, SEEK_CUR);
293
index->packets.push_back(FileSegment(file.GetOffset(), ltp - 12));
297
bool FileManager::ReadPLTMarker(const File& file, CodestreamIndex *index)
301
uint64_t PLT_offset = file.GetOffset() + 3;
304
res = res && file.ReadReverse(&lplt);
305
res = res && file.Seek(lplt - 2, SEEK_CUR);
306
// PLT marker length = Lplt - 3 (2 bytes Lplt and 1 byte iplt)
307
index->PLT_markers.push_back(FileSegment(PLT_offset, lplt - 3));
311
bool FileManager::ReadSODMarker(const File& file, CodestreamIndex *index)
315
FileSegment& fs = index->packets.back();
316
fs.length = fs.length - (file.GetOffset() - fs.offset);
317
fs.offset = file.GetOffset();
318
res = res && file.Seek(fs.length, SEEK_CUR);
322
bool FileManager::ReadBoxHeader(const File &file, uint32_t *type_box, uint64_t *length_box)
325
// Get L, if it is not 0 or 1, then box length is L
327
res = res && file.ReadReverse(&L);
331
res = res && file.ReadReverse(&T);
333
// XL indicates the box length
337
res = res && file.ReadReverse(&XL);
338
*length_box = XL - 16;
340
// Box length = eof_offset - offset
343
*length_box = file.GetSize() - file.GetOffset();
348
bool FileManager::ReadJP2(const File& file, ImageInfo *image_info)
354
int pini=0, plen=0, pini_box=0, plen_box=0;
355
//int metadata_bin=1;
357
while (file.GetOffset() != file.GetSize() && res)
359
pini_box=file.GetOffset();
360
plen = pini_box-pini;
361
res = res && ReadBoxHeader(file, &type_box, &length_box);
362
plen_box=file.GetOffset()-pini_box;
366
TRACE("JP2C box...");
367
image_info->meta_data.meta_data.push_back(FileSegment(pini,plen));
368
res = res && ReadCodestream(file, &image_info->coding_parameters, &image_info->codestreams.back());
369
image_info->meta_data.place_holders.push_back(PlaceHolder(image_info->codestreams.size()-1, true, FileSegment(pini_box, plen_box), length_box));
370
pini=file.GetOffset();
376
image_info->meta_data.meta_data.push_back(FileSegment(pini,plen));
377
// Get meta_data info
378
res = res && file.Seek(length_box, SEEK_CUR);
379
image_info->meta_data.place_holders.push_back(PlaceHolder(metadata_bin, false, FileSegment(pini_box, plen_box), length_box));
381
pini=file.GetOffset();
386
res = res && file.Seek(length_box, SEEK_CUR);
389
image_info->meta_data.meta_data.push_back(FileSegment(pini,file.GetOffset()-pini));
393
bool FileManager::ReadJPX(const File& file, ImageInfo *image_info)
400
uint16_t data_reference;
401
vector<uint16_t> v_data_reference;
402
vector<string> v_path_file;
403
int pini=0, plen=0, pini_box=0, plen_box=0, pini_ftbl, plen_ftbl;
404
//int metadata_bin=1;
407
while (file.GetOffset() != file.GetSize() && res)
409
pini_box=file.GetOffset();
410
plen = pini_box-pini;
411
res = res && ReadBoxHeader(file, &type_box, &length_box);
412
plen_box=file.GetOffset()-pini_box;
416
TRACE("JPCH box...");
417
image_info->codestreams.push_back(CodestreamIndex());
420
TRACE("JP2C box...");
421
image_info->meta_data.meta_data.push_back(FileSegment(pini,plen));
422
res = res && ReadCodestream(file, &image_info->coding_parameters, &image_info->codestreams.back());
423
image_info->meta_data.place_holders.push_back(PlaceHolder(image_info->codestreams.size()-1, true, FileSegment(pini_box, plen_box), length_box));
424
pini=file.GetOffset();
428
TRACE("ASOC box...");
429
image_info->meta_data.meta_data.push_back(FileSegment(pini,plen));
430
res = res && file.Seek(length_box, SEEK_CUR);
431
image_info->meta_data.place_holders.push_back(PlaceHolder(metadata_bin, false, FileSegment(pini_box, plen_box), length_box));
433
pini=file.GetOffset();
438
image_info->meta_data.meta_data.push_back(FileSegment(pini,plen));
439
res = res && file.Seek(length_box, SEEK_CUR);
440
image_info->meta_data.place_holders.push_back(PlaceHolder(metadata_bin, false, FileSegment(pini_box, plen_box), length_box));
442
pini=file.GetOffset();
446
TRACE("FTBL box...");
447
image_info->meta_data.meta_data.push_back(FileSegment(pini,plen));
453
TRACE("FLST box...");
454
res = res && ReadFlstBox(file, length_box, &data_reference);
456
image_info->meta_data.meta_data.push_back(FileSegment(0,0));
458
image_info->meta_data.place_holders.push_back(PlaceHolder(v_data_reference.size(), true, FileSegment(pini_ftbl,plen_ftbl), 0));
459
v_data_reference.push_back(data_reference);
460
pini=file.GetOffset();
464
TRACE("DBTL box...");
465
res = res && file.Seek(2, SEEK_CUR);
469
// Add the paths of the hyperlinked images to the paths vector
470
res = res && ReadUrlBox(file, length_box, &path_file);
471
//path_file=root_dir_+path_file; /// OJOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
472
v_path_file.push_back(path_file);
475
res = res && file.Seek(length_box, SEEK_CUR);
478
image_info->meta_data.meta_data.push_back(FileSegment(pini,file.GetOffset()-pini));
479
int ind_codestream=0;
480
for (vector<uint16_t>::const_iterator i = v_data_reference.begin(); i!=v_data_reference.end(); i++)
482
image_info->paths.insert(pair<string, int> (v_path_file[*i-1],ind_codestream));
485
if (image_info->paths.size()>0)
487
image_info->codestreams.resize(image_info->paths.size());
488
image_info->meta_data_hyperlinks.resize(image_info->paths.size());
490
// Get image info of the hyperlinked images
491
for (multimap<string, int>::iterator i = image_info->paths.begin(); i != image_info->paths.end() && res; i++)
493
ImageInfo image_info_hyperlink;
494
res = res && ReadImage((*i).first, &image_info_hyperlink);
495
image_info->coding_parameters = image_info_hyperlink.coding_parameters;
496
image_info->codestreams[(*i).second] = image_info_hyperlink.codestreams.back();
497
image_info->meta_data_hyperlinks[(*i).second] = image_info_hyperlink.meta_data;
502
bool FileManager::ReadNlstBox(const File& file, int *num_codestream, int length_box)
505
// Get the codestream number
507
while (res && (length_box > 0))
509
res = res && file.ReadReverse(&an);
512
*num_codestream = an & 0x00FFFFFF;
519
bool FileManager::ReadFlstBox(const File& file, uint64_t length_box, uint16_t *data_reference)
522
// Get the path of the hyperlinked image
523
res = res && file.Seek(14, SEEK_CUR);
524
res = res && file.ReadReverse(data_reference);
529
bool FileManager::ReadUrlBox(const File& file, uint64_t length_box, string *path_file)
532
// Get the path of the hyperlinked image
533
res = res && file.Seek(4, SEEK_CUR);
534
char path_char[length_box - 4];
535
res = res && file.Read(path_char, length_box - 4);
536
*path_file = path_char;
537
size_t found = path_file->find("file://") + 7;
538
*path_file = path_file->substr(found);
539
//*path_file = path_file->substr(found + 2);
540
// Replace "./" with the root_dir_
541
size_t pos = path_file->find("./");
542
if (pos != string::npos) *path_file = path_file->substr(0, pos) + root_dir_ + path_file->substr(pos + 2);