⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decoder.cpp

📁 vncviewer_source_1.0
💻 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 + -