Tizen 2.1 base
[platform/upstream/hplip.git] / prnt / hpijs / hpcupsfax.cpp
1 /*****************************************************************************\
2     hpcupsfax.cpp : HP CUPS fax filter
3
4     Copyright (c) 2001 - 2010, Hewlett-Packard Co.
5     All rights reserved.
6
7     Redistribution and use in source and binary forms, with or without
8     modification, are permitted provided that the following conditions
9     are met:
10     1. Redistributions of source code must retain the above copyright
11        notice, this list of conditions and the following disclaimer.
12     2. Redistributions in binary form must reproduce the above copyright
13        notice, this list of conditions and the following disclaimer in the
14        documentation and/or other materials provided with the distribution.
15     3. Neither the name of the Hewlett-Packard nor the names of its
16        contributors may be used to endorse or promote products derived
17        from this software without specific prior written permission.
18
19     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24     NOT LIMITED TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29     POSSIBILITY OF SUCH DAMAGE.
30 \*****************************************************************************/
31
32 #include <sys/stat.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <syslog.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <stdint.h>
41 #include <time.h>
42 #include <sys/time.h>
43 #include <arpa/inet.h>
44 #include <math.h>
45 #include <cups/cups.h>
46 #include <cups/raster.h>
47 #include <string>
48 #ifdef FALSE
49 #undef FALSE
50 #endif
51 #ifdef TRUE
52 #undef TRUE
53 #endif
54 #include "hpip.h"
55 #include "hpcupsfax.h"
56 #include "bug.h"
57 using namespace std;
58
59 int    fax_encoding = RASTER_MMR;
60 char   device_name[16];
61 BYTE   szFileHeader[68];
62 BYTE   szPageHeader[64];
63
64 uint32_t (*convert_endian_l)(uint32_t);
65 uint16_t (*convert_endian_s)(uint16_t);
66
67 static int iLogLevel = 1;
68 char hpFileName[] = "/tmp/hplipfaxLog_XXXXXX";
69
70 #define TIFF_HDR_SIZE 8
71 #define LITTLE_ENDIAN_MODE I
72 #define BIG_ENDIAN_MODE M
73
74 #define DBG(args...) syslog(LOG_INFO, __FILE__ " " STRINGIZE(__LINE__) ": " args)
75
76 // GrayLevel = (5/16)R + (9/16)G + (2/16)B
77 #define RGB2BW(r, g, b) (BYTE) (((r << 2) + r + (g << 3) + g + (b << 1)) >> 4)
78
79 void RGB2Gray (BYTE *pRGBData, int iNumPixels, BYTE *pGData)
80 {
81     int     i;
82     BYTE    *pIn = pRGBData;
83     BYTE    *pOut = pGData;
84     for (i = 0; i < iNumPixels; i++, pIn += 3)
85     {
86         *pOut++ = RGB2BW ((unsigned short) *pIn, (unsigned short) pIn[1], (unsigned short) pIn[2]);
87     }
88 }
89
90 static void GetLogLevel ()
91 {
92     FILE    *fp;
93     char    str[258];
94     char    *p;
95     fp = fopen ("/etc/cups/cupsd.conf", "r");
96     if (fp == NULL)
97         return;
98     while (!feof (fp))
99     {
100         if (!fgets (str, 256, fp))
101         {
102             break;
103         }
104         if ((p = strstr (str, "hpLogLevel")))
105         {
106             p += strlen ("hpLogLevel") + 1;
107             iLogLevel = atoi (p);
108             break;
109         }
110     }
111     fclose (fp);
112 }
113
114 void PrintCupsHeader (cups_page_header2_t m_cupsHeader)
115 {
116     if (iLogLevel == 0)
117     {
118         return;
119     }
120     BUG ("DEBUG: HPFAX - startPage...\n");
121     BUG ("DEBUG: HPFAX - MediaClass = \"%s\"\n", m_cupsHeader.MediaClass);
122     BUG ("DEBUG: HPFAX - MediaColor = \"%s\"\n", m_cupsHeader.MediaColor);
123     BUG ("DEBUG: HPFAX - MediaType = \"%s\"\n", m_cupsHeader.MediaType);
124     BUG ("DEBUG: HPFAX - OutputType = \"%s\"\n", m_cupsHeader.OutputType);
125     BUG ("DEBUG: HPFAX - AdvanceDistance = %d\n", m_cupsHeader.AdvanceDistance);
126     BUG ("DEBUG: HPFAX - AdvanceMedia = %d\n", m_cupsHeader.AdvanceMedia);
127     BUG ("DEBUG: HPFAX - Collate = %d\n", m_cupsHeader.Collate);
128     BUG ("DEBUG: HPFAX - CutMedia = %d\n", m_cupsHeader.CutMedia);
129     BUG ("DEBUG: HPFAX - Duplex = %d\n", m_cupsHeader.Duplex);
130     BUG ("DEBUG: HPFAX - HWResolution = [ %d %d ]\n", m_cupsHeader.HWResolution[0], m_cupsHeader.HWResolution[1]);
131     BUG ("DEBUG: HPFAX - ImagingBoundingBox = [ %d %d %d %d ]\n",
132                m_cupsHeader.ImagingBoundingBox[0], m_cupsHeader.ImagingBoundingBox[1],
133                m_cupsHeader.ImagingBoundingBox[2], m_cupsHeader.ImagingBoundingBox[3]);
134     BUG ("DEBUG: HPFAX - InsertSheet = %d\n", m_cupsHeader.InsertSheet);
135     BUG ("DEBUG: HPFAX - Jog = %d\n", m_cupsHeader.Jog);
136     BUG ("DEBUG: HPFAX - LeadingEdge = %d\n", m_cupsHeader.LeadingEdge);
137     BUG ("DEBUG: HPFAX - Margins = [ %d %d ]\n", m_cupsHeader.Margins[0], m_cupsHeader.Margins[1]);
138     BUG ("DEBUG: HPFAX - ManualFeed = %d\n", m_cupsHeader.ManualFeed);
139     BUG ("DEBUG: HPFAX - MediaPosition = %d\n", m_cupsHeader.MediaPosition);
140     BUG ("DEBUG: HPFAX - MediaWeight = %d\n", m_cupsHeader.MediaWeight);
141     BUG ("DEBUG: HPFAX - MirrorPrint = %d\n", m_cupsHeader.MirrorPrint);
142     BUG ("DEBUG: HPFAX - NegativePrint = %d\n", m_cupsHeader.NegativePrint);
143     BUG ("DEBUG: HPFAX - NumCopies = %d\n", m_cupsHeader.NumCopies);
144     BUG ("DEBUG: HPFAX - Orientation = %d\n", m_cupsHeader.Orientation);
145     BUG ("DEBUG: HPFAX - OutputFaceUp = %d\n", m_cupsHeader.OutputFaceUp);
146     BUG ("DEBUG: HPFAX - PageSize = [ %d %d ]\n", m_cupsHeader.PageSize[0], m_cupsHeader.PageSize[1]);
147     BUG ("DEBUG: HPFAX - Separations = %d\n", m_cupsHeader.Separations);
148     BUG ("DEBUG: HPFAX - TraySwitch = %d\n", m_cupsHeader.TraySwitch);
149     BUG ("DEBUG: HPFAX - Tumble = %d\n", m_cupsHeader.Tumble);
150     BUG ("DEBUG: HPFAX - cupsWidth = %d\n", m_cupsHeader.cupsWidth);
151     BUG ("DEBUG: HPFAX - cupsHeight = %d\n", m_cupsHeader.cupsHeight);
152     BUG ("DEBUG: HPFAX - cupsMediaType = %d\n", m_cupsHeader.cupsMediaType);
153     BUG ("DEBUG: HPFAX - cupsRowStep = %d\n", m_cupsHeader.cupsRowStep);
154     BUG ("DEBUG: HPFAX - cupsBitsPerColor = %d\n", m_cupsHeader.cupsBitsPerColor);
155     BUG ("DEBUG: HPFAX - cupsBitsPerPixel = %d\n", m_cupsHeader.cupsBitsPerPixel);
156     BUG ("DEBUG: HPFAX - cupsBytesPerLine = %d\n", m_cupsHeader.cupsBytesPerLine);
157     BUG ("DEBUG: HPFAX - cupsColorOrder = %d\n", m_cupsHeader.cupsColorOrder);
158     BUG ("DEBUG: HPFAX - cupsColorSpace = %d\n", m_cupsHeader.cupsColorSpace);
159     BUG ("DEBUG: HPFAX - cupsCompression = %d\n", m_cupsHeader.cupsCompression);
160     BUG ("DEBUG: HPFAX - cupsPageSizeName = %s\n", m_cupsHeader.cupsPageSizeName);
161 }
162
163 int GetPageSizeFromString(char *string)
164 {
165    int iPageSize = atoi(string);
166    if(iPageSize == 0)
167    {
168       if(strcmp(string,"Letter") ==0){
169          iPageSize = 1;
170       }
171       else if(strcmp(string,"A4") ==0){
172          iPageSize = 2;
173       }
174       else if(strcmp(string,"Legal") ==0){
175          iPageSize = 3;
176       }
177       else{
178          DBG("hpcupsfax: GetPageSizeFromString:Default Page Size is taken,ensure it is ok.\n");
179          iPageSize = 1;
180       }
181    }
182    DBG("hpcupsfax: GetPageSizeFromString: PageSize = %d\n",iPageSize);
183    return iPageSize;
184 }     
185
186 int  ProcessRasterData (cups_raster_t *cups_raster, int fdFax)
187 {
188     int                status = 0;
189     unsigned int                i;
190     int                widthMMR;
191     int                iInputBufSize;
192     BYTE               *pThisScanLine;
193     LPBYTE             pbOutputBuf = NULL;
194     LPBYTE             pInputBuf = NULL;
195     IP_XFORM_SPEC      xForm[3];
196     IP_IMAGE_TRAITS    traits;
197     IP_HANDLE          hJob;
198
199     BYTE                *p;
200     cups_page_header2_t    cups_header;
201     int                    iPageNum = 0;
202     int                    color_mode;
203     char                   *pDev;
204     unsigned    int     uiPageNum = 0;
205
206     pDev = getenv ("DEVICE_URI");
207
208     while (cupsRasterReadHeader2 (cups_raster, &cups_header))
209     {
210         iPageNum++;
211         if (iPageNum == 1)
212         {
213             PrintCupsHeader (cups_header);
214             color_mode = (cups_header.cupsRowStep == 0) ? HPLIPFAX_MONO : HPLIPFAX_COLOR;
215             if (color_mode == HPLIPFAX_COLOR)
216             {
217                 fax_encoding = RASTER_JPEG;
218             }
219             memset (szFileHeader, 0, sizeof (szFileHeader));
220             memcpy (szFileHeader, "hplip_g3", 8);
221             p = szFileHeader + 8;
222             *p++ = 1;                                    // Version Number
223             HPLIPPUTINT32 (p, 0); p += 4;                // Total number of pages in this job
224             HPLIPPUTINT16 (p, cups_header.HWResolution[0]); p += 2;
225             HPLIPPUTINT16 (p, cups_header.HWResolution[1]); p += 2;
226             BUG("ATOI Value  = %d",atoi (cups_header.cupsPageSizeName));
227             *p++ = GetPageSizeFromString(cups_header.cupsPageSizeName);  // Output paper size
228             *p++ = atoi (cups_header.OutputType);        // Output quality
229             *p++ = fax_encoding;                         // MH, MMR or JPEG
230             p += 4;                                      // Reserved 1
231             p += 4;                                      // Reserved 2
232             write (fdFax, szFileHeader, (p - szFileHeader));
233         }
234
235         widthMMR = (((cups_header.cupsWidth + 7) >> 3)) << 3;
236         
237 /*
238  *      Devices in the HPFax2 category require fixed width of 2528 pixels.
239  *      Example: LaserJet 2727 MFP
240  */
241        
242         if (strcmp (device_name, "HPFax4") ==0)
243         {
244             widthMMR = 1728;                      
245         }
246         else if (!strcmp (device_name, "HPFax2"))
247         {
248             widthMMR = 2528;
249         }              
250         iInputBufSize = widthMMR * cups_header.cupsHeight;
251
252         pInputBuf = (LPBYTE) malloc (iInputBufSize);
253         if (pInputBuf == NULL)
254         {
255             BUG ("Unable to allocate pInputBuf, size = %d\n", iInputBufSize);
256             goto BUGOUT;
257         }
258         memset (pInputBuf, 0xFF, iInputBufSize);
259
260         pThisScanLine = new BYTE[cups_header.cupsBytesPerLine];
261         if (pThisScanLine == NULL)
262         {
263             BUG ("Unable to allocate pThisScanLine, size = %d\n", cups_header.cupsBytesPerLine);
264             goto BUGOUT;
265         }
266
267         for (i = 0; i < cups_header.cupsHeight; i++)
268         {
269             cupsRasterReadPixels (cups_raster, pThisScanLine, cups_header.cupsBytesPerLine);
270             RGB2Gray (pThisScanLine, cups_header.cupsWidth, pInputBuf + i * widthMMR);
271         }
272
273         WORD         wResult;
274         DWORD        dwInputAvail;
275         DWORD        dwInputUsed;
276         DWORD        dwInputNextPos;
277         DWORD        dwOutputAvail;
278         DWORD        dwOutputUsed;
279         DWORD        dwOutputThisPos;
280         pbOutputBuf = (LPBYTE) malloc (iInputBufSize);
281         if (pbOutputBuf == NULL)
282         {
283             BUG ("unable to allocate pbOutputBuf,  buffer size = %d\n", iInputBufSize);
284             goto BUGOUT;
285         }
286         memset (pbOutputBuf, 0xFF, iInputBufSize);
287
288         memset (xForm, 0, sizeof (xForm));
289
290         if (color_mode == HPLIPFAX_MONO)
291         {
292             i = 0;
293             xForm[i].eXform = X_GRAY_2_BI;
294
295             // 0   - Error diffusion
296             // >0  - Threshold value
297
298             xForm[i].aXformInfo[IP_GRAY_2_BI_THRESHOLD].dword = 127;
299             i++;
300
301             xForm[i].eXform = X_FAX_ENCODE;
302             if (fax_encoding== RASTER_MMR)
303             {
304                 xForm[i].aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MMR;
305             }
306             else
307             {
308                 xForm[i].aXformInfo[IP_FAX_FORMAT].dword = IP_FAX_MH;
309             }
310  /*         0 = EOLs are in data as usual; */
311  /*         1 = no EOLs in data. */
312             xForm[i].aXformInfo[IP_FAX_NO_EOLS].dword = 0;
313             xForm[i].pXform = NULL;
314             xForm[i].pfReadPeek = NULL;
315             xForm[i].pfWritePeek = NULL;
316             i++;
317
318             wResult = ipOpen (i, xForm, 0, &hJob);
319             traits.iComponentsPerPixel = 1;
320             traits.iBitsPerPixel = 8;
321         }
322         else
323         {
324             xForm[0].eXform = X_CNV_COLOR_SPACE;
325             xForm[0].aXformInfo[IP_CNV_COLOR_SPACE_WHICH_CNV].dword = IP_CNV_SRGB_TO_YCC;
326             xForm[1].eXform = X_CNV_COLOR_SPACE;
327             xForm[1].aXformInfo[IP_CNV_COLOR_SPACE_WHICH_CNV].dword = IP_CNV_YCC_TO_CIELAB;
328             xForm[0].eXform = X_JPG_ENCODE;
329             xForm[0].aXformInfo[IP_JPG_ENCODE_FOR_COLOR_FAX].dword = 1;
330             wResult = ipOpen (1, xForm, 0, &hJob);
331             traits.iComponentsPerPixel = 3;
332             traits.iBitsPerPixel = 8;
333         }
334
335         if (wResult != IP_DONE)
336         {
337             BUG ("ipOpen failed: wResult = %x\n", wResult);
338             goto BUGOUT;
339         }
340         traits.iPixelsPerRow = widthMMR;
341         traits.lHorizDPI     = cups_header.HWResolution[0];
342         traits.lVertDPI      = cups_header.HWResolution[1];
343         traits.lNumRows      = cups_header.cupsHeight;
344         traits.iNumPages     = 1;
345         traits.iPageNum      = 1;
346
347         wResult = ipSetDefaultInputTraits (hJob, &traits);
348         if (wResult != IP_DONE)
349         {
350             BUG ("ipSetDefaultInputTraits failed: wResult = %x\n", wResult);
351             wResult = ipClose (hJob);
352             goto BUGOUT;
353         }
354         dwInputAvail = iInputBufSize;
355         dwOutputAvail = dwInputAvail;
356
357         wResult = ipConvert (hJob, dwInputAvail, pInputBuf, &dwInputUsed,
358                              &dwInputNextPos, dwOutputAvail, pbOutputBuf,
359                              &dwOutputUsed, &dwOutputThisPos);
360
361         if (wResult == IP_FATAL_ERROR)
362         {
363             BUG ("ipConvert failed, wResult = %d\n", wResult);
364             goto BUGOUT;
365         }
366         if (iLogLevel > 0)
367         {
368             BUG ("dwInputAvail = %d dwInputUsed = %d dwOutputUsed = %d\n",
369                  dwInputAvail, dwInputUsed, dwOutputUsed);
370         }
371         wResult = ipClose (hJob);
372         hJob = 0;
373
374         uiPageNum++;
375
376         p = szPageHeader;
377         HPLIPPUTINT32 (p, uiPageNum); p += 4;                // Current page number
378         HPLIPPUTINT32 (p, widthMMR); p += 4;                // Num of pixels per row
379         HPLIPPUTINT32 (p, cups_header.cupsHeight); p += 4;    // Num of rows in this page
380         HPLIPPUTINT32 (p, dwOutputUsed); p += 4;            // Size in bytes of encoded data
381         HPLIPPUTINT32 (p, 0); p += 4;                        // Thumbnail data size
382         HPLIPPUTINT32 (p, 0); p += 4;                        // Reserved for future use
383         write (fdFax, szPageHeader, (p - szPageHeader));
384         write (fdFax, pbOutputBuf, dwOutputUsed);
385 /*
386  *      Write the thumbnail data here
387  */
388
389         // Send this to fax handler
390
391         free (pbOutputBuf);
392         free (pInputBuf);
393         free (pThisScanLine);
394         pbOutputBuf = NULL;
395         pInputBuf = NULL;
396         pThisScanLine = NULL;
397
398     } /* end while (1) */
399
400     lseek (fdFax, 9, SEEK_SET);
401     HPLIPPUTINT32 ((szFileHeader + 9), uiPageNum);
402     write (fdFax, szFileHeader + 9, 4);
403
404 BUGOUT:
405     if (pbOutputBuf)
406     {
407         free (pbOutputBuf);
408     }
409
410     if (pInputBuf)
411     {
412         free (pInputBuf);
413     }
414
415     return status;
416 }
417
418 /* 
419  * Return Zero if all the below are successful
420  * Reading from stdin into a temp file
421  * Getting the final file with HPLIP file and page headers
422  */
423 int ProcessTiffData(int fromFD, int toFD)
424 {
425     BYTE      *p;
426     int       fdTiff;
427     BYTE      pTmp[4096];
428     struct timeval tv;
429     fd_set fds;
430     int page_length;
431     unsigned int page_counter;
432     unsigned int current_ifd_start;
433     unsigned int *ifd_offset;
434     unsigned int next_ifd_offset;
435     unsigned short ifd_count;
436     bool big_endian = false;
437     int i, ret, len;
438     BYTE   szTiffHeader[TIFF_HDR_SIZE];
439     int bytes_written = 0;
440     int ret_status = 0;
441     int bytes_read = 0;
442     char hpTiffFileName[] = "/tmp/hpliptiffXXXXXX";
443     long input_file_size = 0;
444
445     fdTiff = mkstemp (hpTiffFileName);
446     if (fdTiff < 0)
447     {
448         BUG ("ERROR: Unable to open Fax output file - %s for writing\n", hpTiffFileName);
449         return 1;
450     }
451
452     memset (szFileHeader, 0, sizeof (szFileHeader));
453     memcpy (szFileHeader, "hplip_g3", 8);
454     p = szFileHeader + 8;
455     *p++ = 1;                                    // Version Number
456     HPLIPPUTINT32 (p, 0); p += 4;                // Total number of pages in this job
457     HPLIPPUTINT16 (p, 0); p += 2;  //HWResolution[0]
458     HPLIPPUTINT16 (p, 0); p += 2;  //HWResolution[0]
459     *p++ = atoi ("0");  // Output paper size (cupsPageSizeName)
460     *p++ = atoi ("0");        // Output quality (cups OutputType)
461     *p++ = fax_encoding;                         // MH, MMR or JPEG, TIFF
462     p += 4;                                      // Reserved 1
463     p += 4;                                      // Reserved 2
464     write (toFD, szFileHeader, (p - szFileHeader));
465
466     FD_ZERO(&fds);
467     FD_SET(fromFD, &fds);
468     tv.tv_sec = 0;
469     tv.tv_usec = 100 * 1000; //100 ms
470     i = 0;
471
472     
473     len = read (fromFD, pTmp, 4096);
474     if (len > 0) {
475        DBG("hpcupsfax: read %d bytes from stdin", len);
476        write (fdTiff, pTmp, len);
477        bytes_written += len;
478     } else {
479            DBG("hpcupsfax: No data was available...");
480     }
481
482     while (i++ < 10)
483     {
484         memset (pTmp, 0, 4096);
485         ret = select(fromFD+1, &fds, NULL, NULL, &tv);
486         if (ret < 0) {
487             DBG("hpcupsfax: Timed out, Continue...");
488             continue;
489         }
490
491         if (FD_ISSET(fromFD, &fds)) {
492            DBG("hpcupsfax: Data is available");
493            while(1) {
494               memset (pTmp, 0, 4096);
495               len = read (fromFD, pTmp, 4096);
496               DBG("hpcupsfax: read %d bytes from stdin", len);
497               if (len <= 0) {
498                   DBG("hpcupsfax: No data was available, Continue...");
499                   break; //break from inner while()
500               }
501               write (fdTiff, pTmp, len);
502               bytes_written += len;
503            }
504         }
505     }
506     DBG("hpcupsfax: total bytes written to fdTiff is  %d ", bytes_written);
507     input_file_size = bytes_written;
508
509     ret = lseek (fdTiff, 0, SEEK_SET);
510     memset (szTiffHeader, 0, sizeof (TIFF_HDR_SIZE));
511     ret = read (fdTiff, szTiffHeader, 8);
512     DBG("hpcupsfax: read %d bytes from fdTiff", ret);
513     ifd_offset = (unsigned int *) &(szTiffHeader[4]);
514     if (szTiffHeader[0] == 'M') {
515        DBG("hpcupsfax: it is big endian");
516        big_endian = true;
517        *ifd_offset = ntohl(*ifd_offset); 
518     }
519     DBG("hpcupsfax: ifd_offset is %d", *ifd_offset);
520  
521     current_ifd_start = 0;
522     page_counter = 0;
523     bytes_written = 0;
524 //WHILE
525     while(1) {
526         // Note down the number of tags 
527         ret = lseek (fdTiff, *ifd_offset, SEEK_SET);
528         ret = read (fdTiff, &ifd_count, 2);
529         if (big_endian) {
530             ifd_count = ntohs(ifd_count);
531         }
532         DBG("hpcupsfax: read %d bytes from fdTiff; ifd count is %d", ret, ifd_count);
533
534         // Read the end of IFD to check if there is another IFD following (for e.g., next page or image)
535         ret = lseek (fdTiff, (*ifd_offset+2+((ifd_count)*12)), SEEK_SET);
536         ret = read (fdTiff, &next_ifd_offset, 4);
537         if (big_endian) {
538             next_ifd_offset = ntohs(next_ifd_offset);
539         }
540         DBG("hpcupsfax: read %d bytes from fdTiff at %d; next ifd offset is %d", 
541                                   ret, (*ifd_offset+2+((ifd_count)*12)), next_ifd_offset);
542
543         // Increment the page counter
544         page_counter = page_counter + 1;
545         DBG("hpcupsfax: Current page_counter is %d", page_counter);
546
547        // Write Tiff data for the current page (IFD)
548        page_length = next_ifd_offset-current_ifd_start;
549        DBG("hpcupsfax: page_length is %d ", page_length);
550        if (page_length <= 0) {
551            len = lseek (fdTiff, 0, SEEK_END);
552            page_length = len - current_ifd_start;
553        }
554        DBG("hpcupsfax: current_ifd_start=%d next_ifd_offset=%d total bytes are %d", current_ifd_start, next_ifd_offset, page_length);
555
556        // Write HPLIP page header
557        p = szPageHeader;
558        HPLIPPUTINT32 (p, page_counter); p += 4;     // Current page number
559        HPLIPPUTINT32 (p, 0); p += 4;                // Num of pixels per row - It is ImageWidth for Tiff
560        HPLIPPUTINT32 (p, 0); p += 4;                // Num of rows in this page - It is ImageLength for Tiff
561        HPLIPPUTINT32 (p, page_length); p += 4;      // Size in bytes of encoded data
562        HPLIPPUTINT32 (p, 0); p += 4;                // Thumbnail data size
563        HPLIPPUTINT32 (p, 0); p += 4;                // Reserved for future use
564        ret = write (toFD, szPageHeader, (p - szPageHeader));
565
566        ret = lseek (fdTiff, current_ifd_start, SEEK_SET);
567        while (page_length > 0) {
568             if (page_length < 4096) {
569                 len = page_length;
570             } else {
571                 len = 4096;
572             } 
573             bytes_read = read (fdTiff, pTmp, len);
574             ret = write (toFD, pTmp, bytes_read);
575             page_length = page_length - ret;
576             bytes_written += ret;
577        }
578
579        // If there is no next IFD, break from the loop. Else, continue...
580        if (bytes_written > input_file_size) {
581             BUG("Error!! Bytes written to toFD is becoming more than input file size.");
582             ret_status = -1;
583             break; // while(1) for page counting
584        }
585
586        if (next_ifd_offset == 0) {
587             break; // while(1) for page counting
588        }
589        current_ifd_start = *ifd_offset = next_ifd_offset;
590     } // while(1) for page counting
591
592     lseek (toFD, 9, SEEK_SET);
593     HPLIPPUTINT32 ((szFileHeader + 9), page_counter);
594     write (toFD, szFileHeader + 9, 4);
595
596     return ret_status;
597 }
598
599
600 int send_data_to_stdout(int fromFD)
601 {
602     int     iSize, i;
603     int     len;
604     BYTE    *pTmp = NULL;
605
606     iSize = lseek (fromFD, 0, SEEK_END);
607     lseek (fromFD, 0, SEEK_SET);
608
609     DBG("hpcupsfax: lseek(fromFD) returned %d", iSize);
610     if (iSize > 0)
611     {
612         pTmp = (BYTE *) malloc (iSize);
613     }
614     if (pTmp == NULL)
615     {
616         iSize = 1024;
617         pTmp = (BYTE *) malloc  (iSize);
618         if (pTmp == NULL)
619         {
620           return 1;
621         }
622     }
623
624     while ((len = read (fromFD, pTmp, iSize)) > 0)
625     {
626         write (STDOUT_FILENO, pTmp, len);
627     }
628     free (pTmp);
629
630     return 0;
631 }
632
633 int main (int argc, char **argv)
634 {
635     int                 status = 0;
636     int                 fd = 0;
637     int                 fdFax = -1;
638     int i = 0;
639     FILE                *fdTiff;
640     cups_raster_t       *cups_raster;
641     ppd_file_t          *ppd;
642     ppd_attr_t          *attr;
643     ppd_attr_t          *compression_attr;
644
645     /*********** PROLOGUE ***********/
646
647     GetLogLevel();
648     openlog("hpcupsfax", LOG_PID,  LOG_DAEMON);
649
650     if (argc < 6 || argc > 7)
651     {
652         BUG ("ERROR: %s job-id user title copies options [file]\n", *argv);
653         return 1;
654     }
655
656     if (argc == 7)
657     {
658         if ((fd = open (argv[6], O_RDONLY)) == -1)
659         {
660             BUG ("ERROR: Unable to open raster file %s\n", argv[6]);
661             return 1;
662         }
663     }
664
665     while (argv[i] != NULL) {
666          DBG("hpcupsfax: argv[%d] = %s\n", i, argv[i]);
667          i++;
668     }
669
670     fdFax = mkstemp (hpFileName);
671     if (fdFax < 0)
672     {
673         BUG ("ERROR: Unable to open Fax output file - %s for writing\n", hpFileName);
674         return 1;
675     }
676
677     /*********** MAIN ***********/
678
679     ppd = ppdOpenFile (getenv ("PPD"));
680     if (ppd == NULL)
681     {
682         BUG ("ERROR: Unable to open ppd file %s\n", getenv ("PPD"));
683         return 1;
684     }
685     if ((attr = ppdFindAttr (ppd, "cupsModelName", NULL)) == NULL ||
686         (attr && attr->value == NULL))
687     {
688         ppdClose (ppd);
689         BUG ("ERROR: Required cupsModelName is missing in ppd file\n");
690         return 1;
691     }
692
693     memset (device_name, 0, sizeof (device_name));
694     strncpy (device_name, attr->value, 15);
695
696     if ((attr = ppdFindAttr (ppd, "DefaultEncoding", NULL)) == NULL ||
697         (attr && attr->value == NULL))
698     {
699         ppdClose (ppd);
700         BUG ("ERROR: Required DefaultEncoding is missing in ppd file\n");
701         return 1;
702     }     
703     if (strstr(argv[5],"Encoding=MMR"))
704     {
705        fax_encoding = RASTER_MMR;
706     }   
707     else if(strstr(argv[5],"Encoding=MH"))
708     {
709        fax_encoding = RASTER_MH; 
710     }       
711     else if (strstr(argv[5],"Encoding=Auto"))
712     { 
713        BUG ("WARNING: AUTO is selected for Fax Encoding! Ensure this type is correct for the device");                 
714        fax_encoding = RASTER_AUTO;
715     }    
716     else if (strstr(argv[5],"Encoding=TIFF"))
717     {
718        fax_encoding = RASTER_TIFF;
719     }
720     else
721     {
722        if(strcmp(attr->value,"MH") == 0) {
723           fax_encoding = RASTER_MH;
724        } else if(strcmp(attr->value,"MMR") == 0){
725           fax_encoding = RASTER_MMR;
726        }else if(strcmp(attr->value,"TIFF") ==0){
727           fax_encoding = RASTER_TIFF;               
728        }else if(strcmp(attr->value,"Auto") ==0){
729           BUG ("WARNING: AUTO is selected for Fax Encoding! Ensure this type is correct for the device");                 
730           fax_encoding = RASTER_AUTO;
731        }
732     }
733     if (fax_encoding < 0) {
734         BUG ("ERROR: Required DefaultEncoding is invalid in ppd file\n");
735         return 1;
736     }
737     DBG("hpcupsfax: main: fax_encoding = %d \n", fax_encoding);
738     ppdClose (ppd);
739
740     if (fax_encoding == RASTER_TIFF)
741     {
742         status = ProcessTiffData(fd, fdFax);
743     } else {
744        cups_raster = cupsRasterOpen (fd, CUPS_RASTER_READ);
745        if (cups_raster == NULL)
746        {
747            status = 1;
748            BUG ("cupsRasterOpen failed, fd = %d\n", fd);
749            goto EPILOGUE;
750        }
751
752        status = ProcessRasterData (cups_raster, fdFax);
753
754        cupsRasterClose (cups_raster);
755     }
756
757     DBG("hpcupsfax: Send data to stdout \n");
758     status = send_data_to_stdout(fdFax);
759
760     /*********** EPILOGUE ***********/
761 EPILOGUE:
762     if (fd != 0)
763     {
764         close (fd);
765     }
766
767     if (fdFax > 0)
768     {
769         close (fdFax);
770         if (!(iLogLevel & SAVE_PCL_FILE))
771         {
772              //Retain the intermediate file only if it is needed for debugging purpose.
773              unlink(hpFileName);
774         }
775     }
776
777     return status;
778 }
779