Beispiel #1
0
        /// <summary>
        /// Load bitmap data to Paint.NET surface.
        /// </summary>
        /// <param name="header">The bitmap header to convert.</param>
        /// <param name="offset">The offset of the header in the stream.</param>
        /// <param name="source">The source stream.</param>
        /// <param name="surface">Paint.NET surface.</param>
        unsafe static void LoadBitmapToSurface(SBMHeader header, UInt32 offset, Stream source, Surface surface)
        {
            UInt32 lastPos = (UInt32)source.Position;

            source.Seek(offset + header.headerLength, SeekOrigin.Begin);

            UInt32 compressedSize = header.bitmapSize - header.headerLength;
            UInt32 stride         = (UInt32)MbmFile.GetStride(header.sizeInPixel.Width, (Byte)(header.bitsPerPixel));
            UInt32 realSize       = (UInt32)header.sizeInPixel.Height * stride;

            byte[]       decompressedData  = new byte[realSize];
            MemoryStream destinationStream = new MemoryStream(decompressedData, 0, (int)realSize);

            destinationStream.Seek(0, SeekOrigin.Begin);

            switch (header.compression)
            {
            case BitmapCompression comp when(comp <= BitmapCompression.ThirtyTwoABitsRLE && comp > BitmapCompression.None):
                Algorithm.RLEDecompressor.Decompress(destinationStream, source, (int)compressedSize, comp);

                break;

            default:
                source.Read(decompressedData, 0, (int)realSize);
                break;
            }

            destinationStream.Seek(0, SeekOrigin.Begin);

            for (int y = 0; y < header.sizeInPixel.Height; y++)
            {
                destinationStream.Seek(stride * y, SeekOrigin.Begin);
                ColorBgra *rowData = surface.GetRowAddress(y);

                // Convert to PDN representation
                switch (header.bitsPerPixel)
                {
                // These case are generally easy
                // Each channel is represent by 8 bits
                case UInt32 i when(i % 8 == 0):
                    for (int x = 0; x < header.sizeInPixel.Width; x++)
                    {
                        rowData[x].R = (i >= 8) ? (Byte)destinationStream.ReadByte() : (Byte)0;
                        rowData[x].G = (i >= 16) ? (Byte)destinationStream.ReadByte() : (Byte)0;
                        rowData[x].B = (i >= 24) ? (Byte)destinationStream.ReadByte() : (Byte)0;
                        rowData[x].A = (i >= 32) ? (Byte)destinationStream.ReadByte() : (Byte)255;
                    }

                    break;

                default:
                    throw new MbmException(String.Format("Unhandled converting {0} bits per pixel to Paint.NET surface", header.bitsPerPixel));
                }
            }

            source.Seek(lastPos, SeekOrigin.Begin);
        }
Beispiel #2
0
        static Document LoadIndex(MbmFile file, Stream source, int index)
        {
            SBMHeader header       = file.GetBitmapHeader(index);
            UInt32    headerOffset = file.GetBitmapHeaderOffset(index);
            Document  doc          = new Document(header.sizeInPixel);

            // Create background layer
            BitmapLayer layer   = Layer.CreateBackgroundLayer(header.sizeInPixel.Width, header.sizeInPixel.Height, "Bitmap");
            Surface     surface = layer.Surface;

            LoadBitmapToSurface(header, headerOffset, source, surface);

            doc.Layers.Add(layer);

            return(doc);
        }
Beispiel #3
0
        SBMHeader ReadSingleBitmapHeader(MbmBinaryReader input, UInt32 offset)
        {
            SBMHeader bitmapHeader = new SBMHeader();

            // Seek to trailer
            UInt32 lastPos = input.Tell();

            input.Seek(offset);

            bitmapHeader.bitmapSize   = input.ReadUInt32();
            bitmapHeader.headerLength = input.ReadUInt32();
            bitmapHeader.sizeInPixel  = input.ReadSize();
            bitmapHeader.sizeInTwips  = input.ReadSize();
            bitmapHeader.bitsPerPixel = input.ReadUInt32();
            bitmapHeader.colorMode    = (BitmapColor)input.ReadUInt32();
            bitmapHeader.paletteSize  = input.ReadUInt32();
            bitmapHeader.compression  = (BitmapCompression)input.ReadUInt32();

            input.Seek(lastPos);

            return(bitmapHeader);
        }
Beispiel #4
0
        public static void Save(Document input, Stream output, Surface scratchSurface, UInt32 bpp, BitmapColor colorMode)
        {
            // Flatten the image first
            input.Flatten(scratchSurface);

            // Build up SBM Header
            SBMHeader header = new SBMHeader();

            header.headerLength       = 40;
            header.sizeInPixel.Width  = input.Width;
            header.sizeInPixel.Height = input.Height;
            header.sizeInTwips.Width  = input.Width * 15;
            header.sizeInTwips.Height = input.Height * 15;
            header.colorMode          = colorMode;
            header.bitsPerPixel       = bpp;

            // Determine what compression to use
            BitmapCompression compressionToUse = ChooseBestCompressionMode(input.Width, input.Height, bpp, colorMode);

            header.compression = compressionToUse;

            Int32 stride = MbmFile.GetStride(input.Width, (Byte)bpp);

            byte[] rawBitmapData        = new byte[stride * input.Height];
            byte[] compressedBitmapData = null;

            MemoryStream bitmapStream = new MemoryStream(rawBitmapData, 0, rawBitmapData.Length);

            ReadRawBitmapData(scratchSurface, bitmapStream, (Byte)bpp);

            bitmapStream.Seek(0, SeekOrigin.Begin);

            switch (compressionToUse)
            {
            case BitmapCompression comp when(comp >= BitmapCompression.ByteRLE && comp <= BitmapCompression.ThirtyTwoABitsRLE):
                compressedBitmapData = new byte[stride * input.Height];

                MemoryStream compressedDestStream = new MemoryStream(compressedBitmapData, 0, compressedBitmapData.Length);
                compressedDestStream.Seek(0, SeekOrigin.Begin);
                Algorithm.RLECompressor.Compress(compressedDestStream, bitmapStream, stride * input.Height, compressionToUse);
                header.bitmapSize = (UInt32)(40 + compressedDestStream.Position);

                break;

            case BitmapCompression.None:
                header.bitmapSize = (UInt32)(40 + stride * input.Height);
                break;

            default:
                throw new MbmException(String.Format("Unsupported bitmap compression type {0}", compressionToUse.ToString()));
            }

            output.Seek(/*sizeof(MbmHeader)*/ 20, SeekOrigin.Begin);

            MbmBinaryWriter writer = new MbmBinaryWriter(output);

            // Try to write our header
            writer.WriteUInt32(header.bitmapSize);
            writer.WriteUInt32(header.headerLength);
            writer.WriteSize(header.sizeInPixel);
            writer.WriteSize(header.sizeInTwips);
            writer.WriteUInt32(header.bitsPerPixel);
            writer.WriteUInt32((UInt32)header.colorMode);
            writer.WriteUInt32(header.paletteSize);
            writer.WriteUInt32((UInt32)header.compression);

            // Write data
            switch (compressionToUse)
            {
            case BitmapCompression comp when(comp >= BitmapCompression.ByteRLE && comp <= BitmapCompression.ThirtyTwoABitsRLE):
                output.Write(compressedBitmapData, 0, (int)(header.bitmapSize - header.headerLength));

                break;

            case BitmapCompression.None:
                output.Write(rawBitmapData, 0, rawBitmapData.Length);
                break;

            default:
                break;
            }

            // Write trailer
            UInt32 trailerOffset = writer.Tell();

            writer.WriteUInt32(1);
            writer.WriteUInt32(20);

            // Seek back and write our header
            writer.Seek(0);
            writer.WriteUInt32(MbmHeader.directFileStoreUIDNum);
            writer.WriteUInt32(MbmHeader.multiBitmapUIDNum);
            writer.WriteUInt32(0);
            writer.WriteUInt32(0);      // Checksum
            writer.WriteUInt32(trailerOffset);
        }