diff --git a/pdfio-content.c b/pdfio-content.c index afdcd57..a5a7d93 100644 --- a/pdfio-content.c +++ b/pdfio-content.c @@ -68,9 +68,13 @@ pdfioContentClip( bool // O - `true` on success, `false` on failure pdfioContentDrawImage( pdfio_stream_t *st, // I - Stream - const char *name) // I - Image name + const char *name, // I - Image name + float x, // I - X offset of image + float y, // I - Y offset of image + float w, // I - Width of image + float h) // I - Height of image { - return (pdfioStreamPrintf(st, "/%s Do\n", name)); + return (pdfioStreamPrintf(st, "q %g 0 0 %g %g %g cm/%s Do Q\n", w, h, x, y, name)); } @@ -962,7 +966,7 @@ pdfioFileCreateImageObject( } pdfioDictSetName(dict, "Type", "XObject"); - pdfioDictSetName(dict, "SubType", "Image"); + pdfioDictSetName(dict, "Subtype", "Image"); pdfioDictSetBoolean(dict, "Interpolate", interpolate); obj = (copy_func)(dict, fd); @@ -974,6 +978,28 @@ pdfioFileCreateImageObject( } +// +// 'pdfioImageGetHeight()' - Get the height of an image object. +// + +float // O - Height in lines +pdfioImageGetHeight(pdfio_obj_t *obj) // I - Image object +{ + return (pdfioDictGetNumber(obj->value.value.dict, "Height")); +} + + +// +// 'pdfioImageGetWidth()' - Get the width of an image object. +// + +float // O - Width in columns +pdfioImageGetWidth(pdfio_obj_t *obj) // I - Image object +{ + return (pdfioDictGetNumber(obj->value.value.dict, "Width")); +} + + // // 'copy_gif()' - Copy a GIF image. // @@ -1094,7 +1120,8 @@ copy_jpeg(pdfio_dict_t *dict, // I - Dictionary pdfioDictSetNumber(dict, "Width", width); pdfioDictSetNumber(dict, "Height", height); pdfioDictSetNumber(dict, "BitsPerComponent", 8); - pdfioDictSetName(dict, "ColorSpace", num_colors == 3 ? "CalRGB" : "CalGray"); + // TODO: Add proper JPEG CalRGB/Gray color spaces + pdfioDictSetName(dict, "ColorSpace", num_colors == 3 ? "DeviceRGB" : "DeviceGray"); pdfioDictSetName(dict, "Filter", "DCTDecode"); obj = pdfioFileCreateObject(dict->pdf, dict); diff --git a/pdfio-content.h b/pdfio-content.h index bbd9d56..0979119 100644 --- a/pdfio-content.h +++ b/pdfio-content.h @@ -79,7 +79,7 @@ extern const float pdfioSRGBWhitePoint[]; // PDF content drawing functions... extern bool pdfioContentBeginText(pdfio_stream_t *st) PDFIO_PUBLIC; extern bool pdfioContentClip(pdfio_stream_t *st, bool even_odd) PDFIO_PUBLIC; -extern bool pdfioContentDrawImage(pdfio_stream_t *st, const char *name) PDFIO_PUBLIC; +extern bool pdfioContentDrawImage(pdfio_stream_t *st, const char *name, float x, float y, float w, float h) PDFIO_PUBLIC; extern bool pdfioContentEndText(pdfio_stream_t *st) PDFIO_PUBLIC; extern bool pdfioContentFill(pdfio_stream_t *st, bool even_odd) PDFIO_PUBLIC; extern bool pdfioContentFillAndStroke(pdfio_stream_t *st, bool even_odd) PDFIO_PUBLIC; @@ -129,17 +129,21 @@ extern bool pdfioContentTextNextLine(pdfio_stream_t *st) PDFIO_PUBLIC; extern bool pdfioContentTextShow(pdfio_stream_t *st, const char *s, bool new_line) PDFIO_PUBLIC; extern bool pdfioContentTextShowJustified(pdfio_stream_t *st, size_t num_fragments, const float *offsets, const char * const *fragments) PDFIO_PUBLIC; +// Resource helpers... +extern pdfio_obj_t *pdfioFileCreateFontObject(pdfio_file_t *pdf, const char *filename) PDFIO_PUBLIC; +extern pdfio_obj_t *pdfioFileCreateICCProfileObject(pdfio_file_t *pdf, const char *filename) PDFIO_PUBLIC; +extern pdfio_obj_t *pdfioFileCreateImageObject(pdfio_file_t *pdf, const char *filename, bool interpolate) PDFIO_PUBLIC; + +// Image object helpers... +extern float pdfioImageGetHeight(pdfio_obj_t *obj) PDFIO_PUBLIC; +extern float pdfioImageGetWidth(pdfio_obj_t *obj) PDFIO_PUBLIC; + // Page dictionary helpers... extern bool pdfioPageDictAddICCColorSpace(pdfio_dict_t *dict, const char *name, pdfio_obj_t *obj) PDFIO_PUBLIC; extern bool pdfioPageDictAddCalibratedColorSpace(pdfio_dict_t *dict, const char *name, size_t num_colors, const float *white_point, float gamma) PDFIO_PUBLIC; extern bool pdfioPageDictAddFont(pdfio_dict_t *dict, const char *name, pdfio_obj_t *obj) PDFIO_PUBLIC; extern bool pdfioPageDictAddImage(pdfio_dict_t *dict, const char *name, pdfio_obj_t *obj) PDFIO_PUBLIC; -// Resource helpers... -extern pdfio_obj_t *pdfioFileCreateFontObject(pdfio_file_t *pdf, const char *filename) PDFIO_PUBLIC; -extern pdfio_obj_t *pdfioFileCreateICCProfileObject(pdfio_file_t *pdf, const char *filename) PDFIO_PUBLIC; -extern pdfio_obj_t *pdfioFileCreateImageObject(pdfio_file_t *pdf, const char *filename, bool interpolate) PDFIO_PUBLIC; - // // C++ magic... diff --git a/pdfio-file.c b/pdfio-file.c index 13d32b4..07b7aa5 100644 --- a/pdfio-file.c +++ b/pdfio-file.c @@ -1294,7 +1294,7 @@ write_trailer(pdfio_file_t *pdf) // I - PDF file // TODO: Look at adding support for xref streams... xref_offset = _pdfioFileTell(pdf); - if (!_pdfioFilePrintf(pdf, "xref\n0 %lu \n0000000000 65535 f \n", (unsigned long)pdf->num_objs)) + if (!_pdfioFilePrintf(pdf, "xref\n0 %lu \n0000000000 65535 f \n", (unsigned long)pdf->num_objs + 1)) { _pdfioFileError(pdf, "Unable to write cross-reference table."); ret = false; diff --git a/pdfio-object.c b/pdfio-object.c index 88b89ce..0c805e9 100644 --- a/pdfio-object.c +++ b/pdfio-object.c @@ -38,11 +38,26 @@ pdfioObjClose(pdfio_obj_t *obj) // I - Object // Write what remains for the object... if (!obj->offset) - return (write_obj_header(obj)); // Just write the object value + { + // Write the object value + if (!write_obj_header(obj)) + return (false); + } else if (obj->stream) - return (pdfioStreamClose(obj->stream)); + { + // Close the stream... + if (!pdfioStreamClose(obj->stream)) + return (false); + } else - return (true); // Already closed + { + // Already closed + return (true); + } + + // If we get here we wrote the object header or closed the stream and still + // need to write the "endobj" line... + return (_pdfioFilePuts(obj->pdf, "endobj\n")); } diff --git a/testpdfio.c b/testpdfio.c index 05c8e18..7d226ed 100644 --- a/testpdfio.c +++ b/testpdfio.c @@ -321,6 +321,12 @@ write_page(pdfio_file_t *pdf, // I - PDF file // TODO: Add font object support... pdfio_dict_t *dict; // Page dictionary pdfio_stream_t *st; // Page contents stream + float width, // Width of image + height; // Height of image + float swidth, // Scaled width + sheight, // Scaled height + tx, // X offset + ty; // Y offset fputs("pdfioDictCreate: ", stdout); @@ -356,20 +362,31 @@ write_page(pdfio_file_t *pdf, // I - PDF file else return (1); - fputs("pdfioContentMatrixScale(72.0, 72.0): ", stdout); - if (pdfioContentMatrixScale(st, 72.0f, 72.0f)) + fputs("pdfioImageGetWidth(): ", stdout); + if ((width = pdfioImageGetWidth(image)) > 0.0f) puts("PASS"); else return (1); -// fputs("pdfioContentTranslate(144.0, 144.0): ", stdout); -// if (pdfioContentMatrixTranslate(st, 144.0f, 144.0f)) -// puts("PASS"); -// else -// return (1); + fputs("pdfioImageGetHeight(): ", stdout); + if ((height = pdfioImageGetHeight(image)) > 0.0f) + puts("PASS"); + else + return (1); - fputs("pdfioContentDrawImage(\"IM1\"): ", stdout); - if (pdfioContentDrawImage(st, "IM1")) + swidth = 400.0f; + sheight = swidth * height / width; + if (sheight > 600.0f) + { + sheight = 600.0f; + swidth = sheight * width / height; + } + + tx = 0.5 * (595.28 - swidth); + ty = 0.5 * (792 - sheight); + + printf("pdfioContentDrawImage(\"IM1\", x=%g, y=%g, w=%g, h=%g): ", tx, ty, swidth, sheight); + if (pdfioContentDrawImage(st, "IM1", tx, ty, swidth, sheight)) puts("PASS"); else return (1);