/*
Copyright (c) 2000-2010, Dirk Krause
All rights reserved.

Redistribution and use in source and binary forms,
with or without modification, are permitted provided
that the following conditions are met:

* Redistributions of source code must retain the above
  copyright notice, this list of conditions and the
  following disclaimer.
* Redistributions in binary form must reproduce the above 
  opyright notice, this list of conditions and the following
  disclaimer in the documentation and/or other materials
  provided with the distribution.
* Neither the name of the Dirk Krause nor the names of
  contributors may be used to endorse or promote
  products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/



/**	@file	b2pdf.c
	Conversion to PDF.
*/



/** Inside the b2pdf.c module. */
#define B2PDF_C		1
#include "bmepsi.h"
#include "bmeps.h"




#line 53 "b2pdf.ctr"




/**	Keywords used for output.
*/
static char *kw[] = {
  /*  0 */	"\r\n",
  /*  1 */	" ",
  /*  2 */	"%PDF-",
  /*  3 */	"1.2",
  /*  4 */	"1.3",
  /*  5 */	"1.4",
  /*  6 */	"<<",
  /*  7 */	">>",
  /*  8 */	"obj",
  /*  9 */	"endobj",
  /* 10 */	"[",
  /* 11 */	"]",
  /* 12 */	"xref",
  /* 13 */	"trailer",
  /* 14 */	"startxref",
  /* 15 */	"%%EOF",
  /* 16 */	"0000000000 65535 f",
  /* 17 */	"%010lu 00000 n",
  /* 18 */	"/Size",
  /* 19 */	"/Info 1 0 R /Root 2 0 R",
  /* 20 */	"/Producer (bmeps)",
  /* 21 */	"/Type /Catalog",
  /* 22 */	"/Pages",
  /* 23 */	"R",
  /* 24 */	"/Type /Pages",
  /* 25 */	"/Count",
  /* 26 */	"/Kids",
  /* 27 */	"/Type /Page",
  /* 28 */	"/MediaBox",
  /* 29 */	"/Parent",
  /* 30 */	"/Resources",
  /* 31 */	"/ProcSet",
  /* 32 */	"/XObject",
  /* 33 */	"/PDF",
  /* 34 */	"/ImageC",
  /* 35 */	"/ImageB",
  /* 36 */	"/Contents",
  /* 37 */	"/X",
  /* 38 */	"/Length",
  /* 39 */	"stream",
  /* 40 */	"endstream",
  /* 41 */	"/ASCIIHexDecode",
  /* 42 */	"/ASCII85Decode",
  /* 43 */	"/LZWDecode",		/* reserved for future use */
  /* 44 */	"/FlateDecode",
  /* 45 */	"/RunLengthDecode",
  /* 46 */	"/DCTDecode",
  /* 47 */	"/Type /XObject",
  /* 48 */	"/Subtype /Image",
  /* 49 */	"/Width",
  /* 50 */	"/Height",
  /* 51 */	"/ColorSpace",
  /* 52 */	"/DeviceRGB",
  /* 53 */	"/DeviceGray",
  /* 54 */	"/DeviceCMYK",
  /* 55 */	"/BitsPerComponent",
  /* 56 */	"/Length",
  /* 57 */	"/Filter",
  /* 58 */	"/Interpolate",
  /* 59 */	"true",
  /* 60 */	"false",
  /* 61 */	"/SMask",
  /* 62 */	"/Mask",
  /* 63 */	"/OpenAction",
  /* 64 */	"/Fit",
  /* 65 */	"/FitH",
  /* 66 */	"/FitV 0",
  /* 67 */	"q",
  /* 68 */	"Q",
  /* 69 */	"g",	/* gray for fill operations */
  /* 70 */	"rg",	/* set rgb for fill operations */
  /* 71 */	"m",	/* start path and moveto */
  /* 72 */	"l",	/* lineto */
  /* 73 */	"h",	/* closepath */
  /* 74 */	"f",	/* fill */
  /* 75 */	"re",	/* rectangle */
  /* 76 */	"/Type /Outlines",
  /* 77 */	"/First",
  /* 78 */	"/Last",
  /* 79 */	"/Title",
  /* 80 */	"/Prev",
  /* 81 */	"/Next",
  /* 82 */	"/Dest",
  /* 83 */	"(",
  /* 84 */	")",
  /* 85 */	"/Outlines",
  /* 86 */	"/Decode [1 0 1 0 1 0 1 0]",
  /* 87 */	"/Group <</S /Transparency /I true /CS /DeviceRGB>>",
  /* 88 */	"/Predictor ",
  /* 89 */	"/DecodeParms",
  /* 90 */	"null",
  /* 91 */	"/Colors",
  /* 92 */	"/Columns",
  /* 93 */	"3",
  /* 94 */	"1",
  NULL
};

/** Number of elements in kw.
*/
static size_t sz_kw = sizeof(kw)/sizeof(PCHAR);



/** Open a dictionary.
*/
#define pdf_open_dictionary(bj) kw_out(bj, 6)

/** Close a dictionary.
*/
#define pdf_close_dictionary(bj) kw_out(bj, 7)



/**	Print one keyword to output stream.
	@param	bj	Bmeps job.
	@param	i	Index of keyword to print.
*/
static
void
kw_out DK_P2(BJ *,bj, size_t,i)
{
  if(i < sz_kw) {
    if(bj) {
      if(bj->os) {
        dkstream_puts(bj->os, kw[i]);
      }
    }
  }
}



/**	Write reference to another object.
	@param	bj	Bmeps job.
	@param	n	Index of object to reference.
*/
static
void
pdf_write_reference DK_P2(BJ *,bj, unsigned long,n)
{
  dkstream_puts_ul(bj->os, n);
  kw_out(bj, 1);
  dkstream_puts_ul(bj->os, 0UL);
  kw_out(bj, 1);
  kw_out(bj, 23);
}



/**	Begin PDF object.
	@param	bj	Bmeps job.
	@param	objno	Number of new object.
*/
static
int
pdf_begin_object DK_P2(BJ *,bj, unsigned long,objno)
{
  int back = 0;		/* Function result. */
  PDFOBJPOS *pop;	/* PDF object position. */
  pop = dk_new(PDFOBJPOS,1);
  if(pop) {
    pop->objno = objno;
    pop->pos = dkstream_get_bytes_written(bj->os);
    if(dksto_add(bj->pdfobjs, (void *)pop)) {
      dkstream_puts_ul(bj->os, objno);
      kw_out(bj, 1);
      dkstream_puts_ul(bj->os, 0UL);
      kw_out(bj, 1); kw_out(bj, 8); kw_out(bj, 0);
      back = 1;
    } else {
      bmeps_tool_error_memory(bj); bj->exval = 1;
    }
  } else {
    bmeps_tool_error_memory(bj); bj->exval = 1;
  }
  return back;
}



/**	End PDF object.
	@param	bj	Bmeps job.
*/
static
void
pdf_end_object DK_P1(BJ *,bj)
{
  kw_out(bj, 9); kw_out(bj, 0);
}



/**	Compare two PDF object positions.
	@param	l	Pointer to left object position.
	@param	r	Pointer to right object position.
	@param	cr	Comparison criteria.
	@return	The comparison result.
*/
static
int
compare_obj_pos DK_P3(void *,l, void *,r, int,cr)
{
  int back = 0;
  PDFOBJPOS *ptrl, *ptrr;
  unsigned long *ulptr;
  if(l) {
    if(r) {
      ptrl = (PDFOBJPOS *)l; ptrr = (PDFOBJPOS *)r;
      ulptr = (unsigned long *)r;
      switch(cr) {
        case 1: {
	  if(ptrl->objno > *ulptr) back = 1;
	  else {
	    if(ptrl->objno < *ulptr) back = -1;
	  }
	} break;
	default: {
          if(ptrl->objno > ptrr->objno) back = 1;
          else {
            if(ptrl->objno < ptrr->objno) back = -1;
          }
	} break;
      }
    } else  back = 1;
  } else {
    if(r) back = -1;
  }
  return back;
}



/**	Start PDF file.
	@param	bj	Bmeps job
	@param	how	Ignored.
*/
static
void
pdf_file_start DK_P2(BJ *,bj, int,how)
{
  long i = 0;
  dkbif_set_frame(bj->bif, bj->frame_s);
  bmeps_tool_calculate_areas(bj);
  kw_out(bj, 2);
  switch((bj->bo)->l) {
    case BMEPS_PDF_LEVEL_12: { kw_out(bj, 3); } break;
    case BMEPS_PDF_LEVEL_13: { kw_out(bj, 4); } break;
    default: { kw_out(bj, 5); } break;
  }
  kw_out(bj, 0);
  i += pdf_begin_object(bj, bj->nexto);
  bj->nexto += 1UL;
  pdf_open_dictionary(bj); kw_out(bj, 0);
  kw_out(bj, 20); kw_out(bj, 0);
  pdf_close_dictionary(bj); kw_out(bj, 0);
  pdf_end_object(bj);
  i += pdf_begin_object(bj, bj->nexto); bj->nexto += 1UL;
  bj->psp = bj->nexto;
  pdf_open_dictionary(bj); kw_out(bj, 0);
  kw_out(bj, 21); kw_out(bj, 0);
  if(bj->frame_e > bj->frame_s) {
    /* reserve object numbers for outline */
    kw_out(bj, 85); kw_out(bj, 1);
    bj->olo = bj->nexto;
    pdf_write_reference(bj, bj->olo); kw_out(bj, 0);
    bj->psp += (1UL + bj->frame_n);
  }
  
  kw_out(bj, 22); kw_out(bj, 1);
  dkstream_puts_ul(bj->os, bj->psp);
  kw_out(bj, 1);
  dkstream_puts_ul(bj->os, 0UL); kw_out(bj, 1);
  kw_out(bj, 23); kw_out(bj, 0);
  if((bj->bo)->pdfopt & BMEPS_PDFOPT_FIT_MASK) {
    kw_out(bj, 63); kw_out(bj, 1); kw_out(bj, 10); kw_out(bj, 1);
    pdf_write_reference(bj, (bj->psp + 1UL)); kw_out(bj, 1);
    switch((int)((bj->bo)->pdfopt & BMEPS_PDFOPT_FIT_MASK)) {
      case (int)BMEPS_PDFOPT_FIT_WIDTH: {
        kw_out(bj, 65); kw_out(bj, 1);
	dkstream_puts_ul(bj->os, (bj->trans).bb.y1);
      } break;
      case (int)BMEPS_PDFOPT_FIT_HEIGHT: {
        kw_out(bj, 66);
      } break;
      case (int)BMEPS_PDFOPT_FIT_PAGE: {
        kw_out(bj, 64);
      } break;
    }
    kw_out(bj, 1); kw_out(bj, 11); kw_out(bj, 0);
  }
  pdf_close_dictionary(bj); kw_out(bj, 0);
  pdf_end_object(bj);
  if(bj->frame_e > bj->frame_s) {
    /* create outline objects */
    pdf_begin_object(bj, bj->nexto); bj->nexto += 1UL;
    pdf_open_dictionary(bj); kw_out(bj, 0);
    kw_out(bj, 76); kw_out(bj, 0);
    kw_out(bj, 77); kw_out(bj, 1);
    pdf_write_reference(bj, bj->nexto); kw_out(bj, 0);
    kw_out(bj, 78); kw_out(bj, 1);
    pdf_write_reference(bj, (bj->nexto + bj->frame_n - 1UL)); kw_out(bj, 0);
    pdf_close_dictionary(bj); kw_out(bj, 0);
    pdf_end_object(bj);
    for(i = 0UL; i < bj->frame_n; i++) {
      dkbif_set_frame(bj->bif, (bj->frame_s + i));
      bmeps_tool_calculate_areas(bj);
      pdf_begin_object(bj, bj->nexto); bj->nexto += 1UL;
      pdf_open_dictionary(bj); kw_out(bj, 0);
      kw_out(bj, 79); kw_out(bj, 1);
      kw_out(bj, 83);
      dkstream_puts_ul(bj->os, i+1UL);
      kw_out(bj, 84); kw_out(bj, 0);
      kw_out(bj, 29); kw_out(bj, 1);
      pdf_write_reference(bj, bj->olo); kw_out(bj, 0);
      if(i != 0UL) {
        kw_out(bj, 80); kw_out(bj, 1);
	pdf_write_reference(bj, (bj->nexto - 2UL));
	kw_out(bj, 0);
      }
      if(i != (bj->frame_n - 1L)) {
        kw_out(bj, 81); kw_out(bj, 1);
	pdf_write_reference(bj, bj->nexto);
	kw_out(bj, 0);
      }
      kw_out(bj, 82); kw_out(bj, 1);
      kw_out(bj, 10);
      pdf_write_reference(bj, (bj->psp + 1UL + i));
      kw_out(bj, 65); kw_out(bj, 1);
      dkstream_puts_ul(bj->os, (bj->trans).bb.y1);
      kw_out(bj, 11); kw_out(bj, 0);
      pdf_close_dictionary(bj); kw_out(bj, 0);
      pdf_end_object(bj);
    }
    /* set object number to start pages */
    bj->nexto = bj->psp;
  }
  i += pdf_begin_object(bj, bj->nexto); bj->nexto += 1UL;
  pdf_open_dictionary(bj); kw_out(bj, 0);
  kw_out(bj, 24); kw_out(bj, 0);
  kw_out(bj, 25); kw_out(bj, 1);
  dkstream_puts_ul(bj->os, bj->frame_n); kw_out(bj, 0);
  kw_out(bj, 26); kw_out(bj, 1);
  kw_out(bj, 10); kw_out(bj, 0);
  for(i = 0; i < bj->frame_n; i++) {
    dkstream_puts_ul(bj->os, (bj->nexto + i));
    kw_out(bj, 1);
    dkstream_puts_ul(bj->os, 0UL); kw_out(bj, 1);
    kw_out(bj, 23); kw_out(bj, 0);
  }
  kw_out(bj, 11); kw_out(bj, 0);
  pdf_close_dictionary(bj); kw_out(bj, 0);
  pdf_end_object(bj);
}



/**	Transfer entire file.
	@param	bj	Bmeps job.
	@param	os	Output stream.
	@param	f	Input file.
*/
static
void
transfer_entire_file DK_P3(BJ *,bj, dk_stream_t *,os, FILE *,f)
{
  char buffer[512];
  size_t bs, bu, br;
  int cc = 0, write_error = 0;
  
  bs = sizeof(buffer);
  cc = 1;
  while(cc) {
    br = fread(buffer,1,sizeof(buffer),f);
    if(br > 0) {
      bu = dkstream_write(os, buffer, br);
      if(bu < br) {
	cc = 0; write_error = 1;
      }
    } else {
      cc = 0;
    }
  }
  if(write_error) {
    bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 53);
    bj->exval = 1;
  }
  
}



/**	Transfer a file to a stream.
	@param	os	Output stream.
	@param	f	Input file.
	@param	fs	File size.
*/
static
void
transfer_file_to_stream DK_P3(dk_stream_t *,os, FILE *,f, unsigned long,fs)
{
  char buffer[512];
  size_t bs, bu, br;
  unsigned long bytes_to_handle;
  int cc;
  
  bs = sizeof(buffer); cc = 1; bytes_to_handle = fs;
  while(cc) {
    if(bytes_to_handle > 0UL) {
      if(bytes_to_handle >= (unsigned long)bs) {
        bu = bs;
      } else {
        bu = (size_t)bytes_to_handle;
      }
      br = fread(buffer, 1, bu, f);
      if(br > 0) {
        dkstream_write(os, buffer, br);
	bytes_to_handle -= (unsigned long)br;
      } else {
        cc = 0;
      }
    } else {
      cc = 0;
    }
  }
  
}



/**	Calculate value to pass to flate compression for PNG sub predictor.
	@param	v	Current value.
	@param	v1	Value one point to the left.
	@return	Difference v - v1.
*/
static
unsigned char
png_sub DK_P2(unsigned char,v, unsigned char,v1) {
  unsigned char back;
  back = v - v1;
  return back;
}



/**	Calculate value to pass to flate compression for PNG up predictor.
	@param	v	 Current value.
	@param	v2	Value one row up.
	@return	Difference v - v2.
*/
static
unsigned char
png_up DK_P2(unsigned char,v, unsigned char,v2) {
  unsigned char back;
  back = v - v2;
  return back;
}


/**	Calculate value to pass to flate compression for PNG avg predictor.
	@param	v	Current value.
	@param	v1	Value one point to the left.
	@param	v2	Value one row up.
	@return	Difference v - (v1 + v2)/2.
*/
static
unsigned char
png_avg DK_P3(unsigned char,v, unsigned char,v1, unsigned char,v2) {
  unsigned char back;
  back = v
       - (unsigned char)((((unsigned short)v1 + (unsigned short)v2) / 2)
         & 0x00FF);
  return back;
}



/**	Caluclate Paeth prediction value.
	@param	v1	Value one point to the left.
	@param	v2	Value one row up.
	@param	v3	Value one row up one point to the left.
	@return	Predicted value.
*/
static
unsigned char
png_pp DK_P3(unsigned char,v1, unsigned char,v2, unsigned char,v3) {
  unsigned char back;
  short p, pa, pb, pc;
  p = (short)v1 + (short)v2 - (short)v3;
  pa = p - (short)v1;
  pb = p - (short)v2;
  pc = p - (short)v3;
  if(pa < 0) pa = 0 - pa;
  if(pb < 0) pb = 0 - pb;
  if(pc < 0) pc = 0 - pc;
  if((pa <= pb) && (pa <= pc)) {
    back = v1;
  } else {
    if(pb <= pc) {
      back = v2;
    } else {
      back = v3;
    }
  }
  return back;
}



/**	Calculate value to pass to flate compression for PNG Paeth predictor.
	@param	v	Current value.
	@param	v1	Value one point to the left.
	@param	v2	Value one row up.
	@param	v3	Value one row up one point to the left.
	@return	Difference v - paeth(v1,v2,v3).
*/
static
unsigned char
png_paeth DK_P4(unsigned char,v, unsigned char,v1, unsigned char,v2, unsigned char,v3)
{
  unsigned char back;
  back = v - png_pp(v1,v2,v3);
  return back;
}



/**	Retrieve high byte from 16-bit value.
	@param	v	16-bit value.
	@return	Higher byte.
*/
static
unsigned char hb DK_P1(unsigned short, v) {
  unsigned char back;
  back = (unsigned char)((v >> 8) & 0x00FF);
  return back;
}



/**	Retrieve low byte from 16-bit value.
	@param	v	16-bit value.
	@return	Lower byte.
*/
static
unsigned char
lb DK_P1(unsigned short,v) {
  unsigned char back;
  back = (unsigned char)(v & 0x00FF);
  return back;
}



/**	Create word from two bytes.
	@param	h	Higher byte.
	@param	l	Lower byte.
	@return	Word constructed from the two bytes.
*/
static
unsigned short
mw DK_P2(unsigned char,h, unsigned char,l) {
  unsigned short back;
  back = ((((unsigned short)h) << 8) & 0xFF00) | (((unsigned short)l) & 0x00FF);
  return back;
}



/**	Create objects structure for normal conversion.
	@param	bj	Bmeps job.
*/
static
void
pdf_file_objects_normally DK_P1(BJ *,bj)
{
  unsigned char use_mask_or_alpha;	/* flag to indicate mask/alpha usage */
  unsigned short bpcs;			/* bits per component */
  unsigned long bpc;			/* also bits per component */
  unsigned char c;			/* one byte of output for 8-bit input */
  unsigned long psp;			/* pages start position (object number) */
  unsigned long csp;			/* contents start position (object number) */
  unsigned long xsp;			/* xobjects start position (object number) */
  unsigned long i;			/* */
  unsigned long w;			/* width of output image */
  unsigned long h;			/* height of output image */
  unsigned long origw;			/* width of input image */
  unsigned long origh;			/* height of input image */
  unsigned long filesize;		/* file size of temporary file */
  unsigned long x;			/* x position of source pixel */
  unsigned long y;			/* y position of source pixel */
  unsigned long iy;			/* y position of destination pixel */
  unsigned long j;			/* x position of destination pixel */
  long fno;				/* number of current frame */
  dk_stat_t stbuf;			/* stat buffer to obtain file info */
  int number_of_filters = 0;		/* number of filters for encoding */
  int ch = 0;				/* number of channels in input file */
  int dummy = 0;			/* dummy variable for fopen failure */
  int data_ok = 0;			/* indicate output data file ok */
  int mask_ok = 0;			/* indicate mask data file ok */
  dk_stream_t *ofs1 = NULL;		/* unfiltered output stream */
  dk_stream_t *ofs2 = NULL;		/* filter output stream */
  dk_bitshift_t *obs = NULL;		/* output bit shifter */
  FILE *gfile = NULL;			/* temporary file */
  size_t nf;				/* number of next filter cell to set */
  
  fno = bj->frame_s;
  psp = bj->nexto;
  csp = psp + bj->frame_n;
  xsp = csp + bj->frame_n;
  i = 0UL;
  bj->nexto = xsp + bj->frame_n;
  while(fno <= bj->frame_e) {
    
    use_mask_or_alpha = 0x00;
    dkmem_cpy(bj->bo2, bj->bo, sizeof(BO));
    
    if(dkbif_set_frame(bj->bif, fno)) {
      
      data_ok = 0; mask_ok = 0;
      bmeps_tool_calculate_areas(bj);
      
      origw = w = dkbif_get_width(bj->bif);
      origh = h = dkbif_get_height(bj->bif);
      if((bj->trans).must_rotate) {
        w = origh; h = origw;
      }
      bpcs = dkbif_get_bits_per_component(bj->bif);
      bpcs = bmeps_tool_pdf_output_bits(bpcs);
      bpc  = (unsigned long)bpcs;
      switch(dkbif_get_channels(bj->bif)) {
        case 1: case 2: {
	  (bj->bo2)->opt &= (~(BMEPS_OPT_COLOR_OUTPUT));
	} break;
      }
      dkbif_set_bits_per_component(bj->bif, bpcs);
      
      switch(dkbif_get_channels(bj->bif)) {
        case 2: case 4: {	
	  if((bj->bo2)->opt & BMEPS_OPT_TRANSFER_ALPHA) {
	    
	    use_mask_or_alpha = 0x01;
	  } else {
	    
	    if((bj->bo2)->opt & BMEPS_OPT_IMAGE_MASK) {
	      
	      dkbif_set_mask_trigger_level(bj->bif, (bj->bo2)->mtl);
	      use_mask_or_alpha = 0x01;
	    }
	    if((bj->bo2)->opt & BMEPS_OPT_ALPHA_MIX) {
	      
	      dkbif_set_mixing(bj->bif,
	        (((bj->bo2)->opt & BMEPS_OPT_PREFER_SPEC_BG) ? 2 : 1),
	        (bj->bo2)->dbgr, (bj->bo2)->dbgg, (bj->bo2)->dbgb
	      );
	    }
	  }
	} break;
	default: {		
	  (bj->bo2)->opt &= (~(BMEPS_OPT_IMAGE_MASK));
	  (bj->bo2)->opt &= (~(BMEPS_OPT_ALPHA_MIX));
	  (bj->bo2)->opt &= (~(BMEPS_OPT_PREFER_SPEC_BG));
	  (bj->bo2)->opt &= (~(BMEPS_OPT_TRANSFER_ALPHA));
	} break;
      }
      
      /* PAGE OBJECT */
      pdf_begin_object(bj, (psp + i));
      pdf_open_dictionary(bj); kw_out(bj, 0);
      /* type */
      kw_out(bj, 27); kw_out(bj, 0);
      /* parent */
      kw_out(bj, 29); kw_out(bj, 1);
      pdf_write_reference(bj, bj->psp); kw_out(bj, 0);
      /* media box */
      kw_out(bj, 28); kw_out(bj, 1);
      kw_out(bj, 10); kw_out(bj, 1);
      if(bmeps_tool_how_to_handle_bb(bj) == 1) {
        dkstream_puts_double(bj->os, 0.0);
	kw_out(bj, 1);
        dkstream_puts_double(bj->os, 0.0);
	kw_out(bj, 1);
        dkstream_puts_double(bj->os, ((bj->trans).iu.x1 - (bj->trans).iu.x0));
	kw_out(bj, 1);
        dkstream_puts_double(bj->os, ((bj->trans).iu.y1 - (bj->trans).iu.y0));
	kw_out(bj, 1);
      } else {
        dkstream_puts_ul(bj->os, (bj->trans).bb.x0); kw_out(bj, 1);
        dkstream_puts_ul(bj->os, (bj->trans).bb.y0); kw_out(bj, 1);
        dkstream_puts_ul(bj->os, (bj->trans).bb.x1); kw_out(bj, 1);
        dkstream_puts_ul(bj->os, (bj->trans).bb.y1); kw_out(bj, 1);
      }
      kw_out(bj, 11); kw_out(bj, 0);
      kw_out(bj, 30); kw_out(bj, 1); pdf_open_dictionary(bj); kw_out(bj, 0);
      /* procset */
      kw_out(bj, 31); kw_out(bj, 1); kw_out(bj, 10); kw_out(bj, 1);
      kw_out(bj, 33); kw_out(bj, 1);
      if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
        kw_out(bj, 34);
      } else {
        kw_out(bj, 35);
      } kw_out(bj, 1);
      kw_out(bj, 11); kw_out(bj, 0);
      /* xobject */
      kw_out(bj, 32); kw_out(bj, 1);
      pdf_write_reference(bj, (xsp + i)); kw_out(bj, 0);
      pdf_close_dictionary(bj); kw_out(bj, 0);
      /* contents */
      kw_out(bj, 36); kw_out(bj, 1);
      pdf_write_reference(bj, (csp + i)); kw_out(bj, 0);
      /* pdf page attributes for transparency */
      if(use_mask_or_alpha) {
        if(((bj->bo2)->opt) & BMEPS_OPT_TRANSFER_ALPHA) {
	  if(((bj->bo2)->pdfopt) & BMEPS_PDFOPT_ALLOW_PDF_PAGE_ATTRIBUTES) {
	    kw_out(bj, 87); kw_out(bj, 0);
	  }
	}
      }
      pdf_close_dictionary(bj); kw_out(bj, 0);
      pdf_end_object(bj);
      /* GRAPHICS INSTRUCTIONS OBJECT */
      pdf_begin_object(bj, (csp + i));
      gfile = dksf_fopen(bj->tmp2, "wb");
      if(gfile) {
        fprintf(gfile, "q%s", kw[0]);
	switch(bmeps_tool_how_to_handle_bb(bj)) {
	  case 2: {	/* use paper size */
	    fputs("1 0 0 1 ", gfile);
	    dkma_fputs_double_no_exp(gfile, (bj->trans).iu.x0);
	    fputc(' ', gfile);
	    dkma_fputs_double_no_exp(gfile, (bj->trans).iu.y0);
	    fputs(" cm", gfile);
	    fprintf(gfile, "%s", kw[0]);
	    dkma_fputs_double_no_exp(gfile, (bj->trans).sfx);
	    fputs(" 0 0 ", gfile);
	    dkma_fputs_double_no_exp(gfile, (bj->trans).sfy);
	    fputs(" 0 0 cm", gfile);
	    fprintf(gfile, "%s", kw[0]);
	    fprintf(gfile, "%lu 0 0 %lu 0 0 cm%s", w, h, kw[0]);
	  } break;
	  case 1: {	/* use resolution */
	    if(0) {	/* remove these lines if PDF output is ok */
	      fputs("1 0 0 1 ", gfile);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).iu.x0);
	      fputc(' ', gfile);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).iu.y0);
	      fputs(" cm", gfile);
	      fprintf(gfile, "%s", kw[0]);
	    }
	    dkma_fputs_double_no_exp(gfile, (bj->trans).sfx);
	    fputs(" 0 0 ", gfile);
	    dkma_fputs_double_no_exp(gfile, (bj->trans).sfy);
	    fputs(" 0 0 cm", gfile);
	    fprintf(gfile, "%s", kw[0]);
	    fprintf(gfile, "%lu 0 0 %lu 0 0 cm%s", w, h, kw[0]);
	  } break;
	  default: {	/* do not scale */
	    fprintf(gfile, "%lu 0 0 %lu 0 0 cm%s", w, h, kw[0]);
	  } break;
	}
	fprintf(gfile, "/X%lu Do%s", bj->nexto, kw[0]);
	fprintf(gfile, "Q%s", kw[0]); fflush(gfile);
        fclose(gfile); gfile = NULL;
	if(dkstat_get(&stbuf, bj->tmp2)) {
	  filesize = (unsigned long)dkstat_size(&stbuf);
	  gfile = dksf_fopen(bj->tmp2, "rb");
	  if(gfile) {
	    pdf_open_dictionary(bj); kw_out(bj, 1);
	    kw_out(bj, 38); kw_out(bj, 1);
	    dkstream_puts_ul(bj->os, filesize);
	    kw_out(bj, 1);
	    pdf_close_dictionary(bj); kw_out(bj, 0);
	    kw_out(bj, 39); kw_out(bj, 0);
	    transfer_file_to_stream(bj->os, gfile, filesize);
	    kw_out(bj, 40); kw_out(bj, 0);
	    fclose(gfile); gfile = NULL;
	  } else {
	    bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 62, 63, bj->tmp2);
	    bj->exval = 1;
	  }
	} else {
	  bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 64, 65, bj->tmp2);
	  bj->exval = 1;
	}
	dksf_remove_file(bj->tmp2);
      } else {
	bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 66, 67, bj->tmp2);
	bj->exval = 1;
      }
      pdf_end_object(bj);
      /* XOBJECT DICTIONARY */
      pdf_begin_object(bj, (xsp + i));
      pdf_open_dictionary(bj); kw_out(bj, 0);
      kw_out(bj, 37);
      dkstream_puts_ul(bj->os, bj->nexto); kw_out(bj, 1);
      pdf_write_reference(bj, bj->nexto); kw_out(bj, 0);
      if(use_mask_or_alpha) {
        kw_out(bj, 37);
	dkstream_puts_ul(bj->os, (1UL + bj->nexto)); kw_out(bj, 1);
	pdf_write_reference(bj, (1UL + bj->nexto)); kw_out(bj, 0);
      }
      pdf_close_dictionary(bj); kw_out(bj, 0);
      pdf_end_object(bj);
      /* XOBJECT OBJECTS, use nexto */
      /* image and alpha/mask */
      number_of_filters = 2;
      if((bj->bo2)->enc & (BMEPS_ENCODING_FLATE)) {
        
        number_of_filters++;
      }
      if((bj->bo2)->enc & BMEPS_ENCODING_RUNLENGTH) {
        
        number_of_filters++;
      }
      ofs1 = dkstream_openfile(bj->tmp2, "wb", 0, &dummy);
      if(ofs1) {		
        ofs2 = dkof_open(ofs1, number_of_filters);
	if(ofs2) {		
	  obs = NULL;
	  if(bpc != 8) {	
	    obs = dkof_bs_open(ofs2);
	  }
	  if((bpc == 8) || (obs)) {	
	    data_ok = 1;
	    if(!dkof_set(ofs2, 0, DK_OF_TYPE_BUFFERED)) {
	      data_ok = 0;	
	    }
	    if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
	      if(!dkof_set(ofs2, 1, DK_OF_TYPE_ASCII85)) {
	        data_ok = 0;	
	      }
	    } else {
	      if(!dkof_set(ofs2, 1, DK_OF_TYPE_ASCIIHEX)) {
  	        data_ok = 0;	
	      }
	    }
	    dkof_set_crnl(ofs2, 1); nf = 2;
	    if((bj->bo2)->enc & BMEPS_ENCODING_FLATE) {
	      nf = 3;
	      if(!dkof_set(ofs2, 2, DK_OF_TYPE_FLATE)) {
	        data_ok = 0;	
	      }
	    } else {
	    }
	    if((bj->bo2)->enc & BMEPS_ENCODING_RUNLENGTH) {
	      
	      if(!dkof_set(ofs2, nf, DK_OF_TYPE_PSRL)) {
	        data_ok = 0;	
	      }
	    }
	    if(data_ok) {	
	      if(dkof_start_chunk(ofs2)) {	
	        ch = dkbif_get_channels(bj->bif);
		if((bj->bo2)->pred == BMEPS_PREDICTOR_INPUT) {
		  
		  (bj->bo2)->pred = BMEPS_PREDICTOR_NONE;
		  
		  switch(dkbif_get_predictor(bj->bif)) {
		    case DKBIF_PREDICTOR_PIXEL_SUB: {
		      (bj->bo2)->pred = BMEPS_PREDICTOR_TIFF;
		    } break;
		    case DKBIF_PREDICTOR_BYTE_SUB: {
		      (bj->bo2)->pred = BMEPS_PREDICTOR_PNG_SUB;
		    } break;
		    case DKBIF_PREDICTOR_BYTE_UP: {
		      (bj->bo2)->pred = BMEPS_PREDICTOR_PNG_UP;
		    } break;
		    case DKBIF_PREDICTOR_BYTE_AVG: {
		      (bj->bo2)->pred = BMEPS_PREDICTOR_PNG_AVERAGE;
		    } break;
		    case DKBIF_PREDICTOR_BYTE_PAETH: {
		      (bj->bo2)->pred = BMEPS_PREDICTOR_PNG_PAETH;
		    } break;
		  }
		}
		if((bpc != 8) && (bpc != 16)) {		
		  switch((bj->bo2)->pred) {
		    case BMEPS_PREDICTOR_PNG_SUB:
		    case BMEPS_PREDICTOR_PNG_AVERAGE:
		    case BMEPS_PREDICTOR_PNG_PAETH: {
		      (bj->bo2)->pred = BMEPS_PREDICTOR_TIFF;	
		    } break;
		    default: {
		      (bj->bo2)->pred = BMEPS_PREDICTOR_NONE;	
		    } break;
		  }
		}
		if((bj->bo2)->enc & BMEPS_ENCODING_RUNLENGTH) {
		  (bj->bo2)->pred = BMEPS_PREDICTOR_NONE;	
		}
		if(((bj->bo2)->enc & BMEPS_ENCODING_FLATE) && ((bj->bo2)->pred))
		{
		  switch((bj->bo2)->pred) {
		    case BMEPS_PREDICTOR_TIFF: {
		      unsigned short or, og, ob, nr, ng, nb;
		      
	              for(iy = 0UL; iy < h; iy++) {
		        or = og = ob = 0;
	                for(j = 0UL; j < w; j++) {
		          y = iy; x = j;
		          if((bj->trans).must_rotate) { x = iy; y = w - 1UL - j; }
		          if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
		            if((bpc != 8) && (obs)) {
			      nr = dkbif_get_red(bj->bif, x, y);
		              dkof_bs_put(
			        obs, (unsigned short)(nr - or),
			        (unsigned short)bpc
			      ); or = nr;
			      ng = dkbif_get_green(bj->bif, x, y);
		              dkof_bs_put(
			            obs, (unsigned short)(ng - og),
			            (unsigned short)bpc
			      ); og = ng;
			      nb = dkbif_get_blue(bj->bif, x, y);
		              dkof_bs_put(
			        obs, (unsigned short)(nb - ob),
			        (unsigned short)bpc
			      ); ob = nb;
		            } else {
			      nr = dkbif_get_red(bj->bif, x, y);
			      ng = dkbif_get_green(bj->bif, x, y);
			      nb = dkbif_get_blue(bj->bif, x, y);
			      c = (unsigned char)(nr - or);
			      dkstream_write(ofs2, (char *)(&c), 1);
			      c = (unsigned char)(ng - og);
			      dkstream_write(ofs2, (char *)(&c), 1);
			      c = (unsigned char)(nb - ob);
			      dkstream_write(ofs2, (char *)(&c), 1);
			      or = nr; og = ng; ob = nb;
		            }
		          } else {
		            if((bpc != 8) && (obs)) {
			      ng = dkbif_get_gray(bj->bif, x, y);
		              dkof_bs_put(
			        obs, (unsigned short)(ng - og),
			        (unsigned short)bpc
			      ); og = ng;
		            } else {
			      ng = dkbif_get_gray(bj->bif, x, y);
		              c = (unsigned char)(ng - og);
		              dkstream_write(ofs2, (char *)(&c), 1);
			      og = ng;
		            }
		          }
		        }
		        if(obs) {
		          dkof_bs_flush(obs);
		        }
	              }
		    } break;
		    case BMEPS_PREDICTOR_PNG_SUB:
		    case BMEPS_PREDICTOR_PNG_UP:
		    case BMEPS_PREDICTOR_PNG_AVERAGE:
		    case BMEPS_PREDICTOR_PNG_PAETH:
		    {
		      unsigned long x1, y1, x2, y2, x3, y3;
		      unsigned short r, g, b, r1, g1, b1, r2, g2, b2, r3, g3, b3;
		      
		      for(iy = 0UL; iy < h; iy++) {
		        /* Row filtertype byte */
		        switch((bj->bo2)->pred) {
		          case BMEPS_PREDICTOR_PNG_SUB: {
			    c = 0x01;
			  } break;
		          case BMEPS_PREDICTOR_PNG_UP: {
			    c = 0x02;
			  } break;
		          case BMEPS_PREDICTOR_PNG_AVERAGE: {
			    c = 0x03;
			  } break;
		          case BMEPS_PREDICTOR_PNG_PAETH: {
			    c = 0x04;
			  } break;
			}
			dkstream_write(ofs2, (char *)(&c), 1);
		        for(j = 0UL; j < w; j++) {
			  y = iy; x = j;
			  x1 = x - 1UL; y1 = y;
			  x2 = x; y2 = y - 1UL;
			  x3 = x - 1UL; y3 = y - 1UL;
			  if((bj->trans).must_rotate) {	
			    x = iy; y = w - 1UL - j;
			    x1 = x; y1 = y + 1UL;
			    x2 = x - 1UL; y2 = y;
			    x3 = x - 1UL; y3 = y1;
			  }
			  if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
			    
			    r = dkbif_get_red(bj->bif, x, y);
			    g = dkbif_get_green(bj->bif, x, y);
			    b = dkbif_get_blue(bj->bif, x, y);
			    
			    r1 = dkbif_get_red(bj->bif, x1, y1);
			    g1 = dkbif_get_green(bj->bif, x1, y1);
			    b1 = dkbif_get_blue(bj->bif, x1, y1);
			    
			    r2 = dkbif_get_red(bj->bif, x2, y2);
			    g2 = dkbif_get_green(bj->bif, x2, y2);
			    b2 = dkbif_get_blue(bj->bif, x2, y2);
			    
			    r3 = dkbif_get_red(bj->bif, x3, y3);
			    g3 = dkbif_get_green(bj->bif, x3, y3);
			    b3 = dkbif_get_blue(bj->bif, x3, y3);
			    if(bpc == 16) {	
			      switch((bj->bo2)->pred) {
			        case BMEPS_PREDICTOR_PNG_SUB: {	
				  r = mw(png_sub(hb(r), hb(r1)), png_sub(lb(r), lb(r1)));
				  g = mw(png_sub(hb(g), hb(g1)), png_sub(lb(g), lb(g1)));
				  b = mw(png_sub(hb(b), hb(b1)), png_sub(lb(b), lb(b1)));
				} break;
				case BMEPS_PREDICTOR_PNG_UP: {	
				  r = mw(png_up(hb(r), hb(r2)), png_up(lb(r), lb(r2)));
				  g = mw(png_up(hb(g), hb(g2)), png_up(lb(g), lb(g2)));
				  b = mw(png_up(hb(b), hb(b2)), png_up(lb(b), lb(b2)));
				} break;
				case BMEPS_PREDICTOR_PNG_AVERAGE: {	
				  r = mw(png_avg(hb(r), hb(r1), hb(r2)), png_avg(lb(r), lb(r1), lb(r2)));
				  g = mw(png_avg(hb(g), hb(g1), hb(g2)), png_avg(lb(g), lb(g1), lb(g2)));
				  b = mw(png_avg(hb(b), hb(b1), hb(b2)), png_avg(lb(b), lb(b1), lb(b2)));
				} break;
				case BMEPS_PREDICTOR_PNG_PAETH: {	
				  r = mw(png_paeth(hb(r), hb(r1), hb(r2), hb(r3)), png_paeth(lb(r), lb(r1), lb(r2), lb(r3)));
				  g = mw(png_paeth(hb(g), hb(g1), hb(g2), hb(g3)), png_paeth(lb(g), lb(g1), lb(g2), lb(g3)));
				  b = mw(png_paeth(hb(b), hb(b1), hb(b2), hb(b3)), png_paeth(lb(b), lb(b1), lb(b2), lb(b3)));
				} break;
			      }
			      dkof_bs_put(obs, r, (unsigned short)bpc);
			      dkof_bs_put(obs, g, (unsigned short)bpc);
			      dkof_bs_put(obs, b, (unsigned short)bpc);
			    } else {		
			      switch((bj->bo2)->pred) {
			        case BMEPS_PREDICTOR_PNG_SUB: {		
				  r = mw(0x00, png_sub(lb(r), lb(r1)));
				  g = mw(0x00, png_sub(lb(g), lb(g1)));
				  b = mw(0x00, png_sub(lb(b), lb(b1)));
				} break;
				case BMEPS_PREDICTOR_PNG_UP: {		
				  r = mw(0x00, png_up(lb(r), lb(r2)));
				  g = mw(0x00, png_up(lb(g), lb(g2)));
				  b = mw(0x00, png_up(lb(b), lb(b2)));
				} break;
				case BMEPS_PREDICTOR_PNG_AVERAGE: {	
				  r = mw(0x00, png_avg(lb(r), lb(r1), lb(r2)));
				  g = mw(0x00, png_avg(lb(g), lb(g1), lb(g2)));
				  b = mw(0x00, png_avg(lb(b), lb(b1), lb(b2)));
				} break;
				case BMEPS_PREDICTOR_PNG_PAETH: {	
				  r = mw(0x00, png_paeth(lb(r), lb(r1), lb(r2), lb(r3)));
				  g = mw(0x00, png_paeth(lb(g), lb(g1), lb(g2), lb(g3)));
				  b = mw(0x00, png_paeth(lb(b), lb(b1), lb(b2), lb(b3)));
				} break;
			      }
			      c = (unsigned char)(r & 0x00FF);
			      dkstream_write(ofs2, (char *)(&c), 1);
			      c = (unsigned char)(g & 0x00FF);
			      dkstream_write(ofs2, (char *)(&c), 1);
			      c = (unsigned char)(b & 0x00FF);
			      dkstream_write(ofs2, (char *)(&c), 1);
			    }
			  } else {		
			    r = dkbif_get_gray(bj->bif, x, y);
			    
			    r1 = dkbif_get_gray(bj->bif, x1, y1);
			    
			    r2 = dkbif_get_gray(bj->bif, x2, y2);
			    
			    r3 = dkbif_get_gray(bj->bif, x3, y3);
			    if(bpc == 16) {	
			      switch((bj->bo2)->pred) {
			        case BMEPS_PREDICTOR_PNG_SUB: {		
				  r = mw(png_sub(hb(r), hb(r1)), png_sub(lb(r), lb(r1)));
				} break;
				case BMEPS_PREDICTOR_PNG_UP: {		
				  r = mw(png_up(hb(r), hb(r2)), png_up(lb(r), lb(r2)));
				} break;
				case BMEPS_PREDICTOR_PNG_AVERAGE: {	
				  r = mw(png_avg(hb(r), hb(r1), hb(r2)), png_avg(lb(r), lb(r1), lb(r2)));
				} break;
				case BMEPS_PREDICTOR_PNG_PAETH: {	
				  r = mw(png_paeth(hb(r), hb(r1), hb(r2), hb(r3)), png_paeth(lb(r), lb(r1), lb(r2), lb(r3)));
				} break;
			      }
			      dkof_bs_put(obs, r, (unsigned short)bpc);
			    } else {		
			      switch((bj->bo2)->pred) {
			        case BMEPS_PREDICTOR_PNG_SUB: {		
				  r = mw(0x00, png_sub(lb(r), lb(r1)));
				} break;
				case BMEPS_PREDICTOR_PNG_UP: {		
				  r = mw(0x00, png_up(lb(r), lb(r2)));
				} break;
				case BMEPS_PREDICTOR_PNG_AVERAGE: {	
				  r = mw(0x00, png_avg(lb(r), lb(r1), lb(r2)));
				} break;
				case BMEPS_PREDICTOR_PNG_PAETH: {	
				  r = mw(0x00, png_paeth(lb(r), lb(r1), lb(r2), lb(r3)));
				} break;
			      }
			      c = (unsigned char)(r & 0x00FF);
			      dkstream_write(ofs2, (char *)(&c), 1);
			    }
			  }
			}
		      }
		    } break;
		  }
		} else {
	          for(iy = 0UL; iy < h; iy++) {
	            for(j = 0UL; j < w; j++) {
		      y = iy; x = j;
		      if((bj->trans).must_rotate) { x = iy; y = w - 1UL - j; }
		      if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
		        if((bpc != 8) && (obs)) {
		          dkof_bs_put(
			    obs, dkbif_get_red(bj->bif, x, y),
			    (unsigned short)bpc
			  );
		          dkof_bs_put(
			    obs, dkbif_get_green(bj->bif, x, y),
			    (unsigned short)bpc
			  );
		          dkof_bs_put(
			    obs, dkbif_get_blue(bj->bif, x, y),
			    (unsigned short)bpc
			  );
		        } else {
		          c = (unsigned char)dkbif_get_red(bj->bif, x, y);
		          dkstream_write(ofs2, (char *)(&c), 1);
		          c = (unsigned char)dkbif_get_green(bj->bif, x, y);
		          dkstream_write(ofs2, (char *)(&c), 1);
		          c = (unsigned char)dkbif_get_blue(bj->bif, x, y);
		          dkstream_write(ofs2, (char *)(&c), 1);
		        }
		      } else {
		        if((bpc != 8) && (obs)) {
		          dkof_bs_put(
			    obs, dkbif_get_gray(bj->bif, x, y),
			    (unsigned short)bpc
			  );
		        } else {
		          c = (unsigned char)dkbif_get_gray(bj->bif, x, y);
		          dkstream_write(ofs2, (char *)(&c), 1);
		        }
		      }
		    }
		    if(obs) {
		      dkof_bs_flush(obs);
		    }
	          }
		}
	        if(!dkof_end_chunk(ofs2)) {
	          data_ok = 0;			
	        } else {			
		}
	      } else {				
		bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 69);
		bj->exval = 1;
	      }
	    } else {		
	    }
	  } else {
	    bmeps_tool_error_memory(bj); bj->exval = 1;
	  }
	  if(obs) {
	    dkof_bs_close(obs);
	  }
	  obs = NULL;
	  dkof_close(ofs2); ofs2 = NULL;
	} else {		
	  bmeps_tool_error_memory(bj); bj->exval = 1;
	}
        dkstream_close(ofs1); ofs1 = NULL;
      } else {			
	bmeps_tool_error_memory(bj); bj->exval = 1;
      }
      if(use_mask_or_alpha) {		
	ofs1 = dkstream_openfile(bj->tmp3, "wb", 0, &dummy);
	if(ofs1) {			
	  ofs2 = dkof_open(ofs1, number_of_filters);
	  if(ofs2) {			
	    mask_ok = 1;
	    if(!dkof_set(ofs2, 0, DK_OF_TYPE_BUFFERED)) {
	      mask_ok = 0;	
	    }
	    if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
	      if(!dkof_set(ofs2, 1, DK_OF_TYPE_ASCII85)) {
	        mask_ok = 0;	
	      }
	    } else {
	      if(!dkof_set(ofs2, 1, DK_OF_TYPE_ASCIIHEX)) {
  	        mask_ok = 0;	
	      }
	    }
	    dkof_set_crnl(ofs2, 1); nf = 2;
	    if((bj->bo2)->enc & BMEPS_ENCODING_FLATE) {
	      nf = 3;
	      if(!dkof_set(ofs2, 2, DK_OF_TYPE_FLATE)) {
	        mask_ok = 0;	
	      }
	    } else {
	    }
	    if((bj->bo2)->enc & BMEPS_ENCODING_RUNLENGTH) {
	      
	      if(!dkof_set(ofs2, nf, DK_OF_TYPE_PSRL)) {
	        mask_ok = 0;	
	      }
	    }
	    if(mask_ok) {
	      if(dkof_start_chunk(ofs2)) {
	        if((bj->bo2)->opt & BMEPS_OPT_TRANSFER_ALPHA) {	
	          obs = NULL;	
		  if(bpc != 8) {
		    obs = dkof_bs_open(ofs2);
		  }
		  if((bpc == 8) || (obs)) {	
		    for(iy = 0UL; iy < h; iy++) {
		      for(j = 0UL; j < w; j++) {
		        unsigned short m;
		        y = iy; x = j;
		        if((bj->trans).must_rotate) { x = iy; y = w - 1UL - j; }
		        m = dkbif_get_alpha(bj->bif, x, y);
		        if(obs) {
		          dkof_bs_put(obs, m, (unsigned short)bpc);
		        } else {
		          c = (unsigned char)m;
			  dkstream_write(ofs2, (char *)(&c), 1);
		        }
		      }
		      if(obs) {
		        dkof_bs_flush(obs);
		      }
		    }
		    if(obs) {
		      dkof_bs_close(obs); obs = NULL;
		    }
		  } else {		
		    bmeps_tool_error_memory(bj); bj->exval = 1;
		  }
	        } else {		
	          obs = dkof_bs_open(ofs2);
		  if(obs) {		
		    for(iy = 0UL; iy < h; iy++) {
		      for(j = 0UL; j < w; j++) {
		        y = iy; x = j;
		        if((bj->trans).must_rotate) { x = iy; y = w - 1UL - j; }
		        dkof_bs_put(
			  obs,
			  (unsigned short)(dkbif_get_mask(bj->bif,x,y) ? 1 : 0),
			  (unsigned short)1
			);
		      }
		      if(obs) {
		        dkof_bs_flush(obs);
		      }
		    }
		    dkof_bs_close(obs); obs = NULL;
		  } else {		
		    bmeps_tool_error_memory(bj); bj->exval = 1;
		  }
	        }
	        if(!dkof_end_chunk(ofs2)) {
	          
	          mask_ok = 0;
		  bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 69); bj->exval = 1;
	        }
	      } else {
		bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 68); bj->exval = 1;
	      }
	    } else {
	      
	      bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 70); bj->exval = 1;
	    }
	    dkof_close(ofs2); ofs2 = NULL;
	  } else {			
	    bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 70); bj->exval = 1;
	  }
	  dkstream_close(ofs1); ofs1 = NULL;
	} else {			
	  bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 66, 67, bj->tmp3);
	  bj->exval = 1;
	}
      }
      
      if(data_ok && ((mask_ok) || (use_mask_or_alpha == 0x00))) {
        
        if(dkstat_get(&stbuf, bj->tmp2)) {	
	  filesize = (unsigned long)dkstat_size(&stbuf);
	  pdf_begin_object(bj, bj->nexto); bj->nexto += 1UL;
	  gfile= dksf_fopen(bj->tmp2, "rb");
	  if(gfile) {				
	    pdf_open_dictionary(bj); kw_out(bj, 0);
	    kw_out(bj, 47); kw_out(bj, 0);
	    kw_out(bj, 48); kw_out(bj, 0);
	    kw_out(bj, 49); kw_out(bj, 1);
	    dkstream_puts_ul(bj->os, w); kw_out(bj, 0);
	    kw_out(bj, 50); kw_out(bj, 1);
	    dkstream_puts_ul(bj->os, h); kw_out(bj, 0);
	    kw_out(bj, 51); kw_out(bj, 1);
	    if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
	      kw_out(bj, 52);
	    } else {
	      kw_out(bj, 53);
	    } kw_out(bj, 0);
	    kw_out(bj, 55); kw_out(bj, 1);
	    dkstream_puts_ul(bj->os, bpc); kw_out(bj, 0);
	    if((bj->bo2)->opt & BMEPS_OPT_INTERPOLATE) {
	      kw_out(bj, 58); kw_out(bj, 1); kw_out(bj, 59); kw_out(bj, 0);
	    }
	    if(use_mask_or_alpha) {
	      if((bj->bo2)->opt & BMEPS_OPT_TRANSFER_ALPHA) {
	        kw_out(bj, 61);
		bj->alpha_channel_transferred = 0x01;
	      } else {
	        kw_out(bj, 62);
	      }
              kw_out(bj, 1);
	      dkstream_puts_ul(bj->os, bj->nexto); kw_out(bj, 1);
	      dkstream_puts_ul(bj->os, 0UL); kw_out(bj, 1);
	      kw_out(bj, 23); kw_out(bj, 0);
	    }
	    kw_out(bj, 56); kw_out(bj, 1);
	    dkstream_puts_ul(bj->os, filesize); kw_out(bj, 0);
	    kw_out(bj, 57); kw_out(bj, 1);
	    kw_out(bj, 10); kw_out(bj, 1);
	    if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
	      kw_out(bj, 42);
	    } else {
	      kw_out(bj, 41);
	    } kw_out(bj, 1);
	    if((bj->bo2)->enc & BMEPS_ENCODING_FLATE) {
	      kw_out(bj, 44); kw_out(bj, 1);
	    } else {
	    }
	    if((bj->bo2)->enc & BMEPS_ENCODING_RUNLENGTH) {
	      kw_out(bj, 45);
	    }
	    kw_out(bj, 1); kw_out(bj, 11); kw_out(bj, 0);
	    if((bj->bo2)->enc & BMEPS_ENCODING_FLATE) {
	      switch((bj->bo2)->pred) {
	        case BMEPS_PREDICTOR_TIFF:
		case BMEPS_PREDICTOR_PNG_SUB:
		case BMEPS_PREDICTOR_PNG_UP:
		case BMEPS_PREDICTOR_PNG_AVERAGE:
		case BMEPS_PREDICTOR_PNG_PAETH:
		{
		  /* kw_out(bj, 88); kw_out(bj, 0); */
		  kw_out(bj, 89); kw_out(bj, 1);
		  kw_out(bj, 10); kw_out(bj, 0);
		  kw_out(bj, 1); kw_out(bj, 1);
		  kw_out(bj, 90);
		  kw_out(bj, 0);
		  /* flate predictor dictionary */
		  kw_out(bj, 1); kw_out(bj, 1);
		  kw_out(bj, 6);
		  kw_out(bj, 88);
		  switch((bj->bo2)->pred) {
		    case BMEPS_PREDICTOR_TIFF: {
		      dkstream_puts_ul(bj->os, 2UL);
		    } break;
		    case BMEPS_PREDICTOR_PNG_SUB: {
		      dkstream_puts_ul(bj->os, 11UL);
		    } break;
		    case BMEPS_PREDICTOR_PNG_UP: {
		      dkstream_puts_ul(bj->os, 12UL);
		    } break;
		    case BMEPS_PREDICTOR_PNG_AVERAGE: {
		      dkstream_puts_ul(bj->os, 13UL);
		    } break;
		    case BMEPS_PREDICTOR_PNG_PAETH: {
		      dkstream_puts_ul(bj->os, 14UL);
		    } break;
		  }
		  kw_out(bj, 1);
	          kw_out(bj, 55); kw_out(bj, 1);
	          dkstream_puts_ul(bj->os, bpc); kw_out(bj, 1);
		  kw_out(bj, 91); kw_out(bj, 1);
		  if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
		    kw_out(bj, 93);
		  } else {
		    kw_out(bj, 94);
		  }
		  kw_out(bj, 1);
		  kw_out(bj, 92); kw_out(bj, 1);
	          dkstream_puts_ul(bj->os, w);
		  kw_out(bj, 7); kw_out(bj, 0);
		  if((bj->bo2)->enc & BMEPS_ENCODING_RUNLENGTH) {
		    kw_out(bj, 1); kw_out(bj, 1);
		    kw_out(bj, 90); kw_out(bj, 0);
		  }
		  kw_out(bj, 11);
		  kw_out(bj, 0);
		} break;
	      }
	    }
	    pdf_close_dictionary(bj); kw_out(bj, 0);
	    kw_out(bj, 39); kw_out(bj, 0);
	    transfer_file_to_stream(bj->os, gfile, filesize);
	    kw_out(bj, 40); kw_out(bj, 0);
	    fclose(gfile); gfile = NULL;
	  } else {				
	    bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 62, 63, bj->tmp2);
	    bj->exval = 1;
	  }
          pdf_end_object(bj);
          if(use_mask_or_alpha) {
	    if(dkstat_get(&stbuf, bj->tmp3)) {
	      filesize =(unsigned long)dkstat_size(&stbuf);
              pdf_begin_object(bj, bj->nexto); bj->nexto += 1UL;
	      gfile = dksf_fopen(bj->tmp3, "rb");
	      if(gfile) {
	        pdf_open_dictionary(bj); kw_out(bj, 0);
	        kw_out(bj, 47); kw_out(bj, 0);
	        kw_out(bj, 48); kw_out(bj, 0);
	        kw_out(bj, 49); kw_out(bj, 1);
	        dkstream_puts_ul(bj->os, w); kw_out(bj, 0);
	        kw_out(bj, 50); kw_out(bj, 1);
	        dkstream_puts_ul(bj->os, h); kw_out(bj, 0);
	        kw_out(bj, 51); kw_out(bj, 1);
		kw_out(bj, 53); kw_out(bj, 0);
	        kw_out(bj, 55); kw_out(bj, 1);
		if((bj->bo2)->opt & BMEPS_OPT_TRANSFER_ALPHA) {
		  dkstream_puts_ul(bj->os, bpc);
		} else {
	          dkstream_puts_ul(bj->os, 1UL);
		}
		kw_out(bj, 0);
	        kw_out(bj, 56); kw_out(bj, 1);
	        dkstream_puts_ul(bj->os, filesize); kw_out(bj, 0);
	        kw_out(bj, 57); kw_out(bj, 1);
	        kw_out(bj, 10); kw_out(bj, 1);
	        if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
	          kw_out(bj, 42);
	        } else {
	          kw_out(bj, 41);
	        } kw_out(bj, 1);
	        if((bj->bo2)->enc & BMEPS_ENCODING_FLATE) {
	          kw_out(bj, 44); kw_out(bj, 1);
	        } else {
	        }
	        if((bj->bo2)->enc & BMEPS_ENCODING_RUNLENGTH) {
	          kw_out(bj, 45);
	        }
	        kw_out(bj, 1); kw_out(bj, 11); kw_out(bj, 0);
		pdf_close_dictionary(bj); kw_out(bj, 0);
		kw_out(bj, 39); kw_out(bj, 0);
		transfer_file_to_stream(bj->os, gfile, filesize);
		kw_out(bj, 40); kw_out(bj, 0);
		fclose(gfile); gfile = NULL;
	      } else {
		bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 62, 63, bj->tmp3);
		bj->exval = 1;
	      }
	      pdf_end_object(bj);
	    } else {
	      bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 64, 65, bj->tmp3);
	      bj->exval = 1;
	    }
          }
	} else {				
	  bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 64, 65, bj->tmp2);
	  bj->exval = 1;
	}
      } else {					
      }
    } else {
      bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 71); bj->exval = 1;
    }
    fno++; i++;
  } 
}



/**	Create PDF object structure for DCT-pass-through.
	@param	bj	Bmeps job.
*/
static
void
pdf_file_objects_dct DK_P1(BJ *,bj)
{
#if DK_HAVE_JPEGLIB_H
  unsigned short bpcs;		/* bits per component */
  unsigned long bpc;		/* also bits per component */
  /* unsigned char c; */	/* one byte of output for 8-bit input */
  unsigned long psp;		/* pages start position (object number) */
  unsigned long csp;		/* contents start position (object number) */
  unsigned long xsp;		/* xobjects start position (object number) */
  unsigned long i;		/* */
  unsigned long w;		/* width of output image */
  unsigned long h;		/* height of output image */
  unsigned long origw;		/* width of input image */
  unsigned long origh;		/* height of input image */
  unsigned long filesize;	/* file size of temporary file */
  /* unsigned long x; */	/* x position of source pixel */
  /* unsigned long y; */	/* y position of source pixel */
  /* unsigned long iy; */	/* y position of destination pixel */
  /* unsigned long j; */	/* x position of destination pixel */
  long fno;			/* number of current frame */
  dk_stat_t stbuf;		/* stat buffer to obtain file info */
  int dummy = 0;		/* dummy variable for fopen failure */
  int data_ok = 0;		/* indicate output data file ok */
  dk_stream_t *ofs1 = NULL;	/* unfiltered output stream */
  dk_stream_t *ofs2 = NULL;	/* filter output stream */
  FILE *gfile = NULL;		/* temporary file */
  
  i = 0;
  bj->frame_n = 1;
  fno = bj->frame_s;
  psp = bj->nexto;
  csp = psp + bj->frame_n;
  xsp = csp + bj->frame_n;
  dkmem_cpy(bj->bo2, bj->bo, sizeof(BO));
  bmeps_tool_calculate_areas(bj);
  origw = w = dkbif_get_width(bj->bif);
  origh = h = dkbif_get_height(bj->bif);
  if((bj->trans).must_rotate) {
    w = origh; h = origw;
  }
  bpcs = dkbif_get_bits_per_component(bj->bif);
  bpc  = (unsigned long)bpcs;
  pdf_begin_object(bj, bj->nexto); bj->nexto += 1UL;
  pdf_open_dictionary(bj); kw_out(bj, 0);
  /* type */
  kw_out(bj, 27); kw_out(bj, 0);
  /* parent */
  kw_out(bj, 29); kw_out(bj, 1);
  pdf_write_reference(bj, bj->psp); kw_out(bj, 0);
  /* media box */
  kw_out(bj, 28); kw_out(bj, 1);
  kw_out(bj, 10); kw_out(bj, 1);
  if(bmeps_tool_how_to_handle_bb(bj) == 1) {
    dkstream_puts_double(bj->os, 0.0);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, 0.0);
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, ((bj->trans).iu.x1 - (bj->trans).iu.x0));
    kw_out(bj, 1);
    dkstream_puts_double(bj->os, ((bj->trans).iu.y1 - (bj->trans).iu.y0));
    kw_out(bj, 1);
  } else {
    dkstream_puts_ul(bj->os, (bj->trans).bb.x0); kw_out(bj, 1);
    dkstream_puts_ul(bj->os, (bj->trans).bb.y0); kw_out(bj, 1);
    dkstream_puts_ul(bj->os, (bj->trans).bb.x1); kw_out(bj, 1);
    dkstream_puts_ul(bj->os, (bj->trans).bb.y1); kw_out(bj, 1);
  }
  kw_out(bj, 11); kw_out(bj, 0);
  /* resources */
  kw_out(bj, 30); kw_out(bj, 1); pdf_open_dictionary(bj); kw_out(bj, 0);
  kw_out(bj, 31); kw_out(bj, 1); kw_out(bj, 10); kw_out(bj, 1);
  kw_out(bj, 33); kw_out(bj, 1);
  if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
    kw_out(bj, 34);
  } else {
    kw_out(bj, 35);
  } kw_out(bj, 0);
  kw_out(bj, 11); kw_out(bj, 0);
  kw_out(bj, 32); kw_out(bj, 1);
  pdf_write_reference(bj, (xsp + i)); kw_out(bj, 0);
  pdf_close_dictionary(bj); kw_out(bj, 0);
  /* contents */
  kw_out(bj, 36); kw_out(bj, 1);
  pdf_write_reference(bj, (csp + i)); kw_out(bj, 0);
  pdf_close_dictionary(bj); kw_out(bj, 0);
  pdf_end_object(bj);
  /* GRAPHICS CONTENTS OBJECT */
  pdf_begin_object(bj, bj->nexto); bj->nexto += 1UL;
      gfile = dksf_fopen(bj->tmp2, "w");
      if(gfile) {
        fprintf(gfile, "q%s", kw[0]);
	switch(bmeps_tool_how_to_handle_bb(bj)) {
	  case 2: {	/* use paper size */
#define DO_DEBUG 0
#if DO_DEBUG
	    if((bj->trans).must_rotate) {
	      fputs("1 0 0 1 ", gfile);
	      dkma_fputs_double_no_exp(gfile, 0.5*((bj->trans).iu.x0 + (bj->trans).iu.x1));
	      fputc(' ', gfile);
	      dkma_fputs_double_no_exp(gfile, 0.5*((bj->trans).iu.y1 + (bj->trans).iu.y0));
	      fputs(" cm", gfile);
	      fprintf(gfile, "%s", kw[0]);
	      fprintf(
	        gfile,
		"0 -1 1 0 0 0 cm%s", kw[0]
	      );
	      dkma_fputs_double_no_exp(gfile, 0.5*(bj->trans).sfy);
	      fputs(" 0 0 ", gfile);
	      dkma_fputs_double_no_exp(gfile, 0.5*(bj->trans).sfx);
	      fputs(" 0 0 cm", gfile);
	      fprintf(gfile, "%s", kw[0]);
	      fprintf(gfile, "%lu 0 0 %lu 0 0 cm%s", origw, origh, kw[0]);
	    }
#else
	    if((bj->trans).must_rotate) {
	      fputs("1 0 0 1 ", gfile);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).iu.x0);
	      fputc(' ', gfile);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).iu.y1);
	      fputs(" cm", gfile);
	      fprintf(gfile, "%s", kw[0]);
	      fprintf( gfile, "0 -1 1 0 0 0 cm%s", kw[0]);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).sfy);
	      fputs(" 0 0 ", gfile);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).sfx);
	      fputs(" 0 0 cm", gfile);
	      fprintf(gfile, "%s", kw[0]);
	      fprintf(gfile, "%lu 0 0 %lu 0 0 cm%s", origw, origh, kw[0]);
	    }
#endif
	    else {
	      fputs("1 0 0 1 ", gfile);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).iu.x0);
	      fputc(' ', gfile);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).iu.y0);
	      fputs(" cm", gfile);
	      fprintf(gfile, "%s", kw[0]);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).sfx);
	      fputs(" 0 0 ", gfile);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).sfy);
	      fputs(" 0 0 cm", gfile);
	      fprintf(gfile, "%s", kw[0]);
	    }
	  } break;
	  case 1: {	/* use resolution */
	    if(0) {	/* remove these lines if PDF output is ok */
	      fputs("1 0 0 1 ", gfile);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).iu.x0);
	      fputc(' ', gfile);
	      dkma_fputs_double_no_exp(gfile, (bj->trans).iu.y0);
	      fputs(" cm", gfile);
	      fprintf(gfile, "%s", kw[0]);
	    }
	    dkma_fputs_double_no_exp(gfile, (bj->trans).sfx);
	    fputs(" 0 0 ", gfile);
	    dkma_fputs_double_no_exp(gfile, (bj->trans).sfy);
	    fputs(" 0 0 cm", gfile);
	    fprintf(gfile, "%s", kw[0]);
	    fprintf(gfile, "%lu 0 0 %lu 0 0 cm%s", w, h, kw[0]);
	  } break;
	  default: {	/* do not scale */
	    fprintf(gfile, "%lu 0 0 %lu 0 0 cm%s", w, h, kw[0]);
	  } break;
	}
	fprintf(gfile, "/X%lu Do%s", (bj->nexto + 1UL), kw[0]);
	fprintf(gfile, "Q%s", kw[0]); fflush(gfile);
        fclose(gfile); gfile = NULL;
	if(dkstat_get(&stbuf, bj->tmp2)) {
	  filesize = (unsigned long)dkstat_size(&stbuf);
	  gfile = dksf_fopen(bj->tmp2, "rb");
	  if(gfile) {
	    pdf_open_dictionary(bj); kw_out(bj, 1);
	    kw_out(bj, 38); kw_out(bj, 1);
	    dkstream_puts_ul(bj->os, filesize);
	    kw_out(bj, 1);
	    pdf_close_dictionary(bj); kw_out(bj, 0);
	    kw_out(bj, 39); kw_out(bj, 0);
	    transfer_file_to_stream(bj->os, gfile, filesize);
	    kw_out(bj, 40); kw_out(bj, 0);
	    fclose(gfile); gfile = NULL;
	  } else {
	    bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 62, 63, bj->tmp2);
	    bj->exval = 1;
	  }
	} else {
	  bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 64, 65, bj->tmp2);
	  bj->exval = 1;
	}
	dksf_remove_file(bj->tmp2);
      } else {
	bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 66, 67, bj->tmp2);
	bj->exval = 1;
      }
  pdf_end_object(bj);
  /* XOBJECT DICTIONARY */
  pdf_begin_object(bj, bj->nexto); bj->nexto += 1UL;
      pdf_open_dictionary(bj); kw_out(bj, 0);
      kw_out(bj, 37);
      dkstream_puts_ul(bj->os, bj->nexto); kw_out(bj, 1);
      pdf_write_reference(bj, bj->nexto); kw_out(bj, 0);
      pdf_close_dictionary(bj); kw_out(bj, 0);
  pdf_end_object(bj);
  /* XOBJECT OBJECT */
  pdf_begin_object(bj, bj->nexto); bj->nexto += 1UL;
      data_ok = 0;
      dummy = 0;
      ofs1 = dkstream_openfile(bj->tmp2, "wb", 0, &dummy);
      if(ofs1) {
        ofs2 = dkof_open(ofs1, 2);
	if(ofs2) {
	  data_ok = 1;
	  if(!dkof_set(ofs2, 0, DK_OF_TYPE_BUFFERED)) {
	    data_ok = 0;
	  }
	  if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
	    if(!dkof_set(ofs2, 1, DK_OF_TYPE_ASCII85)) {
	      data_ok = 0;
	    }
	  } else {
	    if(!dkof_set(ofs2, 1, DK_OF_TYPE_ASCIIHEX)) {
	      data_ok = 0;
	    }
	  }
	  dkof_set_crnl(ofs2, 1);
	  if(data_ok) {
	    if(dkof_start_chunk(ofs2)) {
	      rewind(bj->inf);
	      transfer_entire_file(bj, ofs2, bj->inf);
	      if(!dkof_end_chunk(ofs2)) {
		bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 69);
		bj->exval = 1;
	      }
	    } else {
	      bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 68);
	      bj->exval = 1;
	    }
	  } else {
	    /* previous errors */
	  }
	  dkof_close(ofs2); ofs2 = 0;
	} else {
	  bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 70);
	  bj->exval = 1;
	}
        dkstream_close(ofs1); ofs1 = NULL;
      } else {
	bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 66, 67, bj->tmp2);
	bj->exval = 1;
      }
      if(data_ok) {
        if(dkstat_get(&stbuf, bj->tmp2)) {
	  filesize = (unsigned long)dkstat_size(&stbuf);
	  gfile= dksf_fopen(bj->tmp2, "rb");
	  if(gfile) {
	    pdf_open_dictionary(bj); kw_out(bj, 0);
	    kw_out(bj, 47); kw_out(bj, 0);
	    kw_out(bj, 48); kw_out(bj, 0);
	    kw_out(bj, 49); kw_out(bj, 1);
	    dkstream_puts_ul(bj->os, origw); kw_out(bj, 0);
	    kw_out(bj, 50); kw_out(bj, 1);
	    dkstream_puts_ul(bj->os, origh); kw_out(bj, 0);
	    kw_out(bj, 51); kw_out(bj, 1);
	    if(((bj->bif)->d).jpg.jpgana.components > 0x01) {
	      if(((bj->bif)->d).jpg.jpgana.components == 0x03) {
	        kw_out(bj, 52);
	      } else {
	        kw_out(bj, 54);
	      }
	    } else {
	      kw_out(bj, 53);
	    }
	    kw_out(bj, 0);
	    kw_out(bj, 55); kw_out(bj, 1);
	    dkstream_puts_ul(bj->os, bpc);
	    kw_out(bj, 0);
	    if((bj->bo2)->opt & BMEPS_OPT_INTERPOLATE) {
	      if((bj->bo2)->opt & BMEPS_OPT_JPEG_INTERPOLATE) {
	        kw_out(bj, 58); kw_out(bj, 1); kw_out(bj, 59); kw_out(bj, 0);
	      }
	    }
	    kw_out(bj, 56); kw_out(bj, 1);
	    dkstream_puts_ul(bj->os, filesize); kw_out(bj, 0);
	    kw_out(bj, 57); kw_out(bj, 1);
	    kw_out(bj, 10); kw_out(bj, 1);
	    if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
	      kw_out(bj, 42);
	    } else {
	      kw_out(bj, 41);
	    } kw_out(bj, 1);
	    kw_out(bj, 46);
	    kw_out(bj, 1); kw_out(bj, 11); kw_out(bj, 0);
	    if((((bj->bif)->d).jpg.jpgana.components) != 0x01) {
	      if((((bj->bif)->d).jpg.jpgana.components) != 0x03) {
	        if(((bj->bif)->d).jpg.jpgana.adobe_marker_found) {
		  kw_out(bj, 86); kw_out(bj, 0);
		}
	      }
	    }
	    pdf_close_dictionary(bj); kw_out(bj, 0);
	    kw_out(bj, 39); kw_out(bj, 0);
	    transfer_file_to_stream(bj->os, gfile, filesize);
	    kw_out(bj, 40); kw_out(bj, 0);
	    fclose(gfile); gfile = NULL;
	  } else {
	    bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 62, 63, bj->tmp2);
	    bj->exval = 1;
	  }
	}
      }
  pdf_end_object(bj);

  
#endif
}



/** Print one keyword to ofs2. */
#define DKSP(i) dkstream_puts(ofs2, kw[i])



/**	Create draft PDF.
	@param bj	Bmeps job.
*/
static
void
pdf_file_objects_draft DK_P1(BJ *,bj)
{
  long fno;				/* current frame to process */
  unsigned long w, h, origw, origh;	/* image dimensions */
  unsigned long psp;			/* page start position */
  unsigned long csp;			/* contents start position */
  unsigned long i;			/* the frame number */
  unsigned long filesize;		/* length of stream */
  FILE *gfile;				/* used to read encoded stream */
  DI dinner, douter;
  int dummy, data_ok, number_of_filters;
  double r = 0.7, g = 0.0, b = 0.0, gray = 0.9, black = 0.0;
  dk_stream_t *ofs1, *ofs2;
  dk_stat_t stbuf;
  
  fno = bj->frame_s;
  psp = bj->nexto;
  csp = psp + bj->frame_n;
  i = 0UL;
  bj->nexto = csp + bj->frame_n;	/* number of objects at end */
  while(fno <= bj->frame_e) {
    
    w = h = origw = origh = 0UL;
    data_ok = 0;
    ofs1 = NULL; ofs2 = NULL;
    dkmem_cpy(bj->bo2, bj->bo, sizeof(BO));
    if(dkbif_set_frame(bj->bif, fno)) {
      
      data_ok = 0;
      bmeps_tool_calculate_areas(bj);
      origw = w = dkbif_get_width(bj->bif);
      origh = h = dkbif_get_height(bj->bif);
      if((bj->trans).must_rotate) {
        w = origh; h = origw;
      }
      number_of_filters = 2;
      if((bj->bo2)->enc & (BMEPS_ENCODING_FLATE)) {
        
        number_of_filters++;
      }
      if(bmeps_tool_calc_di(bj, &dinner, &douter, 0.05, 0.01)) {
        dummy = 0;
        ofs1 = dkstream_openfile(bj->tmp2, "wb", 0, &dummy);
	if(ofs1) {
	  ofs2 = dkof_open(ofs1, number_of_filters);
	  if(ofs2) {
	    data_ok = 1;
#if DEBUG
	    if(!dkof_set(ofs2, 0, DK_OF_TYPE_BUFFERED)) {
	      data_ok = 0;
	    }
	    if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
	      if(!dkof_set(ofs2, 1, DK_OF_TYPE_BUFFERED)) {
	        data_ok = 0;
	      }
	    } else {
	      if(!dkof_set(ofs2, 1, DK_OF_TYPE_BUFFERED)) {
	        data_ok = 0;
	      }
	    }
	    dkof_set_crnl(ofs2, 1);
	    if((bj->bo2)->enc & BMEPS_ENCODING_FLATE) {
	      if(!dkof_set(ofs2, 2, DK_OF_TYPE_BUFFERED)) {
	        data_ok = 0;
	      }
	    } else {
	    }
#else
	    if(!dkof_set(ofs2, 0, DK_OF_TYPE_BUFFERED)) {
	      data_ok = 0;
	    }
	    if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
	      if(!dkof_set(ofs2, 1, DK_OF_TYPE_ASCII85)) {
	        data_ok = 0;
	      }
	    } else {
	      if(!dkof_set(ofs2, 1, DK_OF_TYPE_ASCIIHEX)) {
	        data_ok = 0;
	      }
	    }
	    dkof_set_crnl(ofs2, 1);
	    if((bj->bo2)->enc & BMEPS_ENCODING_FLATE) {
	      if(!dkof_set(ofs2, 2, DK_OF_TYPE_FLATE)) {
	        data_ok = 0;
	      }
	    } else {
	    }
#endif
	    if(data_ok) {
	      if(dkof_start_chunk(ofs2)) {
	        DKSP(67); DKSP(0);
		/* change color to red or black */
		if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
		  dkstream_puts_double(ofs2, r);
		  DKSP(1);
		  dkstream_puts_double(ofs2, g);
		  DKSP(1);
		  dkstream_puts_double(ofs2, b);
		  DKSP(1); DKSP(70);
		} else {
		  dkstream_puts_double(ofs2, black);
		  DKSP(1); DKSP(69);
		} DKSP(0);
		/* border rectangle */
		dkstream_puts_double(ofs2, (bj->trans).iu.x0);
		DKSP(1);
		dkstream_puts_double(ofs2, (bj->trans).iu.y0);
		DKSP(1);
		dkstream_puts_double(ofs2, ((bj->trans).iu.x1 - (bj->trans).iu.x0));
		DKSP(1);
		dkstream_puts_double(ofs2, ((bj->trans).iu.y1 - (bj->trans).iu.y0));
		DKSP(1); DKSP(75); DKSP(1); DKSP(74); DKSP(0);
		/* change color to gray */
		dkstream_puts_double(ofs2, gray);
		DKSP(1); DKSP(69); DKSP(0);
		/* middle rectangle */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x0 + douter.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y0 + douter.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x1 - (bj->trans).iu.x0 - 2.0 * douter.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y1 - (bj->trans).iu.y0 - 2.0 * douter.d)
		); DKSP(1); DKSP(75); DKSP(1); DKSP(74); DKSP(0);
		/* change color to white */
		dkstream_puts_double(ofs2, 1.0); DKSP(1); DKSP(69); DKSP(0);
		/* inner rectangle */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x0 + dinner.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y0 + dinner.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x1 - (bj->trans).iu.x0 - 2.0 * dinner.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y1 - (bj->trans).iu.y0 - 2.0 * dinner.d)
		); DKSP(1); DKSP(75); DKSP(1); DKSP(74); DKSP(0);
		/* change color to gray */
		dkstream_puts_double(ofs2, gray);
		DKSP(1); DKSP(69); DKSP(0);
		/* large diagonal lines */
		/*	x0+douter.d y0+douter.d moveto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x0 + douter.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y0 + douter.d)
		); DKSP(1); DKSP(71); DKSP(0);
		/*	x0+douter.d+dinner.deltax y0+douter.d lineto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x0 + douter.d + dinner.deltax)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y0 + douter.d)
		); DKSP(1); DKSP(72); DKSP(0);
		/*	x1-douter.d y1-douter.d-dinner.deltay lineto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x1 - douter.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y1 - douter.d - dinner.deltay)
		); DKSP(1); DKSP(72); DKSP(0);
		/*	x1-douter.d y1-douter.d lineto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x1 - douter.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y1 - douter.d)
		); DKSP(1); DKSP(72); DKSP(0);
		/*	x1-douter.d-dinner.deltax y1-douter.d lineto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x1 - douter.d - dinner.deltax)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y1 - douter.d)
		); DKSP(1); DKSP(72); DKSP(0);
		/*	x0+douter.d y0+douter.d+dinnter.deltax lineto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x0 + douter.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y0 + douter.d + dinner.deltax)
		); DKSP(1); DKSP(72); DKSP(0);
		/*	closepath fill */
		DKSP(73); DKSP(1); DKSP(74); DKSP(0);
		/*	x0+douter.d y1-douter.d moveto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x0 + douter.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y1 - douter.d)
		); DKSP(1); DKSP(71); DKSP(0);
		/*	x0+douter.d y1-douter.d-dinner.deltay lineto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x0 + douter.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y1 - douter.d - dinner.deltay)
		); DKSP(1); DKSP(72); DKSP(0);
		/*	x1-douterd-dinner.deltax y0+douter.d lineto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x1 - douter.d - dinner.deltax)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y0 + douter.d)
		); DKSP(1); DKSP(72); DKSP(0);
		/*	x1-douter.d y0+douter.d lineto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x1 - douter.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y0 + douter.d)
		); DKSP(1); DKSP(72); DKSP(0);
		/*	x1-douter.d y0+douter.d+dinner.deltay lineto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x1 - douter.d)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y0 + douter.d + dinner.deltay)
		); DKSP(1); DKSP(72); DKSP(0);
		/*	x0+douter.d+dinner.deltax y1-douter.d lineto */
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.x0 + douter.d + dinner.deltax)
		); DKSP(1);
		dkstream_puts_double(
		  ofs2,
		  ((bj->trans).iu.y1 - douter.d)
		); DKSP(1); DKSP(72); DKSP(0);
		/*	closepath fill */
		DKSP(73); DKSP(1); DKSP(74); DKSP(0);
		/* change color to red or black */
		if((bj->bo2)->opt & BMEPS_OPT_COLOR_OUTPUT) {
		  dkstream_puts_double(ofs2, r);
		  DKSP(1);
		  dkstream_puts_double(ofs2, g);
		  DKSP(1);
		  dkstream_puts_double(ofs2, b);
		  DKSP(1); DKSP(70);
		} else {
		  dkstream_puts_double(ofs2, black);
		  DKSP(1); DKSP(69);
		} DKSP(0);
	        if(!dkof_end_chunk(ofs2)) {
		  bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 69);
		  bj->exval = 1;
		  data_ok = 0;
		}
	      } else {
		bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 68);
		bj->exval = 1;
		data_ok = 0;
	      }
	    } else {
	      bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 70);
	      bj->exval = 1;
	    }
	    dkof_close(ofs2); ofs2 = NULL;
	  } else {
	    bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 70);
	    bj->exval = 1;
	  }
	  dkstream_close(ofs1); ofs1 = NULL;
	  if(data_ok) {
	    if(dkstat_get(&stbuf, bj->tmp2)) {
	      filesize = (unsigned long)dkstat_size(&stbuf);
	      gfile = dksf_fopen(bj->tmp2, "rb");
	      if(gfile) {
	        pdf_begin_object(bj, psp+i);
		pdf_open_dictionary(bj); kw_out(bj, 0);
		kw_out(bj, 27); kw_out(bj, 0);
		kw_out(bj, 29); kw_out(bj, 1);
		pdf_write_reference(bj, bj->psp); kw_out(bj, 0);
		kw_out(bj, 28); kw_out(bj, 1);
		kw_out(bj, 10);
		if(bmeps_tool_how_to_handle_bb(bj) == 1) {
                  dkstream_puts_double(bj->os, 0.0);
	          kw_out(bj, 1);
                  dkstream_puts_double(bj->os, 0.0);
	          kw_out(bj, 1);
                  dkstream_puts_double(bj->os, ((bj->trans).iu.x1 - (bj->trans).iu.x0));
	          kw_out(bj, 1);
                  dkstream_puts_double(bj->os, ((bj->trans).iu.y1 - (bj->trans).iu.y0));
		} else {
		  dkstream_puts_ul(bj->os, (bj->trans).bb.x0);
		  kw_out(bj, 1);
		  dkstream_puts_ul(bj->os, (bj->trans).bb.y0);
		  kw_out(bj, 1);
		  dkstream_puts_ul(bj->os, (bj->trans).bb.x1);
		  kw_out(bj, 1);
		  dkstream_puts_ul(bj->os, (bj->trans).bb.y1);
		}
		kw_out(bj, 11); kw_out(bj, 0);
		kw_out(bj, 30); kw_out(bj, 1);
		pdf_open_dictionary(bj); kw_out(bj, 1);
		kw_out(bj, 31); kw_out(bj, 1);
		kw_out(bj, 10); kw_out(bj, 33); kw_out(bj, 11);
		pdf_close_dictionary(bj); kw_out(bj, 0);
		kw_out(bj, 36); kw_out(bj, 1);
		pdf_write_reference(bj, csp+i); kw_out(bj, 0);
		pdf_close_dictionary(bj); kw_out(bj, 0);
		pdf_end_object(bj);
		pdf_begin_object(bj, csp+i);
		pdf_open_dictionary(bj);
		kw_out(bj, 38); kw_out(bj, 1);
		dkstream_puts_ul(bj->os, filesize);
#if !DEBUG
		kw_out(bj, 1); kw_out(bj, 57); kw_out(bj, 1); kw_out(bj, 10);
		if((bj->bo2)->enc & BMEPS_ENCODING_ASCII85) {
		  kw_out(bj, 42);
		} else {
		  kw_out(bj, 41);
		}
		if((bj->bo2)->enc & BMEPS_ENCODING_FLATE) {
		  kw_out(bj, 1); kw_out(bj, 44);
		} else {
		}
		kw_out(bj, 11);
#endif
		pdf_close_dictionary(bj); kw_out(bj, 0);
		kw_out(bj, 39); kw_out(bj, 0);
		transfer_file_to_stream(bj->os, gfile, filesize);
		kw_out(bj, 40); kw_out(bj, 0);
		pdf_end_object(bj);
	        fclose(gfile); gfile = NULL;
	      } else {
	        bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 62, 63, bj->tmp2);
	        bj->exval = 1;
	      }
	    } else {
	      bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 64, 65, bj->tmp2);
	      bj->exval = 1;
	    }
	  }
	} else {
	  bmeps_tool_msg_3(bj, DK_LOG_LEVEL_ERROR, 66, 67, bj->tmp2);
	  bj->exval = 1;
	}
      } else {
	bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 72); bj->exval = 1;
      }
    } else {
      bmeps_tool_msg_1(bj, DK_LOG_LEVEL_ERROR, 71); bj->exval = 1;
    }
    fno++; i++;
    
  }
  
}



/**	Create PDF object structure.
	@param	bj	Bmeps job.
	@param	how	0=normal,1=DCT,2=draft.
*/
static
void
pdf_file_objects DK_P2(BJ *,bj, int,how)
{
  switch(how) {
    case 1: {	
#if DK_HAVE_JPEGLIB_H
      pdf_file_objects_dct(bj);
#else
      pdf_file_objects_normally(bj);
#endif
    } break;
    case 2: {	
      pdf_file_objects_draft(bj);
    } break;
    default: {	
      pdf_file_objects_normally(bj);
    } break;
  }
}



/**	Finish PDF file (write xref table).
	@param	bj	Bmeps job.
	@param	how	Ignored.
*/
static
void
pdf_file_end DK_P2(BJ *,bj, int,how)
{
  unsigned long i;
  unsigned long pos, start_xref;
  char buffer[32];
  PDFOBJPOS *pop;
  start_xref = dkstream_get_bytes_written(bj->os);
  kw_out(bj, 12); kw_out(bj, 1);
  dkstream_puts_ul(bj->os, 0UL);
  kw_out(bj, 1);
  dkstream_puts_ul(bj->os, bj->nexto);
  kw_out(bj, 0);
  kw_out(bj, 16); kw_out(bj, 0);
  for(i = 1UL; i < bj->nexto; i++) {
    pos = 0UL;
    pop = dksto_it_find_like(bj->pdfobjsi, (void *)(&i), 1);
    if(pop) { pos = pop->pos; }
    sprintf(buffer, kw[17], pos);
    dkstream_puts(bj->os, buffer); kw_out(bj, 0);
  }
  kw_out(bj, 13); kw_out(bj, 0);
  pdf_open_dictionary(bj); kw_out(bj, 1);
  kw_out(bj, 18); kw_out(bj, 1);
  dkstream_puts_ul(bj->os, bj->nexto); kw_out(bj, 1);
  kw_out(bj, 19); kw_out(bj, 1);
  pdf_close_dictionary(bj); kw_out(bj, 0);
  kw_out(bj, 14); kw_out(bj, 0);
  dkstream_puts_ul(bj->os, start_xref); kw_out(bj, 0);
  kw_out(bj, 15); kw_out(bj, 0);
}



/**	Convert to PDF.
	@param	bj	Bmeps job.
	@param	how	Conversion type (0=normal, 1=DCT-passthrough, 2=draft.
*/
void
bmeps_pdf DK_P2(BJ *,bj, int,how)
{
  PDFOBJPOS *pop;
  BO mybo;
  if(bj) {
    if(bj->os) {
      dkstream_set_double_no_exponent(bj->os, 1);
    }
    bj->bo2 = &mybo;
    bj->pdfobjs = dksto_open(0);
    if(bj->pdfobjs) {
      dksto_set_comp(bj->pdfobjs, compare_obj_pos, 0);
      bj->pdfobjsi = dksto_it_open(bj->pdfobjs);
      if(bj->pdfobjsi) {
        bj->nexto = 1UL;
	bj->frame_n = bj->frame_e - bj->frame_s + 1L;
	pdf_file_start(bj, how);
	pdf_file_objects(bj, how);
	pdf_file_end(bj, how);
	dksto_it_reset(bj->pdfobjsi);
	/* release objects */
	while((pop = dksto_it_next(bj->pdfobjsi)) != NULL) {
	  dk_delete(pop);
	}
        dksto_it_close(bj->pdfobjsi); bj->pdfobjsi = NULL;
      } else {
	bmeps_tool_error_memory(bj);
      }
      dksto_close(bj->pdfobjs); bj->pdfobjs = NULL;
    } else {
      bmeps_tool_error_memory(bj);
    }
    bj->bo2 = NULL;
  }
}




