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.
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.
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.")
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()
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.
Once loaded, OK will appear. Type RUN.
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.
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
Thanks for this!
Jeff