Beispiel #1
0
/**
 * Uses jpeg library api to write APP01 segment consisting
 * of JPEG_XMP_SEGMENT_HEADER and metadata associated with
 * given image. If there is no metadata, or its size exceeds
 * JPEG_METADATA_LIMIT, then nothing is written.
 *
 * @param cinfo
 * @param decoded_image
 */
static void writeMetadata(
    jpeg_compress_struct& cinfo,
    const DecodedImage& decoded_image) {

  const unsigned metadata_length = decoded_image.getMetadataLength();
  if (metadata_length == 0 || metadata_length > JPEG_METADATA_LIMIT) {
    return;
  }

  jpeg_write_m_header(
      &cinfo,
      JPEG_APP0 + 1,
      JPEG_XMP_SEGMENT_HEADER_LENGTH + metadata_length);

  auto jpeg_metadata_writer = [&] (int c) { jpeg_write_m_byte(&cinfo, c); };

  // Write xmp header
  std::for_each(
      JPEG_XMP_SEGMENT_HEADER,
      JPEG_XMP_SEGMENT_HEADER + JPEG_XMP_SEGMENT_HEADER_LENGTH,
      jpeg_metadata_writer);

  // Write xmp data
  std::for_each(
      decoded_image.getMetadataPtr(),
      decoded_image.getMetadataPtr() + metadata_length,
      jpeg_metadata_writer);
}
Beispiel #2
0
static void
write_icc_profile (j_compress_ptr cinfo,
                   const JOCTET *icc_data_ptr,
                   unsigned int icc_data_len)
{
  unsigned int num_markers;	/* total number of markers we'll write */
  int cur_marker = 1;		/* per spec, counting starts at 1 */
  unsigned int length;		/* number of bytes to write in this marker */

  /* Calculate the number of markers we'll need, rounding up of course */
  num_markers = icc_data_len / MAX_DATA_BYTES_IN_MARKER;
  if (num_markers * MAX_DATA_BYTES_IN_MARKER != icc_data_len)
    num_markers++;

  while (icc_data_len > 0)
  {
    /* length of profile to put in this marker */
    length = icc_data_len;
    if (length > MAX_DATA_BYTES_IN_MARKER)
      length = MAX_DATA_BYTES_IN_MARKER;
    icc_data_len -= length;

    /* Write the JPEG marker header (APP2 code and marker length) */
    jpeg_write_m_header(cinfo, ICC_MARKER,
                        (unsigned int) (length + ICC_OVERHEAD_LEN));

    /* Write the marker identifying string "ICC_PROFILE" (null-terminated).
     * We code it in this less-than-transparent way so that the code works
     * even if the local character set is not ASCII.
     */
    jpeg_write_m_byte(cinfo, 0x49);
    jpeg_write_m_byte(cinfo, 0x43);
    jpeg_write_m_byte(cinfo, 0x43);
    jpeg_write_m_byte(cinfo, 0x5F);
    jpeg_write_m_byte(cinfo, 0x50);
    jpeg_write_m_byte(cinfo, 0x52);
    jpeg_write_m_byte(cinfo, 0x4F);
    jpeg_write_m_byte(cinfo, 0x46);
    jpeg_write_m_byte(cinfo, 0x49);
    jpeg_write_m_byte(cinfo, 0x4C);
    jpeg_write_m_byte(cinfo, 0x45);
    jpeg_write_m_byte(cinfo, 0x0);

    /* Add the sequencing info */
    jpeg_write_m_byte(cinfo, cur_marker);
    jpeg_write_m_byte(cinfo, (int) num_markers);

    /* Add the profile data */
    while (length--)
    {
      jpeg_write_m_byte(cinfo, *icc_data_ptr);
      icc_data_ptr++;
    }
    cur_marker++;
  }
}
Beispiel #3
0
static 
void jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo)
{
  jpeg_saved_marker_ptr marker;

  /* In the current implementation, we don't actually need to examine the
   * option flag here; we just copy everything that got saved.
   * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
   * if the encoder library already wrote one.
   */
  for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
    if (dstinfo->write_JFIF_header &&
    marker->marker == JPEG_APP0 &&
    marker->data_length >= 5 &&
    GETJOCTET(marker->data[0]) == 0x4A &&
    GETJOCTET(marker->data[1]) == 0x46 &&
    GETJOCTET(marker->data[2]) == 0x49 &&
    GETJOCTET(marker->data[3]) == 0x46 &&
    GETJOCTET(marker->data[4]) == 0)
      continue;         /* reject duplicate JFIF */

    if (dstinfo->write_Adobe_marker &&
    marker->marker == JPEG_APP0+14 &&
    marker->data_length >= 5 &&
    GETJOCTET(marker->data[0]) == 0x41 &&
    GETJOCTET(marker->data[1]) == 0x64 &&
    GETJOCTET(marker->data[2]) == 0x6F &&
    GETJOCTET(marker->data[3]) == 0x62 &&
    GETJOCTET(marker->data[4]) == 0x65)
      continue;         /* reject duplicate Adobe */

#ifdef NEED_FAR_POINTERS
    /* We could use jpeg_write_marker if the data weren't FAR... */
    {
      unsigned int i;

      jpeg_write_m_header(dstinfo, marker->marker, marker->data_length);
      for (i = 0; i < marker->data_length; i++)
        jpeg_write_m_byte(dstinfo, marker->data[i]);
    }
#else
    jpeg_write_marker(dstinfo, marker->marker,
              marker->data, marker->data_length);
#endif
  }
}