예제 #1
0
파일: pngimage.c 프로젝트: leo-liu/ptex-ng
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;
}
예제 #2
0
pdf_obj *
spc_lookup_object (const char *key)
{
    pdf_obj    *value = NULL;
    pdf_coord   cp;
    int         k;

    ASSERT(named_objects);

    if (!key)
        return  NULL;

    for (k = 0; _rkeys[k] && strcmp(key, _rkeys[k]); k++);
    switch (k) {
    case  K_OBJ__XPOS:
        cp.x = dvi_dev_xpos();
        cp.y = 0.0;
        pdf_dev_transform(&cp, NULL);
        value = pdf_new_number(ROUND(cp.x, .01));
        break;
    case  K_OBJ__YPOS:
        cp.x = 0.0;
        cp.y = dvi_dev_ypos();
        pdf_dev_transform(&cp, NULL);
        value = pdf_new_number(ROUND(cp.y, .01));
        break;
    case  K_OBJ__THISPAGE:
        value = pdf_doc_this_page();
        break;
    case  K_OBJ__PAGES:
        value = pdf_doc_page_tree();
        break;
    case  K_OBJ__NAMES:
        value = pdf_doc_names();
        break;
    case  K_OBJ__RESOURCES:
        value = pdf_doc_current_page_resources();
        break;
    case  K_OBJ__CATALOG:
        value = pdf_doc_catalog();
        break;
    case  K_OBJ__DOCINFO:
        value = pdf_doc_docinfo();
        break;
    default:
        value = pdf_names_lookup_object(named_objects, key, strlen(key));
        break;
    }

    /* spc_handler_pdfm_bead() in spc_pdfm.c controls NULL too.
      if (!value) {
        ERROR("Object reference %s not exist.", key);
      }
    */

    return  value;
}
예제 #3
0
파일: pngimage.c 프로젝트: leo-liu/ptex-ng
static pdf_obj *
create_ckey_mask (png_structp png_ptr, png_infop info_ptr)
{
  pdf_obj  *colorkeys;
  png_byte  color_type;
  png_bytep trans;
  int       num_trans, i;
  png_color_16p colors;

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

  colorkeys  = pdf_new_array();
  color_type = png_get_color_type(png_ptr, info_ptr);

  switch (color_type) {
  case PNG_COLOR_TYPE_PALETTE:
    for (i = 0; i < num_trans; i++) {
      if (trans[i] == 0x00) {
        pdf_add_array(colorkeys, pdf_new_number(i));
        pdf_add_array(colorkeys, pdf_new_number(i));
      } else if (trans[i] != 0xff) {
        WARN("%s: You found a bug in pngimage.c.", PNG_DEBUG_STR);
      }
    }
    break;
  case PNG_COLOR_TYPE_RGB:
    pdf_add_array(colorkeys, pdf_new_number(colors->red));
    pdf_add_array(colorkeys, pdf_new_number(colors->red));
    pdf_add_array(colorkeys, pdf_new_number(colors->green));
    pdf_add_array(colorkeys, pdf_new_number(colors->green));
    pdf_add_array(colorkeys, pdf_new_number(colors->blue));
    pdf_add_array(colorkeys, pdf_new_number(colors->blue));
    break;
  case PNG_COLOR_TYPE_GRAY:
    pdf_add_array(colorkeys, pdf_new_number(colors->gray));
    pdf_add_array(colorkeys, pdf_new_number(colors->gray));
    break;
  default:
    WARN("%s: You found a bug in pngimage.c.", PNG_DEBUG_STR);
    pdf_release_obj(colorkeys);
    colorkeys = NULL;
  }

  return colorkeys;
}
예제 #4
0
static void html_make_link_dict (char *name)
{
  pdf_obj *color;
  if (!link_dict) {
    link_dict = pdf_new_dict();
    pdf_add_dict(link_dict, pdf_new_name("Type"), pdf_new_name ("Annot"));
    pdf_add_dict(link_dict, pdf_new_name("Subtype"), pdf_new_name ("Link"));
    color = pdf_new_array ();
    pdf_add_array (color, pdf_new_number (0));
    pdf_add_array (color, pdf_new_number (1));
    pdf_add_array (color, pdf_new_number (1));
    pdf_add_dict(link_dict, pdf_new_name("C"), color);
    if (name && *name == '#' && !(base_value)) {
      pdf_add_dict (link_dict, pdf_new_name("Dest"), pdf_new_string(name+1,strlen(name+1)));
    } else if (name) {    /* Assume its a URL */
      char *url;
      int len;
      pdf_obj *action;
      len = strlen(name)+1;
      if (base_value)
	len+=strlen(base_value);
      url = NEW (len, char);
      if (base_value)
	strcpy (url, base_value);
      else
	url[0] = 0;
      strcat (url, name);
      action = pdf_new_dict();
      pdf_add_dict (action, pdf_new_name ("Type"), pdf_new_name ("Action"));
      pdf_add_dict (action, pdf_new_name ("S"), pdf_new_name ("URI"));
      pdf_add_dict (action, pdf_new_name ("URI"),
		    pdf_new_string (url, len));
      pdf_add_dict (link_dict, pdf_new_name ("A"), pdf_ref_obj (action));
      pdf_release_obj (action);
      RELEASE (url);
    }
    pdf_doc_begin_annot (link_dict);
  } else {
예제 #5
0
파일: pngimage.c 프로젝트: leo-liu/ptex-ng
/*
 * Set up Indexed ColorSpace for color-type PALETTE:
 *
 *  PNG allows only RGB color for base color space. If gAMA and/or cHRM
 *  chunk is available, we can use CalRGB color space instead of DeviceRGB
 *  for base color space.
 *
 */
static pdf_obj *
create_cspace_Indexed (png_structp png_ptr, png_infop info_ptr)
{
  pdf_obj   *colorspace;
  pdf_obj   *base, *lookup;
  png_byte  *data_ptr;
  png_colorp plte;
  int        num_plte, i;

  if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE) ||
      !png_get_PLTE(png_ptr, info_ptr, &plte, &num_plte)) {
    WARN("%s: PNG does not have valid PLTE chunk.", PNG_DEBUG_STR);
    return NULL;
  }

  /* Order is important. */
  colorspace = pdf_new_array ();
  pdf_add_array(colorspace, pdf_new_name("Indexed"));

  if (png_get_valid(png_ptr, info_ptr, PNG_INFO_iCCP))
    base = create_cspace_ICCBased(png_ptr, info_ptr);
  else {
    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB))
      base = create_cspace_sRGB(png_ptr, info_ptr);
    else
      base = create_cspace_CalRGB(png_ptr, info_ptr);
  }

  if (!base)
    base = pdf_new_name("DeviceRGB");

  pdf_add_array(colorspace, base);
  pdf_add_array(colorspace, pdf_new_number(num_plte-1));
  data_ptr = NEW(num_plte*3, png_byte);
  for (i = 0; i < num_plte; i++) {
    data_ptr[3*i]   = plte[i].red;
    data_ptr[3*i+1] = plte[i].green;
    data_ptr[3*i+2] = plte[i].blue;
  }
  lookup = pdf_new_string(data_ptr, num_plte*3);
  RELEASE(data_ptr);
  pdf_add_array(colorspace, lookup);

  return colorspace;
}
예제 #6
0
파일: pdfencoding.c 프로젝트: MiKTeX/miktex
/* Creates a PDF Differences array for the encoding, based on the
 * base encoding baseenc (if not NULL). Only character codes which
 * are actually used in the document are considered.
 */
static pdf_obj *
make_encoding_differences (char **enc_vec, char **baseenc, const char *is_used)
{
  pdf_obj *differences = NULL;
  int      code, count = 0;
  int      skipping = 1;

  ASSERT(enc_vec);

  /*
   *  Write all entries (except .notdef) if baseenc is unknown.
   *  If is_used is given, write only used entries.
   */
  differences = pdf_new_array();
  for (code = 0; code < 256; code++) {
    /* We skip NULL (= ".notdef"). Any character code mapped to ".notdef"
     * glyph should not be used in the document.
     */
    if ((is_used && !is_used[code]) || !enc_vec[code])
      skipping = 1;
    else if (!baseenc || !baseenc[code] ||
             strcmp(baseenc[code], enc_vec[code]) != 0) {
      /*
       * Difference found.
       */
      if (skipping)
        pdf_add_array(differences, pdf_new_number(code));
      pdf_add_array(differences,   pdf_new_name(enc_vec[code]));
      skipping = 0;
      count++;
    } else
      skipping = 1;
  }

  /*
   * No difference found. Some PDF viewers can't handle differences without
   * any differences. We return NULL.
   */
  if (count == 0) {
    pdf_release_obj(differences);
    differences = NULL;
  }

  return differences;
}
예제 #7
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;
}
예제 #8
0
파일: epdf.c 프로젝트: clerkma/ptex-ng
/* 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;
}
예제 #9
0
파일: pngimage.c 프로젝트: leo-liu/ptex-ng
/* 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;
}
예제 #10
0
파일: pngimage.c 프로젝트: leo-liu/ptex-ng
static pdf_obj *
make_param_Cal (png_byte color_type,
		double G, /* Gamma */
		double xw, double yw,
		double xr, double yr, double xg, double yg, double xb, double yb)
{
  pdf_obj *cal_param;
  pdf_obj *white_point, *matrix, *dev_gamma;
  double Xw, Yw, Zw; /* Yw = 1.0 */
  double Xr, Xg, Xb, Yr, Yb, Yg, Zr, Zg, Zb;

#ifndef ABS
#define ABS(x) ((x) < 0 ? -(x) : (x))
#endif
  /*
   * TODO: Check validity
   *
   * Conversion found in
   *
   *  com.sixlegs.image.png - Java package to read and display PNG images
   *  Copyright (C) 1998, 1999, 2001 Chris Nokleberg
   *
   *  http://www.sixlegs.com/software/png/
   *
   */
  {
    double zw, zr, zg, zb;
    double fr, fg, fb;
    double det;

    /* WhitePoint */
    zw = 1 - (xw + yw);
    zr = 1 - (xr + yr); zg = 1 - (xg + yg); zb = 1 - (xb + yb);
    Xw = xw / yw; Yw = 1.0; Zw = zw / yw;

    /* Matrix */
    det = xr * (yg * zb - zg * yb) - xg * (yr * zb - zr * yb) + xb * (yr * zg - zr * yg);
    if (ABS(det) < 1.0e-10) {
      WARN("Non invertible matrix: Maybe invalid value(s) specified in cHRM chunk.");
      return NULL;
    }
    fr  = (Xw * (yg * zb - zg * yb) - xg * (zb - Zw * yb) + xb * (zg - Zw * yg)) / det;
    fg  = (xr * (zb - Zw * yb) - Xw * (yr * zb - zr * yb) + xb * (yr * Zw - zr)) / det;
    fb  = (xr * (yg * Zw - zg) - xg * (yr * Zw - zr) + Xw * (yr * zg - zr * yg)) / det;
    Xr = fr * xr; Yr = fr * yr; Zr = fr * zr;
    Xg = fg * xg; Yg = fg * yg; Zg = fg * zg;
    Xb = fb * xb; Yb = fb * yb; Zb = fb * zb;
  }

  if (G < 1.0e-2) {
    WARN("Unusual Gamma specified: 1.0 / %g", G);
    return NULL;
  }

  cal_param = pdf_new_dict();

  /* White point is always required. */
  white_point = pdf_new_array();
  pdf_add_array(white_point, pdf_new_number(ROUND(Xw, 0.00001)));
  pdf_add_array(white_point, pdf_new_number(ROUND(Yw, 0.00001)));
  pdf_add_array(white_point, pdf_new_number(ROUND(Zw, 0.00001)));
  pdf_add_dict(cal_param, pdf_new_name("WhitePoint"), white_point);

  /* Matrix - default: Identity */
  if (color_type & PNG_COLOR_MASK_COLOR) {
    if (G != 1.0) {
      dev_gamma = pdf_new_array();
      pdf_add_array(dev_gamma, pdf_new_number(ROUND(G, 0.00001)));
      pdf_add_array(dev_gamma, pdf_new_number(ROUND(G, 0.00001)));
      pdf_add_array(dev_gamma, pdf_new_number(ROUND(G, 0.00001)));
      pdf_add_dict(cal_param, pdf_new_name("Gamma"), dev_gamma);
    }

    matrix = pdf_new_array();
    pdf_add_array(matrix, pdf_new_number(ROUND(Xr, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Yr, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Zr, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Xg, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Yg, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Zg, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Xb, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Yb, 0.00001)));
    pdf_add_array(matrix, pdf_new_number(ROUND(Zb, 0.00001)));
    pdf_add_dict (cal_param, pdf_new_name("Matrix"), matrix);
  } else { /* Gray */
    if (G != 1.0)
      pdf_add_dict(cal_param,
		   pdf_new_name("Gamma"),
		   pdf_new_number(ROUND(G, 0.00001)));
  }

  return cal_param;
}
예제 #11
0
pdf_obj *pdf_include_page(FILE *image_file, struct xform_info *p, char *res_name)
{
  pdf_obj *trailer = NULL, *catalog = NULL, *page_tree = NULL;
  pdf_obj *kids_ref, *kids;
  pdf_obj *media_box = NULL, *crop_box = NULL, *resources = NULL,
    *contents = NULL, *contents_ref = NULL;
  pdf_obj *tmp1;
#ifdef MEM_DEBUG
MEM_START
#endif
  if (!(trailer = pdf_open (image_file))) {
    fprintf (stderr, "\nCorrupt PDF file?\n");
  }
 
  /* Now just lookup catalog location */
  /* Deref catalog */
  if (trailer && (catalog = pdf_deref_obj(pdf_lookup_dict (trailer,"Root"))) ==
      NULL) {
    fprintf (stderr, "\nCatalog isn't where I expect it.\n");
  }
  if (trailer)
    pdf_release_obj (trailer);

  /* Lookup page tree in catalog */
  if (catalog) {
    page_tree = pdf_deref_obj (pdf_lookup_dict (catalog, "Pages"));
    /* Should be finished with catalog */
    pdf_release_obj (catalog);
  }
  /* Media box and resources can be inherited so start looking for
     them here */
  if (page_tree) {
    if ((tmp1 = pdf_lookup_dict (page_tree, "CropBox")))
      crop_box = pdf_deref_obj (tmp1);
    if ((tmp1 = pdf_lookup_dict (page_tree, "MediaBox")))
      media_box = pdf_deref_obj (tmp1);
    resources = pdf_deref_obj (pdf_lookup_dict (page_tree, "Resources"));
    if (resources == NULL) {
      resources = pdf_new_dict();
    }
    while ((kids_ref = pdf_lookup_dict (page_tree, "Kids")) != NULL) {
      kids = pdf_deref_obj (kids_ref);
      pdf_release_obj (page_tree);
      page_tree = pdf_deref_obj (pdf_get_array(kids, 0));
      pdf_release_obj (kids);
      /* Replace MediaBox if it's here */
      tmp1 = pdf_deref_obj(pdf_lookup_dict (page_tree, "MediaBox"));
      if (tmp1 && media_box)
	pdf_release_obj (media_box);
      if (tmp1) 
	media_box = tmp1;
      /* Do same for CropBox */
      tmp1 = pdf_deref_obj(pdf_lookup_dict (page_tree, "CropBox"));
      if (tmp1 && crop_box)
	pdf_release_obj (crop_box);
      if (tmp1) 
	crop_box = tmp1;
      /* Add resources if they're here */
      tmp1 = pdf_deref_obj (pdf_lookup_dict (page_tree, "Resources"));
      if (tmp1) {
	pdf_merge_dict (tmp1, resources);
	pdf_release_obj (resources);
	resources = tmp1;
      }
    }
    /* At this point, page_tree contains the first page.  media_box,
       crop_box,  and resources should also be set. */
    /* If there's a crop_box, replace media_box with crop_box.
       The rest of this routine assumes crop_box has been released */
    if (crop_box) {
      pdf_release_obj (media_box);
      media_box = crop_box;
      crop_box = NULL;
    }
    /* This gets bit confusing.  In the following code,
       media_box is the box the image is cropped to. 
       The bounding box is the box the image is scaled to */
    /* If user did not supply bounding box, use media_box
       (which may really be cropbox) as bounding box */
    /* Set the crop box parameters in the xform_info structure */
    p->c_llx = pdf_number_value (pdf_get_array (media_box, 0));
    p->c_lly = pdf_number_value (pdf_get_array (media_box, 1));
    p->c_urx = pdf_number_value (pdf_get_array (media_box, 2));
    p->c_ury = pdf_number_value (pdf_get_array (media_box, 3));

    /* Adjust scaling and clipping information as necessary */
    pdf_scale_image (p);

    /* Set the media box to whatever pdf_scale_image() decided
       for the crop box (which may be unchanged) */
    pdf_release_obj (media_box);
    media_box = pdf_new_array ();
    pdf_add_array (media_box, pdf_new_number (p->c_llx));
    pdf_add_array (media_box, pdf_new_number (p->c_lly));
    pdf_add_array (media_box, pdf_new_number (p->c_urx));
    pdf_add_array (media_box, pdf_new_number (p->c_ury));

    if ((contents =
	 pdf_deref_obj(pdf_lookup_dict(page_tree,"Contents")))==NULL) {
      fprintf (stderr, "\nNo Contents found\n");
      return NULL;
    }
    pdf_release_obj (page_tree);
  }
  /* Arrays of contents must be handled very differently (not implemented) */
  if (contents && contents -> type != PDF_ARRAY) {
    doc_make_form_xobj (contents, media_box,
			p->user_bbox? p->u_llx: 0.0,
			p->user_bbox? p->u_lly: 0.0,
			1.0, 1.0,
			resources, res_name);
  } else {
    fprintf (stderr, "\nIgnoring stream with with multiple segments\n");
    contents = NULL;
  }
  if (contents) {
    contents_ref = pdf_ref_obj (contents);
    pdf_release_obj (contents);
  }
  pdf_close ();
#ifdef MEM_DEBUG
MEM_END
#endif
  return (contents_ref);
}
예제 #12
0
/*
 * The following routine returns copies, not the original object.
 */
pdf_obj *
spc_lookup_reference (const char *key)
{
    pdf_obj    *value = NULL;
    pdf_coord   cp;
    int         k;

    ASSERT(named_objects);

    if (!key)
        return  NULL;

    for (k = 0; _rkeys[k] && strcmp(key, _rkeys[k]); k++);
    switch (k) {
    /* xpos and ypos must be position in device space here. */
    case  K_OBJ__XPOS:
        cp.x = dvi_dev_xpos();
        cp.y = 0.0;
        pdf_dev_transform(&cp, NULL);
        value = pdf_new_number(ROUND(cp.x, .01));
        break;
    case  K_OBJ__YPOS:
        cp.x = 0.0;
        cp.y = dvi_dev_ypos();
        pdf_dev_transform(&cp, NULL);
        value = pdf_new_number(ROUND(cp.y, .01));
        break;
    case  K_OBJ__THISPAGE:
        value = pdf_doc_this_page_ref();
        break;
    case  K_OBJ__PREVPAGE:
        value = pdf_doc_prev_page_ref();
        break;
    case  K_OBJ__NEXTPAGE:
        value = pdf_doc_next_page_ref();
        break;
    case  K_OBJ__PAGES:
        value = pdf_ref_obj(pdf_doc_page_tree());
        break;
    case  K_OBJ__NAMES:
        value = pdf_ref_obj(pdf_doc_names());
        break;
    case  K_OBJ__RESOURCES:
        value = pdf_ref_obj(pdf_doc_current_page_resources());
        break;
    case  K_OBJ__CATALOG:
        value = pdf_ref_obj(pdf_doc_catalog());
        break;
    case  K_OBJ__DOCINFO:
        value = pdf_ref_obj(pdf_doc_docinfo());
        break;
    default:
        if (ispageref(key))
            value = pdf_doc_ref_page(atoi(key + 4));
        else {
            value = pdf_names_lookup_reference(named_objects, key, strlen(key));
        }
        break;
    }

    if (!value) {
        ERROR("Object reference %s not exist.", key);
    }

    return  value;
}
예제 #13
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;
}
예제 #14
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;
}
예제 #15
0
파일: bmpimage.c 프로젝트: leo-liu/ptex-ng
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 {
예제 #16
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;
}