tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

jdicc.c (5409B)


      1 /*
      2 * jdicc.c
      3 *
      4 * Copyright (C) 1997-1998, Thomas G. Lane, Todd Newman.
      5 * Copyright (C) 2017, D. R. Commander.
      6 * For conditions of distribution and use, see the accompanying README.ijg
      7 * file.
      8 *
      9 * This file provides code to read International Color Consortium (ICC) device
     10 * profiles embedded in JFIF JPEG image files.  The ICC has defined a standard
     11 * for including such data in JPEG "APP2" markers.  The code given here does
     12 * not know anything about the internal structure of the ICC profile data; it
     13 * just knows how to get the profile data from a JPEG file while reading it.
     14 */
     15 
     16 #define JPEG_INTERNALS
     17 #include "jinclude.h"
     18 #include "jpeglib.h"
     19 #include "jerror.h"
     20 
     21 
     22 #define ICC_MARKER  (JPEG_APP0 + 2)     /* JPEG marker code for ICC */
     23 #define ICC_OVERHEAD_LEN  14            /* size of non-profile data in APP2 */
     24 
     25 
     26 /*
     27 * Handy subroutine to test whether a saved marker is an ICC profile marker.
     28 */
     29 
     30 LOCAL(boolean)
     31 marker_is_icc(jpeg_saved_marker_ptr marker)
     32 {
     33  return
     34    marker->marker == ICC_MARKER &&
     35    marker->data_length >= ICC_OVERHEAD_LEN &&
     36    /* verify the identifying string */
     37    marker->data[0] == 0x49 &&
     38    marker->data[1] == 0x43 &&
     39    marker->data[2] == 0x43 &&
     40    marker->data[3] == 0x5F &&
     41    marker->data[4] == 0x50 &&
     42    marker->data[5] == 0x52 &&
     43    marker->data[6] == 0x4F &&
     44    marker->data[7] == 0x46 &&
     45    marker->data[8] == 0x49 &&
     46    marker->data[9] == 0x4C &&
     47    marker->data[10] == 0x45 &&
     48    marker->data[11] == 0x0;
     49 }
     50 
     51 
     52 /*
     53 * See if there was an ICC profile in the JPEG file being read; if so,
     54 * reassemble and return the profile data.
     55 *
     56 * TRUE is returned if an ICC profile was found, FALSE if not.  If TRUE is
     57 * returned, *icc_data_ptr is set to point to the returned data, and
     58 * *icc_data_len is set to its length.
     59 *
     60 * IMPORTANT: the data at *icc_data_ptr is allocated with malloc() and must be
     61 * freed by the caller with free() when the caller no longer needs it.
     62 * (Alternatively, we could write this routine to use the IJG library's memory
     63 * allocator, so that the data would be freed implicitly when
     64 * jpeg_finish_decompress() is called.  But it seems likely that many
     65 * applications will prefer to have the data stick around after decompression
     66 * finishes.)
     67 */
     68 
     69 GLOBAL(boolean)
     70 jpeg_read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr,
     71                      unsigned int *icc_data_len)
     72 {
     73  jpeg_saved_marker_ptr marker;
     74  int num_markers = 0;
     75  int seq_no;
     76  JOCTET *icc_data;
     77  unsigned int total_length;
     78 #define MAX_SEQ_NO  255         /* sufficient since marker numbers are bytes */
     79  char marker_present[MAX_SEQ_NO + 1];      /* 1 if marker found */
     80  unsigned int data_length[MAX_SEQ_NO + 1]; /* size of profile data in marker */
     81  unsigned int data_offset[MAX_SEQ_NO + 1]; /* offset for data in marker */
     82 
     83  if (icc_data_ptr == NULL || icc_data_len == NULL)
     84    ERREXIT(cinfo, JERR_BUFFER_SIZE);
     85  if (cinfo->global_state < DSTATE_READY)
     86    ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state);
     87 
     88  *icc_data_ptr = NULL;         /* avoid confusion if FALSE return */
     89  *icc_data_len = 0;
     90 
     91  /* This first pass over the saved markers discovers whether there are
     92   * any ICC markers and verifies the consistency of the marker numbering.
     93   */
     94 
     95  for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++)
     96    marker_present[seq_no] = 0;
     97 
     98  for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
     99    if (marker_is_icc(marker)) {
    100      if (num_markers == 0)
    101        num_markers = marker->data[13];
    102      else if (num_markers != marker->data[13]) {
    103        WARNMS(cinfo, JWRN_BOGUS_ICC);  /* inconsistent num_markers fields */
    104        return FALSE;
    105      }
    106      seq_no = marker->data[12];
    107      if (seq_no <= 0 || seq_no > num_markers) {
    108        WARNMS(cinfo, JWRN_BOGUS_ICC);  /* bogus sequence number */
    109        return FALSE;
    110      }
    111      if (marker_present[seq_no]) {
    112        WARNMS(cinfo, JWRN_BOGUS_ICC);  /* duplicate sequence numbers */
    113        return FALSE;
    114      }
    115      marker_present[seq_no] = 1;
    116      data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
    117    }
    118  }
    119 
    120  if (num_markers == 0)
    121    return FALSE;
    122 
    123  /* Check for missing markers, count total space needed,
    124   * compute offset of each marker's part of the data.
    125   */
    126 
    127  total_length = 0;
    128  for (seq_no = 1; seq_no <= num_markers; seq_no++) {
    129    if (marker_present[seq_no] == 0) {
    130      WARNMS(cinfo, JWRN_BOGUS_ICC);  /* missing sequence number */
    131      return FALSE;
    132    }
    133    data_offset[seq_no] = total_length;
    134    total_length += data_length[seq_no];
    135  }
    136 
    137  if (total_length == 0) {
    138    WARNMS(cinfo, JWRN_BOGUS_ICC);  /* found only empty markers? */
    139    return FALSE;
    140  }
    141 
    142  /* Allocate space for assembled data */
    143  icc_data = (JOCTET *)malloc(total_length * sizeof(JOCTET));
    144  if (icc_data == NULL)
    145    ERREXIT1(cinfo, JERR_OUT_OF_MEMORY, 11);  /* oops, out of memory */
    146 
    147  /* and fill it in */
    148  for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
    149    if (marker_is_icc(marker)) {
    150      JOCTET FAR *src_ptr;
    151      JOCTET *dst_ptr;
    152      unsigned int length;
    153      seq_no = marker->data[12];
    154      dst_ptr = icc_data + data_offset[seq_no];
    155      src_ptr = marker->data + ICC_OVERHEAD_LEN;
    156      length = data_length[seq_no];
    157      while (length--) {
    158        *dst_ptr++ = *src_ptr++;
    159      }
    160    }
    161  }
    162 
    163  *icc_data_ptr = icc_data;
    164  *icc_data_len = total_length;
    165 
    166  return TRUE;
    167 }