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