Download BbmPaletteLoader.zip version 1.0.0.0, last updated 11/01/2014 (340.61 KB)

Download
  • md5: 277a85ced16921e1e3ae9967aba61e71
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;

// Loading the color palette from a BBM/LBM image file using C
// http://cyotek.com/blog/loading-the-color-palette-from-a-bbm-lbm-image-file-using-csharp

// The sample file used by program by MindChamber works
// http://opengameart.org/content/background-art

namespace BbmPaletteLoader
{
  public partial class MainForm : Form
  {
    #region Constants

    private const int DefaultX = 6;

    private const int DefaultY = 6;

    private const int Spacing = 6;

    private const int CellSize = 24;

    #endregion

    #region Instance Fields

    private List<Color> _loadedPalette;

    #endregion

    #region Public Constructors

    public MainForm()
    {
      InitializeComponent();
    }

    #endregion

    #region Overridden Methods

    /// <summary>
    /// Raises the <see cref="E:System.Windows.Forms.Form.Load"/> event.
    /// </summary>
    /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data. </param>
    protected override void OnLoad(EventArgs e)
    {
      base.OnLoad(e);

      this.AddFiles("lbm");
      this.AddFiles("bbm");
    }

    #endregion

    #region Private Members

    private void AddFiles(string extension)
    {
      string path;

      path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data");
      foreach (string fileName in Directory.GetFiles(path, "*." + extension))
        filesListBox.Items.Add(new FileInfo(fileName));
    }

    private List<Color> ReadColorMap(string fileName)
    {
      List<Color> colorPalette;

      colorPalette = new List<Color>();

      using (FileStream stream = File.OpenRead(fileName))
      {
        byte[] buffer;
        string header;

        // read the FORM header that identifies the document as an IFF file
        buffer = new byte[4];
        stream.Read(buffer, 0, buffer.Length);
        if (Encoding.ASCII.GetString(buffer) != "FORM")
          throw new InvalidDataException("Form header not found.");

        // the next value is the size of all the data in the FORM chunk
        // We don't actually need this value, but we have to read it
        // regardless to advance the stream
        this.ReadInt(stream);

        // read either the PBM or ILBM header that identifies this document as an image file
        stream.Read(buffer, 0, buffer.Length);
        header = Encoding.ASCII.GetString(buffer);
        if (header != "PBM " && header != "ILBM")
          throw new InvalidDataException("Bitmap header not found.");

        while (stream.Read(buffer, 0, buffer.Length) == buffer.Length)
        {
          int chunkLength;

          chunkLength = this.ReadInt(stream);

          if (Encoding.ASCII.GetString(buffer) != "CMAP")
          {
            // some other LBM chunk, skip it
            if (stream.CanSeek)
              stream.Seek(chunkLength, SeekOrigin.Current);
            else
            {
              for (int i = 0; i < chunkLength; i++)
                stream.ReadByte();
            }
          }
          else
          {
            // color map chunk!
            for (int i = 0; i < chunkLength / 3; i++)
            {
              int r;
              int g;
              int b;

              r = stream.ReadByte();
              g = stream.ReadByte();
              b = stream.ReadByte();

              colorPalette.Add(Color.FromArgb(r, g, b));
            }

            // all done so stop reading the rest of the file
            break;
          }

          // chunks always contain an even number of bytes even if the recorded length is odd
          // if the length is odd, then there's a padding byte in the file - just read and discard
          if (chunkLength % 2 != 0)
            stream.ReadByte();
        }
      }

      return colorPalette;
    }

private int ReadInt(Stream stream)
{
  byte[] buffer;

  // big endian conversion: http://stackoverflow.com/a/14401341/148962

  buffer = new byte[4];
  stream.Read(buffer, 0, buffer.Length);

  return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
}

    #endregion

    #region Event Handlers

    private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
    {
      using (Form dialog = new AboutDialog())
        dialog.ShowDialog(this);
    }

    private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
      this.Close();
    }

    private void filesListBox_SelectedIndexChanged(object sender, EventArgs e)
    {
      FileInfo selectedFile;

      selectedFile = filesListBox.SelectedItem as FileInfo;

      if (selectedFile != null)
      {
        _loadedPalette = this.ReadColorMap(selectedFile.FullPath);
        this.Text = string.Format("{0} - {1}", Path.GetFileName(selectedFile.FullPath), Application.ProductName);
      }
      else
      {
        _loadedPalette = null;
        this.Text = Application.ProductName;
      }

      palettePanel.Invalidate();
    }

    private void palettePanel_Paint(object sender, PaintEventArgs e)
    {
      if (_loadedPalette != null)
      {
        int x;
        int y;

        x = DefaultX;
        y = DefaultY;

        e.Graphics.Clear(palettePanel.BackColor);

        foreach (Color color in _loadedPalette)
        {
          Rectangle bounds;

          if (x > palettePanel.Width - (CellSize + DefaultX))
          {
            x = DefaultX;
            y += DefaultY + CellSize + Spacing;
          }

          bounds = new Rectangle(x, y, CellSize, CellSize);

          using (Brush brush = new SolidBrush(color))
            e.Graphics.FillRectangle(brush, bounds);

          e.Graphics.DrawRectangle(Pens.Black, bounds);

          x += (CellSize + Spacing);
        }
      }
    }

    #endregion
  }
}

Donate

Donate