Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/LibRawLite/internal/libraw_x3f.cpp view on Meta::CPAN
x3f_table32_t plane_size; /* Size of the 3 planes */
uint8_t *plane_address[TRUE_PLANES]; /* computed offset to the planes */
x3f_hufftree_t tree; /* Coding tree */
x3f_table16_t x3rgb16; /* 3x16 bit X3-RGB data */
} x3f_true_t;
typedef struct x3f_quattro_s {
struct {
uint16_t columns;
uint16_t rows;
} plane[TRUE_PLANES];
uint32_t unknown;
} x3f_quattro_t;
typedef struct x3f_huffman_s {
x3f_table16_t mapping; /* Value Mapping = X3F lossy compression */
x3f_table32_t table; /* Coding Table */
x3f_hufftree_t tree; /* Coding tree */
x3f_table32_t row_offsets; /* Row offsets */
x3f_table8_t rgb8; /* 3x8 bit RGB data */
x3f_table16_t x3rgb16; /* 3x16 bit X3-RGB data */
} x3f_huffman_t;
typedef struct x3f_image_data_s {
/* 2.0 Fields */
/* ------------------------------------------------------------------ */
/* Known combinations of type and format are:
1-6, 2-3, 2-11, 2-18, 3-6 */
uint32_t type; /* 1 = RAW X3 (SD1)
2 = thumbnail or maybe just RGB
3 = RAW X3 */
uint32_t format; /* 3 = 3x8 bit pixmap
6 = 3x10 bit huffman with map table
11 = 3x8 bit huffman
18 = JPEG */
uint32_t type_format; /* type<<16 + format */
/* ------------------------------------------------------------------ */
uint32_t columns; /* width / row size in pixels */
uint32_t rows; /* height */
uint32_t row_stride; /* row size in bytes */
/* NULL if not used */
x3f_huffman_t *huffman; /* Huffman help data */
x3f_true_t *tru; /* TRUE help data */
x3f_quattro_t *quattro; /* Quattro help data */
void *data; /* Take from file if NULL. Otherwise,
this is the actual data bytes in
the file. */
uint32_t data_size;
} x3f_image_data_t;
typedef struct camf_entry_s {
uint32_t id;
uint32_t version;
uint32_t entry_size;
uint32_t name_offset;
uint32_t value_offset;
void *entry; /* pointer into decoded data */
/* computed values */
uint8_t *name_address;
void *value_address;
} camf_entry_t;
typedef struct camf_entry_table_s {
uint32_t size;
camf_entry_t *element;
} camf_entry_table_t;
typedef struct x3f_camf_typeN_s {
uint32_t val0;
uint32_t val1;
uint32_t val2;
uint32_t val3;
} x3f_camf_typeN_t;
typedef struct x3f_camf_type2_s {
uint32_t reserved;
uint32_t infotype;
uint32_t infotype_version;
uint32_t crypt_key;
} x3f_camf_type2_t;
typedef struct x3f_camf_type4_s {
uint32_t reserved;
uint32_t decode_bias;
uint32_t block_size;
uint32_t block_count;
} x3f_camf_type4_t;
typedef struct x3f_camf_s {
/* Header info */
uint32_t type;
union {
x3f_camf_typeN_t tN;
x3f_camf_type2_t t2;
x3f_camf_type4_t t4;
};
/* The encrypted raw data */
void *data;
uint32_t data_size;
/* Help data for type 4 Huffman compression */
x3f_true_huffman_t table;
x3f_hufftree_t tree;
uint8_t *decoding_start;
/* The decrypted data */
void *decoded_data;
uint32_t decoded_data_size;
/* Pointers into the decrypted data */
camf_entry_table_t entry_table;
} x3f_camf_t;
typedef struct x3f_directory_entry_header_s {
uint32_t identifier; /* Should be ´SECp´, "SECi", ... */
uint32_t version; /* 0x00020001 is version 2.1 */
union {
x3f_property_list_t property_list;
x3f_image_data_t image_data;
x3f_camf_t camf;
} data_subsection;
} x3f_directory_entry_header_t;
typedef struct x3f_directory_entry_s {
struct {
uint32_t offset;
uint32_t size;
} input, output;
uint32_t type;
x3f_directory_entry_header_t header;
} x3f_directory_entry_t;
typedef struct x3f_directory_section_s {
uint32_t identifier; /* Should be ´SECd´ */
uint32_t version; /* 0x00020001 is version 2.1 */
/* 2.0 Fields */
uint32_t num_directory_entries;
x3f_directory_entry_t *directory_entry;
} x3f_directory_section_t;
typedef struct x3f_header_s {
/* 2.0 Fields */
uint32_t identifier; /* Should be ´FOVb´ */
uint32_t version; /* 0x00020001 means 2.1 */
uint8_t unique_identifier[SIZE_UNIQUE_IDENTIFIER];
uint32_t mark_bits;
uint32_t columns; /* Columns and rows ... */
uint32_t rows; /* ... before rotation */
uint32_t rotation; /* 0, 90, 180, 270 */
/* Added for 2.1 and 2.2 */
uint8_t white_balance[SIZE_WHITE_BALANCE];
uint8_t extended_types[NUM_EXT_DATA]; /* x3f_extended_types_t */
uint32_t extended_data[NUM_EXT_DATA];
} x3f_header_t;
typedef struct x3f_info_s {
char *error;
struct {
LibRaw_abstract_datastream *file; /* Use if more data is needed */
} input, output;
} x3f_info_t;
typedef struct x3f_s {
x3f_info_t info;
src/Source/LibRawLite/internal/libraw_x3f.cpp view on Meta::CPAN
save_dir_pos = infile->tell();
infile->seek(DE->input.offset, SEEK_SET);
/* Read the type independent part of the entry header */
DEH = &DE->header;
GET4(DEH->identifier);
GET4(DEH->version);
/* NOTE - the tests below could be made on DE->type instead */
if (DEH->identifier == X3F_SECp) {
x3f_property_list_t *PL = &DEH->data_subsection.property_list;
/* Read the property part of the header */
GET4(PL->num_properties);
GET4(PL->character_format);
GET4(PL->reserved);
GET4(PL->total_length);
/* Set all not read data block pointers to NULL */
PL->data = NULL;
PL->data_size = 0;
}
if (DEH->identifier == X3F_SECi) {
x3f_image_data_t *ID = &DEH->data_subsection.image_data;
/* Read the image part of the header */
GET4(ID->type);
GET4(ID->format);
ID->type_format = (ID->type << 16) + (ID->format);
GET4(ID->columns);
GET4(ID->rows);
GET4(ID->row_stride);
/* Set all not read data block pointers to NULL */
ID->huffman = NULL;
ID->data = NULL;
ID->data_size = 0;
}
if (DEH->identifier == X3F_SECc) {
x3f_camf_t *CAMF = &DEH->data_subsection.camf;
/* Read the CAMF part of the header */
GET4(CAMF->type);
GET4(CAMF->tN.val0);
GET4(CAMF->tN.val1);
GET4(CAMF->tN.val2);
GET4(CAMF->tN.val3);
/* Set all not read data block pointers to NULL */
CAMF->data = NULL;
CAMF->data_size = 0;
/* Set all not allocated help pointers to NULL */
CAMF->table.element = NULL;
CAMF->table.size = 0;
CAMF->tree.nodes = NULL;
CAMF->decoded_data = NULL;
CAMF->decoded_data_size = 0;
CAMF->entry_table.element = NULL;
CAMF->entry_table.size = 0;
}
/* Reset the file pointer back to the directory */
infile->seek(save_dir_pos, SEEK_SET);
}
return x3f;
}
/* --------------------------------------------------------------------- */
/* Clean up an x3f structure */
/* --------------------------------------------------------------------- */
/* extern */ x3f_return_t x3f_delete(x3f_t *x3f)
{
x3f_directory_section_t *DS;
int d;
if (x3f == NULL)
return X3F_ARGUMENT_ERROR;
DS = &x3f->directory_section;
for (d=0; d<DS->num_directory_entries; d++) {
x3f_directory_entry_t *DE = &DS->directory_entry[d];
x3f_directory_entry_header_t *DEH = &DE->header;
if (DEH->identifier == X3F_SECp) {
x3f_property_list_t *PL = &DEH->data_subsection.property_list;
FREE(PL->property_table.element);
FREE(PL->data);
}
if (DEH->identifier == X3F_SECi) {
x3f_image_data_t *ID = &DEH->data_subsection.image_data;
cleanup_huffman(&ID->huffman);
FREE(ID->data);
}
if (DEH->identifier == X3F_SECc) {
x3f_camf_t *CAMF = &DEH->data_subsection.camf;
FREE(CAMF->data);
FREE(CAMF->table.element);
cleanup_huffman_tree(&CAMF->tree);
FREE(CAMF->decoded_data);
FREE(CAMF->entry_table.element);
}
}
FREE(DS->directory_entry);
FREE(x3f);
return X3F_OK;
}
/* --------------------------------------------------------------------- */
/* Getting a reference to a directory entry */
/* --------------------------------------------------------------------- */
/* TODO: all those only get the first instance */
static x3f_directory_entry_t *x3f_get(x3f_t *x3f,
uint32_t type,
uint32_t image_type)
{
x3f_directory_section_t *DS;
int d;
if (x3f == NULL) return NULL;
DS = &x3f->directory_section;
for (d=0; d<DS->num_directory_entries; d++) {
x3f_directory_entry_t *DE = &DS->directory_entry[d];
x3f_directory_entry_header_t *DEH = &DE->header;
if (DEH->identifier == type) {
switch (DEH->identifier) {
case X3F_SECi:
{
x3f_image_data_t *ID = &DEH->data_subsection.image_data;
if (ID->type_format == image_type)
return DE;
}
break;
default:
return DE;
}
}
}
return NULL;
}
/* extern */ x3f_directory_entry_t *x3f_get_raw(x3f_t *x3f)
{
x3f_directory_entry_t *DE;
if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_HUFFMAN_X530)) != NULL)
return DE;
if ((DE = x3f_get(x3f, X3F_SECi, X3F_IMAGE_RAW_HUFFMAN_10BIT)) != NULL)
return DE;
src/Source/LibRawLite/internal/libraw_x3f.cpp view on Meta::CPAN
fprintf(stderr, "Unknown huffman image type\n");
#endif
break;
}
if (row_stride == 0)
return x3f_load_huffman_compressed(I, DE, bits, use_map_table);
else
return x3f_load_huffman_not_compressed(I, DE, bits, use_map_table, row_stride);
}
static void x3f_load_pixmap(x3f_info_t *I, x3f_directory_entry_t *DE)
{
x3f_load_image_verbatim(I, DE);
}
static void x3f_load_jpeg(x3f_info_t *I, x3f_directory_entry_t *DE)
{
x3f_load_image_verbatim(I, DE);
}
static void x3f_load_image(x3f_info_t *I, x3f_directory_entry_t *DE)
{
x3f_directory_entry_header_t *DEH = &DE->header;
x3f_image_data_t *ID = &DEH->data_subsection.image_data;
read_data_set_offset(I, DE, X3F_IMAGE_HEADER_SIZE);
switch (ID->type_format) {
case X3F_IMAGE_RAW_TRUE:
case X3F_IMAGE_RAW_MERRILL:
case X3F_IMAGE_RAW_QUATTRO:
x3f_load_true(I, DE);
break;
case X3F_IMAGE_RAW_HUFFMAN_X530:
case X3F_IMAGE_RAW_HUFFMAN_10BIT:
x3f_load_huffman(I, DE, 10, 1, ID->row_stride);
break;
case X3F_IMAGE_THUMB_PLAIN:
x3f_load_pixmap(I, DE);
break;
case X3F_IMAGE_THUMB_HUFFMAN:
x3f_load_huffman(I, DE, 8, 0, ID->row_stride);
break;
case X3F_IMAGE_THUMB_JPEG:
x3f_load_jpeg(I, DE);
break;
default:
#ifdef DCRAW_VERBOSE
fprintf(stderr, "Unknown image type\n");
#endif
break;
}
}
static void x3f_load_camf_decode_type2(x3f_camf_t *CAMF)
{
uint32_t key = CAMF->t2.crypt_key;
int i;
CAMF->decoded_data_size = CAMF->data_size;
CAMF->decoded_data = malloc(CAMF->decoded_data_size);
for (i=0; i<CAMF->data_size; i++) {
uint8_t old, _new;
uint32_t tmp;
old = ((uint8_t *)CAMF->data)[i];
key = (key * 1597 + 51749) % 244944;
tmp = (uint32_t)(key * ((int64_t)301593171) >> 24);
_new = (uint8_t)(old ^ (uint8_t)(((((key << 8) - tmp) >> 1) + tmp) >> 17));
((uint8_t *)CAMF->decoded_data)[i] = _new;
}
}
/* NOTE: the unpacking in this code is in big respects identical to
true_decode_one_color(). The difference is in the output you
build. It might be possible to make some parts shared. NOTE ALSO:
This means that the meta data is obfuscated using an image
compression algorithm. */
static void camf_decode_type4(x3f_camf_t *CAMF)
{
uint32_t seed = CAMF->t4.decode_bias;
int row;
uint8_t *dst;
bool_t odd_dst = 0;
x3f_hufftree_t *tree = &CAMF->tree;
bit_state_t BS;
int32_t row_start_acc[2][2];
uint32_t rows = CAMF->t4.block_count;
uint32_t cols = CAMF->t4.block_size;
CAMF->decoded_data_size = (cols * rows * 3) / 2;
CAMF->decoded_data = malloc(CAMF->decoded_data_size);
dst = (uint8_t *)CAMF->decoded_data;
set_bit_state(&BS, CAMF->decoding_start);
row_start_acc[0][0] = seed;
row_start_acc[0][1] = seed;
row_start_acc[1][0] = seed;
row_start_acc[1][1] = seed;
for (row = 0; row < rows; row++) {
int col;
bool_t odd_row = row&1;
int32_t acc[2];
for (col = 0; col < cols; col++) {
bool_t odd_col = col&1;
int32_t diff = get_true_diff(&BS, tree);
int32_t prev = col < 2 ?
row_start_acc[odd_row][odd_col] :
acc[odd_col];
int32_t value = prev + diff;
acc[odd_col] = value;
if (col < 2)
row_start_acc[odd_row][odd_col] = value;
switch(odd_dst) {
case 0:
*dst++ = (uint8_t)((value>>4)&0xff);
*dst = (uint8_t)((value<<4)&0xf0);
break;
case 1:
*dst++ |= (uint8_t)((value>>8)&0x0f);
*dst++ = (uint8_t)((value<<0)&0xff);
break;
}
odd_dst = !odd_dst;
} /* end col */
} /* end row */
}
static void x3f_load_camf_decode_type4(x3f_camf_t *CAMF)
{
int i;
uint8_t *p;
x3f_true_huffman_element_t *element = NULL;
for (i=0, p = (uint8_t*)CAMF->data; *p != 0; i++) {
/* TODO: Is this too expensive ??*/
element =
(x3f_true_huffman_element_t *)realloc(element, (i+1)*sizeof(*element));
element[i].code_size = *p++;
element[i].code = *p++;
}
CAMF->table.size = i;
CAMF->table.element = element;
/* TODO: where does thes value 32 come from? */
#define CAMF_T4_DATA_OFFSET 32
CAMF->decoding_start = (uint8_t *)CAMF->data + CAMF_T4_DATA_OFFSET;
/* TODO: can it be fewer than 8 bits? Maybe taken from TRU->table? */
new_huffman_tree(&CAMF->tree, 8);
populate_true_huffman_tree(&CAMF->tree, &CAMF->table);
#ifdef DBG_PRNT
print_huffman_tree(CAMF->tree.nodes, 0, 0);
#endif
camf_decode_type4(CAMF);
}
static void x3f_setup_camf_entries(x3f_camf_t *CAMF)
{
uint8_t *p = (uint8_t *)CAMF->decoded_data;
uint8_t *end = p + CAMF->decoded_data_size;
camf_entry_t *table = NULL;
int i;
for (i=0; p < end; i++) {
uint32_t *p4 = (uint32_t *)p;
if ((*p4 & 0xffffff) != X3F_CMb) {
/* TODO: whats this all about ? Is it OK to just terminate if
you find an invalid entry ? */
#ifdef DCRAW_VERBOSE
fprintf(stderr, "Unknown CAMF entry %x\n", *p4);
#endif
break;
}
/* TODO: lots of realloc - may be inefficient */
table = (camf_entry_t *)realloc(table, (i+1)*sizeof(camf_entry_t));
table[i].id = *p4++;
table[i].version = *p4++;
table[i].entry_size = *p4++;
table[i].name_offset = *p4++;
table[i].value_offset = *p4++;
table[i].entry = p;
table[i].name_address = p + table[i].name_offset;
table[i].value_address = p + table[i].value_offset;
p += table[i].entry_size;
}
CAMF->entry_table.size = i;
CAMF->entry_table.element = table;
}
static void x3f_load_camf(x3f_info_t *I, x3f_directory_entry_t *DE)
{
x3f_directory_entry_header_t *DEH = &DE->header;
x3f_camf_t *CAMF = &DEH->data_subsection.camf;
read_data_set_offset(I, DE, X3F_CAMF_HEADER_SIZE);
CAMF->data_size = read_data_block(&CAMF->data, I, DE, 0);
switch (CAMF->type) {
case 2: /* Older SD9-SD14 */
x3f_load_camf_decode_type2(CAMF);
break;
case 4: /* TRUE DP1-... */
x3f_load_camf_decode_type4(CAMF);
break;
default:
#ifdef DCRAW_VERBOSE
fprintf(stderr, "Unknown CAMF type\n");
#endif
break;
}
if (CAMF->decoded_data != NULL)
x3f_setup_camf_entries(CAMF);
#ifdef DCRAW_VERBOSE
else
fprintf(stderr, "No decoded CAMF data\n");
#endif
}
/* extern */ x3f_return_t x3f_load_data(x3f_t *x3f, x3f_directory_entry_t *DE)
{
x3f_info_t *I = &x3f->info;
if (DE == NULL)
return X3F_ARGUMENT_ERROR;
switch (DE->header.identifier) {
case X3F_SECp:
x3f_load_property_list(I, DE);
break;
case X3F_SECi:
x3f_load_image(I, DE);
break;
case X3F_SECc:
x3f_load_camf(I, DE);
break;
default:
#ifdef DCRAW_VERBOSE
fprintf(stderr, "Unknown directory entry type\n");
#endif
return X3F_INTERNAL_ERROR;
}
return X3F_OK;
}
/* extern */ x3f_return_t x3f_load_image_block(x3f_t *x3f, x3f_directory_entry_t *DE)
{
x3f_info_t *I = &x3f->info;
if (DE == NULL)
return X3F_ARGUMENT_ERROR;
switch (DE->header.identifier) {
case X3F_SECi:
read_data_set_offset(I, DE, X3F_IMAGE_HEADER_SIZE);
x3f_load_image_verbatim(I, DE);
break;
default:
#ifdef DCRAW_VERBOSE
fprintf(stderr, "Unknown image directory entry type\n");
#endif
return X3F_INTERNAL_ERROR;
}
return X3F_OK;
}
/* --------------------------------------------------------------------- */
/* The End */
/* --------------------------------------------------------------------- */
( run in 3.167 seconds using v1.01-cache-2.11-cpan-8450f2e95f3 )