Code sync
[external/hplip.git] / prnt / hpcups / LJZjStream.cpp
1 /*****************************************************************************\
2   LJZjStream.cpp : Implementation for the LJZjStream class
3
4   Copyright (c) 1996 - 2009, 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 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 IMPLIED
20   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
22   NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24   TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25   OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26   ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30   Author: Naga Samrat Chowdary Narla,
31 \*****************************************************************************/
32
33 #include "CommonDefinitions.h"
34 #include "Pipeline.h"
35 #include "Encapsulator.h"
36 #include "ColorMatcher.h"
37 #include "Halftoner.h"
38 #include "ModeJbig.h"
39 #include "resources.h"
40 #include "ColorMaps.h"
41 #include "PrinterCommands.h"
42 #include "LJZjStream.h"
43 #include "Utils.h"
44 #include "hpjbig_wrapper.h"
45
46 #define ZJC_BAND_HEIGHT    100
47
48 LJZjStream::LJZjStream () : Encapsulator ()
49 {
50     memset(&m_PM, 0, sizeof(m_PM));
51     strcpy(m_szLanguage, "ZJS");
52     m_pModeJbig = NULL;
53     m_bNotSent = true;
54 }
55
56 LJZjStream::~LJZjStream()
57 {
58 }
59
60 DRIVER_ERROR LJZjStream::addJobSettings()
61 {
62     BYTE    cItems[3] = {ZJI_DMCOLLATE, ZJI_PAGECOUNT, ZJI_DMDUPLEX};
63         int nItems = 0;
64     addToHeader("%s", "@PJL ENTER LANGUAGE=ZJS\x0AJZJZ");
65     BYTE    *p = cur_pcl_buffer_ptr;
66
67         if (m_pJA->e_duplex_mode == DUPLEXMODE_NONE)
68     {
69             p[3] = 52;
70                 p[7] = ZJT_START_DOC;   
71             p[11] = 3;
72                 p[13] = 36 ;
73                 nItems = 3;             
74     }
75     else
76     {
77             p[3] = 28;
78                 p[7] = ZJT_START_DOC;   
79             p[11] = 1;
80                 p[13] = 12;
81                 nItems = 1;
82     }
83         
84         p[14] = 'Z';
85     p[15] = 'Z';
86     int    i = 16;
87     for (int j = 0; j < nItems; j++)
88     {
89         p[i + 3] = 12;
90         p[i + 5] = cItems[j];
91         p[i + 6] = ZJIT_UINT32;
92                 p[i + 11] = j / 2;                      
93         i += 12;
94     }
95     cur_pcl_buffer_ptr += i;
96     DRIVER_ERROR err = Cleanup();
97     return err;
98 }
99
100 DRIVER_ERROR LJZjStream::Configure(Pipeline **pipeline)
101 {
102     DRIVER_ERROR err;
103     Pipeline    *p = NULL;
104     Pipeline    *head;
105     unsigned int width;
106     ColorMatcher *pColorMatcher;
107     Halftoner    *pHalftoner;
108     int          iRows[MAXCOLORPLANES];
109     unsigned int uiResBoost;
110     head = *pipeline;
111
112 /*
113  *  I need a flag in the printmode structure to whether create a CMYGraymap
114  *  and set the ulMap1 to it.
115  */
116
117     m_PM.BaseResX = m_pQA->horizontal_resolution;
118     m_PM.BaseResY = m_pQA->vertical_resolution;
119     m_PM.eHT = FED;
120     m_PM.MixedRes = false;
121     m_PM.BlackFEDTable = HTBinary_open;
122     if (m_pJA->color_mode == 0)
123     {
124         m_PM.cmap.ulMap1 = NULL;
125         m_PM.cmap.ulMap2 = NULL;
126         m_PM.cmap.ulMap3 = ucMapDJ4100_KCMY_Photo_BestA_12x12x1;
127         m_PM.dyeCount = 4;
128         m_PM.ColorFEDTable = HT1200x1200x1PhotoBest_open;
129     }
130     else
131     {
132         m_PM.cmap.ulMap1 = ulMapDJ600_CCM_K;
133         m_PM.dyeCount = 1;
134         m_PM.ColorFEDTable = HTBinary_open;
135     }
136
137     for (int i = 0; i < MAXCOLORPLANES; i++)
138     {
139         m_PM.ColorDepth[i] = 1;
140         m_PM.ResolutionX[i] = m_pQA->horizontal_resolution;
141         m_PM.ResolutionY[i] = m_pQA->vertical_resolution;
142         iRows[i] = m_PM.ResolutionX[i] / m_PM.BaseResX;
143     }
144
145     uiResBoost = m_PM.BaseResX / m_PM.BaseResY;
146     if (uiResBoost == 0)
147         uiResBoost = 1;
148
149     width = m_pMA->printable_width;
150
151     pColorMatcher = new ColorMatcher(m_PM.cmap, m_PM.dyeCount, width);
152     head = new Pipeline(pColorMatcher);
153     pHalftoner = new Halftoner (&m_PM, width, iRows, uiResBoost, m_PM.eHT == MATRIX);
154     p = new Pipeline(pHalftoner);
155     head->AddPhase(p);
156     m_pModeJbig = new ModeJbig(width);
157     p = new Pipeline(m_pModeJbig);
158     head->AddPhase(p);
159     m_pModeJbig->myplane = COLORTYPE_COLOR;
160
161     m_iPlanes = 1;
162     m_iBpp = 1;
163     int    height = m_pMA->printable_height;
164     ZJPLATFORM    ezj_platform = ZJSTREAM;
165     if (!strcmp(m_pJA->printer_platform, "ljzjscolor"))
166     {
167         m_iBpp = 2;
168         ezj_platform = ZJCOLOR;
169         if (m_pJA->color_mode == 0)
170         {
171             m_iPlanes = 4;
172         }
173         height = ZJC_BAND_HEIGHT;
174
175     if(m_pJA->printer_platform_version == 2) 
176     {
177       height = m_pMA->printable_height;
178       ezj_platform = ZJCOLOR2; 
179     }
180     }
181     err = m_pModeJbig->Init(height, m_iPlanes, m_iBpp, ezj_platform);
182
183     *pipeline = head;
184     return err;
185 }
186
187 DRIVER_ERROR LJZjStream::StartPage_ljzjcolor2 (JobAttributes *pJA)
188 {
189   DWORD               dwNumItems = 13;
190   BYTE                szStr[16 + 12 * 13];
191   int                 i=0;
192
193   i = SendChunkHeader (szStr, 16 + dwNumItems * 12, ZJT_START_PAGE, dwNumItems);
194   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_PLANE, m_iPlanes);
195   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_DMPAPER, m_pMA->pcl_id);
196   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_DMCOPIES, 1);
197   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_DMDEFAULTSOURCE, m_pJA->media_source);
198   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_DMMEDIATYPE, m_pQA->media_type);     
199   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_NBIE, m_iPlanes);
200   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_RESOLUTION_X, m_pQA->horizontal_resolution);
201   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_RESOLUTION_Y, m_pQA->vertical_resolution);
202   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_RASTER_X, (((m_pMA->printable_width + 31) / 32) * 32) * m_iBpp);
203   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_RASTER_Y, m_pMA->printable_height);
204   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_VIDEO_BPP, m_iBpp);
205   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_VIDEO_X, (((m_pMA->printable_width + 31) / 32) * 32));
206   i += SendItem (szStr+i, ZJIT_UINT32, ZJI_VIDEO_Y, m_pMA->printable_height);
207   return Send ((const BYTE *) szStr, i);
208 }
209
210 DRIVER_ERROR LJZjStream::StartPage (JobAttributes *pJA)
211 {
212     DRIVER_ERROR        err = NO_ERROR;
213     DWORD               dwNumItems = 15;
214     BYTE                szStr[16 + 16 * 12];
215     int                 i;
216     int                 width;
217
218     m_iPlaneNumber = 0;
219     m_iCurRaster   = 0;
220     if((strcmp(m_pJA->printer_platform, "ljzjscolor") == 0) && (m_pJA->printer_platform_version == 2))
221     {
222        return StartPage_ljzjcolor2(pJA);
223     }
224
225         
226     if (m_pJA->e_duplex_mode == DUPLEXMODE_NONE)
227     {
228         dwNumItems = 14;                
229     }
230     else
231     {
232         dwNumItems = 15;                                
233     }
234
235     width = ((m_pMA->printable_width + 31) / 32) * 32;
236     if (m_pJA->color_mode == 0)
237         dwNumItems++;
238
239     i = 0;
240     i += SendChunkHeader (szStr, 16 + dwNumItems * 12, ZJT_START_PAGE, dwNumItems);
241     if (m_pJA->color_mode == 0)
242     {
243         i += SendItem (szStr+i, ZJIT_UINT32, ZJI_PLANE, m_iPlanes);
244     }
245
246     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_DMCOPIES, 1);
247         
248         // Job is duplex
249         if (m_pJA->e_duplex_mode != DUPLEXMODE_NONE)
250         {
251                 // Long edge
252                 if  (m_pJA->e_duplex_mode == DUPLEXMODE_BOOK)
253                 {
254                         i += SendItem (szStr+i, ZJIT_UINT32, ZJI_DMDUPLEX, 2);
255                 }
256                 // short edge
257                 else
258                 {
259                         i += SendItem (szStr+i, ZJIT_UINT32, ZJI_DMDUPLEX, 3);                  
260                 }
261         }
262
263     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_DMMEDIATYPE, m_pQA->media_type);   
264     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_DMPAPER, m_pMA->pcl_id);   
265         i += SendItem (szStr+i, ZJIT_UINT32, ZJI_DMDEFAULTSOURCE, m_pJA->media_source);
266     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_NBIE, m_iPlanes);
267     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_RESOLUTION_X, m_pQA->horizontal_resolution);
268     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_RESOLUTION_Y, m_pQA->vertical_resolution);
269     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_RASTER_X, width * m_iBpp);
270     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_RASTER_Y, m_pMA->printable_height);
271     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_VIDEO_BPP, m_iBpp);
272     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_VIDEO_X, width);
273     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_VIDEO_Y, m_pMA->printable_height);
274     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_RET, RET_ON);
275     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_TONER_SAVE, (m_pQA->print_quality == -1) ? 1 : 0);
276
277     err = sendBuffer ((const BYTE *) szStr, i);
278     return err;
279 }
280
281 DRIVER_ERROR LJZjStream::sendBlankBands()
282 {
283     if (strcmp(m_pJA->printer_platform, "ljzjscolor"))
284     {
285         return NO_ERROR;
286     }
287     if(m_pJA->printer_platform_version == 2)
288     {
289       return NO_ERROR;
290     }
291     DRIVER_ERROR    err = NO_ERROR;
292     int    remaining_rasters = m_pMA->printable_height - m_iCurRaster;
293     int    num_planes = (m_pJA->color_mode == 0) ? 4 : 1;
294     if (remaining_rasters <= 0)
295     {
296         return NO_ERROR;
297     }
298
299     RASTERDATA    raster_data;
300     if (remaining_rasters < ZJC_BAND_HEIGHT)
301     {
302         memset(&raster_data, 0, sizeof(raster_data));
303         m_pModeJbig->SetBandHeight(remaining_rasters);
304         for (int k = 0; k < num_planes; k++)
305         {
306             m_pModeJbig->Flush();
307             m_pModeJbig->NextOutputRaster(raster_data);
308             err = Encapsulate(&raster_data, true);
309             if (err != NO_ERROR)
310                 return err;
311         }
312         m_pModeJbig->SetBandHeight(ZJC_BAND_HEIGHT);
313         return err;
314     }
315
316     memset(&raster_data, 0, sizeof(raster_data));
317     m_pModeJbig->Process(&raster_data);
318     m_pModeJbig->Flush();
319     m_pModeJbig->NextOutputRaster(raster_data);
320     while (remaining_rasters > 0)
321     {
322         for (int k = 0; k < num_planes; k++)
323         {
324             err = Encapsulate(&raster_data, true);
325             if (err != NO_ERROR)
326             {
327                 return err;
328             }
329         }
330         remaining_rasters -= ZJC_BAND_HEIGHT;
331     }
332     if (remaining_rasters <= 0)
333     {
334         return NO_ERROR;
335     }
336
337     memset(&raster_data, 0, sizeof(raster_data));
338     m_pModeJbig->SetBandHeight(remaining_rasters);
339     m_pModeJbig->Process(&raster_data);
340     m_pModeJbig->Flush();
341     m_pModeJbig->NextOutputRaster(raster_data);
342     for (int k = 0; k < num_planes; k++)
343     {
344         err = Encapsulate(&raster_data, true);
345     }
346     m_pModeJbig->SetBandHeight(ZJC_BAND_HEIGHT);
347
348     return err;
349 }
350
351 DRIVER_ERROR LJZjStream::FormFeed ()
352 {
353     DRIVER_ERROR        err = NO_ERROR;
354     BYTE                szStr[128];
355     int                 size = 16;
356
357     err = sendBlankBands();
358     if (err != NO_ERROR)
359         return err;
360
361     if(((strcmp(m_pJA->printer_platform, "ljzjscolor") == 0) && (m_pJA->printer_platform_version == 2)) == 0)
362     {
363       SendChunkHeader (szStr, 16, ZJT_END_PAGE, 0);
364     }
365
366     if (!strcmp(m_pJA->printer_platform, "ljzjscolor"))
367     {
368         int                 i = 0;
369         int                 iCol = (m_pJA->color_mode == 0) ? 1 : 0;
370
371         memset(szStr, 0, sizeof(szStr));
372         i = SendChunkHeader (szStr, 112, ZJT_END_PAGE, 8);
373         for (int j = 0; j < 8; j++)
374         {
375             i += SendItem (szStr+i, ZJIT_UINT32, 0x8200+j, (j % 4 == 3) ? 1 : iCol);
376         }
377         size = 112;
378         if(m_pJA->printer_platform_version == 2)
379         {
380           return Send ((const BYTE *) szStr, size);
381         }
382     }
383
384     err = sendBuffer ((const BYTE *) szStr, size);
385
386     return err;
387 }
388
389 DRIVER_ERROR LJZjStream::EndJob()
390 {
391     BYTE    szStr[16];
392     memset(szStr, 0, sizeof(szStr));
393     szStr[3] = 16;
394     szStr[7] = ZJT_END_DOC;
395     szStr[14] = 'Z';
396     szStr[15] = 'Z';
397     return this->sendBuffer((const BYTE *) szStr, 16);
398 }
399
400 DRIVER_ERROR    LJZjStream::Encapsulate (RASTERDATA *raster, bool bLastPlane)
401 {
402 if (raster->rasterdata[COLORTYPE_COLOR] == NULL || raster->rastersize[COLORTYPE_COLOR] == 0)
403 {
404     return NO_ERROR;
405 }
406     if (!strcmp(m_pJA->printer_platform, "ljzjscolor"))
407     {
408         return encapsulateColor(raster);
409     }
410
411     DRIVER_ERROR        err = NO_ERROR;
412     BYTE                szStr[36];
413     int                 i = 0;
414     int                 iTotalSize = raster->rastersize[COLORTYPE_COLOR];
415
416     /* Send JBIG header info */
417
418     i = SendChunkHeader (szStr, 36, ZJT_JBIG_BIH, 0);
419
420     memcpy (szStr + 16, raster->rasterdata[COLORTYPE_COLOR], 20);
421     err = sendBuffer ((const BYTE *) szStr, 36);
422     ERRCHECK;
423
424     iTotalSize -= 20;
425     int     iPadCount = 0;
426     if (iTotalSize % 16)
427     {
428         iPadCount = ((iTotalSize / 16 + 1) * 16) - iTotalSize;
429     }
430     int      dwTotal = iTotalSize;
431     BYTE     *p = raster->rasterdata[COLORTYPE_COLOR] + 20;
432     i = dwTotal / 65536;
433
434     for (int j = 0; j < i; j++)
435     {
436         SendChunkHeader (szStr, 16 + 65536, ZJT_JBIG_HID, 0);
437         err = sendBuffer ((const BYTE *) szStr, 16);
438         ERRCHECK;
439         err = sendBuffer ((const BYTE *) p, 65536);
440         ERRCHECK;
441         dwTotal -= 65536;
442         p += 65536;
443     }
444     i = SendChunkHeader (szStr, 16 + dwTotal + iPadCount, ZJT_JBIG_HID, 0);
445     err = sendBuffer ((const BYTE *) szStr, 16);
446     ERRCHECK;
447     err = sendBuffer ((const BYTE *) p, dwTotal);
448     ERRCHECK;
449     if (iPadCount != 0)
450     {
451         memset (szStr, 0, iPadCount);
452         err = sendBuffer ((const BYTE *) szStr, iPadCount);
453     }
454     i = SendChunkHeader (szStr, 16, ZJT_END_JBIG, 0);
455     if (err == NO_ERROR)
456         err = sendBuffer ((const BYTE *) szStr, 16);
457     err = Cleanup();
458     return err;
459 }
460
461 DRIVER_ERROR LJZjStream::encapsulateColor2 (RASTERDATA *raster)
462 {
463     DRIVER_ERROR    err = NO_ERROR;
464     BYTE            szStr[256];
465     int             i = 0;
466     int plane[] = {3, 2, 1, 4};
467
468     if (m_pJA->color_mode == 0)
469     {
470       i = SendChunkHeader (szStr, 28, ZJT_START_PLANE, 1);
471       i += SendItem (szStr+i, ZJIT_UINT32, ZJI_PLANE, plane[m_iPlaneNumber]);
472       err = Send ((const BYTE *) szStr, i);
473     }
474
475     i=0;
476     i += SendChunkHeader (szStr+i, 36, ZJT_JBIG_BIH, 0);
477     err = Send ((const BYTE *) szStr, i);
478     err = Send ((const BYTE *) raster->rasterdata[COLORTYPE_COLOR], 20);
479
480     BYTE *p = raster->rasterdata[COLORTYPE_COLOR] + 20;
481
482     DWORD dwTotalSize = raster->rastersize[COLORTYPE_COLOR];
483     dwTotalSize -= 20;
484     int iPadCount = 0;
485
486     i = 0;
487     if (dwTotalSize % 4)
488     {
489         iPadCount = ((dwTotalSize / 4 + 1) * 4) - dwTotalSize;
490     }
491
492     DWORD dwMaxChunkSize = 0x10000;
493     DWORD dwCurrentChunkSize = 0;
494     bool bLastChunk = false; 
495
496     for(DWORD dwLoopCount = 0; dwLoopCount < dwTotalSize ; dwLoopCount +=dwMaxChunkSize)
497     {
498          memset (szStr, 0, sizeof(szStr));
499          dwCurrentChunkSize = dwMaxChunkSize;
500
501          if(dwLoopCount + dwCurrentChunkSize > dwTotalSize)
502          {
503               dwCurrentChunkSize = dwTotalSize - (dwLoopCount);
504               bLastChunk = true;
505          }
506          if (!bLastChunk)
507          {
508               i = SendChunkHeader (szStr, dwCurrentChunkSize + 16, ZJT_JBIG_HID, 0);
509          }
510          else 
511          {
512               i = SendChunkHeader (szStr, dwCurrentChunkSize + 16 + iPadCount, ZJT_JBIG_HID, 0);
513          }
514          err = Send ((const BYTE *) szStr, i);
515          err = Send ((const BYTE *) p, dwCurrentChunkSize);
516          p += dwCurrentChunkSize;
517     }
518     if(iPadCount != 0)
519     {
520         memset (szStr, 0, iPadCount);
521         err = Send ((const BYTE *) szStr, iPadCount);
522     }
523
524     i=0;
525     memset (szStr, 0, sizeof(szStr));
526     i = SendChunkHeader (szStr, 16, ZJT_END_JBIG, 0);
527     if (m_pJA->color_mode == 0)
528     {
529       i += SendChunkHeader (szStr+i, 28, ZJT_END_PLANE, 1);
530       i += SendItem (szStr+i, ZJIT_UINT32, ZJI_PLANE, plane[m_iPlaneNumber]);
531     }
532     err = Send ((const BYTE *) szStr, i);
533
534     if (m_pJA->color_mode == 0)
535     {
536         m_iPlaneNumber++;
537         if (m_iPlaneNumber == 4) m_iPlaneNumber = 0;
538     }
539     return err;
540 }
541
542 DRIVER_ERROR    LJZjStream::encapsulateColor (RASTERDATA *raster)
543 {
544     bool            bLastStride = true;
545     int             kEnd = 2;
546     DRIVER_ERROR    err = NO_ERROR;
547     BYTE            szStr[256];
548     int             i = 0;
549
550     if (m_pJA->printer_platform_version == 2)
551     {
552       return encapsulateColor2(raster);
553     }
554
555     HPLJZjsJbgEncSt     *se = (HPLJZjsJbgEncSt *) (raster->rasterdata[COLORTYPE_COLOR] + raster->rastersize[COLORTYPE_COLOR]);
556
557     if (m_pJA->color_mode == 0)
558     {
559         kEnd = 5;
560     }
561     if (m_iPlaneNumber == 0 || m_pJA->color_mode != 0)
562         m_iCurRaster += se->yd;
563     if (m_iCurRaster < m_pMA->printable_height)
564     {
565         bLastStride = false;
566     }
567
568
569 /*
570  *  Send JBIG header info
571  */
572
573     // Send out the JBIG header if first plane and it hasn't already been sent out yet.
574     if (m_iPlaneNumber == 0 && m_bNotSent)
575     {
576         m_bNotSent = false;
577         i = 0;
578         for (int k = 1; k < kEnd; k++)
579         {
580             i = SendChunkHeader (szStr, 132, ZJT_BITMAP, 8);
581             szStr[13] += 20;
582             i += SendItem (szStr+i, ZJIT_UINT32, ZJI_BITMAP_TYPE, 1);
583             i += SendItem (szStr+i, ZJIT_UINT32, ZJI_BITMAP_PIXELS, se->xd);
584             i += SendItem (szStr+i, ZJIT_UINT32, ZJI_BITMAP_STRIDE, se->xd);
585             i += SendItem (szStr+i, ZJIT_UINT32, ZJI_BITMAP_LINES, se->yd);
586             i += SendItem (szStr+i, ZJIT_UINT32, ZJI_BITMAP_BPP, 1);
587             i += SendItem (szStr+i, ZJIT_UINT32, ZJI_VIDEO_BPP, m_iBpp);
588             i += SendItem (szStr+i, ZJIT_UINT32, ZJI_PLANE,
589                            (m_pJA->color_mode == 0) ? k : 4);
590             i += SendItemExtra (szStr+i, ZJIT_BYTELUT, ZJI_ENCODING_DATA, 20, 20);
591             szStr[i++] = se->dl;
592             szStr[i++] = se->d;
593             szStr[i++] = se->planes;
594             szStr[i++] = 0;
595             for (int j = 3; j >= 0; j--)
596             {
597                 szStr[i] = (BYTE) ((se->xd  >> (8 * j)) & 0xFF);
598                 szStr[4+i] = (BYTE) ((se->yd  >> (8 * j)) & 0xFF);
599                 szStr[8+i] = (BYTE) ((se->l0  >> (8 * j)) & 0xFF);
600                 i++;
601             }
602             i += 8;
603
604             szStr[i++] = se->mx;
605             szStr[i++] = se->my;
606             szStr[i++] = se->order;
607             szStr[i++] = se->options;
608             err = sendBuffer ((const BYTE *) szStr, 132);
609             ERRCHECK;
610         }
611     }
612
613     BYTE    *p = raster->rasterdata[COLORTYPE_COLOR] + 20;
614     int     dwNumItems;
615     int     dwSize;
616
617     DWORD    dwTotalSize = raster->rastersize[COLORTYPE_COLOR];
618     dwTotalSize -= 20;
619     int     iPadCount = 0;
620
621     i = 0;
622     if (dwTotalSize % 4)
623     {
624         iPadCount = ((dwTotalSize / 4 + 1) * 4) - dwTotalSize;
625     }
626
627     dwSize = 16 + dwTotalSize + iPadCount;
628     dwNumItems = 1;
629     if (bLastStride)
630     {
631         dwNumItems = 3;
632         m_bNotSent = true;
633     }
634     dwSize += (dwNumItems * 12);
635     i = SendChunkHeader (szStr, dwSize, ZJT_BITMAP, dwNumItems);
636     i += SendItem (szStr+i, ZJIT_UINT32, ZJI_PLANE, (kEnd == 5) ? m_iPlaneNumber+1 : 4);
637     if (bLastStride)
638     {
639         i += SendItem (szStr+i, ZJIT_UINT32, ZJI_BITMAP_LINES, se->yd);
640         i += SendItem (szStr+i, ZJIT_UINT32, ZJI_END_PLANE, bLastStride);
641     }
642     err = sendBuffer ((const BYTE *) szStr, i);
643     ERRCHECK;
644
645     err = sendBuffer ((const BYTE *) p, dwTotalSize);
646     ERRCHECK;
647     if (iPadCount != 0)
648     {
649         memset (szStr, 0, iPadCount);
650         err = sendBuffer ((const BYTE *) szStr, iPadCount);
651     }
652
653     if (m_pJA->color_mode == 0)
654     {
655         m_iPlaneNumber++;
656         if (m_iPlaneNumber == 4)
657         {
658             m_iPlaneNumber = 0;
659         }
660     }
661     return err;
662 }
663