An 80’s Themed Image Filter for Photographs.

This week in our seminar for HIST5709 Photography and Public History we discussed a reading from Nathan Jurgenson’s The Social Photo. He describes the use of image filters to give digital photographs an aesthetic that evokes nostalgia and authenticity. Below is a description of a retro image filter inspired by the Radio Shack Color Computer.

I was very fortunate that my parents bought this computer when we moved to Ottawa in 1983. I learned a lot using it and I used it a lot. As much as I loved it, I found its basic graphic mode odd. Coloured blocks were available, but instead of being square they were about 1.5 times tall as they were wide. (See a list of the yellow blocks below.)

While I used these blocks for a few purposes, like printing large letters, their rectangular shape made them less satisfactory for drawing. Still, they are distinctive. I wanted to see if I could make an image filter with them and evoke a sense of the 1980’s.

I used the Xroar emulator as a virtual Color Computer rather than going fully retro and using the actual machine. See: https://www.6809.org.uk/xroar/. It takes a few steps to set up on a computer. There is an easier to run on-line version of the CoCo at: http://www.6809.org.uk/xroar/online/. To follow along, just set Machine: “Tandy CoCo (NTSC)” in the menu for XRoar Online.

Above: Color Computer running on XRoar Online.

To see one of these graphical blocks, type in PRINT CHR$(129) and hit Enter in XRoar. (And note that the CoCo keyboard uses Shift+8 for ( and Shift+9 for ). Try a few different values like PRINT CHR$(130) or 141 and you will see rectangular graphics like the yellow blocks in the screen above.

Using these to represent a photograph provides a maximum resolution of 64 pixels wide X 32 pixels tall. (The screen is 32 characters wide with 16 rows.) I wanted to leave a row for text, so I used a resolution of 64 X 30. However, since the pixels are 1.5 times taller than wide I would use a photograph with an aspect ratio of 64X45 (30*1.5).

I used the picture below. It’s a screen grab my daughter took that has some contrast and could be used for my Twitter profile.

Raw image in grayscale. It’s 192X135 or 3 times larger than 64×45.

Here’s the Python code I used:

# import the necessary packages
# Credit to: Adrian Rosebrock https://www.pyimagesearch.com/
from imutils import paths
from matplotlib import pyplot
import argparse
import sys
import cv2
import os

import shutil
from pathlib import Path
img_local_folder = "C:\\xroar\\"
path = Path(img_local_folder)
os.chdir(path)
# 192X135 is used since it's a multiple of 64X45. 
img_file_name = "jeffb_192x135.jpg"
hash_image = cv2.imread(img_file_name)

# if the image is None then we could not load it from disk (so skip it)
if not hash_image is None:
    # convert the image to grayscale and compute the hash
    pyplot.imshow(hash_image)    
    pyplot.show()

    hash_image = cv2.cvtColor(hash_image, cv2.COLOR_BGR2GRAY)
    pyplot.imshow(hash_image,cmap='gray')    
    pyplot.show()

    # resize the input image to 64 pixels wide and 30 high.
   
    resized = cv2.resize(hash_image, (64, 30))
    pyplot.imshow(resized,cmap='gray')
    pyplot.show()
    
else:
    print("no image.")
A flattened 64X30 image.

Let’s convert this to black and white.

#convert the grayscale to black and white using a threshold of 92
(thresh, blackAndWhiteImage) = cv2.threshold(resized, 92, 255, cv2.THRESH_BINARY)
print(blackAndWhiteImage)
pyplot.imshow(blackAndWhiteImage,cmap='gray')
pyplot.show()
A black and white version.

This image needs to be translated in order to import in into the CoCo. We will turn it into a BASIC program of PRINT statements. Here is a sample of this very simple and inefficient program.

 150 PRINT CHR$(128);
 152 PRINT CHR$(128);
 154 PRINT CHR$(143);
 156 PRINT CHR$(143);
 158 PRINT CHR$(143);
 160 PRINT CHR$(143);
 162 PRINT CHR$(131);
 164 PRINT CHR$(131);
 166 PRINT CHR$(131);
 168 PRINT CHR$(135);

This program is generated by Python. Python loops through squares of 4 pixels in the black and white image. For each pixel that has a color of 255/white, the appropriate bit (top/bottom, left/right) on the rectangular graphic block is set to having color.

file = open('C:\\xroar\\xroar-0.35.2-w64\\drawjeff.asc','w') 
for row in range(0,30,2):
    for col in range(0,64,2):        
        linenum = row*64+col
        # bit 1 is lower left
        bit1=0
        # bit 2 is lower right
        bit2=0
        # bit 4 is top left
        bit4=0
        # bit 8 is top right
        bit8=0
        # if a pixel is white (255) - set the bit to 1 (green) else, the bit is 0 (black)
        if(blackAndWhiteImage[row,col]==255):
            bit8=8
        if(blackAndWhiteImage[row,col+1]==255):
            bit4=4
        if(blackAndWhiteImage[row+1,col]==255):
            bit2=2
        if(blackAndWhiteImage[row+1,col+1]==255):
            bit1=1
        chr = 128+bit1+bit2+bit4+bit8
        # write the statement into the program.
        file.write(str(linenum)+" PRINT CHR$("+str(chr)+");\r ")
    # write an end of line statement if line is less than 32 characters
    #file.write(str(linenum)+" PRINT CHR$(128)\r ")
file.close()

A sample of the generated program is here. To run it, in XRoar Online click Load and select the downloaded drawjeff.asc file. Then type CLOAD <enter> in the emulator. (See below.)

Loading will take a moment. Imagine popping a cassette into a tape recorder, typing CLOAD and pressing the play button. F DRAWJEFF will be displayed will the file is loaded.

This will appear during the loading of the file.

Once loaded, OK will appear. Type RUN.

A photograph image filter… Imagination required.

It’s neat that there is an on-line emulator for a computer from almost 4 decades ago. It’s also neat that Python can write programs that will run on it.

The book Getting Started with Extended Color BASIC is on the Internet Archive. I loved this book and think it’s an excellent introduction to programming. There are lots of ideas to try out on XRoar.

2 thoughts on “An 80’s Themed Image Filter for Photographs.”

  1. 200 READ C: IF C = -1 THEN 220
    210 ? CHR$(C);:GOTO 200
    220 END
    230 DATA 128,128,128,128,128,128,128,128,128,128,128,128,128,128,129,130,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128
    240 DATA 128,128,128,128,128,128,128,128,128,128,128,128,128,139,143,143,143,131,131,130,129,131,128,128,128,128,128,128,128,128,128,128
    250 DATA 128,128,128,128,128,128,128,128,128,128,128,128,133,143,143,143,143,143,143,143,143,143,128,128,128,128,128,128,128,128,128,128
    260 DATA 128,128,128,128,128,128,128,128,128,128,128,128,143,143,143,143,143,143,143,143,143,143,128,128,128,128,128,128,128,128,128,128
    270 DATA 128,128,128,128,128,128,128,128,128,128,128,128,128,136,128,132,143,140,128,128,128,140,136,128,128,128,130,128,128,128,128,128
    280 DATA 128,128,128,128,128,128,128,128,128,128,128,128,128,131,131,130,130,128,128,131,131,128,139,130,128,132,138,128,128,128,128,128
    290 DATA 128,128,128,128,128,128,128,128,128,128,128,128,129,140,140,137,143,130,128,132,136,135,143,128,133,136,134,128,128,128,128,128
    300 DATA 128,128,128,128,128,128,128,128,128,128,128,128,133,142,136,143,138,128,128,128,132,140,140,128,133,140,128,128,128,128,128,128
    310 DATA 128,128,128,128,128,128,128,128,128,128,128,128,132,138,135,140,132,136,128,128,128,128,128,128,128,128,128,128,128,128,128,128
    320 DATA 128,128,128,128,128,128,128,128,128,128,128,128,128,141,143,143,143,136,128,128,128,128,128,128,128,128,128,128,128,128,128,128
    330 DATA 128,128,128,128,128,128,128,128,128,128,128,128,128,132,143,143,143,136,128,128,128,128,129,131,138,128,128,128,128,128,128,128
    340 DATA 128,128,128,128,128,128,128,128,128,128,128,128,128,128,133,143,143,131,128,128,128,128,132,129,138,130,128,128,128,128,128,128
    350 DATA 128,128,128,128,128,128,128,128,128,129,130,128,128,128,133,143,143,143,131,128,135,143,128,132,135,139,128,128,128,128,128,128
    360 DATA 128,128,128,128,128,128,128,129,135,143,143,139,130,128,133,143,143,143,143,130,132,129,131,143,143,136,128,128,128,128,128,128
    370 DATA 128,128,128,128,128,128,132,143,143,143,143,143,143,139,130,141,143,143,142,143,143,143,142,136,128,128,128,128,128,128,129,131
    390 DATA -1,-1

Leave a Reply to Bigcode Cancel reply