TernLSB

TernLSB is an esolang invented by User:None1, it uses Steganography to store its program.
==How to write programs==
To write a program in TernLSB, first write a program in brainfuck, then convert it into a sequence of ternary numbers using the table below. After that, add the ternary number 22 at the end of the sequence of ternary numbers which works like a string terminator.
Ternary representation	brainfuck
00 	+
01 	-
02 	,
10 	.
11 	<
12 	>
20 	[
21 	]
Then assign the last two ternary bits with the ternary representation for every channel of every pixel in the image, starting from top-left, going right then restarting at the next line from the left. If the assigned result is larger than 255, then subtract it by 9.
Note: TernLSB programs have to be stored in a lossless compressed or uncompressed image type that uses RGB or RGBA color type (e.g.: BMP and PNG image type).
==How to run programs==
To run a TernLSB program, get the last two ternary bits for every channel of every pixel until you get 22, starting from top-left, going right then restarting at the next line from the left. Then recover the brainfuck program using the table above. Finally, execute the brainfuck program you get.
==Example Programs==
===Hello World===
===Nope. interpreter===
===brainfuck interpreter===
Inspired by dbfi.
===Cat Program===
===Truth Machine===
====Polyglot Truth Machine====
The following program behaves like a Truth Machine when running in either TernLSB or StegFuck.
===Infinite fibonacci sequence===
Made from this brainfuck program.
===XKCD Random Number===
==Interpreter==
Currently, the esolang has a Python interpreter (which is also an encoder for writing programs in the language), written by the author of the language (User:None1), it requires the Python Imaging Library.
#Usage:
#python tlsb.py <filename> - interpret a TernLSB program
#python tlsb.py <inputfn> <brainfuckfn> <outputfn> - Encodes brainfuck into an image file to make it a TernLSB program
import sys
from PIL import Image
def bf(code):
 s1=[]
 s2=[]
 matches={}
 tape=[0]*1000000
 for i,j in enumerate(code):
 if j=='[':
 s1.append(i)
 if j==']':
 m=s1.pop()
 matches[m]=i
 matches[i]=m
 cp=0
 p=0
 while cp<len(code):
 if code[cp]=='+':
 tape[p]=(tape[p]+1)%256
 if code[cp]=='-':
 tape[p]=(tape[p]-1)%256
 if code[cp]==',':
 tape[p]=ord(sys.stdin.read(1))%256
 if code[cp]=='.':
 print(chr(tape[p]),end=)
 if code[cp]=='<':
 p-=1
 if code[cp]=='>':
 p+=1
 if code[cp]=='[':
 if not tape[p]:
 cp=matches[cp]
 if code[cp]==']':
 if tape[p]:
 cp=matches[cp]
 cp+=1
def run(fn):
 im=Image.open(fn)
 d=im.tobytes()
 fuck='+-,.<>[]'
 b=''
 for i in d:
 try:
 b+=fuck[i%9]
 except:
 break
 bf(b)
def enc(fn,b,o):
 im=Image.open(fn)
 fuck='+-,.<>[]'
 d=im.tobytes()
 d=list(d)
 w=''
 for i in b:
 if i in fuck:
 w+=i
 for i,j in enumerate(w):
 d[i]=d[i]//9
 d[i]=d[i]*9
 d[i]+=fuck.index(j)
 if d[i]>=256:
 d[i]-=9
 d[len(w)]=d[len(w)]//9*9+8
 if d[len(w)]>=256:
 d[len(w)]-=9
 db=bytes(d)
 Image.frombytes(im.mode,im.size,db).save(o)
 
if __name__=='__main__':
 a=sys.argv
 if len(a)==2:
 run(a[1])
 if len(a)==4:
 enc(a[1],open(a[2]).read(),a[3])
 if len(a) not in [2,4]:
 print('Must pass 1 or 3 arguments')
==Turing completeness==
The language is of course Turing complete since brainfuck is.
==See also==
* StegFuck, a similar idea but uses binary bits instead of ternary ones.
Category:Languages
Category:Brainfuck derivatives
Category:Brainfuck equivalents
Category:Non-textual
Category:Steganography
Category:Turing complete
Category:2023
Category:Implemented