Jump to content
IGNORED

simonl's Blog - What is an XEF file?


RSS Bot

Recommended Posts

Just in case anyone's interested, in my posting here, the attached program is capable of exporting compressed images. This is useful as a full screen VBXE standard resolution would be 80640 bytes if not compressed so it's a waste of disk/cartridge space. Currently, it uses deflate on 8kb blocks, although it will not compress a block if the compressed data comes out longer. This typically gives a 1/3 reduction in file size, but files from Amiga, C64 etc. give much better compression ratios due to the smaller palette count.

 

For instance, this 320x200 picture would be 62.5k uncompressed:

 

blogentry-12834-125302744774.png

 

The PNG file is 30k, and the corresponding XEF file is 26.3k (I had to change the extension to .zip to upload):

 

zip.gif dotc.zip (26.31K)

Number of downloads: 0

 

This format is currently in the less than useful position of not having an associated viewer on the Atari (although they can be previewed through the application, choose File | Open XeFlate...). I'm working on this at the moment, but if anyone would like to save me the trouble ;) or comment on the format I'm working on, here are the details.

 

The file is structured as follows:

 

**************** File Header ****************Name Length (Bytes) Comment----------------- --------------------- --------------------------------------------Bits Per Pixel 1 Either 4 or 8 depending on the modeGraphics Mode 1 Values: 0x1F = VBXE standard 0x2F = VBXE low resolution 0x3F = VBXE high resolutionImage Width 2* Width in bytes Image Height 2* Height in scan linesBlock Count 2* The number of blocks of data in the filePalette Length 2* The number of palette entries in the file. If zero, the laoo.act palette can be assumed if the palette is not specified elsewhere.Palette Entries 3 x [Palette Length] The palette entries as (R, G, B) three byte tuples* Low byte firstThen, there are [Block Count] blocks, as follows:********** Block **********N.B. The data is currently compressed so that each block is <= 8kb in length when uncompresssed,due to the 8k bank switching arrangement used by VBXE this seemed expecient!Name Length (Bytes) Comment----------------- --------------------- --------------------------------------------Compression Type 1 The compression method used: 0x00 = None 0x01 = Deflate Further methods will be added e.g. RLE Compressed Length 2* The length of the block's data, in bytes, not including the 3 block header bytes.Data [Compressed Length] The block's data * Low byte first

 

The following C# snippet illustrates loading an XEF file into a Windows Bitmap:

 

// Read the file header // Mode byte bitsPerPixel = r.ReadByte(); byte graphicsMode = r.ReadByte(); // Size ushort imageWidthBytes = (ushort)(r.ReadByte() | (r.ReadByte() << 8)); ushort imageHeightScanLines = (ushort)(r.ReadByte() | (r.ReadByte() << 8)); int width = imageWidthBytes * (8 / bitsPerPixel); int height = imageHeightScanLines; byte blockCount = r.ReadByte(); // Palette (if specified - otherwise, assume the default VBXE palette) ushort paletteLength = (ushort)(r.ReadByte() | (r.ReadByte() << 8)); Color[] palette = null; if (paletteLength > 0) { palette = new Color[paletteLength]; for (int color = 0; color < paletteLength; color++) { byte red = r.ReadByte(); byte green = r.ReadByte(); byte blue = r.ReadByte(); palette = Color.FromArgb(red, green, blue); } } else { // Otheriwse, use whatever colors we've currently got loaded palette = Atari.Colors.BrushColors; } int x = 0; int y = 0; Bitmap result = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb); // Read the blocks for (int block = 0; block < blockCount; block++) { // Get the compressed length byte blockCompressionType = r.ReadByte(); ushort blockLength = (ushort)(r.ReadByte() | (r.ReadByte() << 8)); System.Diagnostics.Debug.WriteLine(string.Format("Block {0} -> {1} bytes ({2})", block + 1, blockLength, Enum.ToObject(typeof(BlockCompressionType), blockCompressionType))); byte[] compressed = r.ReadBytes(blockLength); byte[] decompressed = null; int decompressedLength = 0; // On Atari - switch in the correct bank from VBXE memory and decompress to there switch (blockCompressionType) { case 0x00: // Uncompressed - copy straight to VBXE bank decompressed = compressed; decompressedLength = blockLength; break; case 0x01: // Deflate - http://atariarea.krap.pl/x-asm/inflate.html decompressed = new byte[0x2000]; using (MemoryStream ms = new MemoryStream(compressed)) { ms.Position = 0; using (DeflateStream ds = new DeflateStream(ms, CompressionMode.Decompress, true)) { decompressedLength = ds.Read(decompressed, 0, 0x2000); ds.Close(); } } break; } #region Plot the data on the bitmap (obviously redundant on Atari!) for (int i = 0; i < decompressedLength; i++) { result.SetPixel(x, y, palette[decompressed]); x++; if (x >= width) { x = 0; y++; } } #endregion } #region Set the pixel aspect ratio (or set the XDL on Atari!) switch (graphicsMode) { case 0x1F: // Vbxe standard break; case 0x2F: #region Vbxe Low Resolution - rescale to 2 x width Bitmap scaledUpBitmap = new Bitmap(result.Width * 2, result.Height, result.PixelFormat); using (Graphics graphics = Graphics.FromImage(scaledUpBitmap)) { graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed; graphics.DrawImage(result, 0, 0, scaledUpBitmap.Width, scaledUpBitmap.Height); } result.Dispose(); result = scaledUpBitmap; #endregion break; case 0x3F: #region VbxeHighResolution - rescale to 1/2 width (Windows doesn't like rectangular pixels) Bitmap scaledDownBitmap = new Bitmap(result.Width >> 1, result.Height, result.PixelFormat); using (Graphics graphics = Graphics.FromImage(scaledDownBitmap)) { graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; graphics.DrawImage(result, 0, 0, scaledDownBitmap.Width, scaledDownBitmap.Height); } result.Dispose(); result = scaledDownBitmap; #endregion break; } #endregion return result;

 

http://www.atariage.com/forums/index.php?app=blog&blogid=330&showentry=6452

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...