Example #1
0
        private static void ArrangeSlices(Bitmap bm, List <ImageSlice> slices, List <Palette> palettes, List <GTMPFile.PositionData> posData)
        {
            Rectangle  lockRect = new Rectangle(0, 0, bm.Width, bm.Height);
            BitmapData bd       = bm.LockBits(lockRect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
            // docs say this is pixel width, it's a dirty liar. It's the byte width
            int byteStride = bd.Stride;

            foreach (GTMPFile.PositionData pd in posData)
            {
                int[]  colourData       = new int[16 * 8];
                bool   makeTopLeftBlack = false;
                ushort actualTile       = pd.tile;
                //if ((pd.tile & 0x0800) != 0)
                //{
                //    actualTile = (ushort)(pd.tile & ~0x800);
                //    makeTopLeftBlack = true;
                //}
                if (pd.palette != 0xFF)
                {
                    ImageSlice tile    = slices[actualTile];
                    Palette    p       = palettes[pd.palette];
                    Color      topLeft = p.colours[tile.rect[0]];

                    for (int i = 0; i < (16 * 8); ++i)
                    {
                        byte  colourIndex = tile.rect[i];
                        Color pixelColour = p.colours[colourIndex];
                        if (makeTopLeftBlack && (pixelColour == topLeft))
                        {
                            colourData[i] = Color.Black.ToArgb(); //(int)(pixelColour.ToArgb() & 0x00FFFFFF);
                        }
                        else
                        {
                            colourData[i] = pixelColour.ToArgb();
                        }
                    }
                }
                else
                {
                    Color blockColour = GTMPFile.MakeColorFromBGR555(actualTile);
                    int   colourRGB   = blockColour.ToArgb();
                    for (int i = 0; i < (16 * 8); ++i)
                    {
                        colourData[i] = colourRGB;
                    }
                }
                IntPtr scanLineIter = new IntPtr(bd.Scan0.ToInt64() + ((pd.y * byteStride) + (pd.x * 4)));
                for (int i = 0; i < 8; ++i)
                {
                    Marshal.Copy(colourData, i * 16, scanLineIter, 16);
                    scanLineIter = new IntPtr(scanLineIter.ToInt64() + bd.Stride);
                }
            }
            bm.UnlockBits(bd);
        }
Example #2
0
        static void PlotBitmap(BitmapData bmData, List <int> pixels, List <int> palette)
        {
            IntPtr     pData          = bmData.Scan0;
            int        width          = bmData.Width;
            int        numPixels      = pixels.Count;
            List <int> linePixels     = new List <int>(bmData.Width);
            int        paletteEntries = palette.Count;
            int        lastColour     = 0;

            for (int i = 0; i < numPixels; ++i)
            {
                int  paletteIndex = pixels[i];
                bool justColour   = false;
                if (paletteIndex > paletteEntries)
                {
                    Debug.WriteLine(String.Format("Found palette index of {0:x}, there are only {1:x} in the palette", paletteIndex, paletteEntries));
                    paletteIndex = GTMPFile.MakeColorFromBGR555((ushort)paletteIndex).ToArgb();
                    justColour   = true;
                }

                if ((linePixels.Count > 1) && ((linePixels.Count % bmData.Width) == 0))
                {
                    Marshal.Copy(linePixels.ToArray(), 0, pData, linePixels.Count);
                    pData = new IntPtr(pData.ToInt64() + (linePixels.Count * 4));
                    linePixels.Clear();
                }
                //int palColour = palette[paletteIndex];
                //int alphaVal = (int)((palColour & 0xFF000000) >> 24);
                //if (alphaVal != 0x80)
                //{
                //    int percentOfThisColour = (int)((alphaVal / 128.0f) * 100);
                //    int blended = BlendColours(palColour, lastColour, percentOfThisColour);
                //    palColour = blended;
                //}
                //else
                //{
                //    lastColour = palColour;
                //}
                linePixels.Add(justColour ? paletteIndex : palette[paletteIndex]);
            }
            Marshal.Copy(linePixels.ToArray(), 0, pData, linePixels.Count);
        }
Example #3
0
        public static Bitmap Parse(string file)
        {
            List <Palette> paletteList = new List <Palette>();

            byte[] fileData = File.ReadAllBytes(file);
            if (Encoding.ASCII.GetString(fileData, 0, 3) != "GM\x3")
            {
                return(null);
            }
            int[] gmllPositions = FindPattern(fileData, Encoding.ASCII.GetBytes("GMLL"), 4);
            if (gmllPositions.Length == 0)
            {
                return(null);
            }
            int gmllPos1 = gmllPositions[0];
            List <Rectangle> clickablePos = FindClickRects(fileData, gmllPos1);
            int numPositionsEntries       = BitConverter.ToInt32(fileData, gmllPos1 + 4);
            // first +4 for GMLL, second 4 for the number of entries
            int paletteOffset   = gmllPos1 + 4 + 4 + (numPositionsEntries * 4);
            int pixelDataOffset = paletteOffset + 0x404;
            int numImageBytes   = (int)(fileData.Length - pixelDataOffset);

            byte[] imageArray = new byte[numImageBytes];
            Array.Copy(fileData, pixelDataOffset, imageArray, 0, numImageBytes);

            int palettePosIter = paletteOffset;

            for (int i = 0; i < 32; ++i)
            {
                Palette p = new Palette();
                for (int j = 0; j < p.colours.Length; ++j, palettePosIter += 2)
                {
                    // colours are in BGR format
                    ushort color    = BitConverter.ToUInt16(fileData, palettePosIter);
                    Color  rgbColor = GTMPFile.MakeColorFromBGR555(color);
                    p.colours[j] = rgbColor;
                }
                paletteList.Add(p);
            }
            List <ImageSlice> slices = ParseSlices(imageArray);
            // image positiioning seems to be on an absolute 512x504 canvas even if there's
            // only enough image data in the file to cover 512x8
            Bitmap bm = new Bitmap(512, 504, PixelFormat.Format32bppArgb);

            using (Graphics g = Graphics.FromImage(bm))
            {
                g.FillRectangle(Brushes.Black, new Rectangle(0, 0, 512, 504));
            }
            byte[] positionArray = new byte[numPositionsEntries * 4];
            Array.Copy(fileData, gmllPos1 + 8, positionArray, 0, positionArray.Length);
            List <GTMPFile.PositionData> pd = ParsePositionData(positionArray, positionArray.Length);

            ArrangeSlices(bm, slices, paletteList, pd);
            if (clickablePos.Count > 0)
            {
                using (Graphics g = Graphics.FromImage(bm))
                {
                    foreach (Rectangle r in clickablePos)
                    {
                        g.DrawRectangle(Pens.YellowGreen, r);
                    }
                }
            }
            return(bm);
        }