Online File Format Converters

For scripts to aid with computation or simulation in cellular automata.
Post Reply
MXMLLN
Posts: 39
Joined: December 28th, 2022, 12:36 am
Contact:

Online File Format Converters

Post by MXMLLN »

Is there a list of converters to and from different CA formats: RLE, Plaintext, Life, &c?

I'm finding a lot of Github converters, but nothing hosted online.
I often find myself in situations where an online tool would be the optimal solution.

Last Theory is the only one I could find: https://lasttheory.com/tools/rle-to-text-converter
It only does RLE to Plaintext, not vice versa.
User avatar
dvgrn
Moderator
Posts: 12023
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Online File Format Converters

Post by dvgrn »

We had a good start at a set of tools like this in 2024. But Book's "golhobby" website went down without warning or explanation, sometime in the second half of last year. I tried asking if it would be revived, but haven't heard anything back so far.

Here's an Internet Archive snapshot of the key page from 2023.

It still seems to be possible to retrieve the Javascript source for all of the tools from the Internet Archive. For example, the page source for RLE2PNG. htm includes

Code: Select all

let canvas,context,nrow,ncols;
const deadcolor='white';
const livecolor='black';
const gridcolor='silver';
let rowcoords,colcoords;

function doOnload(){
	canvas=document.getElementById('canvas'); //global var
	context=canvas.getContext('2d',{alpha:false}); //global var
	context.fillStyle="white";
	context.fillRect(0,0,canvas.width,canvas.height);
	let RLE=getURLParam("rle");
	if(RLE>""){
		let i=RLE.indexOf("B3/S23");
		RLE=RLE.substr(i+6);
		document.getElementById('ta').value=RLE;
		drawIt(true);
	} else {
		document.getElementById('ta').select();
	}
}
function getURLParam(s){
	var params=new URLSearchParams(location.search);
	var n=0;
	for(var [key,value] of params){
		if(key==s)n=value;
	}
	return n;
}
function drawIt(fit){
	let txt=document.getElementById('ta').value.trim();
	if(txt=="")return;
	let rtn=RLE2Array(txt);
	let rows=parseInt(rtn[1]);
	let cols=parseInt(rtn[2]);
	if(isNaN(rows) || isNaN(cols)){
		alert('Invalid RLE.');
		return;
	}
	let a=new Array(rows);
	for(var i=0;i<rows;i++){
		a[i]=new Array(cols);
		a[i].fill(0);
	}
	const row=0; //for the eval
	const col=0;
	eval(rtn[0]);
	const rotate=document.getElementById('rotate').checked;
	if(rotate){
		a=rotate90Right(a);
		var temp=rows
		rows=cols;
		cols=temp;
	}
	nrows=rows+2; //add borders
	ncols=cols+2;
	if(!fit){
		if(ncols>nrows){ //square
			nrows=ncols;
		} else {
			ncols=nrows;
		}
	}
	if(nrows>1000){
		alert('Pattern too big.');
		return;
	}
	let bigA=new Array(nrows);
	for(var i=0;i<nrows;i++){
		bigA[i]=new Array(ncols);
		bigA[i].fill(0);
	}
	const idelta=Math.round((nrows-rows)/2);
	const jdelta=Math.round((ncols-cols)/2);
	for(var i=0;i<rows;i++){
		for(var j=0;j<cols;j++){
			bigA[i+idelta][j+jdelta]=a[i][j];
		}
	}
	rowcoords=new Array(nrows);
	colcoords=new Array(ncols);
	drawGrid(bigA);
	document.getElementById("download").style.visibility="visible";
}
function drawGrid(a){
	var cellsize=16;
	var w=ncols*(cellsize+1)+1;
	var h=nrows*(cellsize+1)+1;
	if(w>400 || h>400){
		cellsize=11;
		w=ncols*(cellsize+1)+1;
		h=nrows*(cellsize+1)+1;
	}
	if(w>600 || h>600){
		cellsize=6;
		w=ncols*(cellsize+1)+1;
		h=nrows*(cellsize+1)+1;
	}
	if(w>800 || h>800){
		cellsize=4;
		w=ncols*(cellsize+1)+1;
		h=nrows*(cellsize+1)+1;
	}
	canvas.width=w;
	canvas.height=h;
	
	context.fillStyle=deadcolor;
	context.fillRect(0,0,w,h);

	//live cells
	var n=0;
	for(var x=0;x<w-1;x+=(cellsize+1)){
		colcoords[n]=x+1;
		if(cellsize<4)colcoords[n]++;
		n++;
	}
	n=0;
	for(var y=0;y<h-1;y+=(cellsize+1)){
		rowcoords[n]=y;
		if(cellsize<4)rowcoords[n]++;
		n++;
	}
	context.fillStyle=livecolor;
	let paintsize=cellsize-1;
	if(paintsize==1)paintsize=2;
	for(var j=0;j<nrows;j++){
		for(var i=0;i<ncols;i++){
			if(a[j][i]){
				context.fillRect(colcoords[i],rowcoords[j]+1,paintsize,paintsize);
				console.log(colcoords[i],rowcoords[j]);
			}
		}
	}

	//grid lines
	context.beginPath();
	for(var x=0;x<w-1;x+=(cellsize+1)){
		context.moveTo(x,0);
		context.lineTo(x,h);
	}
	context.moveTo(w,0);
	context.lineTo(w,h);
	context.lineWidth=2;
	context.strokeStyle=gridcolor;
	context.stroke();
	context.beginPath();
	for(var y=0;y<h-1;y+=(cellsize+1)){
		context.moveTo(0,y);
		context.lineTo(w,y);
	}
	context.moveTo(0,h);
	context.lineTo(w,h);
	context.lineWidth=2;
	context.stroke();	
}
function saveIt(el){
	const imageURI=canvas.toDataURL("image/png");
	el.href=imageURI;
}
Looks like that ought to work.

If someone wants to go through and "rescue" all of the tools from that golhobby.com archive page, and put everything into a nice package with relative URLs everywhere such that it will work wherever you put it, then I can work on finding a fresh place to host it.

Maybe just conwaylife.com/ref/golhobby ? I haven't looked at them all, but these scripts all seem like they'd run clientside, so they're no more troublesome than the LifeViewers in conwaylife.com/ref/lifepage or similar Javascript in Mark Niemiec's search page.
User avatar
confocaloid
Posts: 6697
Joined: February 8th, 2022, 3:15 pm
Location: learn to protect yourself against stray gliders and sparks and self-destruct mechanisms

Re: Online File Format Converters

Post by confocaloid »

edit: linking related discussions:
dvgrn wrote: May 1st, 2025, 2:08 pm [...] It still seems to be possible to retrieve the Javascript source for all of the tools from the Internet Archive. [...]
Sounds like it could be better to write some new code for the task (following whatever conventions/guidelines there are now) and host it on this website, instead of copying some code with unclear status and with unclear compatibility with what is believed to be the best way of presenting patterns on the wiki and in similar contexts.

While I don't remember the details without doing a forum/wiki search, I *do* remember that there were some disagreements on the issue (i.e. guidelines regarding conversion of CA configurations to static images).

Are there reasons why the LifeViewer feature (see quote below) doesn't work as intended? What are they?
rowett wrote: March 10th, 2022, 10:30 am You can also do similar in LifeViewer:

Code: Select all

x = 8, y = 12, rule = B3/S23
b2o2b2o$3b2o$3b2o$obo2bobo$o6bo2$o6bo$b2o2b2o$2b4o2$3b2o$3b2o!
[[ THEME Inverse GRID GRIDMAJOR 0 AUTOFIT ]]
Use Settings->Pattern->Save Image (hotkey O).
127:1 B3/S234c User:Confocal/R (isotropic CA, incomplete)
Unlikely events happen.
My silence does not imply agreement, nor indifference. If I disagreed with something in the past, then please do not construe my silence as something that could change that.
User avatar
dvgrn
Moderator
Posts: 12023
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Online File Format Converters

Post by dvgrn »

confocaloid wrote: May 1st, 2025, 2:38 pm Are there reasons why the LifeViewer feature (see quote below) doesn't work as intended [for the specific case of RLE-to-PNG conversion]? What are they?
The RLE2PNG extracted code was just one example of a fairly large number of online file format converters collected on the golhobby site.

For the specific case of RLE2PNG, it's definitely possible that LifeViewer can do a better job. I think this is the most recent relevant quote:
rowett wrote: October 29th, 2024, 12:02 pm From LifeViewer build 1205 pressing the ; (semi-colon) key will take a screenshot with the following properties:
  • Inverse Theme
  • Grid lines on with no major grid lines
  • Integer zoom
I'm not so sure about Book's RLE2PNG online converter, just because both Muzik and I have spent some time recently replacing PNGs in LifeWiki articles that were uploaded by Book a couple of years back. They turned out to have unnecessary aliasing -- i.e., they somehow ended up being a non-optimal size, so they had interpolated pixels that weren't just the LifeWiki-standard on, off, and grid colors.

So, long story short, any code retrieved from the golhobby site would ideally need to be tested, and maybe patched up a bit if needed. But then, any code uploaded to a hypothetical online-converters collection would ideally need to be tested in pretty much the same way, whether it's existing or newly written.

Here's the full list of tools that are presumably retrievable from the golhobby archive site:

Code: Select all

Toolkit
- Pattern Lookup
- Tidy RLE
- Inflate RLE
- IMG to RLE
- RLE to PNG
- RLE to SVG
- RLE to Plaintext
- Plaintext to RLE
- Apgcode to PNG
- Apgcode to RLE
- Integer to Life Digits RLE
- Frequency Class Calculator
- Frequency Calculator
(It also lists "RLE to Apgcode" but that was really just a link to Catagolue's Object page.)

I don't have time to write and test all of these converters from scratch in Javascript. So I'm not volunteering to do that. If someone else wants to do that, and do all the necessary testing, that would be great. But if not, well, there's code already available on that golhobby archive site. It's fairly easy to extract, and most of it probably works just fine.

What I can volunteer to do is to help get an online Javascript converter tool collection hosted somewhere like conwaylife.com/ref/golhobby or conwaylife.com/ref/online-converters or whatever.
MXMLLN
Posts: 39
Joined: December 28th, 2022, 12:36 am
Contact:

Re: Online File Format Converters

Post by MXMLLN »

Are there reasons why the LifeViewer feature (see quote below) doesn't work as intended? What are they?
Personally, it's the text file format converters that I could really use, not the image exports. I think they would also benefit beginners like me that haven't fully adapted RLE into their workflow.

And actually, since the RLE to Plaintext converter already exists...
It is the complementary converter, from Plaintext or Life 1.05 to RLE that I'm missing.

Plaintext and Life 1.05 are trivial to convert between. I'm mostly working in spreadsheet and Find and Replace is sufficient.

Other text formats would be appreciated as well.
I think most people already have working solutions for IMG conversions, though I bet they could be streamlined.
Having an SVG exporter would be profound though.

And I'm happy to help out where I can.
User avatar
rowett
Moderator
Posts: 4586
Joined: January 31st, 2013, 2:34 am
Location: UK
Contact:

Re: Online File Format Converters

Post by rowett »

MXMLLN wrote: May 2nd, 2025, 3:02 am And actually, since the RLE to Plaintext converter already exists...
This doesn't appear to help since the Plaintext it creates is not compatible with Golly or LifeViewer given it uses $ as end of line markers in the Plaintext (this is an RLE feature).
MXMLLN wrote: May 2nd, 2025, 3:02 am It is the complementary converter, from Plaintext or Life 1.05 to RLE that I'm missing.
Just open the pattern in Golly or LifeViewer and then use Select All and then Copy. The clipboard will contain RLE.
User avatar
confocaloid
Posts: 6697
Joined: February 8th, 2022, 3:15 pm
Location: learn to protect yourself against stray gliders and sparks and self-destruct mechanisms

Re: Online File Format Converters

Post by confocaloid »

Linking some related discussions:
viewtopic.php?f=7&t=6403#p180189 "How to Copy Cells in "..OO" Pattern Format?"
viewtopic.php?f=7&t=6293 "Finer points of file formats"
MXMLLN
Posts: 39
Joined: December 28th, 2022, 12:36 am
Contact:

Re: Online File Format Converters

Post by MXMLLN »

Thank you, Confocaloid. The related discussion's LUA script is quite useful.
rowett wrote: May 2nd, 2025, 4:51 am This doesn't appear to help since the Plaintext it creates is not compatible with Golly or LifeViewer given it uses $ as end of line markers in the Plaintext (this is an RLE feature).
This is just one use case.
I use Golly in conjunction with my spreadsheets. For the time being, the spreadsheet data is much faster in most of the cases I'm working on.
User avatar
dvgrn
Moderator
Posts: 12023
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Online File Format Converters

Post by dvgrn »

MXMLLN wrote: May 2nd, 2025, 3:02 am Having an SVG exporter would be profound though.

And I'm happy to help out where I can.
Same as all the other online converters that Book provided, there's code for RLE-to-SVG right there in the archived page source:

Code: Select all

let rowcoords,colcoords;
const deadcolor="white";
const livecolor="black";
const gridcolor="silver";

function doOnload(){
	document.getElementById('ta').select();
}
function xRLE2Array(inp){
	//extended RLE
	inp=inp.replaceAll(".","b");
	inp=inp.replaceAll("B","b");
	inp=inp.replaceAll("A","o");
	inp=inp.replaceAll("C","o");
	inp=inp.replaceAll("D","b");
	inp=inp.replaceAll("E","o");
	inp=inp.replaceAll("F","o");
	//
	inp=inp.replaceAll("!","");
	inp=inp.replaceAll(" ","");
	var b="$"+"b$".repeat(998);
	for(var i=999;i>1;i--){
		inp=inp.replaceAll(i+"$",b);
		b=b.slice(2);
	}
	var txt=inp.split("\n");
	var out="";
	var s1="";
	var s2;
	for(var i=0;i<txt.length;i++){
		if(txt[i].charAt(0)!="#" && txt[i].charAt(0)!="x"){
			s1+=txt[i];
		}
	}
	s2=s1.split("$");
	if(s2[s2.length-1]=="")s2.length=s2.length-1;
	var rtn;
	var maxrow=0;
	var maxcol=0;
	for(var i=0;i<s2.length;i++){
		rtn=RLEDecodeLine(i,s2[i]);
		out+=rtn[0];
		maxrow=Math.max(maxrow,rtn[1]);
		maxcol=Math.max(maxcol,rtn[2]);
	}
	return [out,maxrow,maxcol];
}
function xRLEDecodeLine(row,sin){
	var nstr="";
	var n=0;
	var col=0;
	var s,srow,scol;
	var maxcol=0;
	var sout="";
	srow="+"+row;
	if(row==0)srow="";
	for(var i=0;i<sin.length;i++){
		s=sin.charAt(i);
		if(s=="b" || s=="o"){
			if(nstr==""){
				n=1;
			} else {
				n=parseInt(nstr);
			}
			if(s=="o"){
				for(var j=0;j<n;j++){
					scol="+"+(col+j);
					if(col+j==0)scol="";
					sout+="\ta[row"+srow+"][col"+scol+"]=1;\n";
					maxcol=Math.max(maxcol,col+j);
				}
			}
			col+=n;
			n=0;
			nstr="";
		} else {
			nstr+=s;
		}
	}
	return [sout,row+1,maxcol+1];
}
function drawIt(){
	let txt=document.getElementById('ta').value.trim();
	if(txt=="")return;
	let rtn=RLE2Array(txt);
	const rows=parseInt(rtn[1]);
	const cols=parseInt(rtn[2]);
	if(isNaN(rows) || isNaN(cols)){
		alert('Invalid RLE.');
		return;
	}
	let a=new Array(rows);
	for(var i=0;i<rows;i++){
		a[i]=new Array(cols);
		a[i].fill(0);
	}
	const row=0; //for the eval
	const col=0;
	eval(rtn[0]);
	nrows=rows+2; //add borders
	ncols=cols+2;
	if(ncols>nrows){ //square
		nrows=ncols;
	} else {
		ncols=nrows;
	}
	if(nrows>1000){
		alert('Pattern too big.');
		return;
	}
	let bigA=new Array(nrows);
	for(var i=0;i<nrows;i++){
		bigA[i]=new Array(ncols);
		bigA[i].fill(0);
	}
	const idelta=Math.round((nrows-rows)/2);
	const jdelta=Math.round((ncols-cols)/2);
	for(var i=0;i<rows;i++){
		for(var j=0;j<cols;j++){
			bigA[i+idelta][j+jdelta]=a[i][j];
		}
	}
	rowcoords=new Array(nrows);
	colcoords=new Array(ncols);
	drawGrid(bigA);
	document.getElementById('save').disabled=false;
}
function svgDrawLine(x1,y1,x2,y2,w,color){
	const r='<line x1="'+x1+'" y1="'+y1+'" x2="'+x2+'" y2="'+y2+'" style="stroke:'+color+';stroke-width:'+w+'" />';
	return r;
}
function svgDrawRect(x,y,fill,w,h,border,borderw){
	const r='<rect x="'+x+'" y="'+y+'" width="'+w+'" height="'+h+'" style="fill:'+fill+';stroke:'+border+';stroke-width:'+borderw+'" />';
	return r;
}
function svgWrap(w,h,s){
	let r='<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"';
	r+=' x="0px" y="0px" width="'+w+'" height="'+h+'">'+s+'</svg>';
	return r;
}
function drawGrid(a){
	const div=document.getElementById('svg');
	var cellsize=20;
	var w=ncols*(cellsize+1)+1;
	var h;
	while(cellsize>3){
		if(w>512){
			cellsize--;
			w=ncols*(cellsize+1)+1;
		} else {
			break;
		}
	}
	h=w;
	let svg="";
	svg+=svgDrawRect(0,0,deadcolor,w,h,gridcolor,1);
	var n=0;
	for(var x=0;x<w-1;x+=(cellsize+1)){
		if(cellsize)svg+=svgDrawLine(x,0,x,h,1,gridcolor); //else no gridlines
		colcoords[n]=x+1;
		if(cellsize<4)colcoords[n]++;
		n++;
	}
	if(cellsize)svg+=svgDrawLine(w,0,w,h,1,gridcolor); //else no gridlines
	n=0;
	for(var y=0;y<h-1;y+=(cellsize+1)){
		if(cellsize)svg+=svgDrawLine(0,y,w,y,1,gridcolor); //else no gridlines
		rowcoords[n]=y;
		if(cellsize<4)rowcoords[n]++;
		n++;
	}
	if(cellsize)svg+=svgDrawLine(0,h,w,h,1,gridcolor); //else no gridlines
	
	let paintsize=cellsize-1;
	if(paintsize==1)paintsize=2;
	for(var j=0;j<nrows;j++){
		for(var i=0;i<ncols;i++){
			if(a[j][i]){
				svg+=svgDrawRect(colcoords[i],rowcoords[j],livecolor,paintsize,paintsize,gridcolor,1);
			}
		}
	}

	svg=svgWrap(w,h,svg);
	div.style.width=w+'px';
	div.style.height=h+'px';
	div.innerHTML=svg;
}
Scripts are disabled in the Internet Archive, but a local copy of that page could be opened and run, either offline or online, possibly with a few small changes to paths. I haven't looked closely, but this ought to be an easy project for someone to do.

Once someone puts together a collection of these tools in the form of a linked set of HTML files with relative paths such that they work offline, it would be easy to upload them somewhere so that they are available online also.
MXMLLN
Posts: 39
Joined: December 28th, 2022, 12:36 am
Contact:

Re: Online File Format Converters

Post by MXMLLN »

I didn't even think about how downloading an offline copy would get the code to work!
Brilliant.

Sorry if I missed the point in your first message.
I'll get started...
MXMLLN
Posts: 39
Joined: December 28th, 2022, 12:36 am
Contact:

Re: Online File Format Converters

Post by MXMLLN »

🤯 OMG!
RLE to SVG works! I didn't even notice it when I first came across GOL Hobby many years ago, before the page died.

There is a small typo:
RLE2Array
RLEDecodeLine

These two functions reference each other, but sometimes they were prepended by an x, ie, xRLE2Array & xRLEDecodeLine.

A simple text search will find the one or two function calls.
Just remove the x(s) and it should work.
User avatar
Resu
Posts: 803
Joined: May 23rd, 2025, 10:47 am
Location: UTC+14:00
Contact:

Re: Online File Format Converters

Post by Resu »

dvgrn wrote: May 1st, 2025, 2:08 pm If someone wants to go through and "rescue" all of the tools from that golhobby.com archive page, and put everything into a nice package with relative URLs everywhere such that it will work wherever you put it, then I can work on finding a fresh place to host it.
Has anybody done this yet?

Code: Select all

x = 31, y = 13, rule = C
8.2X2.3X.3X.X.X$8.X.X.X3.X3.X.X$8.X.X.3X.3X.X.X$8.2X2.X5.X.X.X$8.X.X.
3X.3X.3X$M2.M$4.M$M3.M$.4M$27.2M$27.M.M$29.M$29.2M! [[ AUTOSTART GPS 10 ]]
User avatar
dvgrn
Moderator
Posts: 12023
Joined: May 17th, 2009, 11:00 pm
Location: Madison, WI
Contact:

Re: Online File Format Converters

Post by dvgrn »

Resu wrote: August 3rd, 2025, 8:01 am Has anybody done this yet?
If they have, nobody has told me.
MXMLLN
Posts: 39
Joined: December 28th, 2022, 12:36 am
Contact:

Re: Online File Format Converters

Post by MXMLLN »

Should we start a 2nd thread to rescue the GolHobby.com converters?


I'm just updating the pages as I need them, but it will be a few weeks until I need everything.

For example, today I wanted the RLE to PlainText converter.
It uses the RLE2Array() function, though it doesnt't seem to have a reference to it anywhere.
However, RLE2Array() is available on the RLE to SVG page.
Easy fix!
Post Reply