Exemplo n.º 1
0
        public static bool Unpack(string inputFile, string outputFile, ProcessData processData)
        {
            var fileStream = OpenFileOrDie(inputFile, FileMode.Open);

            try
            {
                ReadToStructure(fileStream, out AGFHDR hdr, Marshal.SizeOf <AGFHDR>());
                if (hdr.type != AgfType24Bit && hdr.type != AgfType32Bit)
                {
                    Program.Print(Program.ErrorColor, $"File {inputFile} was of unsupported type (possibly an MPEG): {hdr.type}");
                    return(false);
                }
                var bmpHeaderBuff = ReadSector(fileStream);
                var buff          = ReadSector(fileStream);
                // Notice there's a gap of 2 bytes between these... alignment I guess.
                var       bmf    = ByteArrayToStructure <BITMAPFILEHEADER>(bmpHeaderBuff);
                var       bmi    = ByteArrayToStructure <BITMAPINFOHEADER>(bmpHeaderBuff, 16);
                int       offset = 16 + Marshal.SizeOf <BITMAPINFOHEADER>();
                RGBQUAD[] pal    = ByteArrayToStructureArray <RGBQUAD>(bmpHeaderBuff, offset, bmpHeaderBuff.Length - offset);
                if (hdr.type == AgfType32Bit)
                {
                    ReadToStructure(fileStream, out ACIFHDR acifHeader, Marshal.SizeOf <ACIFHDR>());
                    var alphaBuff = ReadSector(fileStream);
                    var colorMap  = DecodeColorMapWithAlpha(bmi, buff, pal, alphaBuff);
                    processData.Decoding = new DecodingData(bmf, bmi, buff, pal, alphaBuff, colorMap, hdr, acifHeader);
                    if (outputFile != null)
                    {
                        WriteBitmap(outputFile,
                                    colorMap,
                                    bmi.biWidth,
                                    bmi.biHeight,
                                    4,
                                    null,
                                    true);
                    }
                }
                else
                {
                    processData.Decoding = new DecodingData(bmf, bmi, buff, pal, null, buff, hdr, default);
                    if (outputFile != null)
                    {
                        WriteBitmap(outputFile,
                                    buff,
                                    bmi.biWidth,
                                    bmi.biHeight,
                                    bmi.biBitCount / 8,
                                    pal,
                                    bmf.bfOffBits == 54);
                    }
                }
            }
            finally
            {
                fileStream.Dispose();
            }
            return(true);
        }
Exemplo n.º 2
0
 public static bool Pack(string inputFileName, string outputFileName, ProcessData processData)
 {
     ReadBitmap(inputFileName, out var decodedData, out _, out var bmf, out var bmi);
     byte[]    encodedData;
     byte[]    outAlphaBuff = null;
     RGBQUAD[] palBuff;
     if (processData.Decoding.AgfHeader.type == AgfType32Bit)
     {
         EncodeColorMapWithAlpha(decodedData, bmi, processData, out encodedData, out outAlphaBuff, out palBuff);
     }
     else
     {
         palBuff = bmi.biBitCount == 8 ? ByteArrayToStructureArray <RGBQUAD>(decodedData, 0, 1024) : null;
         var decodedColorMap = bmi.biBitCount == 8 ? decodedData.Skip(1024) : decodedData;
         encodedData = decodedColorMap.ToArray();
     }
     processData.Encoding = new DecodingData(bmf, bmi, encodedData, palBuff, outAlphaBuff, decodedData);
     WriteAgf(outputFileName, encodedData, palBuff, outAlphaBuff, processData);
     return(true);
 }
Exemplo n.º 3
0
        private static void WriteAgf(string fileName, byte[] encodedData, RGBQUAD[] palArray, byte[] alphaBuff, ProcessData processData)
        {
            var fileStream = OpenFileOrDie(fileName, FileMode.Create);

            try
            {
                fileStream.Write(StructToBytes(processData.Decoding.AgfHeader), 0, Marshal.SizeOf <AGFHDR>());
                var hdrBytes = StructToBytes(processData.Decoding.Bmf).Concat(new byte[] { 0, 0 })
                               .Concat(StructToBytes(processData.Decoding.Bmi));
                if (palArray != null)
                {
                    hdrBytes = hdrBytes.Concat(palArray.SelectMany(StructToBytes));
                }

                WriteSector(fileStream, hdrBytes.ToArray());
                WriteSector(fileStream, encodedData);
                if (alphaBuff == null)
                {
                    return;
                }
                fileStream.Write(StructToBytes(processData.Decoding.AcifHeader), 0, Marshal.SizeOf <ACIFHDR>());
                WriteSector(fileStream, alphaBuff);
            }
            finally
            {
                fileStream.Dispose();
            }
        }
Exemplo n.º 4
0
        private static void EncodeColorMapWithAlpha(byte[] decodedData, BITMAPINFOHEADER bmi, ProcessData processData, out byte[] encodedData, out byte[] alphaData, out RGBQUAD[] pal)
        {
            //must be padded to 4 bytes
            uint rgbStride = (uint)((bmi.biWidth * processData.Decoding.Bmi.biBitCount / 8 + 3) & ~3);

            alphaData   = new byte[processData.Decoding.Bmi.biBitCount == 8 ? bmi.biHeight * bmi.biWidth : processData.Decoding.AlphaBuff.Length];
            encodedData = new byte[processData.Decoding.Bmi.biBitCount == 8 ? bmi.biHeight * rgbStride : processData.Decoding.EncodedData.Length];
            var palList          = useExistingPal ? processData.Decoding?.PalArray.ToList() : new List <RGBQUAD>();
            var additionalPalMap = new Dictionary <RGBQUAD, int>();

            for (long y = 0; y < bmi.biHeight; y++)
            {
                uint alphaLineIndex = (uint)((bmi.biHeight - y - 1) * bmi.biWidth);
                uint rgbaLineIndex  = (uint)(y * bmi.biWidth * 4);
                long rgbLineIndex   = y * rgbStride;
                for (long x = 0; x < bmi.biWidth; x++)
                {
                    long blueIndex = rgbaLineIndex + x * 4 + 0;
                    if (processData.Decoding.Bmi.biBitCount == 8)
                    {
                        var newPal = new RGBQUAD
                        {
                            rgbBlue  = decodedData[blueIndex],
                            rgbGreen = decodedData[blueIndex + 1],
                            rgbRed   = decodedData[blueIndex + 2]
                        };
                        var palIndex = palList.IndexOf(newPal);
                        if (palIndex == -1)
                        {
                            palIndex = useExistingPal ? FindNearestPal(newPal, palList, additionalPalMap) : GetPal(newPal, palList, additionalPalMap);
                        }
                        encodedData[y * rgbStride + x] = (byte)palIndex;
                    }
                    else
                    {
                        encodedData[rgbLineIndex + x * 3]     = decodedData[blueIndex];
                        encodedData[rgbLineIndex + x * 3 + 1] = decodedData[blueIndex + 1];
                        encodedData[rgbLineIndex + x * 3 + 2] = decodedData[blueIndex + 2];
                    }
                    alphaData[alphaLineIndex + x] = decodedData[blueIndex + 3];
                }
            }
            if (palList.Count < 256)
            {
                palList.AddRange(Enumerable.Repeat(new RGBQUAD(), 256 - palList.Count));
            }
            pal = palList.ToArray();
        }