bitblt_g4.c

Wed, 05 Mar 2003 20:39:50 +0000

author
eric
date
Wed, 05 Mar 2003 20:39:50 +0000
changeset 77
544fff830581
parent 73
6e306105c128
child 78
74b6b230f85d
permissions
-rw-r--r--

added count field to struct pdf_bookmark.

     1 /*
     2  * t2p: Create a PDF file from the contents of one or more TIFF
     3  *      bilevel image files.  The images in the resulting PDF file
     4  *      will be compressed using ITU-T T.6 (G4) fax encoding.
     5  *
     6  * PDF routines
     7  * $Id: bitblt_g4.c,v 1.7 2003/03/04 17:58:31 eric Exp $
     8  * Copyright 2001, 2002, 2003 Eric Smith <eric@brouhaha.com>
     9  *
    10  * This program is free software; you can redistribute it and/or modify
    11  * it under the terms of the GNU General Public License version 2 as
    12  * published by the Free Software Foundation.  Note that permission is
    13  * not granted to redistribute this program under the terms of any
    14  * other version of the General Public License.
    15  *
    16  * This program is distributed in the hope that it will be useful,
    17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19  * GNU General Public License for more details.
    20  *
    21  * You should have received a copy of the GNU General Public License
    22  * along with this program; if not, write to the Free Software
    23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
    24  */
    27 #include <stdbool.h>
    28 #include <stdint.h>
    29 #include <stdio.h>
    30 #include <stdlib.h>
    31 #include <string.h>
    34 #include "bitblt.h"
    35 #include "pdf.h"
    36 #include "pdf_util.h"
    37 #include "pdf_prim.h"
    38 #include "pdf_private.h"
    41 #include "pdf_g4_tables.h"
    44 #define SWAP(type,a,b) do { type temp; temp = a; a = b; b = temp; } while (0)
    47 struct pdf_g4_image
    48 {
    49   double width, height;
    50   double x, y;
    51   double r, g, b;  /* fill color, only for ImageMask */
    52   unsigned long Columns;
    53   unsigned long Rows;
    54   bool ImageMask;
    55   bool BlackIs1;
    56   Bitmap *bitmap;
    57   char XObject_name [4];
    58 };
    61 char pdf_new_XObject (pdf_page_handle pdf_page, struct pdf_obj *ind_ref)
    62 {
    63   char XObject_name [4] = "Im ";
    65   XObject_name [2] = ++pdf_page->last_XObject_name;
    67   if (! pdf_page->XObject_dict)
    68     {
    69       pdf_page->XObject_dict = pdf_new_obj (PT_DICTIONARY);
    70       pdf_set_dict_entry (pdf_page->resources, "XObject", pdf_page->XObject_dict);
    71     }
    73   pdf_set_dict_entry (pdf_page->XObject_dict, & XObject_name [0], ind_ref);
    75   return (pdf_page->last_XObject_name);
    76 }
    79 void pdf_write_g4_content_callback (pdf_file_handle pdf_file,
    80 				    struct pdf_obj *stream,
    81 				    void *app_data)
    82 {
    83   struct pdf_g4_image *image = app_data;
    85   /* transformation matrix is: width 0 0 height x y cm */
    86   pdf_stream_printf (pdf_file, stream, "q %g 0 0 %g %g %g cm ",
    87 		     image->width, image->height,
    88 		     image->x, image->y);
    89   if (image->ImageMask)
    90     pdf_stream_printf (pdf_file, stream, "%g %g %g rg ",
    91 		       image->r, image->g, image->b);
    93   pdf_stream_printf (pdf_file, stream, "/%s Do Q\r\n",
    94 		     image->XObject_name);
    95 }
    98 static void pdf_g4_encode_horizontal_run (pdf_file_handle pdf_file,
    99 					  struct pdf_obj *stream,
   100 					  bool black,
   101 					  uint32_t run_length)
   102 {
   103   uint32_t i;
   105   while (run_length >= 2560)
   106     {
   107       pdf_stream_write_bits (pdf_file, stream, 12, 0x01f);
   108       run_length -= 2560;
   109     }
   111   if (run_length >= 1792)
   112     {
   113       i = (run_length - 1792) >> 6;
   114       pdf_stream_write_bits (pdf_file, stream,
   115 			     g4_long_makeup_code [i].count,
   116 			     g4_long_makeup_code [i].bits);
   117       run_length -= (1792 + (i << 6));
   118     }
   119   else if (run_length >= 64)
   120     {
   121       i = (run_length >> 6) - 1;
   122       pdf_stream_write_bits (pdf_file, stream,
   123 			     g4_makeup_code [black] [i].count,
   124 			     g4_makeup_code [black] [i].bits);
   125       run_length -= (i + 1) << 6;
   126     }
   128   pdf_stream_write_bits (pdf_file, stream,
   129 			 g4_h_code [black] [run_length].count,
   130 			 g4_h_code [black] [run_length].bits);
   131 }
   134 uint32_t find_transition (uint8_t *data,
   135 			  uint32_t pos,
   136 			  uint32_t width)
   137 {
   138   if (! data)
   139     return (width);
   140   return (0);  /* $$$ */
   141 }
   144 static void pdf_g4_encode_row (pdf_file_handle pdf_file,
   145 			       struct pdf_obj *stream,
   146 			       uint32_t width,
   147 			       uint8_t *ref,
   148 			       uint8_t *row)
   149 {
   150   int a0, a1, a2;
   151   int b1, b2;
   153   a0 = -1;
   155   while (a0 < width)
   156     {
   157       /* find a1, a2 */
   158       a1 = find_transition (row, a0, width);
   159       a2 = find_transition (row, a1, width);
   161       /* find b1, b2 */
   162       b1 = find_transition (ref, a0, width);
   163       if (0) /* $$$ b1 color = a0 color */
   164 	b1 = find_transition (ref, b1, width);
   165       b2 = find_transition (ref, b2, width);
   167       if (b2 < a1)
   168 	{
   169 	  /* pass mode - 0001 */
   170 	  pdf_stream_write_bits (pdf_file, stream, 4, 0x1);
   171 	  a0 = b2;
   172 	}
   173       else if (abs (a1 - b1) <= 3)
   174 	{
   175 	  /* vertical mode */
   176 	  pdf_stream_write_bits (pdf_file, stream,
   177 				 g4_vert_code [3 + a1 - b1].count,
   178 				 g4_vert_code [3 + a1 - b1].bits);
   179 	  a0 = a1;
   180 	}
   181       else
   182 	{
   183 	  /* horizontal mode - 001 */
   184 	  pdf_stream_write_bits (pdf_file, stream, 3, 0x1);
   185 	  pdf_g4_encode_horizontal_run (pdf_file, stream,
   186 					0 /* $$$ color (a0) */, a1 - a0);
   187 	  pdf_g4_encode_horizontal_run (pdf_file, stream,
   188 					1 /* $$$ color (a1) */, a2 - a1);
   189 	  a0 = a2;
   190 	}
   191     }
   192 }
   195 void pdf_write_g4_fax_image_callback (pdf_file_handle pdf_file,
   196 				      struct pdf_obj *stream,
   197 				      void *app_data)
   198 {
   199   struct pdf_g4_image *image = app_data;
   201   uint32_t row;
   203   word_type *ref_line = NULL;  /* reference (previous) row */
   204   word_type *line = image->bitmap->bits;
   206   for (row = image->bitmap->rect.min.y;
   207        row < image->bitmap->rect.max.y;
   208        row++)
   209     {
   210       pdf_g4_encode_row (pdf_file, stream, image->Columns,
   211 			 (uint8_t *) ref_line,
   212 			 (uint8_t *) line);
   213       ref_line = line;
   214       line += image->bitmap->row_words;
   215     }
   218   /* write EOFB code */
   219   pdf_stream_write_bits (pdf_file, stream, 24, 0x001001);
   221   pdf_stream_flush_bits (pdf_file, stream);
   222 }
   225 void pdf_write_g4_fax_image (pdf_page_handle pdf_page,
   226 			     double x,
   227 			     double y,
   228 			     double width,
   229 			     double height,
   230 			     Bitmap *bitmap,
   231 			     bool ImageMask,
   232 			     double r, /* RGB fill color, only for ImageMask */
   233 			     double g,
   234 			     double b,
   235 			     bool BlackIs1)          /* boolean, typ. false */
   236 {
   237   struct pdf_g4_image *image;
   239   struct pdf_obj *stream;
   240   struct pdf_obj *stream_dict;
   241   struct pdf_obj *decode_parms;
   243   struct pdf_obj *content_stream;
   245   image = pdf_calloc (1, sizeof (struct pdf_g4_image));
   247   image->width = width;
   248   image->height = height;
   249   image->x = x;
   250   image->y = y;
   251   image->r = r;
   252   image->g = g;
   253   image->b = b;
   255   image->bitmap = bitmap;
   256   image->Columns = bitmap->rect.max.x - bitmap->rect.min.x;
   257   image->Rows = bitmap->rect.max.y - bitmap->rect.min.y;
   258   image->ImageMask = ImageMask;
   259   image->BlackIs1 = BlackIs1;
   261   stream_dict = pdf_new_obj (PT_DICTIONARY);
   263   stream = pdf_new_ind_ref (pdf_page->pdf_file,
   264 			    pdf_new_stream (pdf_page->pdf_file,
   265 					    stream_dict,
   266 					    & pdf_write_g4_fax_image_callback,
   267 					    image));
   269   strcpy (& image->XObject_name [0], "Im ");
   270   image->XObject_name [2] = pdf_new_XObject (pdf_page, stream);
   272   pdf_set_dict_entry (stream_dict, "Type",    pdf_new_name ("XObject"));
   273   pdf_set_dict_entry (stream_dict, "Subtype", pdf_new_name ("Image"));
   274   pdf_set_dict_entry (stream_dict, "Name",    pdf_new_name (& image->XObject_name [0]));
   275   pdf_set_dict_entry (stream_dict, "Width",   pdf_new_integer (image->Columns));
   276   pdf_set_dict_entry (stream_dict, "Height",  pdf_new_integer (image->Rows));
   277   pdf_set_dict_entry (stream_dict, "BitsPerComponent", pdf_new_integer (1));
   278   if (ImageMask)
   279     pdf_set_dict_entry (stream_dict, "ImageMask", pdf_new_bool (ImageMask));
   280   else
   281     pdf_set_dict_entry (stream_dict, "ColorSpace", pdf_new_name ("DeviceGray"));
   283   decode_parms = pdf_new_obj (PT_DICTIONARY);
   285   pdf_set_dict_entry (decode_parms,
   286 		      "K",
   287 		      pdf_new_integer (-1));
   289   pdf_set_dict_entry (decode_parms,
   290 		      "Columns",
   291 		      pdf_new_integer (image->Columns));
   293   pdf_set_dict_entry (decode_parms,
   294 		      "Rows",
   295 		      pdf_new_integer (image->Rows));
   297   if (BlackIs1)
   298     pdf_set_dict_entry (decode_parms,
   299 			"BlackIs1",
   300 			pdf_new_bool (BlackIs1));
   302   pdf_stream_add_filter (stream, "CCITTFaxDecode", decode_parms);
   304   /* the following will write the stream, using our callback function to
   305      get the actual data */
   306   pdf_write_ind_obj (pdf_page->pdf_file, stream);
   308   content_stream = pdf_new_ind_ref (pdf_page->pdf_file,
   309 				    pdf_new_stream (pdf_page->pdf_file,
   310 						    pdf_new_obj (PT_DICTIONARY),
   311 						    & pdf_write_g4_content_callback,
   312 						    image));
   314   pdf_set_dict_entry (pdf_page->page_dict, "Contents", content_stream);
   316   pdf_write_ind_obj (pdf_page->pdf_file, content_stream);
   317 }