Beispiel #1
0
void Graphics_::DrawImage(File& f, int x, int y, int scroll, int lines)
{
	//File f;
	//char s[256];
	//sprintf(s,"Draw %d %d %d %d\n",x,y,scroll,lines);
	//print(s);

    Img2 hdr;    
    if (!f.Read(&hdr,sizeof(Img2)) || !cmp(hdr.sig,"img2"))
        return;
    
    //  Load palette
    byte palette[512];    
    int paletteLen = (hdr.colors*2 + 3) & ~3;
    f.Read(palette+2,paletteLen);   // Align to 4
    
    int width = hdr.width;
    if (lines == 0)
        lines = hdr.height;
    int maxy = min(hdr.height,lines) + y;
    
    //  Skip restart indexes
    if (hdr.restartInterval)
    {
        int restarts = (hdr.height + hdr.restartInterval - 1)/hdr.restartInterval + 1;
        if (scroll > 0)   // 
        {
            int i = min(scroll/hdr.restartInterval,restarts-1);
            scroll -= i*hdr.restartInterval;
            maxy -= i*hdr.restartInterval;
            f.Skip(i*4);
            ulong restart;
            f.Read(&restart,4);
            f.SetPos(restart);
        } else
            f.Skip(restarts*4);
    }
    
    //  Skip restart intervals
    if (maxy > 320)
        maxy = 320;
	LCD.SetBounds(x,y,hdr.width,maxy-y);    // TODO: clip
            
    byte format = hdr.format;
    if (format & 0x80)
    {
        f.SetPos(512 + ((long)scroll)*512);
        while (y < maxy)
        {
            // 512 bytes in buffer
            int count;
            const byte* b = f.GetBuffer(&count);
            LCD.Blit(b,width);
            f.Skip(512);
            y++;
        }
        return;
    }
    
    //  Run length compressed
  //  int left = x; // TODO YUCK
	int miny = y;
	y -= scroll;
    long lastPos = 0;
    while (y < maxy)
    {
		bool clip = y < miny;

        //  Repeat line?
        byte repeat = 1;
        long pos = f.GetPos();
        lastPos = pos;
        if (f.ReadByte() == 0xFF)
        {
            repeat = f.ReadByte();
            pos += 2;
			repeat = min(repeat,maxy-y);	// TODO BUG
        }
        
        //  decode a line
        while (repeat--)
        {
            y++;
            f.SetPos(pos);  // Encoder prevents backing up to previous sector
            x = 0;
            while (x < width)
            {
                int n = f.ReadByte();
                bool ex = (n & 0x80) != 0;
                n &= 0x7F;

                if (n > 120)
                {
                    if (n == 126)   // skip
                    {
                        x += f.ReadByte();
						if (!clip)
						{
#if 0
							TODO BUGBUG
							if (x == width)
								LCDSetGRAM(left,y);
							else
								LCDSetGRAM(left+x,y-1);
#endif
						}
                        continue;
                    }
                    n = ((n-121) << 8) | f.ReadByte();
                }
                x += n;
                
                if (x > width)
                {
                    for (;;)
                    {
                    }
                }
                
                int count;
                if (ex)
                {
                    // explicit
                    if (format == 8)
                    {
                        while (n)
                        {
                            const byte* b = f.GetBuffer(&count);
                            count = min(count,n);
							if (!clip)
								LCD.BlitIndexed(b,palette,count);
                            f.Skip(count);  // Always works within buffer
                            n -= count;
                        }
                    }
                    else
                    {
                        while (n)
                        {
                            const byte* b = f.GetBuffer(&count);
                            if (count == 1)
                            {   
                                int color = (f.ReadByte() << 8) | f.ReadByte();  // Wrap around
								if (!clip)
									LCD.Fill(color,1);
                            } else {
                                count >>= 1;
                                count = min(count,n);
								if (!clip)
									LCD.Blit(b,count);
                                f.Skip(count<<1);
                            }
                            n -= count;
                        }
                    }
                } else {
                //  run
                    byte a = f.ReadByte();
                    byte b;
                    if (format == 8)
                    {
                        b = palette[a*2+1];
                        a = palette[a*2];
                    }
                    else
                        b = f.ReadByte(); 
					if (!clip)
						LCD.Fill((a << 8) | b,n);
                }
            }