1 # include "bitmapConfig.h"
2
3 # include <stdlib.h>
4 # include <stdio.h>
5
6 # include <sioHex.h>
7 # include <sioBase85.h>
8 # include <sioFlate.h>
9
10 # include "bmBitmapPrinter.h"
11
12 # include <appDebugon.h>
13
14 /************************************************************************/
15 /* */
16 /* Determine how to print. */
17 /* */
18 /* Note that bmPsSetBitmapPrinter() has a knowledge of the limitations */
19 /* of bmPsWriteBitmapData(). */
20 /* */
21 /************************************************************************/
22
bmPsOpenBitmapPrinter(BitmapPrinter * bp,SimpleOutputStream * sos,const BitmapDescription * bd,int useFilters,int indexedImages)23 int bmPsOpenBitmapPrinter( BitmapPrinter * bp,
24 SimpleOutputStream * sos,
25 const BitmapDescription * bd,
26 int useFilters,
27 int indexedImages )
28 {
29 bp->bpOutput= (SimpleOutputStream *)0;
30 bp->bpHexed= (SimpleOutputStream *)0;
31 bp->bpBase85= (SimpleOutputStream *)0;
32 bp->bpFlate= (SimpleOutputStream *)0;
33
34 if ( useFilters )
35 {
36 const int gzipEmbedded= 0;
37
38 bp->bpBase85= sioOutBase85Open( sos );
39
40 bp->bpFlate= sioOutFlateOpen( bp->bpBase85, gzipEmbedded );
41 bp->bpOutput= bp->bpFlate;
42 }
43 else{
44 const int wide= 72;
45 const int lastNL= 1;
46
47 bp->bpHexed= sioOutHexOpenFolded( sos, wide, lastNL );
48 bp->bpOutput= bp->bpHexed;
49 }
50
51 bp->bpUseFilters= useFilters;
52 bp->bpIndexedImages= indexedImages;
53
54 return 0;
55 }
56
bmCloseBitmapPrinter(BitmapPrinter * bp)57 void bmCloseBitmapPrinter( BitmapPrinter * bp )
58 {
59 if ( bp->bpFlate )
60 { sioOutClose( bp->bpFlate ); }
61
62 if ( bp->bpBase85 )
63 { sioOutClose( bp->bpBase85 ); }
64
65 if ( bp->bpHexed )
66 { sioOutClose( bp->bpHexed ); }
67
68 return;
69 }
70
71 /************************************************************************/
72 /* */
73 /* Print Black/White/Color data in hexadecimal format. */
74 /* */
75 /* 1) The caller of bmPsWriteShortRow() promises to pass even numbers */
76 /* of shorts to the routine. So there is no issue about odd */
77 /* counts. */
78 /* */
79 /************************************************************************/
80
bmPsWriteShortRow(SimpleOutputStream * sos,int invert,int count,const BmUint16 * from)81 static int bmPsWriteShortRow( SimpleOutputStream * sos,
82 int invert,
83 int count,
84 const BmUint16 * from )
85 {
86 int col;
87 int val0;
88 int val1;
89
90 if ( invert )
91 {
92 /* 1 */
93 for ( col= 0; col+ 1 < count; col += 2 )
94 {
95 val0= ~*(from++);
96 val1= ~*(from++);
97
98 val1= val1 >> 4;
99
100 if ( sioOutPutByte( ( val0 >> 8 ), sos ) < 0 )
101 { return -1; }
102 if ( sioOutPutByte(
103 ( val0 & 0xf0 ) | ( ( val1 & 0xf00 ) >> 8 ), sos ) < 0 )
104 { return -1; }
105 if ( sioOutPutByte( ( val1 & 0xff ), sos ) < 0 )
106 { return -1; }
107 }
108
109 if ( col < count )
110 {
111 val0= ~*(from++);
112
113 if ( sioOutPutByte( ( val0 >> 8 ), sos ) < 0 )
114 { return -1; }
115 if ( sioOutPutByte( ( val0 & 0xf0 ), sos ) < 0 )
116 { return -1; }
117 }
118 }
119 else{
120 /* 1 */
121 for ( col= 0; col+ 1 < count; col += 2 )
122 {
123 val0= *(from++);
124 val1= *(from++);
125
126 val1= val1 >> 4;
127
128 if ( sioOutPutByte( ( val0 >> 8 ), sos ) < 0 )
129 { return -1; }
130 if ( sioOutPutByte(
131 ( val0 & 0xf0 ) | ( ( val1 & 0xf00 ) >> 8 ), sos ) < 0 )
132 { return -1; }
133 if ( sioOutPutByte( ( val1 & 0xff ), sos ) < 0 )
134 { return -1; }
135 }
136
137 if ( col < count )
138 {
139 val0= *(from++);
140
141 if ( sioOutPutByte( ( val0 >> 8 ), sos ) < 0 )
142 { return -1; }
143 if ( sioOutPutByte( ( val0 & 0xf0 ), sos ) < 0 )
144 { return -1; }
145 }
146 }
147
148 return 0;
149 }
150
bmPsWriteByteRow0(SimpleOutputStream * sos,int invert,int bytesPerRow,const unsigned char * from)151 static int bmPsWriteByteRow0( SimpleOutputStream * sos,
152 int invert,
153 int bytesPerRow,
154 const unsigned char * from )
155 {
156 int col;
157
158 if ( invert )
159 {
160 for ( col= 0; col < bytesPerRow; col++ )
161 {
162 if ( sioOutPutByte( ( ~*(from) ) & 0xff, sos ) < 0 )
163 { return -1; }
164 from++;
165 }
166 }
167 else{
168 for ( col= 0; col < bytesPerRow; col++ )
169 {
170 if ( sioOutPutByte( *(from) & 0xff, sos ) < 0 )
171 { return -1; }
172 from++;
173 }
174 }
175
176 return 0;
177 }
178
bmPsWriteByteRowX(SimpleOutputStream * sos,int invert,int originBit,int rightShift,int bytesPerRow,const unsigned char * from)179 static int bmPsWriteByteRowX( SimpleOutputStream * sos,
180 int invert,
181 int originBit,
182 int rightShift,
183 int bytesPerRow,
184 const unsigned char * from )
185 {
186 int col;
187 unsigned char val;
188
189 if ( invert )
190 {
191 for ( col= 1; col < bytesPerRow; col++ )
192 {
193 val=
194 ( ~( ( from[0] << originBit ) |
195 ( from[1] >> rightShift ) ) ) &0xff;
196
197 if ( sioOutPutByte( val, sos ) < 0 )
198 { return -1; }
199 from++;
200 }
201
202 val= ( ~( from[0] << originBit ) ) & 0xff;
203 if ( sioOutPutByte( val, sos ) < 0 )
204 { return -1; }
205 }
206 else{
207 for ( col= 1; col < bytesPerRow; col++ )
208 {
209 val= ( from[0] << originBit ) |
210 ( from[1] >> rightShift ) ;
211
212 if ( sioOutPutByte( val, sos ) < 0 )
213 { return -1; }
214
215 from++;
216 }
217
218 val= from[0] << originBit;
219 if ( sioOutPutByte( val, sos ) < 0 )
220 { return -1; }
221 }
222
223 return 0;
224 }
225
bmPsWritePal8Row(SimpleOutputStream * sos,const BitmapDescription * bd,int bytesPerRow,const unsigned char * from)226 static int bmPsWritePal8Row( SimpleOutputStream * sos,
227 const BitmapDescription * bd,
228 int bytesPerRow,
229 const unsigned char * from )
230 {
231 int col;
232 const ColorPalette * cp= &(bd->bdPalette);
233
234 for ( col= 0; col < bytesPerRow; col++ )
235 {
236 if ( sioOutPutByte( cp->cpColors[*from].rgb8Red, sos ) < 0 )
237 { return -1; }
238 if ( sioOutPutByte( cp->cpColors[*from].rgb8Green, sos ) < 0 )
239 { return -1; }
240 if ( sioOutPutByte( cp->cpColors[*from].rgb8Blue, sos ) < 0 )
241 { return -1; }
242
243 from++;
244 }
245
246 return 0;
247 }
248
bmPsWritePal4Row0(SimpleOutputStream * sos,const BitmapDescription * bd,int selWidePix,const unsigned char * from)249 static int bmPsWritePal4Row0( SimpleOutputStream * sos,
250 const BitmapDescription * bd,
251 int selWidePix,
252 const unsigned char * from )
253 {
254 int col;
255 int val;
256 const ColorPalette * cp= &(bd->bdPalette);
257
258 for ( col= 0; col+ 1 < selWidePix; col += 2 )
259 {
260 val= ( *from >> 4 ) & 0x0f;
261
262 if ( sioOutPutByte( cp->cpColors[val].rgb8Red, sos ) < 0 )
263 { return -1; }
264 if ( sioOutPutByte( cp->cpColors[val].rgb8Green, sos ) < 0 )
265 { return -1; }
266 if ( sioOutPutByte( cp->cpColors[val].rgb8Blue, sos ) < 0 )
267 { return -1; }
268
269 val= *from & 0x0f;
270
271 if ( sioOutPutByte( cp->cpColors[val].rgb8Red, sos ) < 0 )
272 { return -1; }
273 if ( sioOutPutByte( cp->cpColors[val].rgb8Green, sos ) < 0 )
274 { return -1; }
275 if ( sioOutPutByte( cp->cpColors[val].rgb8Blue, sos ) < 0 )
276 { return -1; }
277
278 from++;
279 }
280
281 if ( selWidePix % 2 )
282 {
283 val= ( *from >> 4 ) & 0x0f;
284
285 if ( sioOutPutByte( cp->cpColors[val].rgb8Red, sos ) < 0 )
286 { return -1; }
287 if ( sioOutPutByte( cp->cpColors[val].rgb8Green, sos ) < 0 )
288 { return -1; }
289 if ( sioOutPutByte( cp->cpColors[val].rgb8Blue, sos ) < 0 )
290 { return -1; }
291 }
292
293 return 0;
294 }
295
bmPsWritePal4RowX(SimpleOutputStream * sos,const BitmapDescription * bd,int bytesPerRow,const unsigned char * from)296 static int bmPsWritePal4RowX( SimpleOutputStream * sos,
297 const BitmapDescription * bd,
298 int bytesPerRow,
299 const unsigned char * from )
300 {
301 int col;
302 int val;
303 const ColorPalette * cp= &(bd->bdPalette);
304
305 val= *from & 0x0f;
306
307 if ( sioOutPutByte( cp->cpColors[val].rgb8Red, sos ) < 0 )
308 { return -1; }
309 if ( sioOutPutByte( cp->cpColors[val].rgb8Green, sos ) < 0 )
310 { return -1; }
311 if ( sioOutPutByte( cp->cpColors[val].rgb8Blue, sos ) < 0 )
312 { return -1; }
313
314 from++;
315
316 for ( col= 1; col < bytesPerRow; col++ )
317 {
318 val= ( *from >> 4 ) & 0x0f;
319
320 if ( sioOutPutByte( cp->cpColors[val].rgb8Red, sos) < 0 )
321 { return -1; }
322 if ( sioOutPutByte( cp->cpColors[val].rgb8Green, sos) < 0 )
323 { return -1; }
324 if ( sioOutPutByte( cp->cpColors[val].rgb8Blue, sos) < 0 )
325 { return -1; }
326
327 val= *from & 0x0f;
328
329 if ( sioOutPutByte( cp->cpColors[val].rgb8Red, sos) < 0 )
330 { return -1; }
331 if ( sioOutPutByte( cp->cpColors[val].rgb8Green, sos) < 0 )
332 { return -1; }
333 if ( sioOutPutByte( cp->cpColors[val].rgb8Blue, sos) < 0 )
334 { return -1; }
335
336 from++;
337 }
338
339 val= ( *from >> 4 ) & 0x0f;
340
341 if ( sioOutPutByte( cp->cpColors[val].rgb8Red, sos) < 0 )
342 { return -1; }
343 if ( sioOutPutByte( cp->cpColors[val].rgb8Green, sos) < 0 )
344 { return -1; }
345 if ( sioOutPutByte( cp->cpColors[val].rgb8Blue, sos) < 0 )
346 { return -1; }
347
348 return 0;
349 }
350
bmPsWritePal2Row0(SimpleOutputStream * sos,const BitmapDescription * bd,int selWidePix,const unsigned char * from)351 static int bmPsWritePal2Row0( SimpleOutputStream * sos,
352 const BitmapDescription * bd,
353 int selWidePix,
354 const unsigned char * from )
355 {
356 int col;
357 int shift;
358 const ColorPalette * cp= &(bd->bdPalette);
359
360 for ( col= 0; col+ 3 < selWidePix; col += 4 )
361 {
362 for ( shift= 6; shift >= 0; shift -= 2 )
363 {
364 int val= ( *from >> shift ) & 0x03;
365
366 if ( sioOutPutByte( cp->cpColors[val].rgb8Red, sos ) < 0 )
367 { return -1; }
368 if ( sioOutPutByte( cp->cpColors[val].rgb8Green, sos ) < 0 )
369 { return -1; }
370 if ( sioOutPutByte( cp->cpColors[val].rgb8Blue, sos ) < 0 )
371 { return -1; }
372 }
373
374 from++;
375 }
376
377 shift= 6;
378 for ( col= 0; col < selWidePix % 4; shift -= 2, col++ )
379 {
380 int val= ( *from >> shift ) & 0x03;
381
382 if ( sioOutPutByte( cp->cpColors[val].rgb8Red, sos ) < 0 )
383 { return -1; }
384 if ( sioOutPutByte( cp->cpColors[val].rgb8Green, sos ) < 0 )
385 { return -1; }
386 if ( sioOutPutByte( cp->cpColors[val].rgb8Blue, sos ) < 0 )
387 { return -1; }
388 }
389
390 return 0;
391 }
392
bmPsWritePal1Row0(SimpleOutputStream * sos,const BitmapDescription * bd,int selWidePix,const unsigned char * from)393 static int bmPsWritePal1Row0( SimpleOutputStream * sos,
394 const BitmapDescription * bd,
395 int selWidePix,
396 const unsigned char * from )
397 {
398 int col;
399 int shift;
400 const ColorPalette * cp= &(bd->bdPalette);
401
402 for ( col= 0; col+ 7 < selWidePix; col += 8 )
403 {
404 for ( shift= 7; shift >= 0; shift-- )
405 {
406 int val= ( *from >> shift ) & 0x01;
407
408 if ( sioOutPutByte( cp->cpColors[val].rgb8Red, sos ) < 0 )
409 { return -1; }
410 if ( sioOutPutByte( cp->cpColors[val].rgb8Green, sos ) < 0 )
411 { return -1; }
412 if ( sioOutPutByte( cp->cpColors[val].rgb8Blue, sos ) < 0 )
413 { return -1; }
414 }
415
416 from++;
417 }
418
419 shift= 7;
420 for ( col= 0; col < selWidePix % 8; shift--, col++ )
421 {
422 int val= ( *from >> shift ) & 0x01;
423
424 if ( sioOutPutByte( cp->cpColors[val].rgb8Red, sos ) < 0 )
425 { return -1; }
426 if ( sioOutPutByte( cp->cpColors[val].rgb8Green, sos ) < 0 )
427 { return -1; }
428 if ( sioOutPutByte( cp->cpColors[val].rgb8Blue, sos ) < 0 )
429 { return -1; }
430 }
431
432 return 0;
433 }
434
bmPsWriteBitmapData(BitmapPrinter * bp,const DocumentRectangle * drSel,const BitmapDescription * bd,const unsigned char * inputBuffer)435 int bmPsWriteBitmapData( BitmapPrinter * bp,
436 const DocumentRectangle * drSel,
437 const BitmapDescription * bd,
438 const unsigned char * inputBuffer )
439 {
440 SimpleOutputStream * sos= bp->bpOutput;
441 int indexedImages= bp->bpIndexedImages;
442 int directPixels;
443
444 int row;
445
446 int originBit;
447 int originByte;
448 int rightShift;
449
450 int bytesPerRow;
451
452 const unsigned char * from;
453 int selWidePix= drSel->drX1- drSel->drX0+ 1;
454 int selHighPix= drSel->drY1- drSel->drY0+ 1;
455
456 const ColorPalette * cp= &(bd->bdPalette);
457
458 directPixels= 0;
459 if ( bd->bdColorEncoding == BMcoWHITEBLACK )
460 { directPixels= 1; }
461 if ( bd->bdColorEncoding == BMcoBLACKWHITE )
462 { directPixels= 1; }
463 if ( bd->bdColorEncoding == BMcoRGB && ! bd->bdHasAlpha )
464 { directPixels= 1; }
465 if ( bd->bdColorEncoding == BMcoRGB8PALETTE && indexedImages )
466 { directPixels= 1; }
467
468 if ( bd->bdColorEncoding == BMcoRGB8PALETTE &&
469 bd->bdBitsPerPixel == 1 &&
470 cp->cpColors[0].rgb8Red == 255 &&
471 cp->cpColors[0].rgb8Green == 255 &&
472 cp->cpColors[0].rgb8Blue == 255 )
473 { directPixels= 1; }
474
475 if ( bd->bdBitsPerSample == 16 && directPixels )
476 {
477 int invert= bd->bdColorEncoding == BMcoBLACKWHITE;
478 int shortsPerRow;
479
480 originByte= 2* drSel->drX0;
481 shortsPerRow= ( selWidePix* bd->bdBitsPerPixel+ 15 )/ 16;
482
483 for ( row= 0; row < selHighPix; row++ )
484 {
485 from= inputBuffer+
486 ( row+ drSel->drY0 )* bd->bdBytesPerRow+ originByte;
487
488 bmPsWriteShortRow( sos, invert, shortsPerRow,
489 (const BmUint16 *)from );
490 }
491
492 return 0;
493 }
494
495 originBit= ( drSel->drX0* bd->bdBitsPerPixel )% 8;
496 originByte= ( drSel->drX0* bd->bdBitsPerPixel )/ 8;
497 bytesPerRow= ( selWidePix* bd->bdBitsPerPixel+ 7 )/ 8;
498 rightShift= 8- originBit;
499
500 if ( originBit == 0 && directPixels )
501 {
502 int invert= bd->bdColorEncoding == BMcoBLACKWHITE;
503
504 for ( row= 0; row < selHighPix; row++ )
505 {
506 from= inputBuffer+
507 ( row+ drSel->drY0 )* bd->bdBytesPerRow+ originByte;
508
509 bmPsWriteByteRow0( sos, invert, bytesPerRow, from );
510 }
511
512 return 0;
513 }
514
515 if ( bd->bdColorEncoding == BMcoRGB &&
516 bd->bdHasAlpha )
517 {
518 const int invert= 0;
519 unsigned char * scratch;
520
521 scratch= (unsigned char *)malloc( bd->bdBytesPerRow );
522 if ( ! scratch )
523 { LXDEB(bd->bdBytesPerRow,scratch); return -1; }
524
525 if ( bd->bdBitsPerSample == 8 )
526 {
527 for ( row= 0; row < selHighPix; row++ )
528 {
529 int col;
530 unsigned char * to= scratch;
531
532 from= inputBuffer+
533 ( row+ drSel->drY0 )* bd->bdBytesPerRow+ originByte;
534
535 for ( col= 0; col < selWidePix; col++ )
536 {
537 if ( from[3] < 127 )
538 {
539 *(to++)= 0xff;
540 *(to++)= 0xff;
541 *(to++)= 0xff;
542 from += 4;
543 }
544 else{
545 *(to++)= *(from++);
546 *(to++)= *(from++);
547 *(to++)= *(from++);
548 from++;
549 }
550 }
551
552 bmPsWriteByteRow0( sos, invert, 3* selWidePix, scratch );
553 }
554 }
555 else{
556 LDEB(bd->bdBitsPerSample); free( scratch ); return -1;
557 }
558
559 free( scratch );
560 return 0;
561 }
562
563 if ( bd->bdColorEncoding == BMcoWHITEBLACK ||
564 bd->bdColorEncoding == BMcoBLACKWHITE )
565 {
566 const int invert= bd->bdColorEncoding == BMcoBLACKWHITE;
567
568 for ( row= 0; row < selHighPix; row++ )
569 {
570 from= inputBuffer+
571 ( row+ drSel->drY0 )* bd->bdBytesPerRow+ originByte;
572
573 bmPsWriteByteRowX( sos, invert,
574 originBit, rightShift, bytesPerRow, from );
575 }
576
577 return 0;
578 }
579
580 if ( bd->bdColorEncoding == BMcoRGB8PALETTE &&
581 ! directPixels &&
582 bd->bdBitsPerPixel == 8 )
583 {
584 for ( row= 0; row < selHighPix; row++ )
585 {
586 from= inputBuffer+
587 ( row+ drSel->drY0 )* bd->bdBytesPerRow+ originByte;
588
589 bmPsWritePal8Row( sos, bd, bytesPerRow, from );
590 }
591
592 return 0;
593 }
594
595 if ( bd->bdColorEncoding == BMcoRGB8PALETTE &&
596 ! directPixels &&
597 bd->bdBitsPerPixel == 4 &&
598 originBit == 0 )
599 {
600 for ( row= 0; row < selHighPix; row++ )
601 {
602 from= inputBuffer+
603 ( row+ drSel->drY0 )* bd->bdBytesPerRow+ originByte;
604
605 bmPsWritePal4Row0( sos, bd, selWidePix, from );
606 }
607
608 return 0;
609 }
610
611 if ( bd->bdColorEncoding == BMcoRGB8PALETTE &&
612 ! directPixels &&
613 bd->bdBitsPerPixel == 4 &&
614 originBit == 4 )
615 {
616 for ( row= 0; row < selHighPix; row++ )
617 {
618 from= inputBuffer+
619 ( row+ drSel->drY0 )* bd->bdBytesPerRow+ originByte;
620
621 bmPsWritePal4RowX( sos, bd, bytesPerRow, from );
622 }
623
624 return 0;
625 }
626
627 if ( bd->bdColorEncoding == BMcoRGB8PALETTE &&
628 ! directPixels &&
629 bd->bdBitsPerPixel == 2 &&
630 originBit == 0 )
631 {
632 for ( row= 0; row < selHighPix; row++ )
633 {
634 from= inputBuffer+
635 ( row+ drSel->drY0 )* bd->bdBytesPerRow+ originByte;
636
637 bmPsWritePal2Row0( sos, bd, selWidePix, from );
638 }
639
640 return 0;
641 }
642
643 if ( bd->bdColorEncoding == BMcoRGB8PALETTE &&
644 ! directPixels &&
645 bd->bdBitsPerPixel == 1 )
646 {
647 for ( row= 0; row < selHighPix; row++ )
648 {
649 from= inputBuffer+
650 ( row+ drSel->drY0 )* bd->bdBytesPerRow+ originByte;
651
652 bmPsWritePal1Row0( sos, bd, selWidePix, from );
653 }
654
655 return 0;
656 }
657
658 LDEB(directPixels);
659 LDEB(bd->bdBitsPerPixel);
660 LLDEB(originBit,bd->bdColorEncoding); return -1;
661 }
662
663