Commit 2de98f38 authored by Kristian Høgsberg's avatar Kristian Høgsberg

2005-03-28 Kristian Høgsberg <krh@redhat.com>

        * poppler/Page.cc (loadThumb): Backend agnostic method for
        extracting an embedded thumbnail iamge.

        * poppler/Dict.cc (lookupInt): New convenience method.

        * glib/poppler-page.cc (poppler_page_get_thumbnail): New glib
        function for getting the embedded thumbnail image for a page.
parent 591055d1
2005-03-28 Kristian Høgsberg <krh@redhat.com>
* poppler/Page.cc (loadThumb): Backend agnostic method for
extracting an embedded thumbnail iamge.
* poppler/Dict.cc (lookupInt): New convenience method.
* glib/poppler-page.cc (poppler_page_get_thumbnail): New glib
function for getting the embedded thumbnail image for a page.
2005-03-25 Kristian Høgsberg <krh@redhat.com>
* configure.ac: Check for fontconfig for glib bindings.
......
......@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <math.h>
#include <goo/GooList.h>
#include <splash/SplashBitmap.h>
#include <GlobalParams.h>
......@@ -25,6 +27,7 @@
#include <UnicodeMap.h>
#include <GfxState.h>
#include <SplashOutputDev.h>
#include <TextOutputDev.h>
#include "poppler.h"
#include "poppler-private.h"
......@@ -156,6 +159,26 @@ poppler_page_render_to_pixbuf (PopplerPage *page,
delete output_dev;
}
static void
destroy_thumb_data (guchar *pixels, gpointer data)
{
gfree (pixels);
}
GdkPixbuf *
poppler_page_get_thumbnail (PopplerPage *page)
{
unsigned char *data;
int width, height, rowstride;
if (!page->page->loadThumb (&data, &width, &height, &rowstride))
return NULL;
return gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB,
FALSE, 8, width, height, rowstride,
destroy_thumb_data, NULL);
}
static void
poppler_page_get_property (GObject *object,
guint prop_id,
......
......@@ -29,23 +29,21 @@ G_BEGIN_DECLS
#define POPPLER_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), POPPLER_TYPE_PAGE, PopplerPage))
#define POPPLER_IS_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POPPLER_TYPE_PAGE))
GType poppler_page_get_type (void) G_GNUC_CONST;
void poppler_page_render_to_pixbuf (PopplerPage *page,
int src_x,
int src_y,
int src_width,
int src_height,
double scale,
GdkPixbuf *pixbuf,
int dest_x,
int dest_y);
void poppler_page_get_size (PopplerPage *page,
double *width,
double *height);
int poppler_page_get_index (PopplerPage *page);
GType poppler_page_get_type (void) G_GNUC_CONST;
void poppler_page_render_to_pixbuf (PopplerPage *page,
int src_x,
int src_y,
int src_width,
int src_height,
double scale,
GdkPixbuf *pixbuf,
int dest_x,
int dest_y);
void poppler_page_get_size (PopplerPage *page,
double *width,
double *height);
int poppler_page_get_index (PopplerPage *page);
GdkPixbuf *poppler_page_get_thumbnail (PopplerPage *page);
G_END_DECLS
......
......@@ -11,12 +11,11 @@ int main (int argc, char *argv[])
PopplerPage *page;
char *filename, *title, *label;
GError *error;
GdkPixbuf *pixbuf;
GdkPixbuf *pixbuf, *thumb;
double width, height;
filename = argv[1];
if (filename == NULL)
FAIL ("specify filename");
if (argc != 3)
FAIL ("usage: test-poppler-glib FILE PAGE");
g_type_init ();
......@@ -29,9 +28,6 @@ int main (int argc, char *argv[])
printf ("document title: %s\n", title);
g_free (title);
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 100, 100);
gdk_pixbuf_fill (pixbuf, 0x00106000);
page = poppler_document_get_page_by_label (document, argv[2]);
if (page == NULL)
FAIL ("page not found");
......@@ -39,10 +35,24 @@ int main (int argc, char *argv[])
poppler_page_get_size (page, &width, &height);
printf ("page size: %f inches by %f inches\n", width / 72, height / 72);
thumb = poppler_page_get_thumbnail (page);
if (thumb != NULL) {
gdk_pixbuf_save (thumb, "thumb.png", "png", &error, NULL);
if (error != NULL)
FAIL (error->message);
else
printf ("saved thumbnail as thumb.png\n");
g_object_unref (G_OBJECT (thumb));
}
else
printf ("no thumbnail for page\n");
g_object_get (page, "label", &label, NULL);
printf ("page label: %s\n", label);
g_free (label);
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 100, 100);
gdk_pixbuf_fill (pixbuf, 0x00106000);
poppler_page_render_to_pixbuf (page, 100, 100, 50, 50, 1, pixbuf, 10, 10);
g_object_unref (G_OBJECT (page));
......
......@@ -82,6 +82,26 @@ Object *Dict::lookupNF(char *key, Object *obj) {
return (e = find(key)) ? e->val.copy(obj) : obj->initNull();
}
GBool Dict::lookupInt(const char *key, const char *alt_key, int *value)
{
Object obj1;
GBool success = gFalse;
lookup ((char *) key, &obj1);
if (obj1.isNull () && alt_key != NULL) {
obj1.free ();
lookup ((char *) alt_key, &obj1);
}
if (obj1.isInt ()) {
*value = obj1.getInt ();
success = gTrue;
}
obj1.free ();
return success;
}
char *Dict::getKey(int i) {
return entries[i].key;
}
......
......@@ -50,6 +50,7 @@ public:
// if <key> is not in the dictionary.
Object *lookup(char *key, Object *obj);
Object *lookupNF(char *key, Object *obj);
GBool lookupInt(const char *key, const char *alt_key, int *value);
// Iterative accessors.
char *getKey(int i);
......
......@@ -13,6 +13,7 @@
#endif
#include <stddef.h>
#include <limits.h>
#include "GlobalParams.h"
#include "Object.h"
#include "Array.h"
......@@ -22,6 +23,7 @@
#include "OutputDev.h"
#ifndef PDF_PARSER_ONLY
#include "Gfx.h"
#include "GfxState.h"
#include "Annot.h"
#endif
#include "Error.h"
......@@ -368,3 +370,110 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
delete gfx;
#endif
}
GBool Page::loadThumb(unsigned char **data_out,
int *width_out, int *height_out,
int *rowstride_out)
{
ImageStream *imgstr;
unsigned char *pixbufdata;
unsigned int pixbufdatasize;
int row, col;
int width, height, bits;
unsigned char *p;
Object obj1, fetched_thumb;
Dict *dict;
GfxColorSpace *colorSpace;
GBool success = gFalse;
Stream *str;
GfxImageColorMap *colorMap;
/* Get stream dict */
thumb.fetch(xref, &fetched_thumb);
if (fetched_thumb.isNull()) {
fetched_thumb.free();
return gFalse;
}
dict = fetched_thumb.streamGetDict();
str = fetched_thumb.getStream();
if (!dict->lookupInt("Width", "W", &width))
goto fail1;
if (!dict->lookupInt("Height", "H", &height))
goto fail1;
if (!dict->lookupInt("BitsPerComponent", "BPC", &bits))
goto fail1;
/* Check for invalid dimensions and integer overflow. */
if (width <= 0 || height <= 0)
goto fail1;
if (width > INT_MAX / 3 / height)
goto fail1;
pixbufdatasize = width * height * 3;
/* Get color space */
dict->lookup ("ColorSpace", &obj1);
if (obj1.isNull ()) {
obj1.free ();
dict->lookup ("CS", &obj1);
}
colorSpace = GfxColorSpace::parse(&obj1);
obj1.free();
if (!colorSpace) {
fprintf (stderr, "Error: Cannot parse color space\n");
goto fail1;
}
dict->lookup("Decode", &obj1);
if (obj1.isNull()) {
obj1.free();
dict->lookup("D", &obj1);
}
colorMap = new GfxImageColorMap(bits, &obj1, colorSpace);
obj1.free();
if (!colorMap->isOk()) {
fprintf (stderr, "Error: invalid colormap\n");
goto fail1;
}
str->addFilters(&fetched_thumb);
pixbufdata = (unsigned char *) gmalloc(pixbufdatasize);
p = pixbufdata;
imgstr = new ImageStream(str, width,
colorMap->getNumPixelComps(),
colorMap->getBits());
imgstr->reset();
for (row = 0; row < height; ++row) {
for (col = 0; col < width; ++col) {
Guchar pix[gfxColorMaxComps];
GfxRGB rgb;
imgstr->getPixel(pix);
colorMap->getRGB(pix, &rgb);
*p++ = (unsigned char)(rgb.r * 255 + 0.5);
*p++ = (unsigned char)(rgb.g * 255 + 0.5);
*p++ = (unsigned char)(rgb.b * 255 + 0.5);
}
}
success = gTrue;
if (data_out)
*data_out = pixbufdata;
if (width_out)
*width_out = width;
if (height_out)
*height_out = height;
if (rowstride_out)
*rowstride_out = width * 3;
delete imgstr;
delete colorMap;
fail1:
fetched_thumb.free();
return success;
}
......@@ -142,6 +142,7 @@ public:
// Get thumb.
Object *getThumb(Object *obj) { return thumb.fetch(xref, obj); }
GBool loadThumb(unsigned char **data, int *width, int *height, int *rowstride);
// Display a page.
void display(OutputDev *out, double hDPI, double vDPI,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment