Hi all,

       I added new functionality for setting the appearance of the
annotation from the image (png/jpeg) file.
Please give your suggestions

Thanks
--
A Srinivas
Index: poppler-0.16.2/poppler/Annot.h
===================================================================
--- poppler-0.16.2/poppler/Annot.h	(revision 14)
+++ poppler-0.16.2/poppler/Annot.h	(working copy)
@@ -492,6 +492,7 @@
   virtual void draw(Gfx *gfx, GBool printing);
   // Get appearance object.
   Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
+  GBool setAppearanceFromFile(GooString *imgFile);
 
   GBool match(Ref *refA)
     { return ref.num == refA->num && ref.gen == refA->gen; }
Index: poppler-0.16.2/poppler/Annot.cc
===================================================================
--- poppler-0.16.2/poppler/Annot.cc	(revision 14)
+++ poppler-0.16.2/poppler/Annot.cc	(working copy)
@@ -62,6 +62,14 @@
 #include "Link.h"
 #include <string.h>
 
+#ifdef ENABLE_LIBJPEG
+#include <jpeglib.h>
+#endif
+
+#ifdef ENABLE_LIBPNG
+#include <png.h>
+#endif
+
 #define fieldFlagReadOnly           0x00000001
 #define fieldFlagRequired           0x00000002
 #define fieldFlagNoExport           0x00000004
@@ -1336,6 +1344,237 @@
   obj.free();
 }
 
+static MemStream* load_from_png (FILE *f, Object *imgXObj) {
+  #if defined(ENABLE_LIBPNG)
+  png_byte header[8];
+  fread(header, 1, 8, f);
+
+  if (png_sig_cmp(header, 0, 8)) {
+    fclose(f);
+    error(-1, "The file could not be recognized as a PNG file.");
+    return NULL;
+  }
+  
+  png_structp read_png;
+  if (!(read_png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) {
+    fclose(f);
+    error(-1, "png_create_read_struct");
+    return NULL;
+  }
+ 
+  png_infop info_png;
+  if (!(info_png = png_create_info_struct(read_png))) {
+    png_destroy_read_struct (&read_png, (png_infopp)NULL, (png_infopp)NULL);
+    fclose(f);
+    error(-1, "png_create_info_struct");
+    return NULL;
+  }
+  
+  if (setjmp(png_jmpbuf(read_png))) {
+    png_destroy_read_struct (&read_png, &info_png, (png_infopp)NULL);
+    fclose(f);
+    error(-1, "png_jmpbuf");
+    return NULL;
+  }
+  
+  png_init_io(read_png, f);
+  png_set_sig_bytes(read_png, 8);
+  png_read_info(read_png, info_png);
+
+  if (/*info_png->color_type*/png_get_color_type(read_png, info_png) & PNG_COLOR_MASK_ALPHA)
+    png_set_strip_alpha(read_png);
+
+  int width = png_get_image_width(read_png, info_png); //info_png->width;
+  int height = png_get_image_height(read_png, info_png); //info_png->height;
+  png_read_update_info(read_png, info_png);
+  
+  // Read the file
+  if (setjmp(png_jmpbuf(read_png))) {
+    png_destroy_read_struct (&read_png, &info_png, (png_infopp)NULL);
+    fclose(f);
+    error(-1, "png_jmpbuf");
+    return NULL;
+  }
+  
+  long rowbytes = png_get_rowbytes(read_png, info_png);
+  long numbytes = static_cast<long>(/*info_png->rowbytes*/rowbytes * height);
+  char *img_buffer = static_cast<char*>(malloc(sizeof(char) * numbytes));
+  png_bytepp numrows = static_cast<png_bytepp>(malloc(sizeof(png_bytep)*height));
+
+  for(int i=0; i<height; i++) {
+    numrows[i] = reinterpret_cast<png_bytep>(img_buffer + (i * rowbytes));
+  }
+  
+  png_read_image(read_png, numrows);
+  png_read_end(read_png, NULL);
+ 
+  Object obj;
+ 
+  if (/*info_png->channels*/png_get_channels(read_png, info_png) == 3)
+    imgXObj->dictSet("ColorSpace", obj.initName("DeviceRGB"));	  
+  else
+    imgXObj->dictSet("ColorSpace", obj.initName("DeviceGray"));	  
+  
+  imgXObj->dictSet("BitsPerComponent", obj.initInt(/*info_png->bit_depth*/png_get_bit_depth(read_png, info_png)));	  
+  imgXObj->dictSet("Width", obj.initInt(width));	  
+  imgXObj->dictSet("Height", obj.initInt(height));	  
+  imgXObj->dictSet("Length", obj.initInt(numbytes));
+  
+  MemStream *imgStream = new MemStream (img_buffer, 0, numbytes, imgXObj);
+  imgStream->setNeedFree(gTrue);
+
+  png_destroy_read_struct (&read_png, &info_png, (png_infopp)NULL);
+  free(numrows);
+
+  fclose(f);
+  return imgStream;
+  #else
+    fclose(f);
+    error(-1, "Png support is not there");
+    return NULL;
+  #endif
+}
+
+static MemStream* load_from_jpeg (FILE *f, Object *imgXObj)
+{
+  #if defined(ENABLE_LIBJPEG)
+  struct jpeg_decompress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  jmp_buf setjmp_buffer;
+  JSAMPROW row_pointer[1];
+  unsigned long location = 0;
+  int i = 0;
+
+  cinfo.err = jpeg_std_error(&jerr);
+  jpeg_create_decompress(&cinfo);
+
+  if (setjmp(setjmp_buffer)) {
+    jpeg_destroy_decompress(&cinfo);
+    fclose(f);
+    error(-1, "setjmp_buffer");
+    return NULL;
+  }
+
+  jpeg_stdio_src(&cinfo, f);
+  jpeg_read_header(&cinfo, TRUE);
+  jpeg_start_decompress(&cinfo);
+
+  char* raw_image = (char*)malloc(cinfo.output_width*cinfo.output_height*cinfo.num_components);
+  row_pointer[0] = (unsigned char*)malloc(cinfo.output_width*cinfo.num_components);
+
+  while(cinfo.output_scanline < cinfo.image_height) {
+    jpeg_read_scanlines( &cinfo, row_pointer, 1 );
+    for(i=0; i<cinfo.image_width*cinfo.num_components; i++) 
+      raw_image[location++] = row_pointer[0][i];
+  }
+
+  jpeg_finish_decompress(&cinfo);
+  jpeg_destroy_decompress(&cinfo);
+  free(row_pointer[0]);
+  fclose(f);
+
+  Object obj;
+
+  imgXObj->dictSet("Width", obj.initInt (cinfo.output_width));	  
+  imgXObj->dictSet("Height", obj.initInt(cinfo.output_height));	  
+  imgXObj->dictSet("BitsPerComponent", obj.initInt(8));	  
+
+  switch(cinfo.output_components) {
+    case 3:
+      imgXObj->dictSet("ColorSpace", obj.initName("DeviceRGB"));	  
+      break;
+    case 4:
+      imgXObj->dictSet("ColorSpace", obj.initName("DeviceCMYK"));	  
+      break;
+    default:
+      imgXObj->dictSet("ColorSpace", obj.initName("DeviceGray"));	  
+      break;
+  }
+
+  unsigned long length = cinfo.output_width*cinfo.output_height*cinfo.num_components;
+  imgXObj->dictSet("Length", obj.initInt(length));
+  
+  MemStream *imgStream = new MemStream (raw_image, 0, length, imgXObj);
+  imgStream->setNeedFree(gTrue);
+  return imgStream;
+  #else
+    fclose(f);
+    error(-1, "Jpeg support is not there");
+    return NULL;
+  #endif
+}
+
+GBool Annot::setAppearanceFromFile(GooString *img_file) {
+  if (img_file == NULL) { // checking for safe
+    error(-1, "No image file");
+    return gFalse;
+  }
+  
+  const char* file = img_file->getCString();  
+  
+  FILE *fp;
+  if (!(fp = fopen(file, "rb"))) {
+    error(-1, "Couldn't open file: %s", file);
+    return gFalse;
+  }
+
+  unsigned char h[10];
+  size_t header_size = fread(h, 1, 10, fp);   
+
+  if (header_size < 10) { 
+    error(-1, "'%s' has less than 10 bytes", file);
+    return gFalse;
+  }
+
+  if (fseek(fp, 0, SEEK_SET)) {
+    error(-1, "fseek() failed");
+    return gFalse;
+  }
+
+  Ref imgRef;
+  Object obj1, obj2, obj3, obj4, imgXObj;
+  imgXObj.initDict(xref);
+  imgXObj.dictSet("Type", obj1.initName("XObject"));	  
+  imgXObj.dictSet("Subtype", obj1.initName("Image"));	  
+
+  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 (fp, &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 (fp, &imgXObj);
+  else {
+    error(-1, "Image format cannot be supported, only png/jpeg\n");
+    return gFalse;
+  }
+  
+  if (imgStream) {
+    obj1.initStream(imgStream);
+    appearBuf = new GooString("/Im1 Do");	
+    double bbox[4];
+    bbox[0] = bbox[1] = 0;
+    bbox[2] = bbox[3] = 1; 
+    createResourcesDict("Im1", &obj1, "GS0", 1.0, NULL, &obj2); 
+    createForm(bbox, gFalse, &obj2, &obj1);
+
+    Ref appRef = xref->addIndirectObject(&obj1);
+    obj2.initDict(xref);
+    obj2.dictSet("N", obj1.initRef(appRef.num, appRef.gen));
+    update("AP", &obj2);
+
+    obj2.initStream(imgStream);
+    createResourcesDict("Im1", &obj2, "GS0", 1.0, NULL, &obj1); 
+    createForm(bbox, gFalse, &obj1, &obj2);
+    delete appearBuf;
+
+    appRef = xref->addIndirectObject(&obj2);
+    obj1.initDict(xref); // MK dictionary
+    obj1.dictSet("I", obj2.initRef(appRef.num, appRef.gen));
+    update("MK", &obj1); 
+  }
+}
+
 //------------------------------------------------------------------------
 // AnnotPopup
 //------------------------------------------------------------------------
Index: poppler-0.16.2/glib/poppler-annot.cc
===================================================================
--- poppler-0.16.2/glib/poppler-annot.cc	(revision 14)
+++ poppler-0.16.2/glib/poppler-annot.cc	(working copy)
@@ -455,6 +455,26 @@
 }
 
 /**
+ * poppler_annot_set_appearance_from_file:
+ * @poppler_annot: a #PopplerAnnot
+ * @img_file: an image file to set as appearance in annots rectangle area
+ *
+ * Sets the appearance of @poppler_annot 
+ *
+ * Since: 0.18
+ **/
+gboolean
+poppler_annot_set_appearance_from_file (PopplerAnnot *annot,
+			 	         const gchar  *img_file)
+{
+  g_return_val_if_fail (annot != NULL, FALSE);
+  g_return_val_if_fail (img_file != NULL, FALSE);
+
+  GooString *file = new GooString(img_file);
+  annot->annot->setAppearanceFromFile(file);
+}
+
+/**
  * poppler_annot_get_name:
  * @poppler_annot: a #PopplerAnnot
  *
Index: poppler-0.16.2/glib/poppler-annot.h
===================================================================
--- poppler-0.16.2/glib/poppler-annot.h	(revision 14)
+++ poppler-0.16.2/glib/poppler-annot.h	(working copy)
@@ -159,6 +159,8 @@
 gchar                        *poppler_annot_get_contents                       (PopplerAnnot *poppler_annot);
 void                          poppler_annot_set_contents                       (PopplerAnnot *poppler_annot,
 										const gchar  *contents);
+gboolean                      poppler_annot_set_appearance_from_file           (PopplerAnnot *poppler_annot,
+										 const gchar  *img_file);
 gchar                        *poppler_annot_get_name                           (PopplerAnnot *poppler_annot);
 gchar                        *poppler_annot_get_modified                       (PopplerAnnot *poppler_annot);
 PopplerAnnotFlag              poppler_annot_get_flags                          (PopplerAnnot *poppler_annot);
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to