Ejemplo n.º 1
0
        private static PalEntry[] unswizzle8bpp(PalEntry[] pixels, int w, int h)
        {
            PalEntry[] unswizzled = new PalEntry[pixels.Length];

            for (int y = 0; y < h; ++y)
            {
                for (int x = 0; x < w; ++x)
                {
                    int block_location  = (y & (~0xf)) * w + (x & (~0xf)) * 2;
                    int swap_selector   = (((y + 2) >> 2) & 0x1) * 4;
                    int posY            = (((y & (~3)) >> 1) + (y & 1)) & 0x7;
                    int column_location = posY * w * 2 + ((x + swap_selector) & 0x7) * 4;

                    int byte_num = ((y >> 1) & 1) + ((x >> 2) & 2);     // 0,1,2,3

                    int idx = block_location + column_location + byte_num;
                    if (idx < pixels.Length)
                    {
                        unswizzled[(y * w) + x] = pixels[idx];
                    }
                }
            }

            return(unswizzled);
        }
Ejemplo n.º 2
0
        public WriteableBitmap Decode(int offset, int chunkStartOffset)
        {
            // Dark Alliance encodes pointers as offsets from the entry in the texture entry table.
            // Return to arms (more sensibly) encodes pointers as offsets from the current chunk loaded from the disc.
            int deltaOffset = EngineVersion.DarkAlliance == _engineVersion ? offset : chunkStartOffset;

            int pixelWidth           = DataUtil.getLEUShort(fileData, offset);
            int pixelHeight          = DataUtil.getLEUShort(fileData, offset + 2);
            int header10             = DataUtil.getLEInt(fileData, offset + 0x10);
            int compressedDataLen    = DataUtil.getLEInt(fileData, offset + 0x14);
            int compressedDataOffset = header10 + deltaOffset;

            if (compressedDataOffset <= 0 || compressedDataOffset >= fileData.Length)
            {
                return(null);
            }
            int palOffset = DataUtil.getLEInt(fileData, compressedDataOffset) + deltaOffset;

            PalEntry[] palette = PalEntry.readPalette(fileData, palOffset, 16, 16);
            palette = PalEntry.unswizzlePalette(palette);
            HuffVal[] huffVals = decodeHuff(palOffset + 0xc00);

            int p = compressedDataOffset + 4;

            int width  = (pixelWidth + 0x0f) & ~0x0f;
            int height = (pixelHeight + 0x0f) & ~0x0f;

            WriteableBitmap image = new WriteableBitmap(
                width, height,
                96, 96,
                PixelFormats.Bgr32,
                null);

            image.Lock();

            while (fileData[p] != 0xFF)
            {
                int x0 = fileData[p];
                int y0 = fileData[p + 1];
                int x1 = fileData[p + 2];
                int y1 = fileData[p + 3];
                p += 4;
                for (int yblock = y0; yblock <= y1; ++yblock)
                {
                    for (int xblock = x0; xblock <= x1; ++xblock)
                    {
                        int blockDataStart = DataUtil.getLEInt(fileData, p) + deltaOffset;
                        decodeBlock(xblock, yblock, blockDataStart, palOffset + 0x400, image, palette, huffVals);
                        p += 4;
                    }
                }
            }
            // Specify the area of the bitmap that changed.
            image.AddDirtyRect(new Int32Rect(0, 0, width, height));

            // Release the back buffer and make it available for display.
            image.Unlock();

            return(image);
        }
Ejemplo n.º 3
0
        private static PalEntry[] applyPalette(PalEntry[] palette, byte[] bytes)
        {
            var pixels = new PalEntry[bytes.Length];

            for (var i = 0; i < bytes.Length; ++i)
            {
                pixels[i] = palette[bytes[i] & 0xFF];
            }
            return(pixels);
        }
Ejemplo n.º 4
0
 private static PalEntry[] readPixels32(PalEntry[] pixels, byte[] fileData, PalEntry[] palette, int startOffset, int startx, int starty, int rrw, int rrh, int dbw, int dbh)
 {
     if (palette.Length == 256)
     {
         int numDestBytes = dbh * dbw * 4;
         int widthBytes   = dbw * 4;
         if (pixels == null)
         {
             pixels = new PalEntry[numDestBytes];
         }
         int idx = startOffset;
         for (int y = 0; y < rrh && (y + starty) < dbh; ++y)
         {
             for (int x = 0; x < rrw; ++x)
             {
                 int destIdx = (y + starty) * widthBytes + (x + startx) * 4;
                 pixels[destIdx++] = palette[fileData[idx++] & 0xFF];
                 pixels[destIdx++] = palette[fileData[idx++] & 0xFF];
                 pixels[destIdx++] = palette[fileData[idx++] & 0xFF];
                 pixels[destIdx]   = palette[fileData[idx++] & 0xFF];
             }
         }
         return(pixels);
     }
     else
     {
         int numDestBytes = rrh * dbw;
         if (pixels == null)
         {
             pixels = new PalEntry[numDestBytes];
         }
         int  idx    = startOffset;
         bool lowbit = false;
         for (int y = 0; y < rrh; ++y)
         {
             for (int x = 0; x < rrw; ++x)
             {
                 int destIdx = (y + starty) * dbw + x + startx;
                 if (!lowbit)
                 {
                     pixels[destIdx] = palette[fileData[idx] >> 4 & 0x0F];
                 }
                 else
                 {
                     pixels[destIdx] = palette[fileData[idx++] & 0x0F];
                 }
                 lowbit = !lowbit;
             }
         }
         return(pixels);
     }
 }
Ejemplo n.º 5
0
        public static PalEntry[] readPalette(byte[] fileData, int startOffset, int palw, int palh)
        {
            int numEntries = palw * palh;
            PalEntry[] palette = new PalEntry[numEntries];
            for (int i = 0; i < numEntries; ++i) {
                PalEntry pe = new PalEntry();
                pe.r = fileData[startOffset + i * 4];
                pe.g = fileData[startOffset + i * 4 + 1];
                pe.b = fileData[startOffset + i * 4 + 2];
                pe.a = fileData[startOffset + i * 4 + 3];

                palette[i] = pe;
            }
            return palette;
        }
Ejemplo n.º 6
0
        public static PalEntry[] unswizzlePalette(PalEntry[] palette)
        {
            if (palette.Length == 256) {
                PalEntry[] unswizzled = new PalEntry[palette.Length];

                int j = 0;
                for (int i = 0; i < 256; i += 32, j += 32) {
                    copy(unswizzled, i, palette, j, 8);
                    copy(unswizzled, i + 16, palette, j + 8, 8);
                    copy(unswizzled, i + 8, palette, j + 16, 8);
                    copy(unswizzled, i + 24, palette, j + 24, 8);
                }
                return unswizzled;
            } else {
                return palette;
            }
        }
Ejemplo n.º 7
0
        public static PalEntry[] readPalette(byte[] fileData, int startOffset, int palw, int palh)
        {
            int numEntries = palw * palh;

            PalEntry[] palette = new PalEntry[numEntries];
            for (int i = 0; i < numEntries; ++i)
            {
                PalEntry pe = new PalEntry();
                pe.r = fileData[startOffset + i * 4];
                pe.g = fileData[startOffset + i * 4 + 1];
                pe.b = fileData[startOffset + i * 4 + 2];
                pe.a = fileData[startOffset + i * 4 + 3];

                palette[i] = pe;
            }
            return(palette);
        }
Ejemplo n.º 8
0
        private static PalEntry[] readPixels32(byte[] fileData, int startOffset, int w, int h)
        {
            int numPixels = w * h;

            PalEntry[] pixels    = new PalEntry[numPixels];
            int        destIdx   = 0;
            int        endOffset = startOffset + numPixels * 4;

            for (int idx = startOffset; idx < endOffset;)
            {
                PalEntry pe = new PalEntry();
                pe.r = fileData[idx++];
                pe.g = fileData[idx++];
                pe.b = fileData[idx++];
                pe.a = fileData[idx++];

                pixels[destIdx++] = pe;
            }

            return(pixels);
        }
Ejemplo n.º 9
0
        public static PalEntry[] unswizzlePalette(PalEntry[] palette)
        {
            if (palette.Length == 256)
            {
                PalEntry[] unswizzled = new PalEntry[palette.Length];

                int j = 0;
                for (int i = 0; i < 256; i += 32, j += 32)
                {
                    copy(unswizzled, i, palette, j, 8);
                    copy(unswizzled, i + 16, palette, j + 8, 8);
                    copy(unswizzled, i + 8, palette, j + 16, 8);
                    copy(unswizzled, i + 24, palette, j + 24, 8);
                }
                return(unswizzled);
            }
            else
            {
                return(palette);
            }
        }
Ejemplo n.º 10
0
        private static PalEntry[] readPixels32(byte[] fileData, int startOffset, int w, int h)
        {
            var numPixels = w * h;
            var pixels    = new PalEntry[numPixels];
            var destIdx   = 0;
            var endOffset = startOffset + numPixels * 4;

            for (var idx = startOffset; idx < endOffset;)
            {
                var pe = new PalEntry
                {
                    r = fileData[idx++],
                    g = fileData[idx++],
                    b = fileData[idx++],
                    a = fileData[idx++]
                };

                pixels[destIdx++] = pe;
            }

            return(pixels);
        }
Ejemplo n.º 11
0
        private void decodeBlock(int xblock, int yblock, int blockDataStart, int table0Start, WriteableBitmap image, PalEntry[] palette, HuffVal[] huffVals)
        {
            int tableOffset = table0Start + 0x800;
            int table1Len   = DataUtil.getLEInt(fileData, tableOffset) * 2;
            int table1Start = tableOffset + 4;
            int table2Start = table1Start + table1Len;
            int table3Start = table2Start + 0x48;

            int[] pix8s     = new int[16 * 16];
            int   curpix8   = 0;
            int   startBit  = 0;
            int   prevPixel = 0;

            for (int y = 0; y < 16; ++y)
            {
                for (int x = 0; x < 16; ++x)
                {
                    int startWordIdx = startBit / 16;
                    int word1        = DataUtil.getLEUShort(fileData, blockDataStart + startWordIdx * 2);
                    int word2        = DataUtil.getLEUShort(fileData, blockDataStart + startWordIdx * 2 + 2);
                    // if startBit is 0, word == word1
                    // if startBit is 1, word is 15 bits of word1 and 1 bit of word2
                    int word = ((word1 << 16 | word2) >> (16 - (startBit & 0x0f))) & 0xFFFF;

                    int     byte1 = (word >> 8) & 0xff;
                    HuffVal hv    = huffVals[byte1];
                    int     pixCmd;
                    if (hv.numBits != 0)
                    {
                        pixCmd    = hv.val;
                        startBit += hv.numBits;
                    }
                    else
                    {
                        // Must be more than an 8 bit code
                        int bit = 9;
                        int a   = word >> (16 - bit);
                        int v   = DataUtil.getLEInt(fileData, table3Start + bit * 4);
                        while (v < a)
                        {
                            ++bit;
                            if (bit > 16)
                            {
                                throw new Exception("A decoding error occured");
                            }
                            a = word >> (16 - bit);
                            v = DataUtil.getLEInt(fileData, table3Start + bit * 4);
                        }
                        startBit += bit;
                        int val         = DataUtil.getLEInt(fileData, table2Start + bit * 4);
                        int table1Index = a + val;

                        pixCmd = DataUtil.getLEShort(fileData, table1Start + table1Index * 2);
                    }
                    int pix8 = 0;
                    if (pixCmd < 0x100)
                    {
                        pix8 = pixCmd;
                    }
                    else if (pixCmd < 0x105)
                    {
                        int backjump = backJumpTable[pixCmd - 0x100];
                        if ((curpix8 + backjump) >= 0)
                        {
                            pix8 = pix8s[curpix8 + backjump];
                        }
                        else
                        {
                            throw new Exception("Something went wrong");
                        }
                    }
                    else
                    {
                        int table0Index = (pixCmd - 0x105) + prevPixel * 8;
                        pix8 = fileData[table0Start + table0Index] & 0xFF;
                    }

                    pix8s[curpix8++] = pix8;

                    prevPixel = pix8 & 0xFF;
                    PalEntry pixel       = palette[pix8 & 0xFF];
                    var      pBackBuffer = image.BackBuffer;
                    int      xpos        = xblock * 16 + x;
                    int      ypos        = yblock * 16 + y;
                    var      p           = pBackBuffer + ypos * image.BackBufferStride + xpos * 4;
                    unsafe
                    {
                        *((int *)p) = pixel.argb();
                    }
                }
            }
        }
Ejemplo n.º 12
0
        private static PalEntry[] unswizzle8bpp(PalEntry[] pixels, int w, int h)
        {
            PalEntry[] unswizzled = new PalEntry[pixels.Length];

            for (int y = 0; y < h; ++y) {
                for (int x = 0; x < w; ++x) {

                    int block_location = (y & (~0xf)) * w + (x & (~0xf)) * 2;
                    int swap_selector = (((y + 2) >> 2) & 0x1) * 4;
                    int posY = (((y & (~3)) >> 1) + (y & 1)) & 0x7;
                    int column_location = posY * w * 2 + ((x + swap_selector) & 0x7) * 4;

                    int byte_num = ((y >> 1) & 1) + ((x >> 2) & 2);     // 0,1,2,3

                    int idx = block_location + column_location + byte_num;
                    if (idx < pixels.Length) {
                        unswizzled[(y * w) + x] = pixels[idx];
                    }
                }
            }

            return unswizzled;
        }
Ejemplo n.º 13
0
 private static PalEntry[] readPixels32(PalEntry[] pixels, byte[] fileData, PalEntry[] palette, int startOffset, int startx, int starty, int rrw, int rrh, int dbw, int dbh)
 {
     if (palette.Length == 256) {
         int numDestBytes = dbh * dbw * 4;
         int widthBytes = dbw * 4;
         if (pixels == null) {
             pixels = new PalEntry[numDestBytes];
         }
         int idx = startOffset;
         for (int y = 0; y < rrh && (y+starty) < dbh; ++y) {
             for (int x = 0; x < rrw; ++x) {
                 int destIdx = (y+starty) * widthBytes + (x + startx) * 4;
                 pixels[destIdx++] = palette[fileData[idx++] & 0xFF];
                 pixels[destIdx++] = palette[fileData[idx++] & 0xFF];
                 pixels[destIdx++] = palette[fileData[idx++] & 0xFF];
                 pixels[destIdx] = palette[fileData[idx++] & 0xFF];
             }
         }
         return pixels;
     } else {
         int numDestBytes = rrh * dbw;
         if (pixels == null) {
             pixels = new PalEntry[numDestBytes];
         }
         int idx = startOffset;
         bool lowbit = false;
         for (int y = 0; y < rrh; ++y) {
             for (int x = 0; x < rrw; ++x) {
                 int destIdx = (y + starty) * dbw + x + startx;
                 if (!lowbit) {
                     pixels[destIdx] = palette[fileData[idx] >> 4 & 0x0F];
                 } else {
                     pixels[destIdx] = palette[fileData[idx++] & 0x0F];
                 }
                 lowbit = !lowbit;
             }
         }
         return pixels;
     }
 }
Ejemplo n.º 14
0
 private static void copy(PalEntry[] unswizzled, int i, PalEntry[] swizzled, int j, int num)
 {
     for (int x = 0; x < num; ++x) {
         unswizzled[i + x] = swizzled[j + x];
     }
 }
Ejemplo n.º 15
0
        public static WriteableBitmap Decode(byte[] data, int startOffset)
        {
            var gsMem = new GSMemory();

            var length = DataUtil.getLEShort(data, startOffset + 6) * 16;

            int finalw      = BitConverter.ToInt16(data, startOffset);
            int finalh      = BitConverter.ToInt16(data, startOffset + 2);
            var offsetToGIF = DataUtil.getLEInt(data, startOffset + 16);

            var sourcew = finalw;
            var sourceh = finalh;

            PalEntry[] pixels = null;
            byte[]     bytes  = null;

            var curIdx   = offsetToGIF + startOffset;
            var endIndex = curIdx + length;

            var gifTag = new GIFTag();

            gifTag.parse(data, curIdx);

            // This is basically heuristics. Writing a full GIF parser is complex and as the texture files are written by a tool,
            // we can safely make some assumptions about their structure.
            if (gifTag.nloop == 4)
            {
                int palw = DataUtil.getLEShort(data, curIdx + 0x30);
                int palh = DataUtil.getLEShort(data, curIdx + 0x34);

                curIdx += gifTag.Length;
                var gifTag2 = new GIFTag();
                gifTag2.parse(data, curIdx);

                // 8 bit palletised
                var palette = PalEntry.readPalette(data, curIdx + GIFTag.Size, palw, palh);

                palette = PalEntry.unswizzlePalette(palette);

                curIdx += gifTag2.Length;
                var destWBytes = (finalw + 0x0f) & ~0x0f;
                var destHBytes = (finalh + 0x0f) & ~0x0f;

                var dpsm   = PSMCT32;
                var dbw    = 0;
                var dbp    = 0;
                var rrw    = 0;
                var rrh    = 0;
                var startx = 0;
                var starty = 0;

                while (curIdx < endIndex - GIFTag.Size)
                {
                    var gifTag3 = new GIFTag();
                    gifTag3.parse(data, curIdx);
                    while (!gifTag3.IsImage)
                    {
                        var trxregOffset = findADEntry(data, curIdx + GIFTag.Size, gifTag3.nloop, TRXREG);
                        if (trxregOffset != 0)
                        {
                            rrw = DataUtil.getLEShort(data, trxregOffset);
                            rrh = DataUtil.getLEShort(data, trxregOffset + 4);
                        }
                        var trxposOffset = findADEntry(data, curIdx + GIFTag.Size, gifTag3.nloop, TRXPOS);
                        if (trxposOffset != 0)
                        {
                            startx = DataUtil.getLEShort(data, trxposOffset + 0x04) & 0x07FF;
                            starty = DataUtil.getLEShort(data, trxposOffset + 0x06) & 0x07FF;
                        }
                        var bitbltOffset = findADEntry(data, curIdx + GIFTag.Size, gifTag3.nloop, BITBLTBUF);
                        if (bitbltOffset != 0)
                        {
                            //int sbw = fileData[bitbltOffset + 0x02] & 0x3F;
                            dbp  = data[bitbltOffset + 0x04] & 0x3FFF;
                            dbw  = data[bitbltOffset + 0x06] & 0x3F;
                            dpsm = data[bitbltOffset + 0x07] & 0x3F;
                        }

                        curIdx += gifTag3.Length;
                        if (curIdx + GIFTag.Size >= endIndex)
                        {
                            break;
                        }

                        gifTag3.parse(data, curIdx);
                    }
                    curIdx += GIFTag.Size;     // image gif tag
                    var bytesToTransfer = gifTag3.nloop * 16;

                    if (palette.Length == 16)
                    {
                        // source is PSMT4. Dest can be PSMT4 or PSMCT32
                        if (dpsm == PSMCT32)
                        {
                            var imageData    = data;
                            var imageDataIdx = curIdx;
                            // check for multiple IMAGE entries.
                            var nextTagInd = bytesToTransfer + curIdx;
                            if (nextTagInd < endIndex - GIFTag.Size)
                            {
                                var imageTag2 = new GIFTag();
                                imageTag2.parse(data, nextTagInd);
                                if (imageTag2.flg == 2)
                                {
                                    // IMAGE
                                    var bytesToTransfer2 = imageTag2.nloop * 16;
                                    imageDataIdx = 0;
                                    imageData    = new byte[bytesToTransfer + bytesToTransfer2];
                                    var j = curIdx;
                                    for (var i = 0; i < bytesToTransfer; ++i)
                                    {
                                        imageData[i] = data[j];
                                    }
                                    j = nextTagInd + GIFTag.Size;
                                    for (var i = bytesToTransfer; i < bytesToTransfer + bytesToTransfer2; ++i)
                                    {
                                        imageData[i] = data[j];
                                    }
                                    bytesToTransfer += imageTag2.Length;
                                }
                            }

                            gsMem.writeTexPSMCT32(dbp, dbw, startx, starty, rrw, rrh, imageData, imageDataIdx);

                            destWBytes = (finalw + 0x3f) & ~0x3f;
                            bytes      = gsMem.readTexPSMT4(dbp, destWBytes / 0x40, startx, starty, destWBytes, destHBytes);
                            bytes      = expand4bit(bytes);
                        }
                        else
                        {
                            // dest and source are the same and so image isn't swizzled
                            bytes = transferPSMT4(bytes, data, curIdx, startx, starty, rrw, rrh, destWBytes, destHBytes);
                        }
                    }
                    else
                    {
                        // source is PSMT8. Dest is always PSMCT32.
                        gsMem.writeTexPSMCT32(dbp, dbw, startx, starty, rrw, rrh, data, curIdx);
                    }
                    curIdx += bytesToTransfer;
                }
                if (palette.Length == 256)
                {
                    destWBytes = (finalw + 0x3f) & ~0x3f;
                    dbw        = destWBytes / 0x40;
                    bytes      = gsMem.readTexPSMT8(dbp, dbw, 0, 0, destWBytes, finalh);
                }
                // THIS IS A HACK
                if (palette.Length == 1024)
                {
                    destWBytes = (finalw + 0x3f) & ~0x3f;
                    dbw        = destWBytes / 0x40;
                    bytes      = gsMem.readTexPSMT8(dbp, dbw, 0, 0, destWBytes, finalh);
                }
                pixels  = applyPalette(palette, bytes);
                sourcew = destWBytes;
                sourceh = destHBytes;
            }
            else if (gifTag.nloop == 3)
            {
                var gifTag2 = new GIFTag();
                gifTag2.parse(data, startOffset + 0xC0);

                if (gifTag2.flg == 2)
                {
                    // image mode
                    pixels = readPixels32(data, startOffset + 0xD0, finalw, finalh);
                }
            }
            WriteableBitmap image = null;

            if (finalw != 0)
            {
                image = new WriteableBitmap(
                    finalw, finalh,
                    96, 96,
                    PixelFormats.Bgra32,
                    null);
                var imageBytes = new int[finalw * finalh];
                var stride     = 4 * finalw;
                var pixOffset  = 0;
                if (pixels != null)
                {
                    for (var y = 0; y < sourceh && y < finalh; ++y)
                    {
                        for (var x = 0; x < sourcew && x < finalw; ++x)
                        {
                            var pixel = pixels[y * sourcew + x];
                            if (pixel != null)
                            {
                                if (x < finalw && y < finalh)
                                {
                                    imageBytes[pixOffset++] = pixel.argb();
                                }
                            }
                        }
                    }
                }
                image.WritePixels(new Int32Rect(0, 0, finalw, finalh), imageBytes, stride, 0);
            }
            return(image);
        }
Ejemplo n.º 16
0
        public static WriteableBitmap Decode(byte[] data, int startOffset, int length)
        {
            int endIndex = startOffset + length;
            int finalw   = BitConverter.ToInt16(data, startOffset);
            int finalh   = BitConverter.ToInt16(data, startOffset + 2);

            int sourcew = finalw;
            int sourceh = finalh;

            PalEntry[] pixels = null;

            int    curIdx = 0x80 + startOffset;
            GIFTag gifTag = new GIFTag();

            gifTag.parse(data, curIdx);

            // This is basically heuristics. Writing a full GIF parser is complex and as the texture files are written by a tool,
            // we can safely make some assumptions about their structure.
            if (gifTag.nloop == 4)
            {
                int palw = DataUtil.getLEShort(data, curIdx + 0x30);
                int palh = DataUtil.getLEShort(data, curIdx + 0x34);

                curIdx += 0x50;
                GIFTag gifTag2 = new GIFTag();
                gifTag2.parse(data, curIdx);

                // 8 bit palletised
                PalEntry[] palette = PalEntry.readPalette(data, curIdx + 0x10, palw, palh);

                palette = PalEntry.unswizzlePalette(palette);

                int palLen = palw * palh * 4;
                curIdx += (palLen + 0x10);

                GIFTag gifTag50 = new GIFTag();
                gifTag50.parse(data, curIdx);
                curIdx += 0x20;

                int dbw = (sourcew / 2 + 0x07) & ~0x07;
                int dbh = (sourceh / 2 + 0x07) & ~0x07;

                // The following should be a loop, there are repeating sections
                while (curIdx < endIndex - 0x10)
                {
                    GIFTag gifTag3 = new GIFTag();
                    gifTag3.parse(data, curIdx);

                    int dimOffset = 0x10;

                    int thisRrw = DataUtil.getLEShort(data, curIdx + dimOffset);
                    int thisRrh = DataUtil.getLEShort(data, curIdx + dimOffset + 4);

                    int startx = DataUtil.getLEShort(data, curIdx + dimOffset + 20);
                    int starty = DataUtil.getLEShort(data, curIdx + dimOffset + 22);

                    curIdx += gifTag.nloop * 0x10 + 0x10;
                    pixels  = readPixels32(pixels, data, palette, curIdx, startx, starty, thisRrw, thisRrh, dbw, dbh);
                    curIdx += thisRrw * thisRrh * 4;
                }
                if (palLen != 64)
                {
                    pixels  = unswizzle8bpp(pixels, dbw * 2, dbh * 2);
                    sourcew = dbw * 2;
                    sourceh = dbh * 2;
                }
                else
                {
                    sourcew = dbw;
                    sourceh = dbh;
                }
            }
            else if (gifTag.nloop == 3)
            {
                GIFTag gifTag2 = new GIFTag();
                gifTag2.parse(data, startOffset + 0xC0);

                if (gifTag2.flg == 2)
                {
                    // image mode
                    pixels = readPixels32(data, startOffset + 0xD0, finalw, finalh);
                }
            }
            WriteableBitmap image = null;

            if (finalw != 0 && pixels != null)
            {
                image = new WriteableBitmap(
                    finalw, finalh,
                    96, 96,
                    PixelFormats.Bgr32,
                    null);
                image.Lock();
                unsafe {
                    IntPtr pBackBuffer = image.BackBuffer;
                    for (int y = 0; y < sourceh; ++y)
                    {
                        for (int x = 0; x < sourcew; ++x)
                        {
                            PalEntry pixel = pixels[y * sourcew + x];
                            if (pixel != null)
                            {
                                if (x < finalw && y < finalh)
                                {
                                    var p = pBackBuffer + y * image.BackBufferStride + x * 4;
                                    *((int *)p) = pixel.argb();
                                }
                            }
                        }
                    }
                }
                // Specify the area of the bitmap that changed.
                image.AddDirtyRect(new Int32Rect(0, 0, finalw, finalh));

                // Release the back buffer and make it available for display.
                image.Unlock();
            }
            return(image);
        }
Ejemplo n.º 17
0
        private void decodeBlock(int xblock, int yblock, int blockDataStart, int table0Start, WriteableBitmap image, PalEntry[] palette, HuffVal[] huffVals)
        {
            int tableOffset = table0Start + 0x800;
            int table1Len = DataUtil.getLEInt(fileData, tableOffset) * 2;
            int table1Start = tableOffset + 4;
            int table2Start = table1Start + table1Len;
            int table3Start = table2Start + 0x48;

            int[] pix8s = new int[16*16];
            int curpix8=0;
            int startBit=0;
            int prevPixel=0;
            for (int y=0; y<16; ++y){
                for (int x=0; x < 16; ++x){
                    int startWordIdx = startBit / 16;
                    int word1 = DataUtil.getLEUShort(fileData, blockDataStart + startWordIdx * 2);
                    int word2 = DataUtil.getLEUShort(fileData, blockDataStart + startWordIdx * 2 + 2);
                    // if startBit is 0, word == word1
                    // if startBit is 1, word is 15 bits of word1 and 1 bit of word2
                    int word = ((word1 << 16 | word2) >> (16 - (startBit & 0x0f))) & 0xFFFF;

                    int byte1 = (word >> 8) & 0xff;
                    HuffVal hv = huffVals[byte1];
                    int pixCmd;
                    if (hv.numBits != 0){
                        pixCmd = hv.val;
                        startBit += hv.numBits;
                    } else {
                        // Must be more than an 8 bit code
                        int bit=9;
                        int a = word >> (16-bit);
                        int v = DataUtil.getLEInt(fileData, table3Start + bit*4);
                        while (v < a){
                            ++bit;
                            if (bit > 16){
                                throw new Exception("A decoding error occured");
                            }
                            a = word >> (16-bit);
                            v = DataUtil.getLEInt(fileData, table3Start + bit*4);
                        }
                        startBit += bit;
                        int val = DataUtil.getLEInt(fileData, table2Start + bit*4);
                        int table1Index = a + val;

                        pixCmd = DataUtil.getLEShort(fileData, table1Start + table1Index*2);
                    }
                    int pix8 = 0;
                    if (pixCmd < 0x100){
                        pix8 = pixCmd;
                    } else if (pixCmd < 0x105){
                        int backjump = backJumpTable[pixCmd - 0x100];
                        if ((curpix8 + backjump) >= 0){
                            pix8 = pix8s[curpix8 + backjump];
                        } else {
                            throw new Exception("Something went wrong");
                        }
                    } else {
                        int table0Index = (pixCmd - 0x105) + prevPixel * 8;
                        pix8 = fileData[table0Start + table0Index] & 0xFF;
                    }

                    pix8s[curpix8++] = pix8;

                    prevPixel = pix8 & 0xFF;
                    PalEntry pixel = palette[pix8  & 0xFF];
                    var pBackBuffer = image.BackBuffer;
                    int xpos = xblock * 16 + x;
                    int ypos = yblock * 16 + y;
                    var p = pBackBuffer + ypos * image.BackBufferStride + xpos * 4;
                    unsafe
                    {
                        *((int*)p) = pixel.argb();
                    }
                }
            }
        }
Ejemplo n.º 18
0
        private static PalEntry[] readPixels32(byte[] fileData, int startOffset, int w, int h)
        {
            int numPixels = w * h;
            PalEntry[] pixels = new PalEntry[numPixels];
            int destIdx = 0;
            int endOffset = startOffset + numPixels * 4;
            for (int idx = startOffset; idx < endOffset; ) {
                PalEntry pe = new PalEntry();
                pe.r = fileData[idx++];
                pe.g = fileData[idx++];
                pe.b = fileData[idx++];
                pe.a = fileData[idx++];

                pixels[destIdx++] = pe;
            }

            return pixels;
        }