[poppler] Patch for embedding videos in to the pdf
srinivas adicherla
srinivas.adicherla at gmail.com
Fri Mar 25 04:41:05 PDT 2011
Hi Carlos,
Thank you for helping me.
I made the changes suggested by you. Please check the patch. Let
me know for any more changes.
Thanks
--
A Srinivas
On Thu, Mar 24, 2011 at 12:30 AM, <poppler-request at lists.freedesktop.org>wrote:
> Send poppler mailing list submissions to
> poppler at lists.freedesktop.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
> http://lists.freedesktop.org/mailman/listinfo/poppler
> or, via email, send a message with subject or body 'help' to
> poppler-request at lists.freedesktop.org
>
> You can reach the person managing the list at
> poppler-owner at lists.freedesktop.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of poppler digest..."
>
>
> Today's Topics:
>
> 1. Re: poppler Digest, Vol 73, Issue 27 (Carlos Garcia Campos)
> 2. Plans to get Javascript support in Poppler.
> (jose.aliste at gmail.com)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Wed, 23 Mar 2011 15:18:41 +0100
> From: Carlos Garcia Campos <carlosgc at gnome.org>
> Subject: Re: [poppler] poppler Digest, Vol 73, Issue 27
> To: srinivas adicherla <srinivas.adicherla at gmail.com>
> Cc: poppler <poppler at lists.freedesktop.org>
> Message-ID: <1300886015-sup-4220 at charizard>
> Content-Type: text/plain; charset="utf8"
>
> Excerpts from srinivas adicherla's message of mi? mar 23 08:30:32 +0100
> 2011:
> > Hi Carlos,
>
> Hi,
>
> > Thank you for your valuable suggestions. I made the changes
> > according to that. I attached a new patch with this.
>
> Thanks!
>
> > - I have some doubt when setting a 'Rendition' action, we have two
> options
> > one is to set 'OP' other one is 'JS'. I am asking the user to pass the
> > Javascript and set it as a stream here.
>
> Since both options are required when the other one is not present, I
> would add two constructors, one for OP, and another one for JS.
>
> LinkRendition::LinkRendition(XRef *xrefA, MediaRendition *rendition, int
> operation, Annot *annot);
> LinkRendition::LinkRendition(XRef *xrefA, Object *js);
>
> > - One more is i wrote a new function 'get_file_name_from_path' is it
> fine?
> > what is the good place to add this function.
>
> yes, just rename it to follow poppler coding style to something like:
>
> getFileNameFromPath();
>
> > Please give suggestions again.
>
> See comments below
>
> > Thanks
>
> Index: poppler-0.16.2/poppler/Link.cc
> ===================================================================
> --- poppler-0.16.2/poppler/Link.cc (revision 12)
> +++ poppler-0.16.2/poppler/Link.cc (working copy)
> @@ -44,6 +44,7 @@
> #include "Sound.h"
> #include "FileSpec.h"
> #include "Rendition.h"
> +#include "XRef.h"
>
> //------------------------------------------------------------------------
> // LinkAction
> @@ -738,6 +739,32 @@
> }
> }
>
> +LinkRendition::LinkRendition(Annot *annot, const char *video_file,Object
> *obj) {
>
> This method should receive the XRef, and the MediaRendition object
> already created. See the contructors I suggested above.
>
> + Object obj1;
> + XRef *xref = annot->getXRef();
> + renditionObj.initDict(xref);
> + Ref annotref = annot->getRef();
> + renditionObj.dictSet("Type", obj1.initName("Action"));
> + renditionObj.dictSet("S", obj1.initName("Rendition"));
> + if (obj->isInt()) {
> + renditionObj.dictSet("OP", obj);
> + renditionObj.dictSet("AN", obj1.initRef(annotref.num, annotref.gen));
> + }
> + else {
> + renditionObj.dictSet("JS", obj);
> + }
> +
> + // Media Rendition
> + Object MRendition;
> + MediaRendition *MR = new MediaRendition(annot, video_file);
> + MRendition = MR->getMediaRendition();
> +
> + Ref newRef;
> + newRef = xref->addIndirectObject(&MRendition);
> + obj->initRef(newRef.num, newRef.gen);
> + renditionObj.dictSet("R", &obj1);
> +}
> +
> LinkRendition::~LinkRendition() {
> renditionObj.free();
> screenRef.free();
>
> Index: poppler-0.16.2/poppler/Rendition.cc
> ===================================================================
> --- poppler-0.16.2/poppler/Rendition.cc (revision 12)
> +++ poppler-0.16.2/poppler/Rendition.cc (working copy)
> @@ -24,6 +24,7 @@
>
> #include <math.h>
> #include "Rendition.h"
> +#include "XRef.h"
> #include "FileSpec.h"
>
> MediaWindowParameters::MediaWindowParameters() {
> @@ -366,6 +367,40 @@
> tmp2.free();
> }
>
> +MediaRendition::MediaRendition(Annot *annot, const char *mediafile) {
>
> Pass the XRef directly instead of passing the annot object just to get
> the XRef
>
> + Object obj1, obj2;
> +
> + XRef *xref = annot->getXRef();
> + mediaRendition.initDict(xref);
> + mediaRendition.dictSet("S", obj1.initName("MR"));
> +
> + // Media Clip Dictionary
> + Object MClipDict;
> + MClipDict.initDict(xref);
> + MClipDict.dictSet("S", obj1.initName("MCD"));
> +
> + //if (mimetype)
> + //MClipDict.dictSet("CT", obj3.initString(new GooString(mimetype)));
>
> There's a contentType variable for this, so make sure it's updated so
> that MediaRendition::getContentType() will work. Why is this commented?
>
> + obj1.initString(new GooString("TEMPACCESS"));
> + obj2.initDict(xref);
> + obj2.dictSet("TF", &obj1);
> + MClipDict.dictSet("P", &obj2);
>
> The Permissions dictionary is optional, why are you hardcoding
> TEMPACCESS here? We are not even parsing TF when creating a
> MediaRendition from an existing dictionary.
>
> + // File Specification Dictionary
> + Object *fsDict;
> + fsDict = annot->createFilespec(mediafile);
>
> As Pino suggested this should probably be moved to FileSpec.cc since
> it's not specific to annotations.
>
> +
> + Ref newRef;
> + newRef = xref->addIndirectObject(fsDict);
> + obj2.initRef(newRef.num, newRef.gen);
> + MClipDict.dictSet("D", &obj2);
>
> You should initialize the fileName, isEmbedded and embeddedStream
> variables,
> maybe it's the time to add a FileSpec class so that this methos just
> receives a FileSpec object instead of a filename.
>
> + newRef = xref->addIndirectObject(&MClipDict);
> + obj2.initRef(newRef.num, newRef.gen);
> + mediaRendition.dictSet("C", &obj2);
>
> ok variable should be initialized to gTrue.
>
> +}
> +
> void MediaRendition::outputToFile(FILE* fp) {
> if (!isEmbedded)
> return;
> Index: poppler-0.16.2/poppler/Rendition.h
> ===================================================================
> --- poppler-0.16.2/poppler/Rendition.h (revision 12)
> +++ poppler-0.16.2/poppler/Rendition.h (working copy)
> @@ -25,6 +25,7 @@
> #define _RENDITION_H_
>
> #include "Object.h"
> +#include "Annot.h"
>
> struct MediaWindowParameters {
>
> @@ -118,6 +119,7 @@
> class MediaRendition {
> public:
> MediaRendition(Object *obj);
> + MediaRendition(Annot *annot, const char *mediafile);
> ~MediaRendition();
>
> GBool isOk () { return ok; }
> @@ -128,6 +130,7 @@
> GooString* getContentType() { return contentType; }
> GooString* getFileName() { return fileName; }
>
> + Object getMediaRendition() {return mediaRendition;}
> GBool getIsEmbedded() { return isEmbedded; }
> Stream* getEmbbededStream() { return embeddedStream; }
> // write embedded stream to file
> @@ -145,6 +148,7 @@
>
> GBool isEmbedded;
>
> + Object mediaRendition;
>
> mediaRendition should be initilized in the other constructor too,
> simply copy the given object:
>
> obj->copy(&mediaRendition);
>
>
> GooString* contentType;
>
> // if it's embedded
>
> Index: poppler-0.16.2/poppler/Annot.cc
> ===================================================================
> --- poppler-0.16.2/poppler/Annot.cc (revision 12)
> +++ poppler-0.16.2/poppler/Annot.cc (working copy)
>
> +void AnnotScreen::setTitle(GooString *title) {
> + if (title)
> + title = new GooString(title);
> + else
> + title = new GooString();
>
> save the title as a class attr, and add getTitle() method. Make sure
> the string is correctly encoded, see Annot::setContents() for example.
>
> + Object obj1;
> + obj1.initString(title->copy());
> + update ("T", &obj1);
> + delete(title);
> +}
>
>
> +GBool AnnotScreen::setAction(const char* video_file, const char* mimetype,
> const char* img_file, const char* js) {
>
> A screen annot can be used to trigger any action type, not only
> rendition actions, so this should be something like:
>
> GBool AnnotScreen::setAction(LinkAction *actionA);
>
> + if (!video_file) {
> + error(-1, "Need to pass the video file");
> + return gFalse;
> + }
> +
> + // Extract the video name from the file uri
> + const char *video_name = get_file_name_from_path (video_file);
> +
> + Object obj1, obj2, obj3, obj4;
> +
> + GooString *title = new GooString(video_name);
> + setTitle(title);
> + setContents(title);
> + delete(title);
>
> title and contents should be set by the caller, the frontends in this
> case.
>
> + Ref imgRef;
> + Object imgXObj;
> + imgXObj.initDict(xref);
> + imgXObj.dictSet("Type", obj1.initName("XObject"));
> + imgXObj.dictSet("Subtype", obj2.initName("Image"));
> +
> + if (img_file) {
> + FILE *imgfp;
> + if (!(imgfp = fopen(img_file, "rb"))) {
> + error(-1, "Couldn't open file: %s",img_file);
> + return gFalse;
> + }
> + unsigned char h[10];
> + fread(h, 1, 10, imgfp);
> + fseek(imgfp, 0, SEEK_SET);
> +
> + MemStream *imgStream = NULL;
> + // Load the stream from the png file
> + if (h[0] == 0x89 && h[1] == 0x50 && h[2] == 0x4E && h[3] == 0x47)
> + imgStream = load_from_png (imgfp, &imgXObj);
> + // Load the stream from the jpeg file
> + else if(h[0] == 0xFF && h[1] == 0xD8 && h[6] == 0x4A && h[7] == 0x46
> && h[8] == 0x49 && h[9] == 0x46)
> + imgStream = load_from_jpeg (imgfp, &imgXObj);
> + else {
> + error(-1, "Image format cannot be supported, only png/jpeg\n");
> + return gFalse;
> + }
> +
> + if (imgStream) {
> + obj2.initStream(imgStream);
> + appearBuf = new GooString("/Im1 Do");
> + double bbox[4];
> + bbox[0] = bbox[1] = 0;
> + bbox[2] = bbox[3] = 1;
> + createResourcesDict("Im1", &obj2, "GS0", 1.0, NULL, &obj4);
> + createForm(bbox, gFalse, &obj4, &obj1);
> +
> + Ref appRef = xref->addIndirectObject(&obj1);
> + obj2.initDict(xref);
> + obj2.dictSet("N", obj3.initRef(appRef.num, appRef.gen));
> + annotObj.dictSet("AP", &obj2);
> +
> + obj2.initStream(imgStream);
> + createResourcesDict("Im1", &obj2, "GS0", 1.0, NULL, &obj1);
> + createForm(bbox, gFalse, &obj1, &obj4);
> + appRef = xref->addIndirectObject(&obj4);
> +
> + obj2.initDict(xref); // MK dictionary
> + obj2.dictSet("I", obj3.initRef(appRef.num, appRef.gen));
> + annotObj.dictSet("MK", &obj2);
> + }
> + }
>
> I think it would be better to add a generic mehtod to set the annot
> appearance stream from an image, something like
> Annot::setAppearanceFromFile() and call it from the frontends instead
> of doing it here.
>
> + if (js == NULL)
> + obj1.initInt(0);
> + else {
> + obj2.initDict(xref);
> + obj2.dictSet("Length", obj3.initInt(strlen(js)));
> + MemStream *jsstream = new MemStream(copyString((char*)js), 0,
> strlen(js), &obj2);
> + obj1.initStream(jsstream);
> + }
> +
> + LinkRendition *rendition = new LinkRendition(this, video_file, &obj1);
>
> You should update the action variable instead.
>
> + Object *renditionObj = rendition->getRenditionObject();
> + Ref newRef = xref->addIndirectObject(renditionObj);
> + obj1.initRef(newRef.num, newRef.gen);
>
> rendition object should be added by the MediaRendition constructor
> like we currently does for annotations, and here you only need to get
> the Ref.
>
> + annotObj.dictSet("A", &obj1);
> +
> + return gTrue;
> +}
> +
> //------------------------------------------------------------------------
> // AnnotStamp
> //------------------------------------------------------------------------
> Index: poppler-0.16.2/glib/poppler-annot.cc
> ===================================================================
> --- poppler-0.16.2/glib/poppler-annot.cc (revision 12)
> +++ poppler-0.16.2/glib/poppler-annot.cc (working copy)
> @@ -332,7 +332,52 @@
> return poppler_annot;
> }
>
> +/**
> + * poppler_annot_screen_new:
> + * @doc: a #PopplerDocument
> + * @rect: a #PopplerRectangle
> + *
> + * Creates a new Screen annotation that will be
> + * located on @rect when added to a page. See
> + * poppler_page_add_annot()
> + *
> + * Return value: A newly created #PopplerAnnotScreen annotation
> + *
> + */
> +PopplerAnnot *
> +poppler_annot_screen_new (PopplerDocument *doc,
> + PopplerRectangle *rect)
> +{
> + Annot *annot;
> + PDFRectangle pdf_rect(rect->x1, rect->y1,
> + rect->x2, rect->y2);
>
> + annot = new AnnotScreen (doc->doc->getXRef(), &pdf_rect,
> doc->doc->getCatalog());
> + return _poppler_annot_screen_new (annot);
> +}
> +
> +/**
> + * poppler_annot_screen_set_action:
> + * @poppler_annot: a #PopplerAnnot
> + * @video_file: pass the path of the video to be embed
> + * @mimetype: pass the mimetype of the video to put in the Media Clip
> Dictionary
> + * @img_file: pass png/jpeg image file for poster
> + * @js: set the JS as this javascript stream in rendition action else if
> it is null set OP
> +
> + * Set the action for the screen annotation specified @poppler_annot
> + *
> + */
> +void
> +poppler_annot_screen_set_action (PopplerAnnot *poppler_annot,
> + const char* video_file,
> + const char* mimetype,
> + const char* img_file,
> + const char* js)
>
> This is still wrong, you should be able to set any action type to a
> screen annotation.
>
> --
> Carlos Garcia Campos
> PGP key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x523E6462
> -------------- next part --------------
> A non-text attachment was scrubbed...
> Name: signature.asc
> Type: application/pgp-signature
> Size: 198 bytes
> Desc: not available
> URL: <
> http://lists.freedesktop.org/archives/poppler/attachments/20110323/094c9927/attachment-0001.pgp
> >
>
> ------------------------------
>
> Message: 2
> Date: Wed, 23 Mar 2011 13:25:27 -0400
> From: "jose.aliste at gmail.com" <jose.aliste at gmail.com>
> Subject: [poppler] Plans to get Javascript support in Poppler.
> To: poppler at lists.freedesktop.org
> Cc: Ryan Lewis <me at ryanlewis.net>
> Message-ID:
> <AANLkTin98WAdRNo5OfMjs31zHCdWr2X5rXCVXjwtJRZn at mail.gmail.com>
> Content-Type: text/plain; charset=ISO-8859-1
>
> Hi list,
>
> So we are discussing how we can join efforts to start adding poppler
> support for Javascript in poppler. With Carlos and Pino, we got some
> agreements that I want to share with you so you can add comments/
> regards/ questions/ etc. These are by no mean sealed plans, I only try
> to account for a summary of the discussion we had yesterday in IRC.
> The basic plan is:
>
> 1. To start a "plain core js" API in C++ that will use poppler core
> API and will follow as close as possible the PDF JS API [1]
> 2. Each frontend, glib and qt, can then decide how they will bind
> these API to their frontends.
>
> Notes:
> a) Of course, will coding 1, we will need to add functionality to core
> poppler that is not there yet, like for instance, support for
> Javascript Actions.
> b) the plain core js api in 1 should be probably very easy, as it
> should wrap more or less directly from the core poppler, but we choose
> this way so the code can be shared by Okular and Evince.
> c) Just for completness, I give more details about the glib frontend,
> in which I plan to hack: Our idea in 2) is to wrap the "plain core
> js" api into a GObject API, and then use the automatic
> GObject-Javascript glue that (will be) is provided to us by Seed using
> gobject-introspection (BTW, in this case the Javascript engine comes
> from Webkit).
>
> That's more or less it. Comments/questions/rants/patches welcome.
>
> Greets
>
> Jos?
>
>
> @Carlos, Pino, if I forget something (or I got something wrong),
> please add it here.
>
>
> ------------------------------
>
> _______________________________________________
> poppler mailing list
> poppler at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/poppler
>
>
> End of poppler Digest, Vol 73, Issue 35
> ***************************************
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/poppler/attachments/20110325/46fcafc9/attachment.htm>
More information about the poppler
mailing list