Exemple #1
0
static void
pdf_check_stream(PDF *p, size_t len)
{
    size_t max;
    int cur;
    
    if (p->stream.curpos + len <= p->stream.maxpos)
	return;

    if (p->stream.flush & PDF_FLUSH_HEAVY) {
	pdf_flush_stream(p);

	if (p->stream.curpos + len <= p->stream.maxpos)
	    return;
    }

    max = (size_t) (2 * (p->stream.maxpos - p->stream.basepos));
    cur = p->stream.curpos - p->stream.basepos;

    p->stream.basepos = (pdf_byte *)
	p->realloc(p, (void *) p->stream.basepos, max, "pdf_check_stream");
    p->stream.maxpos = p->stream.basepos + max;
    p->stream.curpos = p->stream.basepos + cur;

    pdf_check_stream(p, len);
}
Exemple #2
0
PDFLIB_API void PDFLIB_CALL
PDF_close(PDF *p)
{
    static const char fn[] = "PDF_close";

    PDF_TRACE(("%s\t\t(pdf[%p]);\n", fn, (void *) p));

    if (PDF_SANITY_CHECK_FAILED(p))
	return;

    PDF_CHECK_SCOPE(p, fn, pdf_state_document);

    if (PDF_GET_STATE(p) != pdf_state_error) {
	if (p->current_page == 0)
	    pdf_error(p, PDF_RuntimeError, "Empty document");

	pdf_wrapup_document(p);	/* dump the remaining PDF structures */
    }

    pdf_flush_stream(p);

    pdf_cleanup_document(p);

    /* UPR stuff not released here but in PDF_delete() */

    PDF_SET_STATE(p, fn, pdf_state_object);
}
Exemple #3
0
/* Finish the pattern definition. */
PDFLIB_API void PDFLIB_CALL
PDF_end_pattern(PDF *p)
{
    static const char fn[] = "PDF_end_pattern";
    long length;

    PDF_TRACE(("%s\t(pdf[%p]);\n", fn, (void *) p));

    if (PDF_SANITY_CHECK_FAILED(p))
	return;

    PDF_CHECK_SCOPE(p, fn, pdf_state_pattern);

    /* check whether PDF_save() and PDF_restore() calls are balanced */
    if (p->sl > 0)
	pdf_error(p, PDF_RuntimeError,
	    "Unmatched save level at end of pattern");

    pdf_end_text(p);
    p->contents = c_none;

    if (p->compresslevel)
	pdf_compress_end(p);
					
    length = pdf_tell(p) - p->start_contents_pos;
    pdf_end_stream(p);
    pdf_end_obj(p);				/* pattern */

    pdf_begin_obj(p, p->contents_length_id);	/* Length object */
    pdf_printf(p, "%ld\n", length);
    pdf_end_obj(p);
  
    pdf_begin_obj(p, p->res_id);		/* Resource object */
    pdf_begin_dict(p);				/* Resource dict */

    pdf_write_page_procsets(p);			/* ProcSet resources */

    pdf_write_page_fonts(p);			/* Font resources */

    pdf_write_page_colorspaces(p);		/* Color space resources */

    pdf_write_page_pattern(p);			/* Pattern resources */

    pdf_write_xobjects(p);			/* XObject resources */

    pdf_end_dict(p);				/* resource dict */
    pdf_end_obj(p);				/* resource object */

    PDF_POP_STATE(p, fn);

    if (p->flush & PDF_FLUSH_PAGE)
	pdf_flush_stream(p);
}
Exemple #4
0
PDFLIB_API void PDFLIB_CALL
PDF_end_page(PDF *p)
{
    static const char fn[] = "PDF_end_page";
    int index;


    PDF_TRACE(("%s\t(pdf[%p]);\n", fn, (void *) p));

    if (PDF_SANITY_CHECK_FAILED(p))
	return;

    PDF_CHECK_SCOPE(p, fn, pdf_state_page);

    /* check whether PDF_save() and PDF_restore() calls are balanced */
    if (p->sl > 0)
	pdf_error(p, PDF_RuntimeError, "Unmatched save level at end of page");


    /* restore text parameter and color defaults for out-of-page usage.
    */
    pdf_init_tstate(p);
    pdf_init_cstate(p);

    pdf_end_contents_section(p);

    /* Page object */
    pdf_begin_obj(p, p->pages[p->current_page]);

    pdf_begin_dict(p);
    pdf_puts(p, "/Type/Page\n");
    pdf_printf(p, "/Parent %ld 0 R\n", pdf_get_pnode_id(p));

    p->res_id = pdf_alloc_id(p);
    pdf_printf(p, "/Resources %ld 0 R\n", p->res_id);

    pdf_printf(p, "/MediaBox[0 0 %f %f]\n", p->width, p->height);

    if (p->CropBox.llx != (float) 0 || p->CropBox.lly != (float) 0 ||
        p->CropBox.urx != (float) 0 || p->CropBox.ury != (float) 0 )
    {
	if (p->CropBox.urx <= p->CropBox.llx ||
	    p->CropBox.ury <= p->CropBox.lly)
		pdf_error(p, PDF_ValueError, "Illegal CropBox dimensions");

	pdf_printf(p, "/CropBox[%f %f %f %f]\n",
	    p->CropBox.llx, p->CropBox.lly, p->CropBox.urx, p->CropBox.ury);
    }

    if (p->BleedBox.llx != (float) 0 || p->BleedBox.lly != (float) 0 ||
        p->BleedBox.urx != (float) 0 || p->BleedBox.ury != (float) 0 )
    {
	if (p->BleedBox.urx <= p->BleedBox.llx ||
	    p->BleedBox.ury <= p->BleedBox.lly)
		pdf_error(p, PDF_ValueError, "Illegal BleedBox dimensions");

	pdf_printf(p, "/BleedBox[%f %f %f %f]\n",
	    p->BleedBox.llx, p->BleedBox.lly, p->BleedBox.urx, p->BleedBox.ury);
    }

    if (p->TrimBox.llx != (float) 0 || p->TrimBox.lly != (float) 0 ||
        p->TrimBox.urx != (float) 0 || p->TrimBox.ury != (float) 0 )
    {
	if (p->TrimBox.urx <= p->TrimBox.llx ||
	    p->TrimBox.ury <= p->TrimBox.lly)
		pdf_error(p, PDF_ValueError, "Illegal TrimBox dimensions");

	pdf_printf(p, "/TrimBox[%f %f %f %f]\n",
	    p->TrimBox.llx, p->TrimBox.lly, p->TrimBox.urx, p->TrimBox.ury);
    }

    if (p->ArtBox.llx != (float) 0 || p->ArtBox.lly != (float) 0 ||
        p->ArtBox.urx != (float) 0 || p->ArtBox.ury != (float) 0 )
    {
	if (p->ArtBox.urx <= p->ArtBox.llx ||
	    p->ArtBox.ury <= p->ArtBox.lly)
		pdf_error(p, PDF_ValueError, "Illegal ArtBox dimensions");

	pdf_printf(p, "/ArtBox[%f %f %f %f]\n",
	    p->ArtBox.llx, p->ArtBox.lly, p->ArtBox.urx, p->ArtBox.ury);
    }

    /*
     * The duration can be placed in the transition dictionary (/D)
     * or in the page dictionary (/Dur). We put it here so it can
     * be used without setting a transition effect.
     */

    if (p->duration > 0)
	pdf_printf(p, "/Dur %f\n", p->duration);

    pdf_write_page_transition(p);

    pdf_puts(p, "/Contents[");
    for (index = 0; index < p->next_content; index++) {
	pdf_printf(p, "%ld 0 R", p->contents_ids[index]);
	pdf_putc(p, (char) (index + 1 % 8 ? PDF_SPACE : PDF_NEWLINE));
    }
    pdf_puts(p, "]\n");

    /* Thumbnail image */
    if (p->thumb_id != BAD_ID)
	pdf_printf(p, "/Thumb %ld 0 R\n", p->thumb_id);

    pdf_write_annots_root(p);

    pdf_end_dict(p);				/* Page object */
    pdf_end_obj(p);

    pdf_write_page_annots(p);			/* Annotation dicts */
    
    pdf_begin_obj(p, p->res_id);		/* resource object */
    pdf_begin_dict(p);				/* resource dict */

    pdf_write_page_procsets(p);			/* ProcSet resources */

    pdf_write_page_fonts(p);			/* Font resources */

    pdf_write_page_colorspaces(p);		/* Color space resources */

    pdf_write_page_pattern(p);			/* Pattern resources */

    pdf_write_xobjects(p);			/* XObject resources */

    pdf_end_dict(p);				/* resource dict */
    pdf_end_obj(p);				/* resource object */

    pdf_cleanup_page(p);

    PDF_SET_STATE(p, fn, pdf_state_document);

    if (p->flush & PDF_FLUSH_PAGE)
	pdf_flush_stream(p);
}
Exemple #5
0
void
pdf_write_page_annots(PDF *p)
{
    pdf_annot	*ann;
    long	length, start_pos;
    id		length_id;
    PDF_data_source src;

    for (ann = p->annots; ann != NULL; ann = ann->next) {
	pdf_begin_obj(p, ann->obj_id);	/* Annotation object */
	pdf_begin_dict(p);		/* Annotation dict */

	pdf_puts(p, "/Type/Annot\n");
	switch (ann->type) {
	    case ann_text:
		pdf_puts(p, "/Subtype/Text\n");
		pdf_printf(p, "/Rect[%f %f %f %f]\n", 
		    ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury);

		pdf_write_border_style(p, ann);

		if (ann->open)
		    pdf_puts(p, "/Open true\n");

		if (ann->icon != icon_text_note)	/* note is default */
		    pdf_printf(p, "/Name/%s\n", pdf_icon_names[ann->icon]);

		/* Contents key is required, but may be empty */
		pdf_puts(p, "/Contents");

		if (ann->contents) {
		    pdf_quote_string(p, ann->contents);
		    pdf_putc(p, PDF_NEWLINE);
		} else
		    pdf_puts(p, "()\n"); /* empty contents is OK */

		/* title is optional */
		if (ann->title) {
		    pdf_puts(p, "/T");
		    pdf_quote_string(p, ann->title);
		    pdf_putc(p, PDF_NEWLINE);
		}

		break;

	    case ann_locallink:
		pdf_puts(p, "/Subtype/Link\n");
		pdf_printf(p, "/Rect[%f %f %f %f]\n", 
		    ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury);

		pdf_write_border_style(p, ann);

		/* preallocate page object id for a later page */
		if (ann->dest.page > p->current_page) {
		    while (ann->dest.page >= p->pages_capacity)
			pdf_grow_pages(p);

		    /* if this page has already been used as a link target
		     * it will already have an object id.
		     */
		    if (p->pages[ann->dest.page] == BAD_ID)
			p->pages[ann->dest.page] = pdf_alloc_id(p);
		}

		if (ann->dest.type == retain) {
		    pdf_printf(p, "/Dest[%ld 0 R/XYZ null null 0]\n",
			    p->pages[ann->dest.page]);
		} else if (ann->dest.type == fitpage) {
		    pdf_printf(p, "/Dest[%ld 0 R/Fit]\n",
			    p->pages[ann->dest.page]);
		} else if (ann->dest.type == fitwidth) {
		    pdf_printf(p, "/Dest[%ld 0 R/FitH 0]\n",
			    p->pages[ann->dest.page]);
		} else if (ann->dest.type == fitheight) {
		    pdf_printf(p, "/Dest[%ld 0 R/FitV 0]\n",
			    p->pages[ann->dest.page]);
		} else if (ann->dest.type == fitbbox) {
		    pdf_printf(p, "/Dest[%ld 0 R/FitB]\n",
			    p->pages[ann->dest.page]);
		}

		break;

	    case ann_pdflink:
		pdf_puts(p, "/Subtype/Link\n");
		pdf_printf(p, "/Rect[%f %f %f %f]\n", 
		    ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury);

		pdf_write_border_style(p, ann);

		pdf_puts(p, "/A");
		pdf_begin_dict(p);			/* A dict */
		pdf_puts(p, "/Type/Action/S/GoToR\n");

		if (ann->dest.type == retain) {
		    pdf_printf(p, "/D[%d 0 R/XYZ null null 0]\n",
			    ann->dest.page-1);	/* zero-based */
		} else if (ann->dest.type == fitpage) {
		    /* zero-based */
		    pdf_printf(p, "/D[%d 0 R/Fit]\n", ann->dest.page-1);
		} else if (ann->dest.type == fitwidth) {
		    /* Trick: we don't know the height of a future page yet,
		     * so we use a "large" value for top which will do for
		     * most pages. If it doesn't work, not much harm is done.
		     */
		    /* zero-based */
		    pdf_printf(p, "/D[%d 0 R/FitH 2000]\n", ann->dest.page-1);
		} else if (ann->dest.type == fitheight) {
		    /* zero-based */
		    pdf_printf(p, "/D[%d 0 R/FitV 0]\n", ann->dest.page-1);
		} else if (ann->dest.type == fitbbox) {
		    /* zero-based */
		    pdf_printf(p, "/D[%d 0 R/FitB]\n", ann->dest.page-1);
		}

		pdf_puts(p, "/F");
		pdf_begin_dict(p);			/* F dict */
		pdf_puts(p, "/Type/FileSpec\n");
		pdf_printf(p, "/F(");
		pdf_puts(p, ann->filename);
		pdf_puts(p,")\n");
		pdf_end_dict(p);			/* F dict */

		pdf_end_dict(p);			/* A dict */

		break;

	    case ann_launchlink:
		pdf_puts(p, "/Subtype/Link\n");
		pdf_printf(p, "/Rect[%f %f %f %f]\n", 
		    ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury);

		pdf_write_border_style(p, ann);

		pdf_puts(p, "/A");
		pdf_begin_dict(p);			/* A dict */
		pdf_puts(p, "/Type/Action/S/Launch\n");

		pdf_puts(p, "/F");
		pdf_begin_dict(p);			/* F dict */
		pdf_puts(p, "/Type/FileSpec\n");
		pdf_printf(p, "/F(");
		pdf_puts(p, ann->filename);
		pdf_puts(p,")\n");
		pdf_end_dict(p);			/* F dict */

		pdf_end_dict(p);			/* A dict */

		break;

	    case ann_weblink:
		pdf_puts(p, "/Subtype/Link\n");
		pdf_printf(p, "/Rect[%f %f %f %f]\n", 
		    ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury);

		pdf_write_border_style(p, ann);

		pdf_printf(p, "/A<</S/URI/URI(");
		pdf_puts(p, ann->filename);
		pdf_puts(p, ")>>\n");
		break;

	    case ann_attach:
		pdf_puts(p, "/Subtype/FileAttachment\n");
		pdf_printf(p, "/Rect[%f %f %f %f]\n", 
		    ann->rect.llx, ann->rect.lly, ann->rect.urx, ann->rect.ury);

		pdf_write_border_style(p, ann);

		if (ann->icon != icon_file_pushpin)	/* pushpin is default */
		    pdf_printf(p, "/Name/%s\n",
		    	pdf_icon_names[ann->icon]);

		if (ann->title) {
		    pdf_puts(p, "/T");
		    pdf_quote_string(p, ann->title);
		    pdf_putc(p, PDF_NEWLINE);
		}

		if (ann->contents) {
		    pdf_puts(p, "/Contents");
		    pdf_quote_string(p, ann->contents);
		    pdf_putc(p, PDF_NEWLINE);
		}
		    
		/* the icon is too small without these flags (=28) */
		pdf_printf(p, "/F %d\n",
			pdf_ann_flag_print |
			pdf_ann_flag_nozoom | 
			pdf_ann_flag_norotate);

		pdf_puts(p, "/FS");
		pdf_begin_dict(p);			/* FS dict */
		pdf_puts(p, "/Type/FileSpec\n");

		pdf_printf(p, "/F(");
		pdf_puts(p, ann->filename);
		pdf_puts(p, ")\n");

		/* alloc id for the actual embedded file stream */
		ann->obj_id = pdf_alloc_id(p);
		pdf_printf(p, "/EF<</F %ld 0 R>>\n", ann->obj_id);
		pdf_end_dict(p);			/* FS dict */

		break;

	    default:
		pdf_error(p, PDF_SystemError, "Unknown annotation type %d",
				ann->type);
	}

	pdf_end_dict(p);		/* Annotation dict */
	pdf_end_obj(p);			/* Annotation object */
    }

    /* Write the actual embedded files with preallocated ids */
    for (ann = p->annots; ann != NULL; ann = ann->next) {
	if (ann->type != ann_attach)
	    continue;

	pdf_begin_obj(p, ann->obj_id);	/* EmbeddedFile */
	pdf_puts(p, "<</Type/EmbeddedFile\n");

	if (ann->mimetype)
	    pdf_printf(p, "/Subtype (%s)\n", ann->mimetype);

	if (p->compresslevel)
	    pdf_puts(p, "/Filter/FlateDecode\n");

	length_id = pdf_alloc_id(p);
	pdf_printf(p, "/Length %ld 0 R\n", length_id);
	pdf_end_dict(p);		/* F dict */

	pdf_begin_stream(p);		/* Embedded file stream */
	start_pos = pdf_tell(p);

	/* write the file in the PDF */
	src.private_data = (void *) ann->filename;
	src.init	= pdf_data_source_file_init;
	src.fill	= pdf_data_source_file_fill;
	src.terminate	= pdf_data_source_file_terminate;
	src.length	= (long) 0;
	src.offset	= (long) 0;

	pdf_compress(p, &src);

	length = pdf_tell(p) - start_pos;
	pdf_end_stream(p);		/* Embedded file stream */
	pdf_end_obj(p);			/* EmbeddedFile object */

	pdf_begin_obj(p, length_id);	/* Length object */
	pdf_printf(p, "%ld\n", length);
	pdf_end_obj(p);			/* Length object */

	if (p->flush & PDF_FLUSH_CONTENT)
	    pdf_flush_stream(p);
    }
}
Exemple #6
0
void
pdf_put_image(PDF *p, int im, pdf_bool firststrip)
{
    id		length_id;
    long	length;
    pdf_image	*image;
    int		i;

    image = &p->images[im];

    /* york: how to check? see also F-imagecolor!
    switch (image->colorspace) {
        case ImageMask:
        case DeviceGray:
        case Indexed:
        case DeviceRGB:
        case DeviceCMYK:
	    break;

	default:
	    pdf_error(p, PDF_SystemError, "Unknown color space");
	    break;
    }
    */

    /* Images may also be written to the output before the first page */
    if (PDF_GET_STATE(p) == pdf_state_page)
	pdf_end_contents_section(p);

    /* Image object */

    image->no = pdf_new_xobject(p, image_xobject, NEW_ID);

    pdf_begin_dict(p); 		/* XObject */

    pdf_puts(p, "/Type/XObject\n");
    pdf_puts(p, "/Subtype/Image\n");

    pdf_printf(p,"/Width %d\n", (int) image->width);
    pdf_printf(p,"/Height %d\n", (int) image->height);
    pdf_printf(p,"/BitsPerComponent %d\n", image->bpc);

    /* 
     * Transparency handling
     */

    /* Masking by color: single transparent color value */
    if (image->transparent) {
	if (image->colorspace == Indexed || image->colorspace == DeviceGray)
	    pdf_printf(p,"/Mask[%d %d]\n",
		(int) image->transval[0], (int) image->transval[0]);

	else if (image->colorspace == DeviceRGB)
	    pdf_printf(p,"/Mask[%d %d %d %d %d %d]\n",
		(int) image->transval[0], (int) image->transval[0],
		(int) image->transval[1], (int) image->transval[1],
		(int) image->transval[2], (int) image->transval[2]);

	else if (image->colorspace == DeviceCMYK)
	    pdf_printf(p,"/Mask[%d %d %d %d %d %d %d %d]\n",
		(int) image->transval[0], (int) image->transval[0],
		(int) image->transval[1], (int) image->transval[1],
		(int) image->transval[2], (int) image->transval[2],
		(int) image->transval[3], (int) image->transval[3]);
	else
	    pdf_error(p, PDF_SystemError,
	    	"Unknown color space with transparency");

    /* Masking by position: separate bitmap mask */
    } else if (image->mask != -1) {
	pdf_printf(p, "/Mask %ld 0 R\n",
	    p->xobjects[p->images[image->mask].no].obj_id);
    }

    switch (image->colorspace) {
	case ImageMask:
	    pdf_puts(p, "/ImageMask true\n");
	    break;

	case Indexed:
	    if (firststrip)
		image->colormap_id = pdf_alloc_id(p);

	    pdf_puts(p, "/ColorSpace[/Indexed/DeviceRGB ");
	    pdf_printf(p, "%d %ld 0 R]\n", image->palette_size - 1,
	    	image->colormap_id);
	    break;
	
	default:
            /* colorize the image with a spot color */
            if (image->colorspace >= LastCS) {
                /* TODO: reconsider spot color numbering scheme */
                int spot = image->colorspace - LastCS;
                p->colorspaces[spot].used_on_current_page = pdf_true;
                pdf_printf(p, "/ColorSpace %ld 0 R\n",
                    p->colorspaces[spot].obj_id);

                /* the following is tricky: /Separation color space
                 * always works as a subtractive color space. The
                 * image, however, is Grayscale, and therefore
                 * additive.
                 */
                if (firststrip) {
                    image->invert = !image->invert;
                }
            } else {
                pdf_printf(p, "/ColorSpace/%s\n",
                    pdf_colorspace_names[image->colorspace]);
            }
	    break;
    }

    /* special case: referenced image data instead of direct data */
    if (image->reference != pdf_ref_direct) {

	if (image->compression != none) {
	    pdf_printf(p, "/FFilter[/%s]\n",
		    pdf_filter_names[image->compression]);
	}

	if (image->compression == ccitt) {
	    pdf_puts(p, "/FDecodeParms[<<");

	    if ((int) image->width != 1728)	/* CCITT default width */
		pdf_printf(p, "/Columns %d", (int) image->width);

	    pdf_printf(p, "/Rows %d", (int) image->height);

	    /* write CCITT parameters if required */
	    if (image->params)
		pdf_puts(p, image->params);

	    pdf_puts(p, ">>]\n");

	}

	if (image->reference == pdf_ref_file) {

	    /* LATER: make image file name platform-neutral:
	     * Change : to / on the Mac
	     * Change \ to / on Windows
	     */
	    pdf_printf(p, "/F(%s)/Length 0", image->filename);

	} else if (image->reference == pdf_ref_url) {

	    pdf_printf(p, "/F<</FS/URL/F(%s)>>/Length 0", image->filename);
	}

	pdf_end_dict(p);		/* XObject */

	pdf_begin_stream(p);		/* dummy image data */
	pdf_end_stream(p);		/* dummy image data */

	if (PDF_GET_STATE(p) == pdf_state_page)
	    pdf_begin_contents_section(p);

	pdf_end_obj(p);			/* XObject */

	return;
    }

    /* 
     * Now the (more common) handling of actual image
     * data to be included in the PDF output.
     */
    /* do we need a filter (either ASCII or decompression)? */

    if (p->debug['a']) {
	pdf_puts(p, "/Filter[/ASCIIHexDecode");
	if (image->compression != none)
	    pdf_printf(p, "/%s", pdf_filter_names[image->compression]);
	pdf_puts(p, "]\n");

    } else {
	/* force compression if not a recognized precompressed image format */
	if (!image->use_raw && p->compresslevel)
	    image->compression = flate;

	if (image->compression != none)
	    pdf_printf(p, "/Filter[/%s]\n",
		    pdf_filter_names[image->compression]);
    }

    /* prepare precompressed (raw) image data */
    if (image->use_raw) {
	pdf_printf(p, "/DecodeParms[%s<<", (p->debug['a'] ? "null" : ""));

	/* write EarlyChange or CCITT parameters if required */
	if (image->params)
	    pdf_puts(p, image->params);

	if (image->compression == flate || image->compression == lzw) {
	    if (image->predictor != pred_default) {
		pdf_printf(p, "/Predictor %d", (int) image->predictor);
		pdf_printf(p, "/Columns %d", (int) image->width);
		if (image->bpc != 8)
		    pdf_printf(p, "/BitsPerComponent %d", image->bpc);

		if (image->colorspace < LastCS) {
		    switch (image->colorspace) {
			case Indexed:
			case ImageMask:
			case DeviceGray:
			    /* 1 is default */
			    break;
			case DeviceRGB:
			    pdf_puts(p, "/Colors 3");
			    break;
			case DeviceCMYK:
			    pdf_puts(p, "/Colors 4");
			    break;
			default:
			    pdf_error(p, PDF_SystemError,
			"Unknown colorspace (%d)", (int )image->colorspace);
			    break;
		    }
		}
	    }
	}

	if (image->compression == ccitt) {
	    if ((int) image->width != 1728)	/* CCITT default width */
		pdf_printf(p, "/Columns %d", (int) image->width);

	    pdf_printf(p, "/Rows %d", (int) image->height);
	}
	pdf_puts(p, ">>]\n");		/* DecodeParms dict and array */
    }

    if (image->invert) {
	pdf_puts(p, "/Decode[1 0");
	for (i = 1; i < image->components; i++)
	    pdf_puts(p, " 1 0");
	pdf_puts(p, "]\n");
    }

    /* Write the actual image data */
    length_id = pdf_alloc_id(p);

    pdf_printf(p,"/Length %ld 0 R\n", length_id);
    pdf_end_dict(p);		/* XObject */

    pdf_begin_stream(p);	/* image data */
    p->start_contents_pos = pdf_tell(p);

    /* image data */

    if (p->debug['a'])
	pdf_ASCIIHexEncode(p, &image->src);
    else {
	if (image->use_raw)
	    pdf_copy(p, &image->src);
	else
	    pdf_compress(p, &image->src);
    }

    length = pdf_tell(p) - p->start_contents_pos;

    pdf_end_stream(p);	/* image data */
    pdf_end_obj(p);	/* XObject */

    pdf_begin_obj(p, length_id);		/* Length object */
    pdf_printf(p,"%ld\n", length);
    pdf_end_obj(p);

    if (p->flush & PDF_FLUSH_CONTENT)
	pdf_flush_stream(p);

    /* Image data done */

    /*
     * Write colormap information for indexed color spaces
     */
    if (firststrip && image->colorspace == Indexed) {
	pdf_begin_obj(p, image->colormap_id);		/* colormap object */
	pdf_begin_dict(p); 		

	if (p->debug['a'])
	    pdf_puts(p, "/Filter[/ASCIIHexDecode]\n");
	else if (p->compresslevel)
	    pdf_puts(p, "/Filter[/FlateDecode]\n");

	/* Length of colormap object */
	length_id = pdf_alloc_id(p);
	pdf_printf(p,"/Length %ld 0 R\n", length_id);
	pdf_end_dict(p);

	pdf_begin_stream(p);			/* colormap data */
	p->start_contents_pos = pdf_tell(p);

	if (image->components != 1) {
	    pdf_error(p, PDF_SystemError,
	    	"Bogus indexed colorspace (%d color components)",
		image->components);
	}

	image->src.init		= pdf_noop;
	image->src.fill		= pdf_data_source_buf_fill;
	image->src.terminate	= pdf_noop;

	image->src.buffer_start	= (unsigned char *) image->colormap;
	image->src.buffer_length= (size_t) (image->palette_size * 3);

	image->src.bytes_available = 0;
	image->src.next_byte	= NULL;

	/* Write colormap data */
	if (p->debug['a'])
	    pdf_ASCIIHexEncode(p, &image->src);
	else {
	    pdf_compress(p, &image->src);
	}

	length = pdf_tell(p) - p->start_contents_pos;

	pdf_end_stream(p);			/* Colormap data */
	pdf_end_obj(p);				/* Colormap object */

	pdf_begin_obj(p, length_id);		/* Length object for colormap */
	pdf_printf(p, "%ld\n", length);
	pdf_end_obj(p);				/* Length object for colormap */
    }

    if (PDF_GET_STATE(p) == pdf_state_page)
	pdf_begin_contents_section(p);

    if (p->flush & PDF_FLUSH_CONTENT)
	pdf_flush_stream(p);
}