Esempio n. 1
0
static pdf_obj *
create_soft_mask (png_structp png_ptr, png_infop info_ptr,
		  png_bytep image_data_ptr, png_uint_32 width, png_uint_32 height)
{
  pdf_obj    *smask, *dict;
  png_bytep   smask_data_ptr;
  png_bytep   trans;
  int         num_trans;
  png_uint_32 i;

  if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ||
      !png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL)) {
    WARN("%s: PNG does not have valid tRNS chunk but tRNS is requested.", PNG_DEBUG_STR);
    return NULL;
  }

  smask = pdf_new_stream(STREAM_COMPRESS);
  dict  = pdf_stream_dict(smask);
  smask_data_ptr = (png_bytep) NEW(width*height, png_byte);
  pdf_add_dict(dict, pdf_new_name("Type"),    pdf_new_name("XObject"));
  pdf_add_dict(dict, pdf_new_name("Subtype"), pdf_new_name("Image"));
  pdf_add_dict(dict, pdf_new_name("Width"),      pdf_new_number(width));
  pdf_add_dict(dict, pdf_new_name("Height"),     pdf_new_number(height));
  pdf_add_dict(dict, pdf_new_name("ColorSpace"), pdf_new_name("DeviceGray"));
  pdf_add_dict(dict, pdf_new_name("BitsPerComponent"), pdf_new_number(8));
  for (i = 0; i < width*height; i++) {
    png_byte idx = image_data_ptr[i];
    smask_data_ptr[i] = (idx < num_trans) ? trans[idx] : 0xff;
  }
  pdf_add_stream(smask, (char *)smask_data_ptr, width*height);
  RELEASE(smask_data_ptr);

  return smask;
}
Esempio n. 2
0
static int
concat_stream (pdf_obj *dst, pdf_obj *src)
{
  const char *stream_data;
  long        stream_length;
  pdf_obj    *stream_dict;
  pdf_obj    *filter;

  if (!PDF_OBJ_STREAMTYPE(dst) || !PDF_OBJ_STREAMTYPE(src))
    ERROR("Invalid type.");

  stream_data   = pdf_stream_dataptr(src);
  stream_length = pdf_stream_length (src);
  stream_dict   = pdf_stream_dict   (src);

  if (pdf_lookup_dict(stream_dict, "DecodeParms")) {
    WARN("DecodeParams not supported.");
    return -1;
  }

  filter = pdf_lookup_dict(stream_dict, "Filter");
  if (!filter) {
    pdf_add_stream(dst, stream_data, stream_length);
    return 0;
#if HAVE_ZLIB
  } else {
    char *filter_name;
    if (PDF_OBJ_NAMETYPE(filter)) {
      filter_name = pdf_name_value(filter);
      if (filter_name && !strcmp(filter_name, "FlateDecode"))
	return add_stream_flate(dst, stream_data, stream_length);
      else {
	WARN("DecodeFilter \"%s\" not supported.", filter_name);
	return -1;
      }
    } else if (PDF_OBJ_ARRAYTYPE(filter)) {
      if (pdf_array_length(filter) > 1) {
	WARN("Multiple DecodeFilter not supported.");
	return -1;
      } else {
	filter_name = pdf_name_value(pdf_get_array(filter, 0));
	if (filter_name && !strcmp(filter_name, "FlateDecode"))
	  return add_stream_flate(dst, stream_data, stream_length);
	else {
	  WARN("DecodeFilter \"%s\" not supported.", filter_name);
	  return -1;
	}
      }
    } else
      ERROR("Broken PDF file?");
#endif /* HAVE_ZLIB */
  }

  return -1;
}
Esempio n. 3
0
int
jp2_include_image (pdf_ximage *ximage, FILE *fp)
{
  int      smask = 0;
  pdf_obj *stream, *stream_dict;
  ximage_info info;

  if (pdf_check_version(1, 5) < 0) {
    WARN("JPEG 2000 support requires PDF version >= 1.5.\n");
    return -1;
  }

  pdf_ximage_init_image_info(&info);
  stream = stream_dict = NULL;

  rewind(fp);
  if (scan_file(&info, &smask, fp) < 0) {
    WARN("JPEG2000: Reading JPEG 2000 file failed.");
    return -1;
  }

  stream      = pdf_new_stream(0);
  stream_dict = pdf_stream_dict(stream);
  pdf_add_dict(stream_dict,
               pdf_new_name("Filter"), pdf_new_name("JPXDecode"));
  if (smask)
    pdf_add_dict(stream_dict,
                 pdf_new_name("SMaskInData"), pdf_new_number(1));
  /* Read whole file */
  {
    int nb_read;
    rewind(fp);
    while ((nb_read =
        fread(work_buffer, sizeof(char), WORK_BUFFER_SIZE, fp)) > 0)
      pdf_add_stream(stream, work_buffer, nb_read);
  }

  pdf_ximage_set_image(ximage, &info, stream);

  return 0;
}
Esempio n. 4
0
int
jp2_include_image (pdf_ximage *ximage, FILE *fp)
{
  unsigned pdf_version;
  pdf_obj *stream, *stream_dict;
  ximage_info info;

  pdf_version = pdf_get_version();
  if (pdf_version < 5) {
    WARN("JPEG 2000 support requires PDF version >= 1.5 (Current setting 1.%d)\n", pdf_version);
    return -1;
  }

  pdf_ximage_init_image_info(&info);
  stream = stream_dict = NULL;

  rewind(fp);
  if (scan_file(&info, fp) < 0) {
    WARN("Reading JPEG 2000 file failed.");
    return -1;
  }

  stream      = pdf_new_stream(0);
  stream_dict = pdf_stream_dict(stream);
  pdf_add_dict(stream_dict,
        pdf_new_name("Filter"), pdf_new_name("JPXDecode"));
  /* Read whole file */
  {
    long nb_read;
    rewind(fp);
    while ((nb_read =
        fread(work_buffer, sizeof(char), WORK_BUFFER_SIZE, fp)) > 0)
      pdf_add_stream(stream, work_buffer, nb_read);
  }

  pdf_ximage_set_image(ximage, &info, stream);

  return 0;
}
Esempio n. 5
0
/* ximage here is the result. DONT USE IT FOR PASSING OPTIONS! */
int
pdf_include_page (pdf_ximage        *ximage,
                  FILE              *image_file,
                  const char        *ident,
                  load_options       options)
{
  pdf_file *pf;
  xform_info info;
  pdf_obj *contents = NULL, *catalog;
  pdf_obj *page = NULL, *resources = NULL, *markinfo = NULL;

  pf = pdf_open(ident, image_file);
  if (!pf)
    return -1;

  if (pdf_file_get_version(pf) > pdf_get_version()) {
    WARN("Trying to include PDF file which has newer version number " \
         "than output PDF: 1.%d.", pdf_get_version());
  }

  pdf_ximage_init_form_info(&info);

  if (options.page_no == 0)
    options.page_no = 1;
  page = pdf_doc_get_page(pf,
                          options.page_no, options.bbox_type,
                          &info.bbox, &resources);

  if(!page)
    goto error_silent;

  catalog = pdf_file_get_catalog(pf);
  markinfo = pdf_deref_obj(pdf_lookup_dict(catalog, "MarkInfo"));
  if (markinfo) {
    pdf_obj *tmp = pdf_deref_obj(pdf_lookup_dict(markinfo, "Marked"));
    pdf_release_obj(markinfo);
    if (!PDF_OBJ_BOOLEANTYPE(tmp)) {
      if (tmp)
	pdf_release_obj(tmp);
      goto error;
    } else if (pdf_boolean_value(tmp)) {
      WARN("PDF file is tagged... Ignoring tags.");
    }
    pdf_release_obj(tmp);
  }

  contents = pdf_deref_obj(pdf_lookup_dict(page, "Contents"));
  pdf_release_obj(page);
  page = NULL;

  /*
   * Handle page content stream.
   */
  {
    pdf_obj *content_new;

    if (!contents) {
      /*
       * Empty page
       */
      content_new = pdf_new_stream(0);
      /* TODO: better don't include anything if the page is empty */
    } else if (PDF_OBJ_STREAMTYPE(contents)) {
      /* 
       * We must import the stream because its dictionary
       * may contain indirect references.
       */
      content_new = pdf_import_object(contents);
    } else if (PDF_OBJ_ARRAYTYPE(contents)) {
      /*
       * Concatenate all content streams.
       */
      int idx, len = pdf_array_length(contents);
      content_new = pdf_new_stream(STREAM_COMPRESS);
      for (idx = 0; idx < len; idx++) {
	pdf_obj *content_seg = pdf_deref_obj(pdf_get_array(contents, idx));
	if (!PDF_OBJ_STREAMTYPE(content_seg) ||
	    pdf_concat_stream(content_new, content_seg) < 0) {
	  pdf_release_obj(content_seg);
	  pdf_release_obj(content_new);
	  goto error;
	}
	pdf_release_obj(content_seg);
      }
    } else {
      goto error;
    }

    if (contents)
      pdf_release_obj(contents);
    contents = content_new;
  }

  /*
   * Add entries to contents stream dictionary.
   */
  {
    pdf_obj *contents_dict, *bbox, *matrix;

    contents_dict = pdf_stream_dict(contents);
    pdf_add_dict(contents_dict,
                 pdf_new_name("Type"), pdf_new_name("XObject"));
    pdf_add_dict(contents_dict,
                 pdf_new_name("Subtype"), pdf_new_name("Form"));
    pdf_add_dict(contents_dict,
                 pdf_new_name("FormType"), pdf_new_number(1.0));

    bbox = pdf_new_array();
    pdf_add_array(bbox, pdf_new_number(info.bbox.llx));
    pdf_add_array(bbox, pdf_new_number(info.bbox.lly));
    pdf_add_array(bbox, pdf_new_number(info.bbox.urx));
    pdf_add_array(bbox, pdf_new_number(info.bbox.ury));

    pdf_add_dict(contents_dict, pdf_new_name("BBox"), bbox);

    matrix = pdf_new_array();
    pdf_add_array(matrix, pdf_new_number(1.0));
    pdf_add_array(matrix, pdf_new_number(0.0));
    pdf_add_array(matrix, pdf_new_number(0.0));
    pdf_add_array(matrix, pdf_new_number(1.0));
    pdf_add_array(matrix, pdf_new_number(0.0));
    pdf_add_array(matrix, pdf_new_number(0.0));

    pdf_add_dict(contents_dict, pdf_new_name("Matrix"), matrix);

    pdf_add_dict(contents_dict, pdf_new_name("Resources"),
                 pdf_import_object(resources));
    pdf_release_obj(resources);
  }

  pdf_close(pf);

  pdf_ximage_set_form(ximage, &info, contents);

  return 0;

 error:
  WARN("Cannot parse document. Broken PDF file?");
 error_silent:
  if (resources)
    pdf_release_obj(resources);
  if (markinfo)
    pdf_release_obj(markinfo);
  if (page)
    pdf_release_obj(page);
  if (contents)
    pdf_release_obj(contents);

  pdf_close(pf);

  return -1;
}
Esempio n. 6
0
/* bitdepth is always 8 (16 is not supported) */
static pdf_obj *
strip_soft_mask (png_structp png_ptr, png_infop info_ptr,
		 /* next two values will be modified. */
		 png_bytep image_data_ptr, png_uint_32p rowbytes_ptr,
		 png_uint_32 width, png_uint_32 height)
{
  pdf_obj    *smask, *dict;
  png_byte    color_type, bpc;
  png_bytep   smask_data_ptr;
  png_uint_32 i;

  color_type = png_get_color_type(png_ptr, info_ptr);
  bpc        = png_get_bit_depth (png_ptr, info_ptr);
  if (color_type & PNG_COLOR_MASK_COLOR) {
    int bps = (bpc == 8) ? 4 : 8;
    if (*rowbytes_ptr != bps*width*sizeof(png_byte)) { /* Something wrong */
      WARN("%s: Inconsistent rowbytes value.", PNG_DEBUG_STR);
      return NULL;
    }
  } else {
    int bps = (bpc == 8) ? 2 : 4;
    if (*rowbytes_ptr != bps*width*sizeof(png_byte)) { /* Something wrong */
      WARN("%s: Inconsistent rowbytes value.", PNG_DEBUG_STR);
      return NULL;
    }
  }

  smask = pdf_new_stream(STREAM_COMPRESS);
  dict  = pdf_stream_dict(smask);
  pdf_add_dict(dict, pdf_new_name("Type"),    pdf_new_name("XObject"));
  pdf_add_dict(dict, pdf_new_name("Subtype"), pdf_new_name("Image"));
  pdf_add_dict(dict, pdf_new_name("Width"),      pdf_new_number(width));
  pdf_add_dict(dict, pdf_new_name("Height"),     pdf_new_number(height));
  pdf_add_dict(dict, pdf_new_name("ColorSpace"), pdf_new_name("DeviceGray"));
  pdf_add_dict(dict, pdf_new_name("BitsPerComponent"), pdf_new_number(bpc));

  smask_data_ptr = (png_bytep) NEW((bpc/8)*width*height, png_byte);

  switch (color_type) {
  case PNG_COLOR_TYPE_RGB_ALPHA:
    if (bpc == 8) {
    for (i = 0; i < width*height; i++) {
      memmove(image_data_ptr+(3*i), image_data_ptr+(4*i), 3);
      smask_data_ptr[i] = image_data_ptr[4*i+3];
    }
    *rowbytes_ptr = 3*width*sizeof(png_byte);
    } else {
      for (i = 0; i < width*height; i++) {
        memmove(image_data_ptr+(6*i), image_data_ptr+(8*i), 6);
        smask_data_ptr[2*i]   = image_data_ptr[8*i+6];
        smask_data_ptr[2*i+1] = image_data_ptr[8*i+7];
      }
      *rowbytes_ptr = 6*width*sizeof(png_byte);
    }
    break;
  case PNG_COLOR_TYPE_GRAY_ALPHA:
    if (bpc == 8) {
    for (i = 0; i < width*height; i++) {
      image_data_ptr[i] = image_data_ptr[2*i];
      smask_data_ptr[i] = image_data_ptr[2*i+1];
    }
    *rowbytes_ptr = width*sizeof(png_byte);
    } else {
      for (i = 0; i < width*height; i++) {
        image_data_ptr[2*i]   = image_data_ptr[4*i];
        image_data_ptr[2*i+1] = image_data_ptr[4*i+1];
        smask_data_ptr[2*i]   = image_data_ptr[4*i+2];
        smask_data_ptr[2*i+1] = image_data_ptr[4*i+3];
      }
      *rowbytes_ptr = 2*width*sizeof(png_byte);      
    }
    break;
  default:
    WARN("You found a bug in pngimage.c!");
    pdf_release_obj(smask);
    RELEASE(smask_data_ptr);
    return NULL;
  }

  pdf_add_stream(smask, smask_data_ptr, (bpc/8)*width*height);
  RELEASE(smask_data_ptr);

  return smask;
}
Esempio n. 7
0
int
png_include_image (pdf_ximage *ximage, FILE *png_file)
{
  pdf_obj  *stream;
  pdf_obj  *stream_dict;
  pdf_obj  *colorspace, *mask, *intent;
  png_bytep stream_data_ptr;
  int       trans_type;
  ximage_info info;
  /* Libpng stuff */
  png_structp png_ptr;
  png_infop   png_info_ptr;
  png_byte    bpc, color_type;
  png_uint_32 width, height, rowbytes;

  pdf_ximage_init_image_info(&info);

  stream      = NULL;
  stream_dict = NULL;
  colorspace  = mask = intent = NULL;

  rewind (png_file);
  png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, warn);
  if (png_ptr == NULL ||
      (png_info_ptr = png_create_info_struct (png_ptr)) == NULL) {
    WARN("%s: Creating Libpng read/info struct failed.", PNG_DEBUG_STR);
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
    return -1;
  }

#if PNG_LIBPNG_VER >= 10603
  /* ignore possibly incorrect CMF bytes */
  png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON);
#endif

  /* Inititializing file IO. */
  png_init_io (png_ptr, png_file);

  /* Read PNG info-header and get some info. */
  png_read_info(png_ptr, png_info_ptr);
  color_type = png_get_color_type  (png_ptr, png_info_ptr);
  width      = png_get_image_width (png_ptr, png_info_ptr);
  height     = png_get_image_height(png_ptr, png_info_ptr);
  bpc        = png_get_bit_depth   (png_ptr, png_info_ptr);

  /* Ask libpng to convert down to 8-bpc. */
  if (bpc > 8) {
    if (pdf_get_version() < 5) {
      WARN("%s: 16-bpc PNG requires PDF version 1.5.", PNG_DEBUG_STR);
    png_set_strip_16(png_ptr);
    bpc = 8;
  }
  }
  /* Ask libpng to gamma-correct.
   * It is wrong to assume screen gamma value 2.2 but...
   * We do gamma correction here only when uncalibrated color space is used. 
   */
  if (!png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP) &&
      !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_sRGB) &&
      !png_get_valid(png_ptr, png_info_ptr, PNG_INFO_cHRM) &&
       png_get_valid(png_ptr, png_info_ptr, PNG_INFO_gAMA)) {
    double G = 1.0;
    png_get_gAMA (png_ptr, png_info_ptr, &G);
    png_set_gamma(png_ptr, 2.2, G);
  }

  trans_type = check_transparency(png_ptr, png_info_ptr);
  /* check_transparency() does not do updata_info() */
  png_read_update_info(png_ptr, png_info_ptr);
  rowbytes = png_get_rowbytes(png_ptr, png_info_ptr);

  /* Values listed below will not be modified in the remaining process. */
  info.width  = width;
  info.height = height;
  info.bits_per_component = bpc;

  if (compat_mode)
    info.xdensity = info.ydensity = 72.0 / 100.0;
  else
  {
    png_uint_32 xppm = png_get_x_pixels_per_meter(png_ptr, png_info_ptr);
    png_uint_32 yppm = png_get_y_pixels_per_meter(png_ptr, png_info_ptr);

    if (xppm > 0)
      info.xdensity = 72.0 / 0.0254 / xppm;
    if (yppm > 0)
      info.ydensity = 72.0 / 0.0254 / yppm;
  }

  stream      = pdf_new_stream (STREAM_COMPRESS);
  stream_dict = pdf_stream_dict(stream);

  stream_data_ptr = (png_bytep) NEW(rowbytes*height, png_byte);
  read_image_data(png_ptr, stream_data_ptr, height, rowbytes);

  /* Non-NULL intent means there is valid sRGB chunk. */
  intent = get_rendering_intent(png_ptr, png_info_ptr);
  if (intent)
    pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent);

  switch (color_type) {
  case PNG_COLOR_TYPE_PALETTE:

    colorspace = create_cspace_Indexed(png_ptr, png_info_ptr);

    switch (trans_type) {
    case PDF_TRANS_TYPE_BINARY:
      /* Color-key masking */
      mask = create_ckey_mask(png_ptr, png_info_ptr);
      break;
    case PDF_TRANS_TYPE_ALPHA:
      /* Soft mask */
      mask = create_soft_mask(png_ptr, png_info_ptr, stream_data_ptr, width, height);
      break;
    default:
      /* Nothing to be done here.
       * No tRNS chunk or image already composited with background color.
       */
      break;
    }
    info.num_components = 1;

    break;
  case PNG_COLOR_TYPE_RGB:
  case PNG_COLOR_TYPE_RGB_ALPHA:

    if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP))
      colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr);
    else if (intent) {
      colorspace = create_cspace_sRGB(png_ptr, png_info_ptr);
    } else {
      colorspace = create_cspace_CalRGB(png_ptr, png_info_ptr);
    }
    if (!colorspace)
      colorspace = pdf_new_name("DeviceRGB");

    switch (trans_type) {
    case PDF_TRANS_TYPE_BINARY:
      mask = create_ckey_mask(png_ptr, png_info_ptr);
      break;
    /* rowbytes changes 4 to 3 at here */
    case PDF_TRANS_TYPE_ALPHA:
      mask = strip_soft_mask(png_ptr, png_info_ptr,
                             stream_data_ptr, &rowbytes, width, height);
      break;
    default:
      mask = NULL;
    }
    info.num_components = 3;
    break;

  case PNG_COLOR_TYPE_GRAY:
  case PNG_COLOR_TYPE_GRAY_ALPHA:

    if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_iCCP))
      colorspace = create_cspace_ICCBased(png_ptr, png_info_ptr);
    else if (intent) {
      colorspace = create_cspace_sRGB(png_ptr, png_info_ptr);
    } else {
      colorspace = create_cspace_CalGray(png_ptr, png_info_ptr);
    }
    if (!colorspace)
      colorspace = pdf_new_name("DeviceGray");

    switch (trans_type) {
    case PDF_TRANS_TYPE_BINARY:
      mask = create_ckey_mask(png_ptr, png_info_ptr);
      break;
    case PDF_TRANS_TYPE_ALPHA:
      mask = strip_soft_mask(png_ptr, png_info_ptr,
                             stream_data_ptr, &rowbytes, width, height);
      break;
    default:
      mask = NULL;
    }
    info.num_components = 1;
    break;

  default:
    WARN("%s: Unknown PNG colortype %d.", PNG_DEBUG_STR, color_type);
  }
  pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace);

  pdf_add_stream(stream, stream_data_ptr, rowbytes*height);
  RELEASE(stream_data_ptr);

  if (mask) {
    if (trans_type == PDF_TRANS_TYPE_BINARY)
      pdf_add_dict(stream_dict, pdf_new_name("Mask"), mask);
    else if (trans_type == PDF_TRANS_TYPE_ALPHA) {
      if (info.bits_per_component >= 8 && info.width > 64) {
        pdf_stream_set_predictor(mask, 2, info.width,
                                 info.bits_per_component, 1);
      }
      pdf_add_dict(stream_dict, pdf_new_name("SMask"), pdf_ref_obj(mask));
      pdf_release_obj(mask);
    } else {
      WARN("%s: Unknown transparency type...???", PNG_DEBUG_STR);
      pdf_release_obj(mask);
    }
  }

  /* Finally read XMP Metadata
   * See, XMP Specification Part 3, Storage in Files
   * http://www.adobe.com/jp/devnet/xmp.html
   *
   * We require libpng version >= 1.6.14 since prior versions
   * of libpng had a bug that incorrectly treat the compression
   * flag of iTxt chunks.
   */
#if PNG_LIBPNG_VER >= 10614
  if (pdf_get_version() >= 4) {
    png_textp text_ptr;
    pdf_obj  *XMP_stream, *XMP_stream_dict;
    int       i, num_text;
    int       have_XMP = 0;

    num_text = png_get_text(png_ptr, png_info_ptr, &text_ptr, NULL);
    for (i = 0; i < num_text; i++) {
      if (!memcmp(text_ptr[i].key, "XML:com.adobe.xmp", 17)) {
        /* XMP found */
        if (text_ptr[i].compression != PNG_ITXT_COMPRESSION_NONE ||
            text_ptr[i].itxt_length == 0)
          WARN("%s: Invalid value(s) in iTXt chunk for XMP Metadata.", PNG_DEBUG_STR);
        else if (have_XMP)
          WARN("%s: Multiple XMP Metadata. Don't know how to treat it.", PNG_DEBUG_STR);
        else {
          /* We compress XMP metadata for included images here.
           * It is not recommended to compress XMP metadata for PDF documents but
           * we compress XMP metadata for included images here to avoid confusing
           * application programs that only want PDF document global XMP metadata
           * and scan for that.
           */
          XMP_stream = pdf_new_stream(STREAM_COMPRESS);
          XMP_stream_dict = pdf_stream_dict(XMP_stream);
          pdf_add_dict(XMP_stream_dict,
                       pdf_new_name("Type"), pdf_new_name("Metadata"));
          pdf_add_dict(XMP_stream_dict,
                       pdf_new_name("Subtype"), pdf_new_name("XML"));
          pdf_add_stream(XMP_stream, text_ptr[i].text, text_ptr[i].itxt_length);
          pdf_add_dict(stream_dict,
                       pdf_new_name("Metadata"), pdf_ref_obj(XMP_stream));
          pdf_release_obj(XMP_stream);
          have_XMP = 1;
        }
      }
    }
  }
#endif /* PNG_LIBPNG_VER */

  png_read_end(png_ptr, NULL);

  /* Cleanup */
  if (png_info_ptr)
    png_destroy_info_struct(png_ptr, &png_info_ptr);
  if (png_ptr)
    png_destroy_read_struct(&png_ptr, NULL, NULL);
  if (color_type != PNG_COLOR_TYPE_PALETTE &&
      info.bits_per_component >= 8 &&
      info.height > 64) {
    pdf_stream_set_predictor(stream, 15, info.width,
                             info.bits_per_component, info.num_components);
  }
  pdf_ximage_set_image(ximage, &info, stream);

  return 0;
}
Esempio n. 8
0
int
jpeg_include_image (pdf_ximage *ximage, FILE *fp)
{
  pdf_obj    *stream;
  pdf_obj    *stream_dict;
  pdf_obj    *colorspace;
  int         colortype;
  ximage_info info;
  struct JPEG_info j_info;

  if (!check_for_jpeg(fp)) {
    WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR);
    rewind(fp);
    return -1;
  }
  /* File position is 2 here... */

  pdf_ximage_init_image_info(&info);

  JPEG_info_init(&j_info);

  if (JPEG_scan_file(&j_info, fp) < 0) {
    WARN("%s: Not a JPEG file?", JPEG_DEBUG_STR);
    JPEG_info_clear(&j_info);
    return -1;
  }

  switch (j_info.num_components) {
  case 1:
    colortype = PDF_COLORSPACE_TYPE_GRAY;
    break;
  case 3:
    colortype = PDF_COLORSPACE_TYPE_RGB;
    break;
  case 4:
    colortype = PDF_COLORSPACE_TYPE_CMYK;
    break;
  default:
    WARN("%s: Unknown color space (num components: %d)",
	 JPEG_DEBUG_STR, info.num_components);
    JPEG_info_clear(&j_info);
    return -1;
  }

  /* JPEG image use DCTDecode. */
  stream      = pdf_new_stream (0);
  stream_dict = pdf_stream_dict(stream);
  pdf_add_dict(stream_dict,
	       pdf_new_name("Filter"), pdf_new_name("DCTDecode"));

  colorspace  = NULL;
  if (j_info.flags & HAVE_APPn_ICC) {
    pdf_obj *icc_stream, *intent;

    icc_stream = JPEG_get_iccp(&j_info);

    if (!icc_stream)
      colorspace = NULL;
    else {
      int   cspc_id;

      if (iccp_check_colorspace(colortype,
				pdf_stream_dataptr(icc_stream),
				pdf_stream_length (icc_stream)) < 0)
	colorspace = NULL;
      else {
	cspc_id = iccp_load_profile(NULL, /* noname */
				    pdf_stream_dataptr(icc_stream),
				    pdf_stream_length (icc_stream));
	if (cspc_id < 0)
	  colorspace = NULL;
	else {
	  colorspace = pdf_get_colorspace_reference(cspc_id);
	  intent     = iccp_get_rendering_intent(pdf_stream_dataptr(icc_stream),
						 pdf_stream_length (icc_stream));
	  if (intent)
	    pdf_add_dict(stream_dict, pdf_new_name("Intent"), intent);
	}
      }
      pdf_release_obj(icc_stream);
    }
  }

  /* No ICC or invalid ICC profile. */
  if (!colorspace) {
    switch (colortype) {
    case PDF_COLORSPACE_TYPE_GRAY:
      colorspace = pdf_new_name("DeviceGray");
      break;
    case PDF_COLORSPACE_TYPE_RGB:
      colorspace = pdf_new_name("DeviceRGB");
      break;
    case PDF_COLORSPACE_TYPE_CMYK:
      colorspace = pdf_new_name("DeviceCMYK");
      break;
    }
  }
  pdf_add_dict(stream_dict, pdf_new_name("ColorSpace"), colorspace);

#define IS_ADOBE_CMYK(j) (((j).flags & HAVE_APPn_ADOBE) && (j).num_components == 4)

  if (IS_ADOBE_CMYK(j_info)) {
    pdf_obj *decode;
    int      i;

    WARN("Adobe CMYK JPEG: Inverted color assumed.");
    decode = pdf_new_array();
    for (i = 0; i < j_info.num_components; i++) {
      pdf_add_array(decode, pdf_new_number(1.0));
      pdf_add_array(decode, pdf_new_number(0.0));
    }
    pdf_add_dict(stream_dict, pdf_new_name("Decode"), decode);
  }

  /* Copy file */
  JPEG_copy_stream(&j_info, stream, fp);

  info.width              = j_info.width;
  info.height             = j_info.height;
  info.bits_per_component = j_info.bits_per_component;
  info.num_components     = j_info.num_components;

  jpeg_get_density(&j_info, &info.xdensity, &info.ydensity);

  pdf_ximage_set_image(ximage, &info, stream);
  JPEG_info_clear(&j_info);

  return 0;
}
Esempio n. 9
0
pdf_obj *
CMap_create_stream (CMap *cmap)
{
  pdf_obj         *stream;
  pdf_obj         *stream_dict;
  CIDSysInfo      *csi;
  struct sbuf      wbuf;
  struct rangeDef *ranges;
  unsigned char   *codestr;
  int              i, j, count = 0;

  if (!cmap || !CMap_is_valid(cmap)) {
    WARN("Invalid CMap");
    return NULL;
  }

  if (cmap->type == CMAP_TYPE_IDENTITY)
    return NULL;

  stream      = pdf_new_stream(STREAM_COMPRESS);
  stream_dict = pdf_stream_dict(stream);

  csi = CMap_get_CIDSysInfo(cmap);
  if (!csi) {
    csi = (cmap->type != CMAP_TYPE_TO_UNICODE) ?
      &CSI_IDENTITY : &CSI_UNICODE;
  }

  if (cmap->type != CMAP_TYPE_TO_UNICODE) {
    pdf_obj *csi_dict;

    csi_dict = pdf_new_dict();
    pdf_add_dict(csi_dict,
		 pdf_new_name("Registry"),
		 pdf_new_string(csi->registry, strlen(csi->registry)));
    pdf_add_dict(csi_dict,
		 pdf_new_name("Ordering"),
		 pdf_new_string(csi->ordering, strlen(csi->ordering)));
    pdf_add_dict(csi_dict,
		 pdf_new_name("Supplement"),
		 pdf_new_number(csi->supplement));

    pdf_add_dict(stream_dict,
		 pdf_new_name("Type"),
		 pdf_new_name("CMap"));
    pdf_add_dict(stream_dict,
		 pdf_new_name("CMapName"),
		 pdf_new_name(cmap->name));
    pdf_add_dict(stream_dict,
		 pdf_new_name("CIDSystemInfo"), csi_dict);
    if (cmap->wmode != 0)
      pdf_add_dict(stream_dict,
		   pdf_new_name("WMode"),
		   pdf_new_number(cmap->wmode));
  }

  /* TODO:
   * Predefined CMaps need not to be embedded.
   */
  if (cmap->useCMap) {
    ERROR("UseCMap found (not supported yet)...");
    if (CMap_is_Identity(cmap->useCMap)) { /* not sure */
      if (CMap_get_wmode(cmap) == 1) {
	pdf_add_dict(stream_dict,
		     pdf_new_name("UseCMap"),
		     pdf_new_name("Identity-V"));
      } else {
    	pdf_add_dict(stream_dict,
		     pdf_new_name("UseCMap"),
		     pdf_new_name("Identity-H"));
      }
    } else {
      int      res_id;
      pdf_obj *ucmap_ref;

      res_id = pdf_findresource("CMap", CMap_get_name(cmap->useCMap));
      if (res_id >= 0) {
	ucmap_ref = pdf_get_resource_reference(res_id);
      } else {
	pdf_obj *ucmap_obj;

	ucmap_obj = CMap_create_stream(cmap->useCMap);
	if (!ucmap_obj) {
	  ERROR("Uh ah. I cannot continue...");
	}

	res_id = pdf_defineresource("CMap",
				    CMap_get_name(cmap->useCMap),
				    ucmap_obj, PDF_RES_FLUSH_IMMEDIATE);
	ucmap_ref = pdf_get_resource_reference(res_id);
      }
      pdf_add_dict(stream_dict, pdf_new_name("UseCMap"), ucmap_ref);
    }
  }

#define WBUF_SIZE 40960
  wbuf.buf = NEW(WBUF_SIZE, char);
  codestr  = NEW(cmap->profile.maxBytesIn, unsigned char);
  memset(codestr, 0, cmap->profile.maxBytesIn);

  wbuf.curptr = wbuf.buf;
  wbuf.limptr = wbuf.buf + WBUF_SIZE -
    2 * (cmap->profile.maxBytesIn + cmap->profile.maxBytesOut) + 16;

  /* Start CMap */
  pdf_add_stream(stream, (const void *) CMAP_BEGIN, strlen(CMAP_BEGIN));

  wbuf.curptr += sprintf(wbuf.curptr, "/CMapName ");
  write_name(&wbuf.curptr, wbuf.limptr, cmap->name);
  wbuf.curptr += sprintf(wbuf.curptr, " def\n");
  wbuf.curptr += sprintf(wbuf.curptr, "/CMapType %d def\n" , cmap->type);
  if (cmap->wmode != 0 &&
      cmap->type != CMAP_TYPE_TO_UNICODE)
    wbuf.curptr += sprintf(wbuf.curptr, "/WMode %d def\n", cmap->wmode);

#define CMAP_CSI_FMT "/CIDSystemInfo <<\n\
  /Registry (%s)\n\
  /Ordering (%s)\n\
  /Supplement %d\n\
>> def\n"
  wbuf.curptr += sprintf(wbuf.curptr, "/CIDSystemInfo <<\n");
  wbuf.curptr += sprintf(wbuf.curptr, "  /Registry ");
  write_string(&wbuf.curptr, wbuf.limptr, csi->registry);
  wbuf.curptr += sprintf(wbuf.curptr, "\n");
  wbuf.curptr += sprintf(wbuf.curptr, "  /Ordering ");
  write_string(&wbuf.curptr, wbuf.limptr, csi->ordering);
  wbuf.curptr += sprintf(wbuf.curptr, "\n");
  wbuf.curptr += sprintf(wbuf.curptr, "  /Supplement %d\n>> def\n",
    csi->supplement);
  pdf_add_stream(stream, wbuf.buf, (int)(wbuf.curptr - wbuf.buf));
  wbuf.curptr = wbuf.buf;

  /* codespacerange */
  ranges = cmap->codespace.ranges;
  wbuf.curptr += sprintf(wbuf.curptr,
			 "%d begincodespacerange\n", cmap->codespace.num);
  for (i = 0; i < cmap->codespace.num; i++) {
    *(wbuf.curptr)++ = '<';
    for (j = 0; j < ranges[i].dim; j++) {
      sputx(ranges[i].codeLo[j], &(wbuf.curptr), wbuf.limptr);
    }
    *(wbuf.curptr)++ = '>';
    *(wbuf.curptr)++ = ' ';
    *(wbuf.curptr)++ = '<';
    for (j = 0; j < ranges[i].dim; j++) {
      sputx(ranges[i].codeHi[j], &(wbuf.curptr), wbuf.limptr);
    }
    *(wbuf.curptr)++ = '>';
    *(wbuf.curptr)++ = '\n';
  }
  pdf_add_stream(stream, wbuf.buf, (int)(wbuf.curptr - wbuf.buf));
  wbuf.curptr = wbuf.buf;
  pdf_add_stream(stream,
		 "endcodespacerange\n", strlen("endcodespacerange\n"));

  /* CMap body */
  if (cmap->mapTbl) {
    count = write_map(cmap->mapTbl,
		      0, codestr, 0, &wbuf, stream); /* Top node */
    if (count > 0) { /* Flush */
      char fmt_buf[32];
      if (count > 100)
	ERROR("Unexpected error....: %d", count);
      sprintf(fmt_buf, "%d beginbfchar\n", count);
      pdf_add_stream(stream, fmt_buf,  strlen(fmt_buf));
      pdf_add_stream(stream,
		     wbuf.buf, (int) (wbuf.curptr - wbuf.buf));
      pdf_add_stream(stream,
		     "endbfchar\n", strlen("endbfchar\n"));
      count = 0;
      wbuf.curptr = wbuf.buf;
    }
  }
  /* End CMap */
  pdf_add_stream(stream, CMAP_END, strlen(CMAP_END));

  RELEASE(codestr);
  RELEASE(wbuf.buf);

  return stream;
}
Esempio n. 10
0
int
bmp_include_image (pdf_ximage *ximage, FILE *fp)
{
  pdf_obj *stream, *stream_dict, *colorspace;
  ximage_info     info;
  struct hdr_info hdr;
  int  num_palette, flip;
  int  i;

  pdf_ximage_init_image_info(&info);

  stream = stream_dict = colorspace = NULL;

  rewind(fp);
  if (read_header(fp, &hdr) < 0)
    return -1;

  get_density(&info.xdensity, &info.ydensity, &hdr);
  info.width  = hdr.width;
  info.height = hdr.height;
  if (info.height < 0) {
    info.height = -info.height;
    flip = 0;
  } else {
    flip = 1;
  }


  if (hdr.bit_count < 24) {
    if (hdr.bit_count != 1 &&
        hdr.bit_count != 4 && hdr.bit_count != 8) {
      WARN("Unsupported palette size: %ld", hdr.bit_count);
      return -1;
    }
    num_palette = (hdr.offset - hdr.hsize - DIB_FILE_HEADER_SIZE) / hdr.psize;
    info.bits_per_component = hdr.bit_count;
    info.num_components = 1;
  } else if (hdr.bit_count == 24) { /* full color */
    num_palette = 1; /* dummy */
    info.bits_per_component = 8;
    info.num_components = 3;
  } else {
    WARN("Unkown/Unsupported BMP bitCount value: %ld", hdr.bit_count);
    return -1;
  }

  if (info.width == 0 || info.height == 0 || num_palette < 1) {
    WARN("Invalid BMP file: width=%ld, height=%ld, #palette=%d",
   info.width, info.height, num_palette);
    return -1;
  }

  /* Start reading raster data */
  stream      = pdf_new_stream(STREAM_COMPRESS);
  stream_dict = pdf_stream_dict(stream);

  /* Color space: Indexed or DeviceRGB */
  if (hdr.bit_count < 24) {
    pdf_obj *lookup;
    unsigned char *palette, bgrq[4];

    palette = NEW(num_palette*3+1, unsigned char);
    for (i = 0; i < num_palette; i++) {
      if (fread(bgrq, 1,  hdr.psize, fp) != hdr.psize) {
        WARN("Reading file failed...");
        RELEASE(palette);
        return -1;
      }
      /* BGR data */
      palette[3*i  ] = bgrq[2];
      palette[3*i+1] = bgrq[1];
      palette[3*i+2] = bgrq[0];
    }
    lookup = pdf_new_string(palette, num_palette*3);
    RELEASE(palette);

    colorspace = pdf_new_array();
    pdf_add_array(colorspace, pdf_new_name("Indexed"));
    pdf_add_array(colorspace, pdf_new_name("DeviceRGB"));
    pdf_add_array(colorspace, pdf_new_number(num_palette-1));
    pdf_add_array(colorspace, lookup);
  } else {
Esempio n. 11
0
pdf_obj *start_png_image (FILE *file, char *res_name)
{
  pdf_obj *result = NULL, *dict = NULL;
  png_structp png_ptr;
  png_infop info_ptr;
  unsigned long width, height;
  unsigned bit_depth, color_type;
  rewind (file);
  if (!(png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,    
					  NULL, NULL, NULL)) ||
      !(info_ptr = png_create_info_struct (png_ptr))) {
    fprintf (stderr, "\n\nLibpng failed to initialize\n");
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
    return NULL;
  }
  png_init_io (png_ptr, file);
  /*  png_set_sig_bytes (png_ptr, 0); */
  /* Read PNG header */
  png_read_info (png_ptr, info_ptr);
  {
    png_color_16 default_background;
    png_color_16p file_background;

    default_background.red=255; default_background.green=255;
    default_background.blue=255; default_background.gray=0;
    default_background.index = 0;

    width = png_get_image_width(png_ptr, info_ptr);
    height = png_get_image_height(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    /* Convert paletted images to true color */
    if (color_type == PNG_COLOR_TYPE_PALETTE) {
      png_set_expand(png_ptr);
    }
    /* Limit image component depth to 8 bits */
    if (bit_depth == 16) {
      png_set_strip_16 (png_ptr);
    }
    if (png_get_bKGD(png_ptr, info_ptr, &file_background)) {
      png_set_background(png_ptr, file_background,
			 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
    } else {
      png_set_background(png_ptr, &default_background,
			 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
    }
  }
  { /* Read the image in raw RGB format */
    int i, rowbytes, pdf_bit_depth;
    png_bytep *rows;
    png_read_update_info(png_ptr, info_ptr);
    rows = NEW (height, png_bytep);
    rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    rows[0] = NEW (rowbytes*height, png_byte);
    for (i=1; i<height; i++) {
      rows[i] = rows[0] + rowbytes * i;
    }
    png_read_image(png_ptr, rows);
    result = pdf_new_stream(STREAM_COMPRESS);
    dict = pdf_stream_dict(result);
    pdf_add_dict (dict, pdf_new_name ("Width"),
		  pdf_new_number(width));
    pdf_add_dict (dict, pdf_new_name ("Height"),
		  pdf_new_number(height));
    if (color_type == PNG_COLOR_TYPE_GRAY) {
      pdf_bit_depth = bit_depth;
    } else {
      pdf_bit_depth = 8;
    }
    pdf_add_dict (dict, pdf_new_name ("BitsPerComponent"),
		  pdf_new_number(pdf_bit_depth));
    if (color_type == PNG_COLOR_TYPE_GRAY ||
	color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
      pdf_add_dict (dict, pdf_new_name ("ColorSpace"),
		    pdf_new_name ("DeviceGray"));
    } else{
      pdf_add_dict (dict, pdf_new_name ("ColorSpace"),
		    pdf_new_name ("DeviceRGB"));
    }
    pdf_add_stream (result, (char *)rows[0], rowbytes*height);
    RELEASE (rows[0]);
    RELEASE (rows);
  }
  { /* Cleanup  */
    if (info_ptr)
      png_destroy_info_struct(png_ptr, &info_ptr);
    if (png_ptr)
      png_destroy_read_struct(&png_ptr, NULL, NULL);
  }
  return result;
}