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 )