Skip to content
Image converter for Commodore Plus/4
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


This is my second attempt to write a generic image converter targeting the Commodore Plus/4.

Design goals

I want it to be easily extendible. For this reason I want a converter that doesn't require a specific optimization algorithm for each supported graphic mode. All of these optimization methods are very similar anyway, so I just want to define the problem at hand and a few well written algorithms should do the job. I also want it to be highly customizable. I want to specify the width and height of the target (multi-screen graphic) and I also want to specify simple constraints if needed, like a fixed background color or the same (but optimized) xshift value for the whole screen instead of independently optimized values for each raster line. The complete separation of the optimization problem and the optimization algorithm would even allow the user to define new graphic modes without coding. He/she would only need to write some configuration files that define the optimization variables (typically colors and pixels) and how those variables define the picture and the output file. Actually, every image converter has these definitions, I just want to make them explicit and enable the user to define them.

Design non-goals

I don't want it to be super fast, only reasonably fast, I don't care if it takes a minute to convert an image. I don't want to deal with resizing the image to the dimensions of the given graphic mode. It is your job to prepare your input.

How does the conversion work?

All conversion begins by creating baseline image of the given graphic mode. The baseline is either created randomly or a previous conversion result is imported by the user (see -b and -bf options). Than multipe optimization algorithms are run repeatedly:

  • Coordinate pre-optimization is used to fine tune coordinate shifts (like xshift) to reduce the average number of distinct colors per cell (like character) that exceed the capacity of the given graphic mode.
  • One dimensional brute-force algorithm that tries every possible value of every variable, evaluates the conversion error and keeps the values resulting less error.
  • Two-three dimensional brute-force algorithm that tries every possible variation of certain type of variables if the overall number of variations does not exceed 256.
  • K-Means like optimization that tries to find partitions of the pixels whose means are close to possible palette colors.

Those are combined/iterated until the conversion error cannot be reduced further. If the baseline is randomly generated almost every conversion will yield slightly different results. Use the -seed <integer> option to make it deterministic.


Basic help on options

> dfliconv2 -h

Simple conversion examples

Convert to multi-dfli with preview .png without dithering:

> dfliconv2 image.jpg

To hires, saving image.prg and image_preview.png (the input without file extension is the output file prefix by default):

> dfliconv2 -m hires -i image.jpg -p

To multi, using Bayer4x4 dithering, saving converted.prg and converted_preview.png:

> dfliconv2 -m multi -d bayer4x4 -i image.jpg -o converted -p

To generic multi fli mode with badline config 'clllllll':

> dfliconv2 -m gfli('m','clllllll') -d point5 -i image.jpg -p

Create a dithered preview without conversion

You can simply convert an image to Plus/4 colors with dithering as well.

Create a hires dithered image with Plus/4 colors.

> dfliconv2 -i image.jpg -d point5

Create a multi dithered image with Plus/4 colors.

> dfliconv2 -i image.jpg -d bayer2x2 -2x

Custom palettes

You can use a 16x8 color table in a PNG image as a Plus/4 palette with the -pal option. There are some examples are in the pal folder, two of them were directly downloaded from the website.

Conversion between formats

It is possible to load a previous conversion results or images in supported formats as a baseline and save them in another format and/or create a .png preview for them. Let's suppose you have pic_boti.prg in Multi Botticelli format and you want to create a .prg viewer for it:

> dfliconv2 -m multi -f prg -b pic -bf boti

or you can create only a pic_preview.png too:

> dfliconv2 -m multi -f none -b pic -bf boti -p

Supported graphic modes

Get the list of supported modes by running

> dfliconv2 -m ?

The current list is:

  • hires, hires(w,h)
  • hires+, hires+(w,h)
  • hires-dfli, hires-dfli(w,h)
  • multi, multi(w,h)
  • multi+, multi+(w,h)
  • multi-dfli, multi-dfli(w,h)
  • gfli(m,dma0,dma1,dma2,dma3,dma4,dma5,dma6,dma7), gfli(w,h,m,dma0,dma1,dma2,dma3,dma4,dma5,dma6,dma7)

The list includes parameterized modes too, like hires(w,h) where w and h stands for width and height in characters. So, for example -m "hires(80,25)" means hires bitmap of dimensions 640x200, ie. a double screen hires mode. New graphic modes will be added incrementally.

Supported output formats

Try running a command like below to get the supported output formats for a given mode.

> dfliconv2 -m hires -f ?

The bin format is supported for every native modes, that will save separate files for luma, chroma, bitmap, etc. Not all supported modes have a executable prg format yet, like prg is not supported yet for any of the custom size modes. boti is supported for default size hires and multi modes. p4fli is supported for DFLI modes, this utilizes Plus4Emu's converter viewer as it is.

Supported dithering methods

> dfliconv2 -d ?

  • fs stands for Floyd-Steinberg dithering.
  • point5 only uses plain colors or chessboard dithering.
  • point5, bayer2x2, bayer4x4, ord3x3, ord2x4 only use "close" colors to reduce noise. Option to define what is "close" will be implemented later. Current definition is the distance of color 0x00 and 0x11.

Other dithering methods may be added later.

List of graphic mode variables

You can print a summary of the variables that are optimized when converting to the given mode, like this:

> dfliconv2 -m multi+

You can see that in this mode you have separate color0, color3 and xshift variables for every raster-line.

Variable restrictions

Let's suppose you rather want one xshift value for all lines, but you want the converter to optimize that and you want color0 to be black in every line. You can do it like this:

> dfliconv2 -m multi+ -r "xshift_000...xshift_199=xshift_000" -r "color0_000...color0_199=0"

This will replace the variables xshift_000 to xshift_199 with a single variable xshift_000 and it will also set a fixed 0 value for all the color0 variables.

Let's say you want a hires mode where chars are leaning right 45 degrees. That is

> dfliconv2 -m hires+ -r "xshift_000...xshift_199=7,6,5,4,3,2,1,0"

On the left side of = you can have a variable or a range of variables like above and on the right side you can specify a single or comma separated list of variables and integer constants. If the variable list on the left side is longer than the list on the right side the later is repeated periodically during assignment.

You don't have to use a "full" range, you can use "xshint_008...xshift_015" too. Every variable that is lexicographically between the beginning and the end of the range will be included in the range in lexicographical order.

I think you get the idea.

Other notes

The input image is never resized (as mentioned above). The image is treated as a periodic pattern in both directions.

You can use the -g and -s options to do gamma correction and change the saturation of the image. Gamma is applied in the RGB color space, saturation is applied in the YUV color space. All other computations are done in the Lab color space.


  • add separate options for pre-dithering and post-dithering. The idea is that a pre-dithered image is used to optimize colors and post-dithering is used to create the actual output.
  • option to define what is "close" color.
  • user defined graphic modes with some examples (eg. some c64 modes)
  • add more graphic modes, including character modes with optimized charset to approximate the picture with 256 chars.


  • I have stolen the RGB-to-Lab conversion routine from Larry's fantastic converter's disassembled source code. :)
  • I use IstvanV's great P4FliConverter's DFLI viewer routine as it is.
  • Two custom palettes were generated by
You can’t perform that action at this time.