📄 decoder.cpp
字号:
/* Copyright (C) 2006 Lucas Gomez All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
// INCLUDE FILES
#include "Decoder.h"
#include "MsgReader.h"
#include "VncViewer.pan"
#include "LogWriter.h"
TBool MDecoder::Supported(TEncodings aEncoding)
{
return (aEncoding == EEncodingRaw || aEncoding == EEncodingRRE ||
aEncoding == EEncodingHextile || aEncoding == EEncodingZRLE);
}
MDecoder* MDecoder::CreateDecoder(TEncodings aEncoding,CMsgReader* aReader)
{
switch(aEncoding)
{
case EEncodingRaw: return new RawDecoder(aReader);
case EEncodingRRE: return new RREDecoder(aReader);
case EEncodingHextile: return new HextileDecoder(aReader);
case EEncodingZRLE: return new ZRLEDecoder(aReader);
}
return NULL;
}
RawDecoder::RawDecoder(CMsgReader* aMsgReader)
{
iMsgReader=aMsgReader;
}
RawDecoder::~RawDecoder()
{
}
void RawDecoder::ReadRect(TInt aX,TInt aY,TInt aW,TInt aH,
CMsgHandler* aHandler)
{
RBuf8 imageBuf;
iMsgReader->GetImageBuf(aW,aW*aH,imageBuf);
TInt nPixels=imageBuf.Length()/(iMsgReader->GetBpp()/8);
TInt nRows=nPixels/aW;
TInt bytesPerRow=aW*(iMsgReader->GetBpp()/8);
while(aH>0)
{
if(nRows>aH) nRows=aH;
iMsgReader->GetInStream()->ReadBytes(imageBuf,0,nRows*bytesPerRow);
aHandler->ImageRect(aX,aY,aW,nRows,imageBuf,0);
aH-=nRows;
aY+=nRows;
}
imageBuf.Close();
}
RREDecoder::RREDecoder(CMsgReader* aMsgReader)
{
iMsgReader=aMsgReader;
}
RREDecoder::~RREDecoder()
{
}
void RREDecoder::ReadRect(TInt aX,TInt aY,TInt aW,TInt aH,
CMsgHandler* aHandler)
{
InStream* is=iMsgReader->GetInStream();
int nSubrects=is->ReadU32();
int bg=ReadPixel(is);
aHandler->FillRect(aX,aY,aW,aH,bg);
for(TInt i=0;i<nSubrects;i++)
{
TInt pix=ReadPixel(is);
TInt sx=is->ReadU16();
TInt sy=is->ReadU16();
TInt sw=is->ReadU16();
TInt sh=is->ReadU16();
aHandler->FillRect(aX+sx,aY+sy,sw,sh,pix);
}
}
HextileDecoder::HextileDecoder(CMsgReader* aMsgReader)
{
iMsgReader=aMsgReader;
}
HextileDecoder::~HextileDecoder()
{
}
void HextileDecoder::ReadRect(TInt aX,TInt aY,TInt aW,TInt aH,
CMsgHandler* aHandler)
{
InStream* is = iMsgReader->GetInStream();
RBuf8 buf;
iMsgReader->GetImageBuf(16*16*4,0,buf);
TInt bg=0;
TInt fg=0;
for(TInt ty=aY;ty<aY+aH;ty+=16)
{
TInt th=Min(aY+aH-ty,16);
for(TInt tx=aX;tx<aX+aW;tx+=16)
{
TInt tw=Min(aX+aW-tx,16);
TInt tileType=is->ReadU8();
if((tileType & KHextileRaw)!=0)
{
is->ReadBytes(buf,0,tw*th*(KBPP/8));
aHandler->ImageRect(tx,ty,tw,th,buf,0);
continue;
}
if ((tileType & KHextileBgSpecified)!=0)
bg=ReadPixel(is);
TInt len=tw*th;
TInt ptr=0;
while(len-->0) buf[ptr++]=static_cast<TUint8>(bg);
if((tileType & KHextileFgSpecified)!=0)
fg=ReadPixel(is);
if((tileType & KHextileAnySubrects)!=0)
{
TInt nSubrects=is->ReadU8();
for(TInt i=0;i<nSubrects;i++)
{
if((tileType & KHextileSubrectsColoured)!=0)
fg=ReadPixel(is);
TInt xy=is->ReadU8();
TInt wh=is->ReadU8();
TInt sx=((xy>>4) & 15);
TInt sy=(xy & 15);
TInt sw=((wh >> 4) & 15) + 1;
TInt sh=(wh & 15) + 1;
ptr=sy*tw+sx;
TInt rowAdd=tw-sw;
while(sh-->0)
{
len=sw;
while(len-->0) buf[ptr++]=static_cast<TUint8>(fg);
ptr+=rowAdd;
}
}
}
aHandler->ImageRect(tx,ty,tw,th,buf,0);
}
}
buf.Close();
}
ZRLEDecoder::ZRLEDecoder(CMsgReader* aMsgReader)
{
iMsgReader=aMsgReader;
iZIS=new ZLibInStream();
}
ZRLEDecoder::~ZRLEDecoder()
{
if(iZIS)
{
delete iZIS;
iZIS=NULL;
}
}
void ZRLEDecoder::ReadRect(TInt aX,TInt aY,TInt aW,TInt aH,
CMsgHandler* aHandler)
{
InStream* is=iMsgReader->GetInStream();
RBuf8 buf;
iMsgReader->GetImageBuf(64*64*4,0,buf);
TInt length=is->ReadU32();
iZIS->SetUnderlying(is,length);
for(TInt ty=aY;ty<aY+aH;ty+=64)
{
TInt th=Min(aY+aH-ty,64);
for (TInt tx=aX;tx<aX+aW;tx+=64)
{
TInt tw=Min(aX+aW-tx,64);
TInt mode=iZIS->ReadU8();
TBool rle=(mode & 128)!=0;
TInt palSize=mode & 127;
TInt palette[128];
for(TInt i=0;i<palSize;i++)
{
palette[i]=ReadPixel(iZIS);
}
if(palSize==1)
{
TInt pix=palette[0];
aHandler->FillRect(tx,ty,tw,th,pix);
continue;
}
if(!rle)
{
if(palSize==0)
{
// raw
iZIS->ReadBytes(buf,0,tw*th*(KBPP/8));
}
else
{
// packed pixels
TInt bppp=((palSize>16)?8:
((palSize>4)?4:((palSize>2)?2:1)));
TInt ptr=0;
for(TInt i=0;i<th;i++)
{
TInt eol=ptr+tw;
TInt b=0;
TInt nbits=0;
while(ptr<eol)
{
if(nbits==0)
{
b=iZIS->ReadU8();
nbits=8;
}
nbits-=bppp;
TInt index=(b>>nbits) & ((1<<bppp)-1) & 127;
buf[ptr++]=static_cast<TUint8>(palette[index]);
}
}
}
}
else
{
if(palSize==0)
{
// plain RLE
TInt ptr=0;
TInt end=ptr+tw*th;
while(ptr<end)
{
TInt pix=ReadPixel(iZIS);
TInt len=1;
TInt b;
do
{
b=iZIS->ReadU8();
len+=b;
}while(b==255);
if(!(len<=end-ptr))
User::Leave(EVncViewerZRLEDecoderFailed);
while(len-->0) buf[ptr++]=static_cast<TUint8>(pix);
}
}
else
{
// palette RLE
TInt ptr=0;
TInt end=ptr+tw*th;
while(ptr<end)
{
TInt index=iZIS->ReadU8();
TInt len=1;
if((index & 128)!=0)
{
TInt b;
do
{
b=iZIS->ReadU8();
len+=b;
}while(b==255);
if(!(len<=end-ptr))
User::Leave(EVncViewerZRLEDecoderFailed);
}
index&=127;
TInt pix=palette[index];
while(len-->0) buf[ptr++]=static_cast<TUint8>(pix);
}
}
}
aHandler->ImageRect(tx,ty,tw,th,buf,0);
}
}
buf.Close();
iZIS->Reset();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -