ImageConverter

A forum where you can announce your awesome project(s).

Moderator: MaxCoderz Staff

Post Reply
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

ImageConverter

Post by Timendus »

I'm not sure this really is an independant project that I should be posting about here (I'm not even sure I'll ever finish it :P) but I need a place to put my thoughts down and get some feedback on this, because my brain is a bit of a mess at the moment because I've been learning and thinking too much and too fast :)

<skip if you're not interested in long boring stories>

I'm working on the intro cinematic for The Core of Light, and the most complex part of this turns out to be getting the data in properly and not writing the assembly code to display the images one after another. Part of it is in greyscale, parts in black and white, every frame needs some data to go with it (frame duration, colour depth, rain animation) and I want to compress my images to fit more in.

At first I tried to use the PHP script I wrote a while ago to convert a greyscale image to two b/w images that Brass can include, but the script turned out not to work for bitmaps that are not made with MS Paint using only the predefined black, white, light grey and dark grey. Sigh :( So I rewrote most of the script to make it work with 24 bits bitmaps and accept any image with four distinct colours (sorting them by brightness). This unfortunately took me the better part of an evening.

Next up I wrote a script to take a directory full of text files, take the frame settings that are in the text file and put them with an incbmp command for Brass of the relevant image(s) in an include file. So now I finally had an include file with more or less the right settings and all the b/w and greyscale images included that would automatically get generated when I compiled my project, and I wrote a little assembly program to display all the frames, and it worked and I was happy for a while...

But then I wanted to add the total number of frames at the beginning of the include file (so I'd know when to stop), and I realized that the script didn't know the number of frames untill it was done so I'd have to rewrite part of it to add a simple number. I didn't like that. I also wanted to implement compression algorithms and I realized that this would mean writing yet more PHP scripts. I decided that I had to stop connecting ugly hacks together and write a proper tool for this.

</skip if you're not interested in long boring stories>

The end of the story so far is that I'm now writing (or attempting to, I've had way too much interruptions today) a tool that uses an XML file to define a series of image conversions and how to put them into an include file as image data. I've decided to make it as versatile as possible so maybe others can benefit from it too, and so I don't run into more unexpected obstacles.

Basically it'll be a converter to produce .db hex statements from images like so many others, but with a few advantages: this works not only for b/w images but also for four level greyscale (and maybe 8 level later on) simply depending on how many distinct colours you use in your images, it converts all your images at once to one include file instead of one at a time, it reads normal bmp files (probably in all formats, and perhaps also other image formats depending on how easy it will be to implement in C# :)), it's a nice command line tool that you can incorporate in your compile process (Latenite or otherwise), and it can be used for much more complex things than "just" including images.

This is the XML file I'm currently working with, to give you an idea of just how versatile this will be if I finish it:

Code: Select all

<?xml version="1.0" encoding="utf-8" ?>

<convertscheme>

	<!--
	The header node defines the header for the entire include file
	
	Available node names:
		text				Copied literaly
		number_of_images	Includes the total number of images ( .db xx )
	-->

	<header>
		<text>; Movie include for The Core of Light
; Copyright Smitemeister Software 2002-2006
		</text>
		<number_of_images />
	</header>
	
	<!--
	Every image in the image sequence can be preceded by a header with settings
	Use the next node to define the header in bytes or in bits
	
	Available node names:
		byte				Defines a byte ( .db xx )
			bit0 - bit7		Defines bits 0-7 of a byte ( .db (bit0 || bit1 || bit2) etc )
	-->
	
	<settings>
		<byte>
			<bit0>greyscale</bit0>
			<bit1>rain</bit1>
		</byte>
		<byte>timer</byte>
	</settings>

	<!--
	Next up is the actual sequence of images with their parameters
	
	Available nodes:
		image				Parameter title can be used to add comments in the include
			label			Adds a label to this image in the include
			compression		Specify none, RLE, SRL ...
			file			Filename of image to be included
							2 or 4 colours will be determined from the bitmap data but
							you'll probably want to use a bit in the image header to specify
							the number of colours if you use different colour depths in one
							sequence, so the assembly routine can see what's what
			all settings	Use "yes" or "no" or "true" or "false" to set/reset bits, use
							decimal numeric values 0-255 for bytes
	-->

	<images>

		<image title="Test image one">
			<label>img1</label>
			<compression>none</compression>
			<timer>50</timer>
			<rain>yes</rain>
			<greyscale>yes</greyscale>
			<file>test.bmp</file>
		</image>
		
		<image title="Test image two">
			<label>img2</label>
			<compression>none</compression>
			<timer>10</timer>
			<rain>no</rain>
			<greyscale>no</greyscale>
			<file>test2.bmp</file>
		</image>
		
	</images>

</convertscheme>
Now, you should realize that before today I have never worked with C# (or anything related except Java) or XML parsing before, so don't laugh at me too hard when I say that so far I have a command line tool that accepts a few parameters (XML file name and verbose/silent output, and complains when you get them wrong), parses a few bits of the XML file and starts writing to the include file. So the above XML file currently produces this include file:

Code: Select all

; Movie include for The Core of Light
; Copyright Smitemeister Software 2002-2006
		
  ; Number of images:
  .db 2
In other words, I'm going in the right direction, albeit somewhat slowly :)

So... would anyone be interested in using something like this? It should be useful for all kinds of image and sprite data.
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
User avatar
kv83
Maxcoderz Staff
Posts: 2735
Joined: Wed 15 Dec, 2004 7:26 pm
Location: The Hague, Netherlands
Contact:

Post by kv83 »

It sounds really nice, but if I understand you, this is only for full-screen-images or am I missing something?
Image
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Sounds cool, I normally write a new C# app to do this each time, which is a little tedious. A sort-of-scriptable XML system would be nice.

Thinking more about this - it would be rather cool to write a directives for this (and especially EarlyMorning, as that contains the image data itself) that can be used to call the respective programs and include the data that way. If you can think of a simple way to do this, I'd be interested to hear ;) (Probably simplest would be .inc<something> <args>, where <something> would be the name of your EXE. <args> would get passed to it, and your EXE would send back the result - D<binary> for data, F<fail> for failure or W<warn> for warning messages?)

Incidentally (not having seen the code) - how are you reading images? If using GetPixel, it might be an idea not to (very, very slow). You can use Bitmap.LockBits to return a BitmapData structure, containing a pointer to the first pixel (Scan0). You can then use Marshal.Copy to dump the pixel data into an array and read from there - much, much faster.
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

Post by Timendus »

You mean add a directive to Brass? That would be fun :) Certainly not neccessary though, as adding two lines to your compile.cmd to generate the include before the file is assembled works just as well, and is not so dependant on using Brass. But it would be fun to play with :)

I'm not loading bitmaps at all, I haven't come to that point yet :mrgreen: But I'll take your advice when I get there (and probably ask more questions ;)).
kv83 wrote:It sounds really nice, but if I understand you, this is only for full-screen-images or am I missing something?
That is my first goal, but it'll take it's image dimensions from the original bitmap, so I see no reason why it would have to be restricted to that.
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Aye, I meant a directive in Brass.

Oh, further "tip" -> the Width and Height properties of the Bitmap class are very slow to access. Don't, therefore, create a loop for (int x = 0; x < image.Width; ++x) { }. I have no idea why they are so slow, but there you go.
Post Reply