Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "psputil.hxx"
21 :
22 : #include "generic/printergfx.hxx"
23 : #include "vcl/strhelper.hxx"
24 :
25 : #include <boost/scoped_ptr.hpp>
26 :
27 : namespace psp {
28 :
29 : const sal_uInt32 nLineLength = 80;
30 : const sal_uInt32 nBufferSize = 16384;
31 :
32 : /*
33 : *
34 : * Bitmap compression / Hex encoding / Ascii85 Encoding
35 : *
36 : */
37 :
38 0 : PrinterBmp::~PrinterBmp ()
39 0 : { /* dont need this, but C50 does */ }
40 :
41 : /* virtual base class */
42 :
43 0 : class ByteEncoder
44 : {
45 : private:
46 :
47 : public:
48 :
49 : virtual void EncodeByte (sal_uInt8 nByte) = 0;
50 : virtual ~ByteEncoder () = 0;
51 : };
52 :
53 0 : ByteEncoder::~ByteEncoder ()
54 0 : { /* dont need this, but the C50 does */ }
55 :
56 : /* HexEncoder */
57 :
58 : class HexEncoder : public ByteEncoder
59 : {
60 : private:
61 :
62 : osl::File* mpFile;
63 : sal_uInt32 mnColumn;
64 : sal_uInt32 mnOffset;
65 : sal_Char mpFileBuffer[nBufferSize + 16];
66 :
67 : public:
68 :
69 : HexEncoder (osl::File* pFile);
70 : virtual ~HexEncoder ();
71 : void WriteAscii (sal_uInt8 nByte);
72 : virtual void EncodeByte (sal_uInt8 nByte) SAL_OVERRIDE;
73 : void FlushLine ();
74 : };
75 :
76 0 : HexEncoder::HexEncoder (osl::File* pFile) :
77 : mpFile (pFile),
78 : mnColumn (0),
79 0 : mnOffset (0)
80 0 : {}
81 :
82 0 : HexEncoder::~HexEncoder ()
83 : {
84 0 : FlushLine ();
85 0 : if (mnColumn > 0)
86 0 : WritePS (mpFile, "\n");
87 0 : }
88 :
89 : void
90 0 : HexEncoder::WriteAscii (sal_uInt8 nByte)
91 : {
92 0 : sal_uInt32 nOff = psp::getHexValueOf (nByte, mpFileBuffer + mnOffset);
93 0 : mnColumn += nOff;
94 0 : mnOffset += nOff;
95 :
96 0 : if (mnColumn >= nLineLength)
97 : {
98 0 : mnOffset += psp::appendStr ("\n", mpFileBuffer + mnOffset);
99 0 : mnColumn = 0;
100 : }
101 0 : if (mnOffset >= nBufferSize)
102 0 : FlushLine ();
103 0 : }
104 :
105 : void
106 0 : HexEncoder::EncodeByte (sal_uInt8 nByte)
107 : {
108 0 : WriteAscii (nByte);
109 0 : }
110 :
111 : void
112 0 : HexEncoder::FlushLine ()
113 : {
114 0 : if (mnOffset > 0)
115 : {
116 0 : WritePS (mpFile, mpFileBuffer, mnOffset);
117 0 : mnOffset = 0;
118 : }
119 0 : }
120 :
121 : /* Ascii85 encoder, is abi compatible with HexEncoder but writes a ~> to
122 : indicate end of data EOD */
123 :
124 : class Ascii85Encoder : public ByteEncoder
125 : {
126 : private:
127 :
128 : osl::File* mpFile;
129 : sal_uInt32 mnByte;
130 : sal_uInt8 mpByteBuffer[4];
131 :
132 : sal_uInt32 mnColumn;
133 : sal_uInt32 mnOffset;
134 : sal_Char mpFileBuffer[nBufferSize + 16];
135 :
136 : inline void PutByte (sal_uInt8 nByte);
137 : inline void PutEOD ();
138 : void ConvertToAscii85 ();
139 : void FlushLine ();
140 :
141 : public:
142 :
143 : Ascii85Encoder (osl::File* pFile);
144 : virtual ~Ascii85Encoder ();
145 : virtual void EncodeByte (sal_uInt8 nByte) SAL_OVERRIDE;
146 : void WriteAscii (sal_uInt8 nByte);
147 : };
148 :
149 0 : Ascii85Encoder::Ascii85Encoder (osl::File* pFile) :
150 : mpFile (pFile),
151 : mnByte (0),
152 : mnColumn (0),
153 0 : mnOffset (0)
154 0 : {}
155 :
156 : inline void
157 0 : Ascii85Encoder::PutByte (sal_uInt8 nByte)
158 : {
159 0 : mpByteBuffer [mnByte++] = nByte;
160 0 : }
161 :
162 : inline void
163 0 : Ascii85Encoder::PutEOD ()
164 : {
165 0 : WritePS (mpFile, "~>\n");
166 0 : }
167 :
168 : void
169 0 : Ascii85Encoder::ConvertToAscii85 ()
170 : {
171 0 : if (mnByte < 4)
172 0 : std::memset (mpByteBuffer + mnByte, 0, (4 - mnByte) * sizeof(sal_uInt8));
173 :
174 0 : sal_uInt32 nByteValue = mpByteBuffer[0] * 256 * 256 * 256
175 0 : + mpByteBuffer[1] * 256 * 256
176 0 : + mpByteBuffer[2] * 256
177 0 : + mpByteBuffer[3];
178 :
179 0 : if (nByteValue == 0 && mnByte == 4)
180 : {
181 : /* special case of 4 Bytes in row */
182 0 : mpFileBuffer [mnOffset] = 'z';
183 :
184 0 : mnOffset += 1;
185 0 : mnColumn += 1;
186 : }
187 : else
188 : {
189 : /* real ascii85 encoding */
190 0 : mpFileBuffer [mnOffset + 4] = (nByteValue % 85) + 33;
191 0 : nByteValue /= 85;
192 0 : mpFileBuffer [mnOffset + 3] = (nByteValue % 85) + 33;
193 0 : nByteValue /= 85;
194 0 : mpFileBuffer [mnOffset + 2] = (nByteValue % 85) + 33;
195 0 : nByteValue /= 85;
196 0 : mpFileBuffer [mnOffset + 1] = (nByteValue % 85) + 33;
197 0 : nByteValue /= 85;
198 0 : mpFileBuffer [mnOffset + 0] = (nByteValue % 85) + 33;
199 :
200 0 : mnColumn += (mnByte + 1);
201 0 : mnOffset += (mnByte + 1);
202 :
203 : /* insert a newline if necessary */
204 0 : if (mnColumn > nLineLength)
205 : {
206 0 : sal_uInt32 nEolOff = mnColumn - nLineLength;
207 0 : sal_uInt32 nBufOff = mnOffset - nEolOff;
208 :
209 0 : std::memmove (mpFileBuffer + nBufOff + 1, mpFileBuffer + nBufOff, nEolOff);
210 0 : mpFileBuffer[ nBufOff ] = '\n';
211 :
212 0 : mnOffset++;
213 0 : mnColumn = nEolOff;
214 : }
215 : }
216 :
217 0 : mnByte = 0;
218 0 : }
219 :
220 : void
221 0 : Ascii85Encoder::WriteAscii (sal_uInt8 nByte)
222 : {
223 0 : PutByte (nByte);
224 0 : if (mnByte == 4)
225 0 : ConvertToAscii85 ();
226 :
227 0 : if (mnColumn >= nLineLength)
228 : {
229 0 : mnOffset += psp::appendStr ("\n", mpFileBuffer + mnOffset);
230 0 : mnColumn = 0;
231 : }
232 0 : if (mnOffset >= nBufferSize)
233 0 : FlushLine ();
234 0 : }
235 :
236 : void
237 0 : Ascii85Encoder::EncodeByte (sal_uInt8 nByte)
238 : {
239 0 : WriteAscii (nByte);
240 0 : }
241 :
242 : void
243 0 : Ascii85Encoder::FlushLine ()
244 : {
245 0 : if (mnOffset > 0)
246 : {
247 0 : WritePS (mpFile, mpFileBuffer, mnOffset);
248 0 : mnOffset = 0;
249 : }
250 0 : }
251 :
252 0 : Ascii85Encoder::~Ascii85Encoder ()
253 : {
254 0 : if (mnByte > 0)
255 0 : ConvertToAscii85 ();
256 0 : if (mnOffset > 0)
257 0 : FlushLine ();
258 0 : PutEOD ();
259 0 : }
260 :
261 : /* LZW encoder */
262 :
263 : class LZWEncoder : public Ascii85Encoder
264 : {
265 : private:
266 :
267 : struct LZWCTreeNode
268 : {
269 : LZWCTreeNode* mpBrother; // next node with same parent
270 : LZWCTreeNode* mpFirstChild; // first son
271 : sal_uInt16 mnCode; // code for the string
272 : sal_uInt16 mnValue; // pixelvalue
273 : };
274 :
275 : LZWCTreeNode* mpTable; // LZW compression data
276 : LZWCTreeNode* mpPrefix; // the compression is as same as the TIFF compression
277 : sal_uInt16 mnDataSize;
278 : sal_uInt16 mnClearCode;
279 : sal_uInt16 mnEOICode;
280 : sal_uInt16 mnTableSize;
281 : sal_uInt16 mnCodeSize;
282 : sal_uInt32 mnOffset;
283 : sal_uInt32 mdwShift;
284 :
285 : void WriteBits (sal_uInt16 nCode, sal_uInt16 nCodeLen);
286 :
287 : public:
288 :
289 : LZWEncoder (osl::File* pOutputFile);
290 : virtual ~LZWEncoder ();
291 :
292 : virtual void EncodeByte (sal_uInt8 nByte) SAL_OVERRIDE;
293 : };
294 :
295 0 : LZWEncoder::LZWEncoder(osl::File* pOutputFile) :
296 0 : Ascii85Encoder (pOutputFile)
297 : {
298 0 : mnDataSize = 8;
299 :
300 0 : mnClearCode = 1 << mnDataSize;
301 0 : mnEOICode = mnClearCode + 1;
302 0 : mnTableSize = mnEOICode + 1;
303 0 : mnCodeSize = mnDataSize + 1;
304 :
305 0 : mnOffset = 32; // free bits in dwShift
306 0 : mdwShift = 0;
307 :
308 0 : mpTable = new LZWCTreeNode[ 4096 ];
309 :
310 0 : for (sal_uInt32 i = 0; i < 4096; i++)
311 : {
312 0 : mpTable[i].mpBrother = NULL;
313 0 : mpTable[i].mpFirstChild = NULL;
314 0 : mpTable[i].mnCode = i;
315 0 : mpTable[i].mnValue = (sal_uInt8)mpTable[i].mnCode;
316 : }
317 :
318 0 : mpPrefix = NULL;
319 :
320 0 : WriteBits( mnClearCode, mnCodeSize );
321 0 : }
322 :
323 0 : LZWEncoder::~LZWEncoder()
324 : {
325 0 : if (mpPrefix)
326 0 : WriteBits (mpPrefix->mnCode, mnCodeSize);
327 :
328 0 : WriteBits (mnEOICode, mnCodeSize);
329 :
330 0 : delete[] mpTable;
331 0 : }
332 :
333 : void
334 0 : LZWEncoder::WriteBits (sal_uInt16 nCode, sal_uInt16 nCodeLen)
335 : {
336 0 : mdwShift |= (nCode << (mnOffset - nCodeLen));
337 0 : mnOffset -= nCodeLen;
338 0 : while (mnOffset < 24)
339 : {
340 0 : WriteAscii ((sal_uInt8)(mdwShift >> 24));
341 0 : mdwShift <<= 8;
342 0 : mnOffset += 8;
343 : }
344 0 : if (nCode == 257 && mnOffset != 32)
345 0 : WriteAscii ((sal_uInt8)(mdwShift >> 24));
346 0 : }
347 :
348 : void
349 0 : LZWEncoder::EncodeByte (sal_uInt8 nByte )
350 : {
351 : LZWCTreeNode* p;
352 : sal_uInt16 i;
353 : sal_uInt8 nV;
354 :
355 0 : if (!mpPrefix)
356 : {
357 0 : mpPrefix = mpTable + nByte;
358 : }
359 : else
360 : {
361 0 : nV = nByte;
362 0 : for (p = mpPrefix->mpFirstChild; p != NULL; p = p->mpBrother)
363 : {
364 0 : if (p->mnValue == nV)
365 0 : break;
366 : }
367 :
368 0 : if (p != NULL)
369 : {
370 0 : mpPrefix = p;
371 : }
372 : else
373 : {
374 0 : WriteBits (mpPrefix->mnCode, mnCodeSize);
375 :
376 0 : if (mnTableSize == 409)
377 : {
378 0 : WriteBits (mnClearCode, mnCodeSize);
379 :
380 0 : for (i = 0; i < mnClearCode; i++)
381 0 : mpTable[i].mpFirstChild = NULL;
382 :
383 0 : mnCodeSize = mnDataSize + 1;
384 0 : mnTableSize = mnEOICode + 1;
385 : }
386 : else
387 : {
388 0 : if(mnTableSize == (sal_uInt16)((1 << mnCodeSize) - 1))
389 0 : mnCodeSize++;
390 :
391 0 : p = mpTable + (mnTableSize++);
392 0 : p->mpBrother = mpPrefix->mpFirstChild;
393 0 : mpPrefix->mpFirstChild = p;
394 0 : p->mnValue = nV;
395 0 : p->mpFirstChild = NULL;
396 : }
397 :
398 0 : mpPrefix = mpTable + nV;
399 : }
400 : }
401 0 : }
402 :
403 : /*
404 : *
405 : * bitmap handling routines
406 : *
407 : */
408 :
409 : void
410 0 : PrinterGfx::DrawBitmap (const Rectangle& rDest, const Rectangle& rSrc,
411 : const PrinterBmp& rBitmap)
412 : {
413 0 : double fScaleX = (double)rDest.GetWidth() / (double)rSrc.GetWidth();
414 0 : double fScaleY = (double)rDest.GetHeight() / (double)rSrc.GetHeight();
415 :
416 0 : PSGSave ();
417 0 : PSTranslate (rDest.BottomLeft());
418 0 : PSScale (fScaleX, fScaleY);
419 :
420 0 : if (mnPSLevel >= 2)
421 : {
422 0 : if (rBitmap.GetDepth() == 1)
423 : {
424 0 : DrawPS2MonoImage (rBitmap, rSrc);
425 : }
426 : else
427 0 : if (rBitmap.GetDepth() == 8 && mbColor)
428 : {
429 : // if the palette is larger than the image itself print it as a truecolor
430 : // image to save diskspace. This is important for printing transparent
431 : // bitmaps that are disassembled into small pieces
432 0 : sal_Int32 nImageSz = rSrc.GetWidth() * rSrc.GetHeight();
433 0 : sal_Int32 nPaletteSz = rBitmap.GetPaletteEntryCount();
434 0 : if ((nImageSz < nPaletteSz) || (nImageSz < 24) )
435 0 : DrawPS2TrueColorImage (rBitmap, rSrc);
436 : else
437 0 : DrawPS2PaletteImage (rBitmap, rSrc);
438 : }
439 : else
440 0 : if (rBitmap.GetDepth() == 24 && mbColor)
441 : {
442 0 : DrawPS2TrueColorImage (rBitmap, rSrc);
443 : }
444 : else
445 : {
446 0 : DrawPS2GrayImage (rBitmap, rSrc);
447 : }
448 : }
449 : else
450 : {
451 0 : DrawPS1GrayImage (rBitmap, rSrc);
452 : }
453 :
454 0 : PSGRestore ();
455 0 : }
456 :
457 : /*
458 : *
459 : * Implementation: PS Level 1
460 : *
461 : */
462 :
463 : void
464 0 : PrinterGfx::DrawPS1GrayImage (const PrinterBmp& rBitmap, const Rectangle& rArea)
465 : {
466 0 : sal_uInt32 nWidth = rArea.GetWidth();
467 0 : sal_uInt32 nHeight = rArea.GetHeight();
468 :
469 : sal_Char pGrayImage [512];
470 0 : sal_Int32 nChar = 0;
471 :
472 : // image header
473 0 : nChar += psp::getValueOf (nWidth, pGrayImage + nChar);
474 0 : nChar += psp::appendStr (" ", pGrayImage + nChar);
475 0 : nChar += psp::getValueOf (nHeight, pGrayImage + nChar);
476 0 : nChar += psp::appendStr (" 8 ", pGrayImage + nChar);
477 0 : nChar += psp::appendStr ("[ 1 0 0 1 0 ", pGrayImage + nChar);
478 0 : nChar += psp::getValueOf (nHeight, pGrayImage + nChar);
479 0 : nChar += psp::appendStr ("]", pGrayImage + nChar);
480 0 : nChar += psp::appendStr (" {currentfile ", pGrayImage + nChar);
481 0 : nChar += psp::getValueOf (nWidth, pGrayImage + nChar);
482 0 : nChar += psp::appendStr (" string readhexstring pop}\n", pGrayImage + nChar);
483 0 : nChar += psp::appendStr ("image\n", pGrayImage + nChar);
484 :
485 0 : WritePS (mpPageBody, pGrayImage);
486 :
487 : // image body
488 0 : boost::scoped_ptr<HexEncoder> pEncoder(new HexEncoder (mpPageBody));
489 :
490 0 : for (long nRow = rArea.Top(); nRow <= rArea.Bottom(); nRow++)
491 : {
492 0 : for (long nColumn = rArea.Left(); nColumn <= rArea.Right(); nColumn++)
493 : {
494 0 : unsigned char nByte = rBitmap.GetPixelGray (nRow, nColumn);
495 0 : pEncoder->EncodeByte (nByte);
496 : }
497 : }
498 :
499 0 : pEncoder.reset();
500 :
501 0 : WritePS (mpPageBody, "\n");
502 0 : }
503 :
504 : /*
505 : *
506 : * Implementation: PS Level 2
507 : *
508 : */
509 :
510 : void
511 0 : PrinterGfx::writePS2ImageHeader (const Rectangle& rArea, psp::ImageType nType)
512 : {
513 0 : sal_Int32 nChar = 0;
514 : sal_Char pImage [512];
515 :
516 0 : sal_Int32 nDictType = 0;
517 0 : switch (nType)
518 : {
519 0 : case psp::TrueColorImage: nDictType = 0; break;
520 0 : case psp::PaletteImage: nDictType = 1; break;
521 0 : case psp::GrayScaleImage: nDictType = 2; break;
522 0 : case psp::MonochromeImage: nDictType = 3; break;
523 0 : default: break;
524 : }
525 0 : sal_Int32 nCompressType = mbCompressBmp ? 1 : 0;
526 :
527 0 : nChar += psp::getValueOf (rArea.GetWidth(), pImage + nChar);
528 0 : nChar += psp::appendStr (" ", pImage + nChar);
529 0 : nChar += psp::getValueOf (rArea.GetHeight(), pImage + nChar);
530 0 : nChar += psp::appendStr (" ", pImage + nChar);
531 0 : nChar += psp::getValueOf (nDictType, pImage + nChar);
532 0 : nChar += psp::appendStr (" ", pImage + nChar);
533 0 : nChar += psp::getValueOf (nCompressType, pImage + nChar);
534 0 : nChar += psp::appendStr (" psp_imagedict image\n", pImage + nChar);
535 :
536 0 : WritePS (mpPageBody, pImage);
537 0 : }
538 :
539 : void
540 0 : PrinterGfx::writePS2Colorspace(const PrinterBmp& rBitmap, psp::ImageType nType)
541 : {
542 0 : switch (nType)
543 : {
544 : case psp::GrayScaleImage:
545 :
546 0 : WritePS (mpPageBody, "/DeviceGray setcolorspace\n");
547 0 : break;
548 :
549 : case psp::TrueColorImage:
550 :
551 0 : WritePS (mpPageBody, "/DeviceRGB setcolorspace\n");
552 0 : break;
553 :
554 : case psp::MonochromeImage:
555 : case psp::PaletteImage:
556 : {
557 :
558 0 : sal_Int32 nChar = 0;
559 : sal_Char pImage [4096];
560 :
561 0 : const sal_uInt32 nSize = rBitmap.GetPaletteEntryCount();
562 :
563 0 : nChar += psp::appendStr ("[/Indexed /DeviceRGB ", pImage + nChar);
564 0 : nChar += psp::getValueOf (nSize - 1, pImage + nChar);
565 0 : if (mbCompressBmp)
566 0 : nChar += psp::appendStr ("\npsp_lzwstring\n", pImage + nChar);
567 : else
568 0 : nChar += psp::appendStr ("\npsp_ascii85string\n", pImage + nChar);
569 0 : WritePS (mpPageBody, pImage);
570 :
571 0 : boost::scoped_ptr<ByteEncoder> pEncoder(mbCompressBmp ? new LZWEncoder(mpPageBody)
572 0 : : new Ascii85Encoder(mpPageBody));
573 0 : for (sal_uInt32 i = 0; i < nSize; i++)
574 : {
575 0 : PrinterColor aColor = rBitmap.GetPaletteColor(i);
576 :
577 0 : pEncoder->EncodeByte (aColor.GetRed());
578 0 : pEncoder->EncodeByte (aColor.GetGreen());
579 0 : pEncoder->EncodeByte (aColor.GetBlue());
580 0 : }
581 0 : pEncoder.reset();
582 :
583 0 : WritePS (mpPageBody, "pop ] setcolorspace\n");
584 : }
585 0 : break;
586 0 : default: break;
587 : }
588 0 : }
589 :
590 : void
591 0 : PrinterGfx::DrawPS2GrayImage (const PrinterBmp& rBitmap, const Rectangle& rArea)
592 : {
593 0 : writePS2Colorspace(rBitmap, psp::GrayScaleImage);
594 0 : writePS2ImageHeader(rArea, psp::GrayScaleImage);
595 :
596 0 : boost::scoped_ptr<ByteEncoder> pEncoder(mbCompressBmp ? new LZWEncoder(mpPageBody)
597 0 : : new Ascii85Encoder(mpPageBody));
598 :
599 0 : for (long nRow = rArea.Top(); nRow <= rArea.Bottom(); nRow++)
600 : {
601 0 : for (long nColumn = rArea.Left(); nColumn <= rArea.Right(); nColumn++)
602 : {
603 0 : unsigned char nByte = rBitmap.GetPixelGray (nRow, nColumn);
604 0 : pEncoder->EncodeByte (nByte);
605 : }
606 0 : }
607 0 : }
608 :
609 : void
610 0 : PrinterGfx::DrawPS2MonoImage (const PrinterBmp& rBitmap, const Rectangle& rArea)
611 : {
612 0 : writePS2Colorspace(rBitmap, psp::MonochromeImage);
613 0 : writePS2ImageHeader(rArea, psp::MonochromeImage);
614 :
615 0 : boost::scoped_ptr<ByteEncoder> pEncoder(mbCompressBmp ? new LZWEncoder(mpPageBody)
616 0 : : new Ascii85Encoder(mpPageBody));
617 :
618 0 : for (long nRow = rArea.Top(); nRow <= rArea.Bottom(); nRow++)
619 : {
620 0 : long nBitPos = 0;
621 0 : unsigned char nBit = 0;
622 0 : unsigned char nByte = 0;
623 :
624 0 : for (long nColumn = rArea.Left(); nColumn <= rArea.Right(); nColumn++)
625 : {
626 0 : nBit = rBitmap.GetPixelIdx (nRow, nColumn);
627 0 : nByte |= nBit << (7 - nBitPos);
628 :
629 0 : if (++nBitPos == 8)
630 : {
631 0 : pEncoder->EncodeByte (nByte);
632 0 : nBitPos = 0;
633 0 : nByte = 0;
634 : }
635 : }
636 : // keep the row byte aligned
637 0 : if (nBitPos != 0)
638 0 : pEncoder->EncodeByte (nByte);
639 0 : }
640 0 : }
641 :
642 : void
643 0 : PrinterGfx::DrawPS2PaletteImage (const PrinterBmp& rBitmap, const Rectangle& rArea)
644 : {
645 0 : writePS2Colorspace(rBitmap, psp::PaletteImage);
646 0 : writePS2ImageHeader(rArea, psp::PaletteImage);
647 :
648 0 : boost::scoped_ptr<ByteEncoder> pEncoder(mbCompressBmp ? new LZWEncoder(mpPageBody)
649 0 : : new Ascii85Encoder(mpPageBody));
650 :
651 0 : for (long nRow = rArea.Top(); nRow <= rArea.Bottom(); nRow++)
652 : {
653 0 : for (long nColumn = rArea.Left(); nColumn <= rArea.Right(); nColumn++)
654 : {
655 0 : unsigned char nByte = rBitmap.GetPixelIdx (nRow, nColumn);
656 0 : pEncoder->EncodeByte (nByte);
657 : }
658 0 : }
659 0 : }
660 :
661 : void
662 0 : PrinterGfx::DrawPS2TrueColorImage (const PrinterBmp& rBitmap, const Rectangle& rArea)
663 : {
664 0 : writePS2Colorspace(rBitmap, psp::TrueColorImage);
665 0 : writePS2ImageHeader(rArea, psp::TrueColorImage);
666 :
667 0 : boost::scoped_ptr<ByteEncoder> pEncoder(mbCompressBmp ? new LZWEncoder(mpPageBody)
668 0 : : new Ascii85Encoder(mpPageBody));
669 :
670 0 : for (long nRow = rArea.Top(); nRow <= rArea.Bottom(); nRow++)
671 : {
672 0 : for (long nColumn = rArea.Left(); nColumn <= rArea.Right(); nColumn++)
673 : {
674 0 : PrinterColor aColor = rBitmap.GetPixelRGB (nRow, nColumn);
675 0 : pEncoder->EncodeByte (aColor.GetRed());
676 0 : pEncoder->EncodeByte (aColor.GetGreen());
677 0 : pEncoder->EncodeByte (aColor.GetBlue());
678 0 : }
679 0 : }
680 0 : }
681 :
682 3 : } /* namespace psp */
683 :
684 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|