diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/epdf.h | 47 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/image.h | 14 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc | 328 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/writeimg.w | 30 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/writejbig2.h | 5 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/writejbig2.w | 27 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/writejp2.h | 31 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/writejp2.w | 282 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/writejpg.w | 42 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/image/writepng.w | 61 |
10 files changed, 636 insertions, 231 deletions
diff --git a/Build/source/texk/web2c/luatexdir/image/epdf.h b/Build/source/texk/web2c/luatexdir/image/epdf.h index 0ce09ab13eb..c47c9f19f26 100644 --- a/Build/source/texk/web2c/luatexdir/image/epdf.h +++ b/Build/source/texk/web2c/luatexdir/image/epdf.h @@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License along with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ -/* $Id: epdf.h 3650 2010-04-26 08:13:41Z taco $ */ +/* $Id: epdf.h 4054 2011-01-10 19:05:54Z hhenkel $ */ // this is the common header file for C++ sources pdftoepdf.cc and lepdflib.cc @@ -31,22 +31,15 @@ # include <string.h> # include <kpathsea/c-ctype.h> # include <sys/stat.h> -# ifdef POPPLER_VERSION -# define GString GooString -# include <dirent.h> -# include <poppler-config.h> -# include <goo/GooString.h> -# include <goo/gmem.h> -# include <goo/gfile.h> -# else -# include <aconf.h> -# include <GString.h> -# include <gmem.h> -# include <gfile.h> -# include <assert.h> -# endif +# include <dirent.h> +# include <poppler-config.h> +# include <goo/GooString.h> +# include <goo/gmem.h> +# include <goo/gfile.h> # include "Object.h" # include "Stream.h" +# include "Gfx.h" +# include "Annot.h" # include "Array.h" # include "Dict.h" # include "XRef.h" @@ -64,6 +57,8 @@ extern "C" { extern char *xstrdup(const char *); + typedef enum { FE_FAIL, FE_RETURN_NULL } file_error_mode; + /* the following code is extremly ugly but needed for including web2c/config.h */ typedef const char *const_string; /* including kpathsea/types.h doesn't work on some systems */ @@ -75,7 +70,7 @@ extern "C" { # undef CONFIG_H /* header file */ # endif -# include <w2c/c-auto.h> /* define SIZEOF_LONG */ +# include <c-auto.h> /* define SIZEOF_LONG */ # include "openbsd-compat.h" # include "image.h" @@ -88,25 +83,24 @@ extern "C" { /* pdfgen.c */ __attribute__ ((format(printf, 2, 3))) extern void pdf_printf(PDF, const char *fmt, ...); - extern void pdf_puts(PDF, const char *); extern void pdf_begin_obj(PDF, int, bool); extern void pdf_end_obj(PDF); extern void pdf_begin_stream(PDF); extern void pdf_end_stream(PDF); extern void pdf_room(PDF, int); -# define pdf_out(B,A) do { pdf_room(B,1); B->buf[B->ptr++] = A; } while (0) + extern void pdf_out_block(PDF pdf, const char *s, size_t n); + +# define pdf_out(B, A) do { pdf_room(B, 1); B->buf[B->ptr++] = A; } while (0) +# define pdf_puts(pdf, s) pdf_out_block((pdf), (s), strlen(s)) /* pdftables.c */ extern int pdf_new_objnum(PDF); - /* epdf.c */ - extern void epdf_free(void); - /* pdftoepdf.cc */ extern void read_pdf_info(image_dict *, int, int, img_readtype_e); extern void write_epdf(PDF, image_dict *); extern void unrefPdfDocument(char *); - extern void epdf_check_mem(void); + extern void epdf_free(void); /* utils.c */ __attribute__ ((format(printf, 1, 2))) @@ -129,6 +123,9 @@ extern "C" { // and &obj to get a pointer to the object. // It is no longer necessary to call Object::free explicitely. +# if 0 +// PdfObject is replaced by xpdf's Object type, with manual obj.free() + // *INDENT-OFF* class PdfObject { public: @@ -150,6 +147,7 @@ class PdfObject { Object iObject; }; // *INDENT-ON* +# endif /**********************************************************************/ @@ -165,9 +163,10 @@ struct PdfDocument { PDFDoc *doc; InObj *inObjList; // temporary linked list avl_table *ObjMapTree; // permanent over luatex run - int occurences; // number of references to the PdfDocument; it can be deleted when occurences == 0 + unsigned int occurences; // number of references to the PdfDocument; it can be deleted when occurences == 0 + unsigned int pc; // counter to track PDFDoc generation or deletion }; -PdfDocument *refPdfDocument(char *file_path); +PdfDocument *refPdfDocument(char *file_path, file_error_mode fe); #endif /* EPDF_H */ diff --git a/Build/source/texk/web2c/luatexdir/image/image.h b/Build/source/texk/web2c/luatexdir/image/image.h index c4d0c3963f7..c1b91abafb6 100644 --- a/Build/source/texk/web2c/luatexdir/image/image.h +++ b/Build/source/texk/web2c/luatexdir/image/image.h @@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License along with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ -/* $Id: image.h 3388 2010-01-26 10:59:04Z taco $ */ +/* $Id: image.h 4051 2011-01-09 22:41:33Z hhenkel $ */ #ifndef IMAGE_H # define IMAGE_H @@ -30,7 +30,8 @@ # define JPG_UINT32 unsigned long # define JPG_UINT8 unsigned char -extern int do_zround(double r); /* from utils.c */ +extern int do_zround(double r); /* from utils.w */ +extern scaled one_hundred_bp; /* from pdfgen.w */ # define bp2int(p) do_zround(p * (one_hundred_bp / 100.0)) # define int2bp(i) (i * 100.0 / one_hundred_bp) @@ -53,6 +54,10 @@ typedef struct { JPG_UINT32 length; /* length of file/data */ } jpg_img_struct; +typedef struct { + int length; /* length of file/data */ +} jp2_img_struct; + # if 0 typedef struct { /* currently unused */ } jb2_img_struct; @@ -67,7 +72,7 @@ typedef enum { DICT_NEW, /* fresh dictionary */ } dict_state; typedef enum { IMG_TYPE_NONE, IMG_TYPE_PDF, IMG_TYPE_PNG, IMG_TYPE_JPG, - IMG_TYPE_JBIG2, IMG_TYPE_PDFSTREAM, IMG_TYPE_SENTINEL + IMG_TYPE_JP2, IMG_TYPE_JBIG2, IMG_TYPE_PDFSTREAM, IMG_TYPE_SENTINEL } imgtype_e; typedef enum { IMG_KEEPOPEN, IMG_CLOSEINBETWEEN } img_readtype_e; @@ -111,6 +116,7 @@ typedef struct { pdf_stream_struct *pdfstream; png_img_struct *png; jpg_img_struct *jpg; + jp2_img_struct *jp2; /* jb2_img_struct *jb2; */ } img_struct; } image_dict; @@ -156,6 +162,8 @@ typedef struct { # define img_jpg_ptr(N) ((N)->img_struct.jpg) # define img_jpg_color(N) ((N)->img_struct.jpg->color_space) +# define img_jp2_ptr(N) ((N)->img_struct.jp2) + # define img_jb2_ptr(N) ((N)->img_struct.jb2) # define F_FLAG_BBOX (1 << 0) diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc index 655fdd8842e..8c112d4261b 100644 --- a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc +++ b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc @@ -19,12 +19,13 @@ with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ static const char _svn_version[] = - "$Id: pdftoepdf.cc 3606 2010-04-10 12:58:25Z taco $ " - "$URL: http://foundry.supelec.fr/svn/luatex/branches/0.60.x/source/texk/web2c/luatexdir/image/pdftoepdf.cc $"; + "$Id: pdftoepdf.cc 4136 2011-04-11 22:06:50Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.66.0/source/texk/web2c/luatexdir/image/pdftoepdf.cc $"; -#include "epdf.h" +// define DEBUG -#define one_hundred_bp 6578176 // one_hundred_bp = 7227 * 65536 / 72 +#include "epdf.h" +#define HAVE_GETPDFMAJORVERSION 1 // This file is mostly C and not very much C++; it's just used to interface // the functions of xpdf, which happens to be written in C++. @@ -62,41 +63,121 @@ static PdfDocument *findPdfDocument(char *file_path) return pdf_doc; } -// Returns pointer to PdfDocument structure for PDF file. -// Creates a new structure if it doesn't exist yet. +#define PDF_CHECKSUM_SIZE 32 -char *get_file_checksum(char *a); +static char *get_file_checksum(char *a, file_error_mode fe) +{ + struct stat finfo; + char *ck = NULL; + if (stat(a, &finfo) == 0) { + off_t size = finfo.st_size; + time_t mtime = finfo.st_mtime; + ck = (char *) malloc(PDF_CHECKSUM_SIZE); + if (ck == NULL) + pdftex_fail("PDF inclusion: out of memory while processing '%s'", + a); + snprintf(ck, PDF_CHECKSUM_SIZE, "%llu_%llu", (unsigned long long) size, + (unsigned long long) mtime); + } else { + switch (fe) { + case FE_FAIL: + pdftex_fail("PDF inclusion: could not stat() file '%s'", a); + break; + case FE_RETURN_NULL: + if (ck != NULL) + free(ck); + ck = NULL; + break; + default: + assert(0); + } + } + return ck; +} + +// Returns pointer to PdfDocument structure for PDF file. +// Creates a new PdfDocument structure if it doesn't exist yet. +// When fe = FE_RETURN_NULL, the function returns NULL in error case. -PdfDocument *refPdfDocument(char *file_path) +PdfDocument *refPdfDocument(char *file_path, file_error_mode fe) { - PdfDocument *pdf_doc = findPdfDocument(file_path); - if (pdf_doc == NULL) { - if (PdfDocumentTree == NULL) - PdfDocumentTree = - avl_create(CompPdfDocument, NULL, &avl_xallocator); + char *checksum; + PdfDocument *pdf_doc; + PDFDoc *doc = NULL; + GooString *docName = NULL; + int new_flag = 0; + if ((checksum = get_file_checksum(file_path, fe)) == NULL) { + assert(fe == FE_RETURN_NULL); + return (PdfDocument *) NULL; + } + assert(checksum != NULL); + if ((pdf_doc = findPdfDocument(file_path)) == NULL) { +#ifdef DEBUG + fprintf(stderr, "\nDEBUG: New PdfDocument %s\n", file_path); +#endif + new_flag = 1; pdf_doc = new PdfDocument; pdf_doc->file_path = xstrdup(file_path); - pdf_doc->checksum = get_file_checksum(file_path); - void **aa = avl_probe(PdfDocumentTree, pdf_doc); - assert(aa != NULL); - pdf_doc->ObjMapTree = NULL; + pdf_doc->checksum = checksum; pdf_doc->doc = NULL; - } - if (pdf_doc->doc == NULL) { - GString *docName = new GString(pdf_doc->file_path); - pdf_doc->doc = new PDFDoc(docName); // takes ownership of docName - if (!pdf_doc->doc->isOk() || !pdf_doc->doc->okToPrint()) - pdftex_fail("xpdf: reading PDF image failed"); pdf_doc->inObjList = NULL; + pdf_doc->ObjMapTree = NULL; pdf_doc->occurences = 0; // 0 = unreferenced + pdf_doc->pc = 0; + } else { +#ifdef DEBUG + fprintf(stderr, "\nDEBUG: Found PdfDocument %s (%d)\n", + pdf_doc->file_path, pdf_doc->occurences); +#endif + assert(pdf_doc->checksum != NULL); + if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) { + pdftex_fail("PDF inclusion: file has changed '%s'", file_path); + } + free(checksum); } + assert(pdf_doc != NULL); + if (pdf_doc->doc == NULL) { #ifdef DEBUG - fprintf(stderr, "\nluatex Debug: Creating %s (%d)\n", - pdf_doc->file_path, pdf_doc->occurences); + fprintf(stderr, "\nDEBUG: New PDFDoc %s (%d)\n", + pdf_doc->file_path, pdf_doc->occurences); #endif + docName = new GooString(file_path); + doc = new PDFDoc(docName); // takes ownership of docName + pdf_doc->pc++; + + if (!doc->isOk() || !doc->okToPrint()) { + switch (fe) { + case FE_FAIL: + pdftex_fail("xpdf: reading PDF image failed"); + break; + case FE_RETURN_NULL: + delete doc; + // delete docName; + if (new_flag == 1) { + if (pdf_doc->file_path != NULL) + free(pdf_doc->file_path); + if (pdf_doc->checksum != NULL) + free(pdf_doc->checksum); + delete pdf_doc; + } + return (PdfDocument *) NULL; + break; + default: + assert(0); + } + } + pdf_doc->doc = doc; + } + // PDF file could be opened without problems, checksum ok. + if (PdfDocumentTree == NULL) + PdfDocumentTree = avl_create(CompPdfDocument, NULL, &avl_xallocator); + if ((PdfDocument *) avl_find(PdfDocumentTree, pdf_doc) == NULL) { + void **aa = avl_probe(PdfDocumentTree, pdf_doc); + assert(aa != NULL); + } pdf_doc->occurences++; #ifdef DEBUG - fprintf(stderr, "\nluatex Debug: Incrementing %s (%d)\n", + fprintf(stderr, "\nDEBUG: Incrementing %s (%d)\n", pdf_doc->file_path, pdf_doc->occurences); #endif return pdf_doc; @@ -249,7 +330,7 @@ static char *convertNumToPDF(double n) static void copyObject(PDF, PdfDocument *, Object *); -static void copyString(PDF pdf, GString * string) +static void copyString(PDF pdf, GooString * string) { char *p; unsigned char c; @@ -293,13 +374,14 @@ static void copyName(PDF pdf, char *s) static void copyArray(PDF pdf, PdfDocument * pdf_doc, Array * array) { int i, l; - PdfObject obj1; + Object obj1; pdf_puts(pdf, "["); for (i = 0, l = array->getLength(); i < l; ++i) { array->getNF(i, &obj1); - if (!obj1->isName()) + if (!obj1.isName()) pdf_puts(pdf, " "); copyObject(pdf, pdf_doc, &obj1); + obj1.free(); } pdf_puts(pdf, "]"); } @@ -307,13 +389,14 @@ static void copyArray(PDF pdf, PdfDocument * pdf_doc, Array * array) static void copyDict(PDF pdf, PdfDocument * pdf_doc, Dict * dict) { int i, l; - PdfObject obj1; + Object obj1; pdf_puts(pdf, "<<"); for (i = 0, l = dict->getLength(); i < l; ++i) { copyName(pdf, dict->getKey(i)); pdf_puts(pdf, " "); dict->getValNF(i, &obj1); copyObject(pdf, pdf_doc, &obj1); + obj1.free(); pdf_puts(pdf, "\n"); } pdf_puts(pdf, ">>"); @@ -392,15 +475,16 @@ static void writeRefs(PDF pdf, PdfDocument * pdf_doc) { InObj *r, *n; XRef *xref; + Object obj1; xref = pdf_doc->doc->getXRef(); for (r = pdf_doc->inObjList; r != NULL;) { - PdfObject obj1; xref->fetch(r->ref.num, r->ref.gen, &obj1); - if (obj1->isStream()) + if (obj1.isStream()) pdf_begin_obj(pdf, r->num, 0); else pdf_begin_obj(pdf, r->num, 2); // \pdfobjcompresslevel = 2 is for this copyObject(pdf, pdf_doc, &obj1); + obj1.free(); pdf_puts(pdf, "\n"); pdf_end_obj(pdf); n = r->next; @@ -436,26 +520,6 @@ static PDFRectangle *get_pagebox(Page * page, int pagebox_spec) return page->getMediaBox(); // to make the compiler happy } -#define PDF_CHECKSUM_SIZE 32 -char *get_file_checksum(char *a) -{ - struct stat finfo; - char *ck = NULL; - if (stat(a, &finfo) == 0) { - off_t size = finfo.st_size; - time_t mtime = finfo.st_mtime; - ck = (char *) malloc(PDF_CHECKSUM_SIZE); - if (ck == NULL) - pdftex_fail("PDF inclusion: out of memory while processing '%s'", - a); - snprintf(ck, PDF_CHECKSUM_SIZE, "%llu_%llu", (unsigned long long) size, - (unsigned long long) mtime); - } else { - pdftex_fail("PDF inclusion: could not stat() file '%s'", a); - } - return ck; -} - // Reads various information about the PDF and sets it up for later inclusion. // This will fail if the PDF version of the PDF is higher than // minor_pdf_version_wanted or page_name is given and can not be found. @@ -469,7 +533,6 @@ read_pdf_info(image_dict * idict, int minor_pdf_version_wanted, PdfDocument *pdf_doc; Page *page; int rotate; - char *checksum; PDFRectangle *pagebox; #ifdef HAVE_GETPDFMAJORVERSION int pdf_major_version_found, pdf_minor_version_found; @@ -486,15 +549,8 @@ read_pdf_info(image_dict * idict, int minor_pdf_version_wanted, globalParams->setErrQuiet(gFalse); isInit = gTrue; } - // calculate a checksum string - checksum = get_file_checksum(img_filepath(idict)); // open PDF file - pdf_doc = refPdfDocument(img_filepath(idict)); - if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) { - pdftex_fail("PDF inclusion: file has changed '%s'", - img_filename(idict)); - } - free(checksum); + pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL); // check PDF version // this works only for PDF 1.x -- but since any versions of PDF newer // than 1.x will not be backwards compatible to PDF 1.x, pdfTeX will @@ -503,13 +559,15 @@ read_pdf_info(image_dict * idict, int minor_pdf_version_wanted, pdf_major_version_found = pdf_doc->doc->getPDFMajorVersion(); pdf_minor_version_found = pdf_doc->doc->getPDFMinorVersion(); if ((pdf_major_version_found > 1) - || (pdf_minor_version_found > minor_pdf_version_wanted)) { + || (pdf_minor_version_found > minor_pdf_version_wanted)) { const char *msg = "PDF inclusion: found PDF version <%d.%d>, but at most version <1.%d> allowed"; if (pdf_inclusion_errorlevel > 0) { - pdftex_fail(msg, pdf_major_version_found, pdf_minor_version_found, minor_pdf_version_wanted); + pdftex_fail(msg, pdf_major_version_found, pdf_minor_version_found, + minor_pdf_version_wanted); } else { - pdftex_warn(msg, pdf_major_version_found, pdf_minor_version_found, minor_pdf_version_wanted); + pdftex_warn(msg, pdf_major_version_found, pdf_minor_version_found, + minor_pdf_version_wanted); } } #else @@ -528,7 +586,7 @@ read_pdf_info(image_dict * idict, int minor_pdf_version_wanted, img_totalpages(idict) = pdf_doc->doc->getCatalog()->getNumPages(); if (img_pagename(idict)) { // get page by name - GString name(img_pagename(idict)); + GooString name(img_pagename(idict)); LinkDest *link = pdf_doc->doc->findDest(&name); if (link == NULL || !link->isOk()) pdftex_fail("PDF inclusion: invalid destination <%s>", @@ -607,38 +665,30 @@ read_pdf_info(image_dict * idict, int minor_pdf_version_wanted, // Here the included PDF is copied, so most errors that can happen // during PDF inclusion will arise here. -static void write_epdf1(PDF pdf, image_dict * idict) +void write_epdf(PDF pdf, image_dict * idict) { PdfDocument *pdf_doc; Page *page; Ref *pageref; Dict *pageDict; - PdfObject info, contents, obj1, pageObj, dictObj; + Object obj1, contents, pageobj, pagesobj1, pagesobj2, *op1, *op2, *optmp; PDFRectangle *pagebox; int i, l; float bbox[4]; - char *checksum; char s[256]; - char *pagedictkeys[] = + const char *pagedictkeys[] = { "Group", "LastModified", "Metadata", "PieceInfo", "Resources", "SeparationInfo", NULL }; - assert(idict != NULL); - // calculate a checksum string - checksum = get_file_checksum(img_filepath(idict)); + // open PDF file - pdf_doc = refPdfDocument(img_filepath(idict)); - if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) { - pdftex_fail("PDF inclusion: file has changed '%s'", - img_filename(idict)); - } - free(checksum); + pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL); page = pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict)); pageref = pdf_doc->doc->getCatalog()->getPageRef(img_pagenum(idict)); assert(pageref != NULL); // was checked already in read_pdf_info() - pdf_doc->doc->getXRef()->fetch(pageref->num, pageref->gen, &pageObj); - pageDict = pageObj->getDict(); + pdf_doc->doc->getXRef()->fetch(pageref->num, pageref->gen, &pageobj); + pageDict = pageobj.getDict(); // write the Page header pdf_puts(pdf, "/Type /XObject\n/Subtype /Form\n"); @@ -652,12 +702,13 @@ static void write_epdf1(PDF pdf, image_dict * idict) strlen(pdf_doc->file_path))); pdf_printf(pdf, "/%s.PageNumber %i\n", pdfkeyprefix, (int) img_pagenum(idict)); - pdf_doc->doc->getDocInfoNF(&info); - if (info->isRef()) { + pdf_doc->doc->getDocInfoNF(&obj1); + if (obj1.isRef()) { // the info dict must be indirect (PDF Ref p. 61) pdf_printf(pdf, "/%s.InfoDict ", pdfkeyprefix); - pdf_printf(pdf, "%d 0 R\n", addInObj(pdf, pdf_doc, info->getRef())); + pdf_printf(pdf, "%d 0 R\n", addInObj(pdf, pdf_doc, obj1.getRef())); } + obj1.free(); if (img_is_bbox(idict)) { bbox[0] = int2bp(img_bbox(idict)[0]); bbox[1] = int2bp(img_bbox(idict)[1]); @@ -678,33 +729,54 @@ static void write_epdf1(PDF pdf, image_dict * idict) // Now all relevant parts of the Page dictionary are copied: - // Resources validity check - pageDict->lookupNF("Resources", &dictObj); - if (dictObj->isNull()) { - // Resources can be missing (files without them have been spotted - // in the wild); in which case the /Resouces of the /Page will be used. - // "This practice is not recommended". - pdftex_warn - ("PDF inclusion: /Resources missing. 'This practice is not recommended' (PDF Ref.)"); - } - // Metadata validity check (as a stream it must be indirect) - pageDict->lookupNF("Metadata", &dictObj); - if (!dictObj->isNull() && !dictObj->isRef()) + pageDict->lookupNF((char *) "Metadata", &obj1); + if (!obj1.isNull() && !obj1.isRef()) pdftex_warn("PDF inclusion: /Metadata must be indirect object"); + obj1.free(); // copy selected items in Page dictionary for (i = 0; pagedictkeys[i] != NULL; i++) { - pageDict->lookupNF(pagedictkeys[i], &dictObj); - if (!dictObj->isNull()) { + pageDict->lookupNF((char *) pagedictkeys[i], &obj1); + if (!obj1.isNull()) { pdf_printf(pdf, "/%s ", pagedictkeys[i]); - copyObject(pdf, pdf_doc, &dictObj); // preserves indirection + copyObject(pdf, pdf_doc, &obj1); // preserves indirection } + obj1.free(); + } + + // If there are no Resources in the Page dict of the embedded page, + // try to inherit the Resources from the Pages tree of the embedded + // PDF file, climbing up the tree until the Resources are found. + // (This fixes a problem with Scribus 1.3.3.14.) + pageDict->lookupNF((char *) "Resources", &obj1); + if (obj1.isNull()) { + op1 = &pagesobj1; + op2 = &pagesobj2; + pageDict->lookup((char *) "Parent", op1); + while (op1->isDict()) { + obj1.free(); + op1->dictLookupNF((char *) "Resources", &obj1); + if (!obj1.isNull()) { + pdf_puts(pdf, "/Resources "); + copyObject(pdf, pdf_doc, &obj1); + break; + } + op1->dictLookup((char *) "Parent", op2); + optmp = op1; + op1 = op2; + op2 = optmp; + op2->free(); + }; + if (!op1->isDict()) + pdftex_warn("PDF inclusion: Page /Resources missing."); + op1->free(); } + obj1.free(); // write the Page contents page->getContents(&contents); - if (contents->isStream()) { + if (contents.isStream()) { // Variant A: get stream and recompress under control // of \pdfcompresslevel // @@ -714,37 +786,39 @@ static void write_epdf1(PDF pdf, image_dict * idict) // Variant B: copy stream without recompressing // - contents->streamGetDict()->lookup((char *) "F", &obj1); - if (!obj1->isNull()) { + contents.streamGetDict()->lookup((char *) "F", &obj1); + if (!obj1.isNull()) { pdftex_fail("PDF inclusion: Unsupported external stream"); } - contents->streamGetDict()->lookup((char *) "Length", &obj1); - assert(!obj1->isNull()); + obj1.free(); + contents.streamGetDict()->lookup((char *) "Length", &obj1); + assert(!obj1.isNull()); pdf_puts(pdf, "/Length "); copyObject(pdf, pdf_doc, &obj1); + obj1.free(); pdf_puts(pdf, "\n"); - contents->streamGetDict()->lookup((char *) "Filter", &obj1); - if (!obj1->isNull()) { + contents.streamGetDict()->lookup((char *) "Filter", &obj1); + if (!obj1.isNull()) { pdf_puts(pdf, "/Filter "); copyObject(pdf, pdf_doc, &obj1); + obj1.free(); pdf_puts(pdf, "\n"); - contents->streamGetDict()->lookup((char *) "DecodeParms", &obj1); - if (!obj1->isNull()) { + contents.streamGetDict()->lookup((char *) "DecodeParms", &obj1); + if (!obj1.isNull()) { pdf_puts(pdf, "/DecodeParms "); copyObject(pdf, pdf_doc, &obj1); pdf_puts(pdf, "\n"); } } + obj1.free(); pdf_puts(pdf, ">>\nstream\n"); - copyStreamStream(pdf, contents->getStream()->getBaseStream()); + copyStreamStream(pdf, contents.getStream()->getBaseStream()); pdf_end_stream(pdf); - } else if (contents->isArray()) { + } else if (contents.isArray()) { pdf_begin_stream(pdf); - for (i = 0, l = contents->arrayGetLength(); i < l; ++i) { - PdfObject contentsobj; - copyStreamStream(pdf, - (contents-> - arrayGet(i, &contentsobj))->getStream()); + for (i = 0, l = contents.arrayGetLength(); i < l; ++i) { + copyStreamStream(pdf, (contents.arrayGet(i, &obj1))->getStream()); + obj1.free(); if (i < (l - 1)) { // put a space between streams to be on the safe side (streams // should have a trailing space here, but one never knows) @@ -758,14 +832,13 @@ static void write_epdf1(PDF pdf, image_dict * idict) } // write out all indirect objects writeRefs(pdf, pdf_doc); -} - -// this relay function is needed to keep some destructor quiet (???) - -void write_epdf(PDF pdf, image_dict * idict) -{ - write_epdf1(pdf, idict); + contents.free(); + pageobj.free(); + // unrefPdfDocument() must come after contents.free() and pageobj.free()! + // TH: The next line makes repeated pdf inclusion unacceptably slow +#if 0 unrefPdfDocument(img_filepath(idict)); +#endif } //********************************************************************** @@ -780,8 +853,12 @@ static void deletePdfDocumentPdfDoc(PdfDocument * pdf_doc) n = r->next; delete r; } +#ifdef DEBUG + fprintf(stderr, "\nDEBUG: Deleting PDFDoc %s\n", pdf_doc->file_path); +#endif delete pdf_doc->doc; pdf_doc->doc = NULL; + pdf_doc->pc++; } static void destroyPdfDocument(void *pa, void * /*pb */ ) @@ -798,16 +875,13 @@ void unrefPdfDocument(char *file_path) { PdfDocument *pdf_doc = findPdfDocument(file_path); assert(pdf_doc != NULL); - assert(pdf_doc->occurences > 0); // aim for point landing + assert(pdf_doc->occurences != 0); // aim for point landing pdf_doc->occurences--; #ifdef DEBUG - fprintf(stderr, "\nluatex Debug: Decrementing %s (%d)\n", + fprintf(stderr, "\nDEBUG: Decrementing %s (%d)\n", pdf_doc->file_path, pdf_doc->occurences); #endif if (pdf_doc->occurences == 0) { -#ifdef DEBUG - fprintf(stderr, "\nluatex Debug: Deleting %s\n", pdf_doc->file_path); -#endif assert(pdf_doc->inObjList == NULL); // should be eaten up already deletePdfDocumentPdfDoc(pdf_doc); } @@ -816,7 +890,7 @@ void unrefPdfDocument(char *file_path) // Called when PDF embedding system is finalized. // Now deallocate all remaining PdfDocuments. -void epdf_check_mem() +void epdf_free() { if (PdfDocumentTree != NULL) avl_destroy(PdfDocumentTree, destroyPdfDocument); diff --git a/Build/source/texk/web2c/luatexdir/image/writeimg.w b/Build/source/texk/web2c/luatexdir/image/writeimg.w index 45aeacd5fe7..57f0740f04b 100644 --- a/Build/source/texk/web2c/luatexdir/image/writeimg.w +++ b/Build/source/texk/web2c/luatexdir/image/writeimg.w @@ -22,8 +22,8 @@ @ @c static const char _svn_version[] = - "$Id: writeimg.w 3584 2010-04-02 17:45:55Z hhenkel $ " - "$URL: http://foundry.supelec.fr/svn/luatex/branches/0.60.x/source/texk/web2c/luatexdir/image/writeimg.w $"; + "$Id: writeimg.w 4055 2011-01-10 19:52:50Z oneiros $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.66.0/source/texk/web2c/luatexdir/image/writeimg.w $"; #include <assert.h> #include "ptexlib.h" @@ -33,6 +33,7 @@ static const char _svn_version[] = @ @c #include "image/image.h" #include "image/writejpg.h" +#include "image/writejp2.h" #include "image/writepng.h" #include "image/writejbig2.h" @@ -122,6 +123,7 @@ static const char _svn_version[] = #define HEADER_JPG "\xFF\xD8" #define HEADER_PNG "\x89PNG\r\n\x1A\n" #define HEADER_JBIG2 "\x97\x4A\x42\x32\x0D\x0A\x1A\x0A" +#define HEADER_JP2 "\x6A\x50\x20\x20" #define HEADER_PDF "%PDF-1." #define MAX_HEADER (sizeof(HEADER_PNG)-1) @@ -145,6 +147,8 @@ static void check_type_by_header(image_dict * idict) /* tests */ if (strncmp(header, HEADER_JPG, sizeof(HEADER_JPG) - 1) == 0) img_type(idict) = IMG_TYPE_JPG; + else if (strncmp(header + 4, HEADER_JP2, sizeof(HEADER_JP2) - 1) == 0) + img_type(idict) = IMG_TYPE_JP2; else if (strncmp(header, HEADER_PNG, sizeof(HEADER_PNG) - 1) == 0) img_type(idict) = IMG_TYPE_PNG; else if (strncmp(header, HEADER_JBIG2, sizeof(HEADER_JBIG2) - 1) == 0) @@ -169,6 +173,8 @@ static void check_type_by_extension(image_dict * idict) else if (strcasecmp(image_suffix, ".jpg") == 0 || strcasecmp(image_suffix, ".jpeg") == 0) img_type(idict) = IMG_TYPE_JPG; + else if (strcasecmp(image_suffix, ".jp2") == 0) + img_type(idict) = IMG_TYPE_JP2; else if (strcasecmp(image_suffix, ".jbig2") == 0 || strcasecmp(image_suffix, ".jb2") == 0) img_type(idict) = IMG_TYPE_JBIG2; @@ -257,6 +263,9 @@ void free_image_dict(image_dict * p) case IMG_TYPE_JPG: /* assuming |IMG_CLOSEINBETWEEN| */ assert(img_jpg_ptr(p) == NULL); break; + case IMG_TYPE_JP2: /* */ + assert(img_jp2_ptr(p) == NULL); + break; case IMG_TYPE_JBIG2: /* todo: writejbig2.w cleanup */ break; case IMG_TYPE_PDFSTREAM: @@ -295,7 +304,7 @@ void read_img(PDF pdf, img_filepath(idict) = kpse_find_file(img_filename(idict), kpse_tex_format, true); if (img_filepath(idict) == NULL) - pdftex_fail("cannot find image file"); + pdftex_fail("cannot find image file '%s'", img_filename(idict)); } recorder_record_input(img_filename(idict)); /* type checks */ @@ -314,6 +323,9 @@ void read_img(PDF pdf, case IMG_TYPE_JPG: read_jpg_info(pdf, idict, IMG_CLOSEINBETWEEN); break; + case IMG_TYPE_JP2: + read_jp2_info(idict, IMG_CLOSEINBETWEEN); + break; case IMG_TYPE_JBIG2: if (minor_version < 4) { pdftex_fail @@ -338,9 +350,8 @@ static image_dict *read_image(PDF pdf, char *file_name, int page_num, { image *a = new_image(); image_dict *idict = img_dict(a) = new_image_dict(); - incr(pdf->ximage_count); - pdf_create_obj(pdf, obj_type_ximage, pdf->ximage_count); - img_objnum(idict) = pdf->obj_ptr; + pdf->ximage_count++; + img_objnum(idict) = pdf_create_obj(pdf, obj_type_ximage, pdf->ximage_count); img_index(idict) = pdf->ximage_count; set_obj_data_ptr(pdf, img_objnum(idict), img_index(idict)); idict_to_array(idict); @@ -429,7 +440,7 @@ void scan_pdfrefximage(PDF pdf) scaled_whd alt_rule, dim; alt_rule = scan_alt_rule(); /* scans |<rule spec>| to |alt_rule| */ scan_int(); - check_obj_exists(pdf, obj_type_ximage, cur_val); + check_obj_type(pdf, obj_type_ximage, cur_val); new_whatsit(pdf_refximage_node); idict = idict_array[obj_data_ptr(pdf, cur_val)]; if (alt_rule.wd != null_flag || alt_rule.ht != null_flag @@ -577,6 +588,9 @@ void write_img(PDF pdf, image_dict * idict) case IMG_TYPE_JPG: write_jpg(pdf, idict); break; + case IMG_TYPE_JP2: + write_jp2(pdf, idict); + break; case IMG_TYPE_JBIG2: write_jbig2(pdf, idict); break; @@ -777,8 +791,8 @@ void undumpimagemeta(PDF pdf, int pdfversion, int pdfinclusionerrorlevel) undumpinteger(img_pagenum(idict)); break; case IMG_TYPE_PNG: - break; case IMG_TYPE_JPG: + case IMG_TYPE_JP2: break; case IMG_TYPE_JBIG2: if (pdfversion < 4) { diff --git a/Build/source/texk/web2c/luatexdir/image/writejbig2.h b/Build/source/texk/web2c/luatexdir/image/writejbig2.h index a5715d5732e..6609c2d2f99 100644 --- a/Build/source/texk/web2c/luatexdir/image/writejbig2.h +++ b/Build/source/texk/web2c/luatexdir/image/writejbig2.h @@ -18,13 +18,16 @@ You should have received a copy of the GNU General Public License along with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ -/* $Id: writejbig2.h 2579 2009-06-23 14:12:23Z taco $ */ +/* $Id: writejbig2.h 4051 2011-01-09 22:41:33Z hhenkel $ */ #ifndef WRITEJBIG2_H # define WRITEJBIG2_H # include "image.h" +unsigned int read2bytes(FILE * f); +unsigned int read4bytes(FILE * f); + void flush_jbig2_page0_objects(PDF); void read_jbig2_info(image_dict *); void write_jbig2(PDF, image_dict *); diff --git a/Build/source/texk/web2c/luatexdir/image/writejbig2.w b/Build/source/texk/web2c/luatexdir/image/writejbig2.w index 0e578f9b457..6828ba418aa 100644 --- a/Build/source/texk/web2c/luatexdir/image/writejbig2.w +++ b/Build/source/texk/web2c/luatexdir/image/writejbig2.w @@ -1,7 +1,8 @@ % writejbig2.w % Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> -% Copyright 2006-2009 Taco Hoekwater <taco@@luatex.org> +% Copyright 2006-2011 Taco Hoekwater <taco@@luatex.org> +% Copyright 2003-2011 Hartmut Henkel <hartmut@@luatex.org> % This file is part of LuaTeX. @@ -80,8 +81,8 @@ object exists, reference it. Else create fresh one. @ @c static const char _svn_version[] = - "$Id: writejbig2.w 3584 2010-04-02 17:45:55Z hhenkel $ " - "$URL: http://foundry.supelec.fr/svn/luatex/branches/0.60.x/source/texk/web2c/luatexdir/image/writejbig2.w $"; + "$Id: writejbig2.w 4058 2011-01-10 20:44:28Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.66.0/source/texk/web2c/luatexdir/image/writejbig2.w $"; #undef DEBUG @@ -347,14 +348,14 @@ static SEGINFO *find_seginfo(LIST * slp, unsigned long segnum) } @ @c -static unsigned int read2bytes(FILE * f) +unsigned int read2bytes(FILE * f) { unsigned int c = (unsigned int) ygetc(f); return (c << 8) + (unsigned int) ygetc(f); } @ @c -static unsigned long read4bytes(FILE * f) +unsigned int read4bytes(FILE * f) { unsigned int l = read2bytes(f); return (l << 16) + read2bytes(f); @@ -503,7 +504,7 @@ static boolean readseghdr(FILEINFO * fip, SEGINFO * sip) } /* 7.2.6 Segment page association */ if (sip->pageassocsizeflag) - sip->segpage = (long int) read4bytes(fip->file); + sip->segpage = read4bytes(fip->file); else sip->segpage = ygetc(fip->file); /* 7.2.7 Segment data length */ @@ -683,17 +684,17 @@ static void rd_jbig2_info(FILEINFO * fip) /* 7.4.8 Page information segment syntax */ if (sip->pageinfoflag) { pip->pagenum = (unsigned long) sip->segpage; - pip->width = (unsigned) read4bytes(fip->file); - pip->height = (unsigned) read4bytes(fip->file); - pip->xres = (unsigned) read4bytes(fip->file); - pip->yres = (unsigned) read4bytes(fip->file); + pip->width = read4bytes(fip->file); + pip->height = read4bytes(fip->file); + pip->xres = read4bytes(fip->file); + pip->yres = read4bytes(fip->file); pip->pagesegmentflags = (unsigned) ygetc(fip->file); /* 7.4.8.6 Page striping information */ pip->stripinginfo = read2bytes(fip->file); seekdist -= 19; } if (sip->endofstripeflag) { - pip->stripedheight = (unsigned) read4bytes(fip->file); + pip->stripedheight = read4bytes(fip->file); seekdist -= 4; } if (!fip->sequentialaccess @@ -732,8 +733,8 @@ static void wr_jbig2(PDF pdf, FILEINFO * fip, unsigned long page) pdf_puts(pdf, "/Filter [/JBIG2Decode]\n"); if (fip->page0.last != NULL) { if (fip->pdfpage0objnum == 0) { - pdf_create_obj(pdf, obj_type_others, 0); - fip->pdfpage0objnum = (unsigned long) pdf->obj_ptr; + fip->pdfpage0objnum = + (unsigned long) pdf_create_obj(pdf, obj_type_others, 0); } pdf_printf(pdf, "/DecodeParms [<< /JBIG2Globals %lu 0 R >>]\n", fip->pdfpage0objnum); diff --git a/Build/source/texk/web2c/luatexdir/image/writejp2.h b/Build/source/texk/web2c/luatexdir/image/writejp2.h new file mode 100644 index 00000000000..04e350f3c9e --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/writejp2.h @@ -0,0 +1,31 @@ +/* writejp2.h + + Copyright 2011 Taco Hoekwater <taco@luatex.org> + Copyright 2011 Hartmut Henkel <hartmut@luatex.org> + + This file is part of LuaTeX. + + LuaTeX is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + LuaTeX is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU General Public License along + with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ + +/* $Id: writejp2.h 4060 2011-01-11 00:01:57Z hhenkel $ */ + +#ifndef WRITEJP2_H +# define WRITEJP2_H + +# include "image.h" + +void read_jp2_info(image_dict *, img_readtype_e); +void write_jp2(PDF, image_dict *); + +#endif /* WRITEJP2_H */ diff --git a/Build/source/texk/web2c/luatexdir/image/writejp2.w b/Build/source/texk/web2c/luatexdir/image/writejp2.w new file mode 100644 index 00000000000..1d27f733c56 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/image/writejp2.w @@ -0,0 +1,282 @@ +% writejp2.w + +% Copyright 2011 Taco Hoekwater <taco@@luatex.org> +% Copyright 2011 Hartmut Henkel <hartmut@@luatex.org> + +% This file is part of LuaTeX. + +% LuaTeX is free software; you can redistribute it and/or modify it under +% the terms of the GNU General Public License as published by the Free +% Software Foundation; either version 2 of the License, or (at your +% option) any later version. + +% LuaTeX is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +% License for more details. + +% You should have received a copy of the GNU General Public License along +% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +@ @c +static const char _svn_version[] = + "$Id: writejp2.w 4133 2011-04-11 16:54:11Z oneiros $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.66.0/source/texk/web2c/luatexdir/image/writejp2.w $"; + +@ Basic JPEG~2000 image support. Section and Table references below: +Information technology --- JPEG~2000 image coding system: Core coding system. +ISO/IEC 15444-1, Second edition, 2004-09-15, file |15444-1annexi.pdf|. + +@c +#include <math.h> +#include <assert.h> +#include "ptexlib.h" +#include "image/image.h" +#include "image/writejp2.h" +#include "image/writejbig2.h" /* read2bytes(), read4bytes() */ + +/* Table 1.2 -- Defined boxes */ +#define BOX_JP 0x6A502020 +#define BOX_FTYP 0x66747970 +#define BOX_JP2H 0x6a703268 +#define BOX_IHDR 0x69686472 +#define BOX_BPCC 0x62706363 +#define BOX_COLR 0x636D6170 +#define BOX_CDEF 0x63646566 +#define BOX_RES 0x72657320 +#define BOX_RESC 0x72657363 +#define BOX_RESD 0x72657364 +#define BOX_JP2C 0x6A703263 + +/* 1.4 Box definition */ +typedef struct { + unsigned long long lbox; + unsigned int tbox; +} hdr_struct; + +static unsigned long long read8bytes(FILE * f) +{ + unsigned long long l = read4bytes(f); + l = (l << 32) + read4bytes(f); + return l; +} + +static hdr_struct read_boxhdr(image_dict * idict) +{ + hdr_struct hdr; + hdr.lbox = read4bytes(img_file(idict)); + hdr.tbox = read4bytes(img_file(idict)); + if (hdr.lbox == 1) + hdr.lbox = read8bytes(img_file(idict)); + if (hdr.lbox == 0 && hdr.tbox != BOX_JP2C) + pdftex_fail("reading JP2 image failed (LBox == 0)"); + return hdr; +} + +/* 1.5.3.1 Image Header box */ +static void scan_ihdr(image_dict * idict) +{ + unsigned int height, width, nc; + unsigned char bpc, c, unkc, ipr; + height = read4bytes(img_file(idict)); + width = read4bytes(img_file(idict)); + img_ysize(idict) = (int) height; + img_xsize(idict) = (int) width; + nc = read2bytes(img_file(idict)); + bpc = (unsigned char) xgetc(img_file(idict)); + img_colordepth(idict) = bpc + 1; + c = (unsigned char) xgetc(img_file(idict)); + unkc = (unsigned char) xgetc(img_file(idict)); + ipr = (unsigned char) xgetc(img_file(idict)); +} + +/* 1.5.3.7.1 Capture Resolution box */ +/* 1.5.3.7.2 Default Display Resolution box */ +static void scan_resc_resd(image_dict * idict) +{ + unsigned int vr_n, vr_d, hr_n, hr_d; + unsigned char vr_e, hr_e; + double hr_, vr_; + vr_n = read2bytes(img_file(idict)); + vr_d = read2bytes(img_file(idict)); + hr_n = read2bytes(img_file(idict)); + hr_d = read2bytes(img_file(idict)); + vr_e = (unsigned char) xgetc(img_file(idict)); + hr_e = (unsigned char) xgetc(img_file(idict)); + hr_ = ((double) hr_n / hr_d) * exp(hr_e * log(10.0)) * 0.0254; + vr_ = ((double) vr_n / vr_d) * exp(vr_e * log(10.0)) * 0.0254; + img_xres(idict) = (int) (hr_ + 0.5); + img_yres(idict) = (int) (vr_ + 0.5); +} + +/* 1.5.3.7 Resolution box (superbox) */ +static void scan_res(image_dict * idict, unsigned long long epos_s) +{ + hdr_struct hdr; + unsigned long long spos, epos; + epos = xftell(img_file(idict), img_filepath(idict)); + while (1) { + spos = epos; + hdr = read_boxhdr(idict); + epos = spos + hdr.lbox; + switch (hdr.tbox) { + case (BOX_RESC): + /* arbitrarily: let BOX_RESD have precedence */ + if (img_xres(idict) == 0 && img_yres(idict) == 0) { + scan_resc_resd(idict); + if (xftell(img_file(idict), img_filepath(idict)) != (long)epos) + pdftex_fail + ("reading JP2 image failed (resc box size inconsistent)"); + } + break; + case (BOX_RESD): + scan_resc_resd(idict); + if (xftell(img_file(idict), img_filepath(idict)) != (long)epos) + pdftex_fail + ("reading JP2 image failed (resd box size inconsistent)"); + break; + default:; + } + if (epos > epos_s) + pdftex_fail("reading JP2 image failed (res box size inconsistent)"); + if (epos == epos_s) + break; + xfseek(img_file(idict), (long) epos, SEEK_SET, img_filepath(idict)); + } +} + +/* 1.5.3 JP2 Header box (superbox) */ +static boolean scan_jp2h(image_dict * idict, unsigned long long epos_s) +{ + boolean ihdr_found = false; + hdr_struct hdr; + unsigned long long spos, epos; + epos = xftell(img_file(idict), img_filepath(idict)); + while (1) { + spos = epos; + hdr = read_boxhdr(idict); + epos = spos + hdr.lbox; + switch (hdr.tbox) { + case (BOX_IHDR): + scan_ihdr(idict); + if (xftell(img_file(idict), img_filepath(idict)) != (long)epos) + pdftex_fail + ("reading JP2 image failed (ihdr box size inconsistent)"); + ihdr_found = true; + break; + case (BOX_RES): + scan_res(idict, epos); + break; + default:; + } + if (epos > epos_s) + pdftex_fail + ("reading JP2 image failed (jp2h box size inconsistent)"); + if (epos == epos_s) + break; + xfseek(img_file(idict), (long) epos, SEEK_SET, img_filepath(idict)); + } + return ihdr_found; +} + +static void close_and_cleanup_jp2(image_dict * idict) +{ + assert(idict != NULL); + assert(img_file(idict) != NULL); + assert(img_filepath(idict) != NULL); + xfclose(img_file(idict), img_filepath(idict)); + img_file(idict) = NULL; + assert(img_jp2_ptr(idict) != NULL); + xfree(img_jp2_ptr(idict)); +} + +void read_jp2_info(image_dict * idict, img_readtype_e readtype) +{ + boolean ihdr_found = false; + hdr_struct hdr; + unsigned long long spos, epos; + assert(img_type(idict) == IMG_TYPE_JP2); + img_totalpages(idict) = 1; + img_pagenum(idict) = 1; + img_xres(idict) = img_yres(idict) = 0; + assert(img_file(idict) == NULL); + img_file(idict) = xfopen(img_filepath(idict), FOPEN_RBIN_MODE); + assert(img_jp2_ptr(idict) == NULL); + img_jp2_ptr(idict) = xtalloc(1, jp2_img_struct); + xfseek(img_file(idict), 0, SEEK_END, img_filepath(idict)); + img_jp2_ptr(idict)->length = + (int) xftell(img_file(idict), img_filepath(idict)); + xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict)); + + assert(sizeof(unsigned long long) >= 8); + spos = epos = 0; + + /* 1.5.1 JPEG 2000 Signature box */ + hdr = read_boxhdr(idict); + assert(hdr.tbox == BOX_JP); /* has already been checked */ + epos = spos + hdr.lbox; + xfseek(img_file(idict), (long) epos, SEEK_SET, img_filepath(idict)); + + /* 1.5.2 File Type box */ + spos = epos; + hdr = read_boxhdr(idict); + if (hdr.tbox != BOX_FTYP) + pdftex_fail("reading JP2 image failed (missing ftyp box)"); + epos = spos + hdr.lbox; + xfseek(img_file(idict), (long) epos, SEEK_SET, img_filepath(idict)); + + while (!ihdr_found) { + spos = epos; + hdr = read_boxhdr(idict); + epos = spos + hdr.lbox; + switch (hdr.tbox) { + case BOX_JP2H: + ihdr_found = scan_jp2h(idict, epos); + break; + case BOX_JP2C: + if (!ihdr_found) + pdftex_fail("reading JP2 image failed (no ihdr box found)"); + break; + default:; + } + xfseek(img_file(idict), (long) epos, SEEK_SET, img_filepath(idict)); + } + if (readtype == IMG_CLOSEINBETWEEN) + close_and_cleanup_jp2(idict); +} + +static void reopen_jp2(image_dict * idict) +{ + int width, height, xres, yres; + width = img_xsize(idict); + height = img_ysize(idict); + xres = img_xres(idict); + yres = img_yres(idict); + read_jp2_info(idict, IMG_KEEPOPEN); + if (width != img_xsize(idict) || height != img_ysize(idict) + || xres != img_xres(idict) || yres != img_yres(idict)) + pdftex_fail("writejp2: image dimensions have changed"); +} + +void write_jp2(PDF pdf, image_dict * idict) +{ + long unsigned l; + FILE *f; + assert(idict != NULL); + if (img_file(idict) == NULL) + reopen_jp2(idict); + xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict)); + assert(img_jp2_ptr(idict) != NULL); + pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n"); + if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) + pdf_printf(pdf, "%s\n", img_attr(idict)); + pdf_printf(pdf, "/Width %i\n/Height %i\n/Length %i\n", + (int) img_xsize(idict), + (int) img_ysize(idict), (int) img_jp2_ptr(idict)->length); + pdf_puts(pdf, "/Filter /JPXDecode\n>>\nstream\n"); + for (l = (long unsigned int) img_jp2_ptr(idict)->length, f = + img_file(idict); l > 0; l--) + pdf_out(pdf, xgetc(f)); + pdf_end_stream(pdf); + close_and_cleanup_jp2(idict); +} diff --git a/Build/source/texk/web2c/luatexdir/image/writejpg.w b/Build/source/texk/web2c/luatexdir/image/writejpg.w index 4f77303ce20..e7a202c54f3 100644 --- a/Build/source/texk/web2c/luatexdir/image/writejpg.w +++ b/Build/source/texk/web2c/luatexdir/image/writejpg.w @@ -20,8 +20,8 @@ @ @c static const char _svn_version[] = - "$Id: writejpg.w 3612 2010-04-13 09:29:42Z taco $ " - "$URL: http://foundry.supelec.fr/svn/luatex/branches/0.60.x/source/texk/web2c/luatexdir/image/writejpg.w $"; + "$Id: writejpg.w 4095 2011-03-31 21:14:27Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.66.0/source/texk/web2c/luatexdir/image/writejpg.w $"; #include <assert.h> #include "ptexlib.h" @@ -41,18 +41,18 @@ typedef enum { /* JPEG marker codes */ M_SOF5 = 0xc5, /* differential sequential DCT */ M_SOF6 = 0xc6, /* differential progressive DCT */ - M_SOF7 = 0xc7, /* differential lossless */ + M_SOF7 = 0xc7, /* differential lossless (sequential) */ - M_JPG = 0xc8, /* JPEG extensions */ + M_JPG = 0xc8, /* reserved for JPEG extensions */ M_SOF9 = 0xc9, /* extended sequential DCT */ M_SOF10 = 0xca, /* progressive DCT */ M_SOF11 = 0xcb, /* lossless (sequential) */ M_SOF13 = 0xcd, /* differential sequential DCT */ M_SOF14 = 0xce, /* differential progressive DCT */ - M_SOF15 = 0xcf, /* differential lossless */ + M_SOF15 = 0xcf, /* differential lossless (sequential) */ - M_DHT = 0xc4, /* define Huffman tables */ + M_DHT = 0xc4, /* define Huffman table(s) */ M_DAC = 0xcc, /* define arithmetic conditioning table */ @@ -101,13 +101,6 @@ typedef enum { /* JPEG marker codes */ } JPEG_MARKER; @ @c -static JPG_UINT16 read2bytes(FILE * f) -{ - int c = xgetc(f); - return (JPG_UINT16) ((c << 8) + (int) xgetc(f)); -} - -@ @c static void close_and_cleanup_jpg(image_dict * idict) { assert(idict != NULL); @@ -117,7 +110,6 @@ static void close_and_cleanup_jpg(image_dict * idict) img_file(idict) = NULL; assert(img_jpg_ptr(idict) != NULL); xfree(img_jpg_ptr(idict)); - img_jpg_ptr(idict) = NULL; } @ @c @@ -137,17 +129,17 @@ void read_jpg_info(PDF pdf, image_dict * idict, img_readtype_e readtype) xfseek(img_file(idict), 0, SEEK_END, img_filepath(idict)); img_jpg_ptr(idict)->length = xftell(img_file(idict), img_filepath(idict)); xfseek(img_file(idict), 0, SEEK_SET, img_filepath(idict)); - if (read2bytes(img_file(idict)) != 0xFFD8) + if ((unsigned int) read2bytes(img_file(idict)) != 0xFFD8) pdftex_fail("reading JPEG image failed (no JPEG header found)"); /* currently only true JFIF files allow extracting |img_xres| and |img_yres| */ - if (read2bytes(img_file(idict)) == 0xFFE0) { /* check for JFIF */ + if ((unsigned int) read2bytes(img_file(idict)) == 0xFFE0) { /* check for JFIF */ (void) read2bytes(img_file(idict)); for (i = 0; i < 5; i++) { if (xgetc(img_file(idict)) != jpg_id[i]) break; } if (i == 5) { /* it's JFIF */ - read2bytes(img_file(idict)); + (void) read2bytes(img_file(idict)); units = xgetc(img_file(idict)); img_xres(idict) = (int) read2bytes(img_file(idict)); img_yres(idict) = (int) read2bytes(img_file(idict)); @@ -177,23 +169,25 @@ void read_jpg_info(PDF pdf, image_dict * idict, img_readtype_e readtype) pdftex_fail("reading JPEG image failed (premature file end)"); if (fgetc(img_file(idict)) != 0xFF) pdftex_fail("reading JPEG image failed (no marker found)"); - switch (xgetc(img_file(idict))) { + i = xgetc(img_file(idict)); + switch (i) { + case M_SOF3: /* lossless */ case M_SOF5: case M_SOF6: - case M_SOF7: + case M_SOF7: /* lossless */ case M_SOF9: case M_SOF10: - case M_SOF11: + case M_SOF11: /* lossless */ case M_SOF13: case M_SOF14: - case M_SOF15: - pdftex_fail("unsupported type of compression"); + case M_SOF15: /* lossless */ + pdftex_fail("unsupported type of compression (SOF_%d)", i - M_SOF0); + break; case M_SOF2: if (pdf->minor_version <= 2) pdftex_fail("cannot use progressive DCT with PDF-1.2"); case M_SOF0: case M_SOF1: - case M_SOF3: (void) read2bytes(img_file(idict)); /* read segment length */ img_colordepth(idict) = xgetc(img_file(idict)); img_ysize(idict) = (int) read2bytes(img_file(idict)); @@ -230,7 +224,7 @@ void read_jpg_info(PDF pdf, image_dict * idict, img_readtype_e readtype) case M_RST7: break; default: /* skip variable length markers */ - xfseek(img_file(idict), read2bytes(img_file(idict)) - 2, + xfseek(img_file(idict), (int) read2bytes(img_file(idict)) - 2, SEEK_CUR, img_filepath(idict)); break; } diff --git a/Build/source/texk/web2c/luatexdir/image/writepng.w b/Build/source/texk/web2c/luatexdir/image/writepng.w index fbe80259a63..7d497deea0e 100644 --- a/Build/source/texk/web2c/luatexdir/image/writepng.w +++ b/Build/source/texk/web2c/luatexdir/image/writepng.w @@ -20,8 +20,8 @@ @ @c static const char _svn_version[] = - "$Id: writepng.w 3612 2010-04-13 09:29:42Z taco $ " - "$URL: http://foundry.supelec.fr/svn/luatex/branches/0.60.x/source/texk/web2c/luatexdir/image/writepng.w $"; + "$Id: writepng.w 4133 2011-04-11 16:54:11Z oneiros $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.66.0/source/texk/web2c/luatexdir/image/writepng.w $"; #include <assert.h> #include "ptexlib.h" @@ -42,7 +42,6 @@ static void close_and_cleanup_png(image_dict * idict) png_destroy_read_struct(&(img_png_png_ptr(idict)), &(img_png_info_ptr(idict)), NULL); xfree(img_png_ptr(idict)); - img_png_ptr(idict) = NULL; } @ @c @@ -115,7 +114,7 @@ void read_png_info(PDF pdf, image_dict * idict, img_readtype_e readtype) img_procset(idict) |= PROCSET_IMAGE_C; break; default: - pdftex_fail("unsupported type of color_type <%i>", png_get_color_type(png_p, info_p)); + pdftex_fail("unsupported type of color_type <%i>", (int)png_get_color_type (png_p, info_p)); } img_colordepth(idict) = png_get_bit_depth(png_p, info_p); if (readtype == IMG_CLOSEINBETWEEN) @@ -187,10 +186,9 @@ static void write_png_palette(PDF pdf, image_dict * idict) if (img_colorspace(idict) != 0) { pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); } else { - pdf_create_obj(pdf, obj_type_others, 0); - palette_objnum = pdf->obj_ptr; + palette_objnum = pdf_create_obj(pdf, obj_type_others, 0); pdf_printf(pdf, "[/Indexed /DeviceRGB %i %i 0 R]\n", - num_palette - 1, (int) palette_objnum); + (int) (num_palette - 1), (int) palette_objnum); } pdf_begin_stream(pdf); if (png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE) { @@ -212,7 +210,7 @@ static void write_png_palette(PDF pdf, image_dict * idict) if (palette_objnum > 0) { pdf_begin_dict(pdf, palette_objnum, 0); pdf_begin_stream(pdf); - for (i = 0; (unsigned) i < num_palette; i++) { + for (i = 0; i < num_palette; i++) { pdf_room(pdf, 3); pdf_quick_out(pdf, palette[i].red); pdf_quick_out(pdf, palette[i].green); @@ -264,14 +262,13 @@ static void write_png_gray_alpha(PDF pdf, image_dict * idict) png_bytep smask; int smask_ptr = 0; int smask_size = 0; - int bitdepth; + png_byte bitdepth; if (img_colorspace(idict) != 0) { pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); } else { pdf_puts(pdf, "/DeviceGray\n"); } - pdf_create_obj(pdf, obj_type_others, 0); - smask_objnum = pdf->obj_ptr; + smask_objnum = pdf_create_obj(pdf, obj_type_others, 0); pdf_printf(pdf, "/SMask %i 0 R\n", (int) smask_objnum); smask_size = (int) ((png_get_rowbytes(png_p, info_p) / 2) * png_get_image_height (png_p, info_p)); smask = xtalloc((unsigned) smask_size, png_byte); @@ -302,7 +299,7 @@ static void write_png_gray_alpha(PDF pdf, image_dict * idict) pdf_end_stream(pdf); pdf_flush(pdf); /* now write the Smask object */ - bitdepth = (int) png_get_bit_depth(png_p, info_p); + bitdepth = png_get_bit_depth (png_p, info_p); pdf_begin_dict(pdf, smask_objnum, 0); pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n"); if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) @@ -366,16 +363,15 @@ static void write_png_rgb_alpha(PDF pdf, image_dict * idict) png_bytep smask; int smask_ptr = 0; int smask_size = 0; - int bitdepth; + png_byte bitdepth; if (img_colorspace(idict) != 0) { pdf_printf(pdf, "%i 0 R\n", (int) img_colorspace(idict)); } else { pdf_puts(pdf, "/DeviceRGB\n"); } - pdf_create_obj(pdf, obj_type_others, 0); - smask_objnum = pdf->obj_ptr; + smask_objnum = pdf_create_obj(pdf, obj_type_others, 0); pdf_printf(pdf, "/SMask %i 0 R\n", (int) smask_objnum); - smask_size = (int) ((png_get_rowbytes(png_p, info_p) / 2) * png_get_image_height (png_p, info_p)); + smask_size = (int) ((png_get_rowbytes (png_p, info_p) / 4) * png_get_image_height (png_p, info_p)); smask = xtalloc((unsigned) smask_size, png_byte); pdf_begin_stream(pdf); if (png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE) { @@ -405,7 +401,7 @@ static void write_png_rgb_alpha(PDF pdf, image_dict * idict) pdf_flush(pdf); /* now write the Smask object */ if (smask_objnum > 0) { - bitdepth = (int) png_get_bit_depth(png_p, info_p); + bitdepth = png_get_bit_depth (png_p, info_p); pdf_begin_dict(pdf, smask_objnum, 0); pdf_puts(pdf, "/Type /XObject\n/Subtype /Image\n"); if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) @@ -483,12 +479,12 @@ static void copy_png(PDF pdf, image_dict * idict) "/Filter/FlateDecode\n" "/DecodeParms<<" "/Colors %d" - "/Columns %d" + "/Columns %u" "/BitsPerComponent %i" "/Predictor 10>>\n>>\nstream\n", streamlength, - png_get_color_type(png_p, info_p) == 2 ? 3 : 1, - (int) png_get_image_width (png_p, info_p), - png_get_bit_depth(png_p, info_p)); + png_get_color_type (png_p, info_p) == 2 ? 3 : 1, + png_get_image_width (png_p, info_p), + png_get_bit_depth (png_p, info_p)); /* 2nd pass to copy data */ endflag = false; if (fseek(fp, 8, SEEK_SET) != 0) @@ -575,10 +571,12 @@ void write_png(PDF pdf, image_dict * idict) } /* the switching between |info_p| and |png_p| queries has been trial and error. */ - if (pdf->minor_version > 1 && png_get_interlace_type(png_p, info_p) == PNG_INTERLACE_NONE - &&!(png_get_color_type(png_p, info_p) == PNG_COLOR_TYPE_GRAY_ALPHA || - png_get_color_type(png_p, info_p) == PNG_COLOR_TYPE_RGB_ALPHA) - && ((pdf->image_hicolor != 0) || (png_get_bit_depth(png_p, info_p) <= 8)) + if (pdf->minor_version > 1 + && png_get_interlace_type (png_p, info_p) == PNG_INTERLACE_NONE + && (png_p->transformations == 0 || png_p->transformations == 0x2000) /* gamma */ + &&!(png_get_color_type (png_p, info_p) == PNG_COLOR_TYPE_GRAY_ALPHA || + png_get_color_type (png_p, info_p) == PNG_COLOR_TYPE_RGB_ALPHA) + && ((pdf->image_hicolor != 0) || (png_get_bit_depth (png_p, info_p) <= 8)) && (checked_gamma <= 1.01 && checked_gamma > 0.99) ) { png_colorp palette; @@ -590,8 +588,7 @@ void write_png(PDF pdf, image_dict * idict) } else { switch (png_get_color_type(png_p, info_p)) { case PNG_COLOR_TYPE_PALETTE: - pdf_create_obj(pdf, obj_type_others, 0); - palette_objnum = pdf->obj_ptr; + palette_objnum = pdf_create_obj(pdf, obj_type_others, 0); pdf_printf(pdf, "[/Indexed /DeviceRGB %i %i 0 R]\n", num_palette - 1, (int) palette_objnum); break; @@ -608,7 +605,7 @@ void write_png(PDF pdf, image_dict * idict) if (palette_objnum > 0) { pdf_begin_dict(pdf, palette_objnum, 0); pdf_begin_stream(pdf); - for (i = 0; (unsigned) i < num_palette; i++) { + for (i = 0; i < num_palette; i++) { pdf_room(pdf, 3); pdf_quick_out(pdf, palette[i].red); pdf_quick_out(pdf, palette[i].green); @@ -622,9 +619,11 @@ void write_png(PDF pdf, image_dict * idict) if ((pdf->image_apply_gamma != 0) && (checked_gamma > 1.01 || checked_gamma < 0.99)) tex_printf("gamma delta=%lf ", checked_gamma); - if ((png_get_color_type(png_p, info_p) != PNG_COLOR_TYPE_GRAY) - && (png_get_color_type(png_p, info_p) != PNG_COLOR_TYPE_RGB) - && (png_get_color_type(png_p, info_p) != PNG_COLOR_TYPE_PALETTE)) + if (png_p->transformations != PNG_TRANSFORM_IDENTITY) + tex_printf("transform=%lu", (long) png_p->transformations); + if ((png_get_color_type (png_p, info_p) != PNG_COLOR_TYPE_GRAY) + && (png_get_color_type (png_p, info_p) != PNG_COLOR_TYPE_RGB) + && (png_get_color_type (png_p, info_p) != PNG_COLOR_TYPE_PALETTE)) tex_printf("colortype "); if (pdf->minor_version <= 1) tex_printf("version=%d ", pdf->minor_version); |