// $Revision: 1.2 $ //Copyright (C) 1995 Taligent, Inc. All rights reserved. #ifndef TaligentSamples_DECODEXBM #include "DecodeXBM.h" #endif #ifndef TaligentSamples_XBM #include "XBM.h" #endif #ifndef Taligent_RGBTRANSFERMODES #include #endif #ifndef Taligent_RGBCOLOR #include #endif #ifndef Taligent_GRAPHICIMAGE #include #endif #ifndef Taligent_IMAGE #include #endif #ifndef Taligent_KERNEL #include #endif #ifndef Taligent_RUNTIME #include #endif extern "C" { #include } TXBMDecoder::TXBMDecoder(TStream& inputStream) { fImage = NIL; fStream = &inputStream; ParseHeader(); ParseBody(); } TXBMDecoder::~TXBMDecoder() { delete fImage; } unsigned char TXBMDecoder::GetNextByte() { unsigned char byte; do { byte <<= *fStream; } while (byte == ' ' || byte == '\t' || byte == '\n' || byte == '\r'); return byte; } TXBMDecoder::XBMCode TXBMDecoder::ReadOneCode() { char hexCode[5]; for (int codeIndex = 0 ; codeIndex < 4 ; codeIndex++) { hexCode[codeIndex] = GetNextByte(); }; if ((hexCode[0] == '0') && (hexCode[1] == 'x')) { TXBMDecoder::XBMCode result; hexCode[4] = '\0'; return (TXBMDecoder::XBMCode)strtoul(hexCode, NIL, 16); } ThrowBadData("Invalid hexidecimal data found in stream"); return 0; } unsigned short TXBMDecoder::GetImageSize() { unsigned char charBlock[256]; unsigned char* blockPtr = &charBlock[0]; for (int filled = 0 ; filled<256 ; filled++) { *blockPtr <<= *fStream; switch (*blockPtr) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': blockPtr++; break; case '\n': case '\r': *blockPtr = '\0'; return atoi((const char*)charBlock); default: blockPtr = &charBlock[0]; break; } } ThrowBadData("Invalid header line"); return 0; } void TXBMDecoder::ParseHeader() { if (GetNextByte() == '#') { fImageWidth = GetImageSize(); if (GetNextByte() == '#') { fImageHeight = GetImageSize(); TGrafBundle *tBundle = NIL; tBundle = new TGrafBundle(); tBundle->AdoptImageTransferMode( new TRGBTransparentTransferMode(TRGBColor(1,1,1))); TIndexedImage::TRGBColorArray colorArray(2); fImage = new TIndexedImage(TGPoint(0,0), fImageWidth, fImageHeight, colorArray, TGImage::k72DPI, tBundle); return; } } ThrowBadData("Invalid header data"); } void TXBMDecoder::ParseBody() { while (GetNextByte() != '{') ; TGModifiableImage* pixels = fImage->GetModifiableImage(); unsigned short column = 0; unsigned short row = 0; while (row < fImageHeight) { TXBMDecoder::XBMCode xbmCode = ReadOneCode(); for (short bits=0 ; bits<8 ; bits++, column++) { if (column < fImageWidth) { if ((xbmCode >> bits) & 0x1) { pixels->SetPixel(column, row, TRGBColor(1,1,1)); } else { pixels->SetPixel(column, row, TRGBColor(0,0,0)); } } } if (column >= fImageWidth) { column = 0; if (++row == fImageHeight) { break; } } unsigned char byte = GetNextByte(); if (byte != ',') { qprintf("Bad Byte at row %i -- %i: %c\n", row, (int)byte, byte); ThrowBadData("Expected image size doesn't match data"); } } } TModifiableImage* TXBMDecoder::OrphanImage() { TModifiableImage* result = fImage; fImage = NIL; return result; } void TXBMDecoder::ThrowBadData(const char* reason) { qprintf("TXBMDecoder::ThrowBadData: %s\n", reason); throw TXBMConverter::TXBMConverterException( TXBMConverter::TXBMConverterException::kBadData); }