예제 #1
0
        /// <summary>
        ///     Encodes a PICA200 Texture.
        /// </summary>
        /// <param name="img">Input image to be encoded</param>
        /// <param name="format">Pixel Format of the Texture</param>
        /// <returns></returns>
        public static byte[] encode(Bitmap img, RenderBase.OTextureFormat format)
        {
            byte[] data   = TextureUtils.getArray(img);
            byte[] output = new byte[data.Length];

            uint outputOffset = 0;

            switch (format)
            {
            case RenderBase.OTextureFormat.rgba8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + ((tY * 8 + y) * img.Width)) * 4;

                            Buffer.BlockCopy(data, (int)dataOffset, output, (int)outputOffset + 1, 3);
                            output[outputOffset] = data[dataOffset + 3];

                            outputOffset += 4;
                        }
                    }
                }
                break;

            default: throw new NotImplementedException();
            }

            return(output);
        }
예제 #2
0
        /// <summary>
        ///     Encodes a PICA200 Texture.
        /// </summary>
        /// <param name="img">Input image to be encoded</param>
        /// <param name="format">Pixel Format of the Texture</param>
        /// <returns></returns>
        public static byte[] encode(Bitmap img, RenderBase.OTextureFormat format)
        {
            byte[] data         = TextureUtils.getArray(img);
            byte[] output       = new byte[data.Length];
            bool   toggle       = false;
            uint   outputOffset = 0;

            switch (format)
            {
            case RenderBase.OTextureFormat.rgba8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + ((tY * 8 + y) * img.Width)) * 4;
                            byte b          = (byte)(data[dataOffset]);
                            byte g          = (byte)(data[dataOffset + 1]);
                            byte r          = (byte)(data[dataOffset + 2]);
                            output[outputOffset + 1] = b;
                            output[outputOffset + 2] = g;
                            output[outputOffset + 3] = r;
                            output[outputOffset]     = data[dataOffset + 3];

                            outputOffset += 4;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgb8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + ((tY * 8 + y) * img.Width)) * 4;
                            byte b          = (byte)(data[dataOffset]);
                            byte g          = (byte)(data[dataOffset + 1]);
                            byte r          = (byte)(data[dataOffset + 2]);
                            output[outputOffset]     = b;
                            output[outputOffset + 1] = g;
                            output[outputOffset + 2] = r;

                            outputOffset += 3;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgba5551:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            ulong pixelData = (ulong)(data[dataOffset]);

                            byte b = (byte)(data[dataOffset]);
                            byte g = (byte)(data[dataOffset + 1]);
                            byte r = (byte)(data[dataOffset + 2]);
                            byte a = (byte)(data[dataOffset + 3]);

                            output[outputOffset]     = (byte)((((g >> 3) & 3) << 6) + ((b >> 3) << 1) + (a & 1));
                            output[outputOffset + 1] = (byte)(((r >> 3) << 3) + (g >> 5));

                            outputOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgb565:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            byte b = (byte)(data[dataOffset] / 8);
                            byte g = (byte)(data[dataOffset + 1] / 4);
                            byte r = (byte)(data[dataOffset + 2] / 8);

                            output[outputOffset]     = (byte)(((g & 7) << 5) | b);
                            output[outputOffset + 1] = (byte)((r << 3) | ((g & 0x38) >> 3));

                            outputOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.rgba4:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            byte b = (byte)(data[dataOffset] / 16);
                            byte g = (byte)(data[dataOffset + 1] / 16);
                            byte r = (byte)(data[dataOffset + 2] / 16);
                            byte a = (byte)(data[dataOffset + 3] / 16);

                            output[outputOffset + 1] = (byte)((r << 4) | g);
                            output[outputOffset]     = (byte)((b << 4) | a);

                            outputOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.la8:
            case RenderBase.OTextureFormat.hilo8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            output[outputOffset]     = data[dataOffset];
                            output[outputOffset + 1] = data[dataOffset + 3];

                            outputOffset += 2;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.l8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            output[outputOffset] = data[dataOffset];

                            outputOffset++;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.a8:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            output[outputOffset] = data[dataOffset + 3];

                            outputOffset++;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.la4:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            output[outputOffset] = (byte)((data[dataOffset] / 16) << 4 | data[dataOffset + 3] / 16);

                            outputOffset++;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.l4:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;


                            byte c         = (byte)(data[dataOffset++] >> 4);
                            byte wholeByte = 0;
                            if (toggle)
                            {
                                wholeByte            = (byte)((wholeByte << 4) | (data[dataOffset++] >> 4));
                                output[outputOffset] = wholeByte;
                                outputOffset++;
                            }
                            else
                            {
                                wholeByte = c;
                            }
                            toggle = !toggle;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.a4:
                for (int tY = 0; tY < img.Height / 8; tY++)
                {
                    for (int tX = 0; tX < img.Width / 8; tX++)
                    {
                        for (int pixel = 0; pixel < 64; pixel++)
                        {
                            int  x          = tileOrder[pixel] % 8;
                            int  y          = (tileOrder[pixel] - x) / 8;
                            long dataOffset = ((tX * 8) + x + (((tY * 8 + y)) * img.Width)) * 4;

                            byte c         = (byte)(data[dataOffset + 3] >> 4);
                            byte wholeByte = 0;
                            if (toggle)
                            {
                                wholeByte            = (byte)((wholeByte << 4) | (data[dataOffset++] >> 4));
                                output[outputOffset] = wholeByte;
                                outputOffset++;
                            }
                            else
                            {
                                wholeByte = c;
                            }
                            toggle = !toggle;
                        }
                    }
                }
                break;

            case RenderBase.OTextureFormat.etc1:
            case RenderBase.OTextureFormat.etc1a4:
                int[] etc1Order = etc1Scramble(img.Width, img.Height);

                int i = 0;
                for (int tY = 0; tY < img.Height / 4; tY++)
                {
                    for (int tX = 0; tX < img.Width / 4; tX++)
                    {
                        int TX = etc1Order[i] % (img.Width / 4);
                        int TY = (etc1Order[i] - TX) / (img.Width / 4);
                        outputOffset = (uint)((TX * 4) + (((TY * 4)) * (img.Width / 4))) * 2;
                        if (format == RenderBase.OTextureFormat.etc1a4)
                        {
                            outputOffset = (uint)((TX * 4) + (((TY * 4)) * (img.Width / 4))) * 4;
                            ulong alpha = 0;
                            int   iiii  = 0;
                            for (int x = 0; x < 4; x++)
                            {
                                for (int y = 0; y < 4; y++)
                                {
                                    long dataOffset = ((tX * 4) + (x) + (((tY * 4) + (y)) * img.Width)) * 4;
                                    uint a          = (uint)data[dataOffset + 3] / 16;
                                    alpha |= (ulong)a << (iiii);
                                    iiii  += 4;
                                }
                            }
                            output[outputOffset + 7] = (byte)((alpha >> 56) & 0xFF);
                            output[outputOffset + 6] = (byte)((alpha >> 48) & 0xFF);
                            output[outputOffset + 5] = (byte)((alpha >> 40) & 0xFF);
                            output[outputOffset + 4] = (byte)((alpha >> 32) & 0xFF);
                            output[outputOffset + 3] = (byte)((alpha >> 24) & 0xFF);
                            output[outputOffset + 2] = (byte)((alpha >> 16) & 0xFF);
                            output[outputOffset + 1] = (byte)((alpha >> 8) & 0xFF);
                            output[outputOffset]     = (byte)(alpha & 0xFF);
                            outputOffset            += 8;
                        }
                        Color[] pixels = new Color[4 * 4];
                        for (int yy = 0; yy < 4; yy++)
                        {
                            for (int xx = 0; xx < 4; xx++)
                            {
                                long dataOffset = ((tX * 4) + (xx) + (((tY * 4) + (yy)) * img.Width)) * 4;
                                //if (TX + xx >= img.Width) pixels[yy * 4 + xx] = Color.Transparent;
                                //else if (TY + yy >= img.Height) pixels[yy * 4 + xx] = Color.Transparent;
                                pixels[yy * 4 + xx] = Color.FromArgb((int)data[dataOffset + 0] | (int)data[dataOffset + 1] << 8 | (int)data[dataOffset + 2] << 16 | (int)data[dataOffset + 3] << 24);
                            }
                        }
                        ulong ETC1Chunk = ETC1.GenETC1(pixels);
                        output[outputOffset + 7] = (byte)((ETC1Chunk >> 56) & 0xFF);
                        output[outputOffset + 6] = (byte)((ETC1Chunk >> 48) & 0xFF);
                        output[outputOffset + 5] = (byte)((ETC1Chunk >> 40) & 0xFF);
                        output[outputOffset + 4] = (byte)((ETC1Chunk >> 32) & 0xFF);
                        output[outputOffset + 3] = (byte)((ETC1Chunk >> 24) & 0xFF);
                        output[outputOffset + 2] = (byte)((ETC1Chunk >> 16) & 0xFF);
                        output[outputOffset + 1] = (byte)((ETC1Chunk >> 8) & 0xFF);
                        output[outputOffset + 0] = (byte)(ETC1Chunk & 0xFF);
                        outputOffset            += 8;
                        i += 1;
                    }
                }


                break;

            default: throw new NotImplementedException();
            }

            return(output);
        }