From f6bfab3c745bcb054f49937fd025de4eb46c9036 Mon Sep 17 00:00:00 2001 From: Michael Devendra Date: Fri, 14 Aug 2015 00:25:12 -0700 Subject: [PATCH] Added compatibility with Linux and Windows in addition to OSX. Added ability for Linux and Windows to run this script. Now everyone can use this! Added friendly and instructive error message for when pypng is not installed. Fixed bugs that prevented the proper printing output. Fixed the try/except/finally's to be try/except's. Fixed inconsistent space and tab indentation which will fail with Python 3. Fixed sys.exit(0) to exit with code of 1, which indicates an error to the shell. Added the shebang to the first line so that the script can be run on its own. Fixed the ImageMagick command line to be more compatible running under Windows shell. --- DSK Image/DSK-Image.py | 106 +++++++++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 36 deletions(-) diff --git a/DSK Image/DSK-Image.py b/DSK Image/DSK-Image.py index 726c259..cd26935 100644 --- a/DSK Image/DSK-Image.py +++ b/DSK Image/DSK-Image.py @@ -1,67 +1,71 @@ -# KansasFest 2015 -# HackFest Entry: Disk Images Images -# By Charles Mangin -# @RetroConnector +#! /usr/bin/env python -# requires ImageMagick: http://www.imagemagick.org/ -# and python PNG module: https://pypi.python.org/pypi/pypng +""" + KansasFest 2015 + HackFest Entry: Disk Images Images + By Charles Mangin + @RetroConnector + + requires ImageMagick: http://www.imagemagick.org/ + and python PNG module: https://pypi.python.org/pypi/pypng +""" import os,sys # filesystem functions -import png # PNG image library try: - INPUTFILE = sys.argv[1] # what DSK file to parse + import png # PNG image library +except: + print("\n\n" + sys.argv[0] + " requires the Python PNG module\n\n Download from https://pypi.python.org/pypi/pypng \n Or type in shell: pip install pypng\n\n") + sys.exit(1) # exit on exception - no library installed + +try: + INPUTFILE = sys.argv[1] # what DSK file to parse DSK = open(INPUTFILE, "rb") # open the DSK file for reading except: - print("\n\nUsage: python [filename]\n\n [filename] should be a DSK file of 143kb.\n\n") - sys.exit(0) # exit on exception - no file chosen -finally: + print("\n\nUsage: python "+ sys.argv[0] +" [filename]\n\n [filename] should be a .DSK file of 143kb.\n") + sys.exit(1) # exit on exception - no file chosen - PNG = open("DiskImageTEMP.png", "wb") # open a PNG for writing +TEMPFILENAME = "DiskImageTEMP.png" +PNG = open(TEMPFILENAME, "wb") # open a PNG for writing # The point: Make a PNG image from the data on a floppy disk image. # 35 tracks, each with 16 sectors of 256 bytes each, for a total of 143,360 bytes # so 35 lines of 4096 px. # new, empty arrays -BYTES = [] +BYTES = [] PIXELS = [] try: byte = DSK.read(1) # read a byte - while byte !="": # while the file still has bytes in it + while byte != "": # while the file still has bytes in it byte = DSK.read(1) - if len(byte) > 0: # the last byte, for whatever reason, is length 0. Bah. - BYTES.append(ord(byte)) # append the number representing the byte (0-255) to the BYTES array - + if len(byte) > 0: # the last byte, for whatever reason, is length 0. Bah. + BYTES.append(ord(byte)) # append the number representing the byte (0-255) to the BYTES array except: print("\n\nOops. Is " + INPUTFILE + " a DSK file of 143kb?\n\n") - sys.exit(0) # exit on exception - file is empty, etc -finally: - - sys.stdout.write("\r Starting.\n\n") + sys.exit(1) # exit on exception - file is empty, etc - for TRACK in range(0,35,1): # for each of the 35 tracks - LINE=[] # start a new line of pixels - for SECTOR in range(0,4096,1): # write the bytes for the sectors in that track to the line array - offset = (SECTOR * TRACK) + SECTOR - LINE.append(BYTES[(SECTOR * TRACK) + SECTOR]) +print("\n Starting.\n") - sys.stdout.write("\r Track: " + str(TRACK)) - sys.stdout.flush() - PIXELS.append(LINE) # add the array of pixels to the array of arrays +for TRACK in range(0,35,1): # for each of the 35 tracks + LINE=[] # start a new line of pixels + for SECTOR in range(0,4096,1): # write the bytes for the sectors in that track to the line array + offset = (SECTOR * TRACK) + SECTOR + LINE.append(BYTES[(SECTOR * TRACK) + SECTOR]) - sys.stdout.write("\n\n\r Done.\n\n") - sys.stdout.flush() + print(" Track: " + str(TRACK)) + PIXELS.append(LINE) # add the array of pixels to the array of arrays + +print("\n Done.\n") # write to the PNG file w = png.Writer(4096,35, greyscale=True, bitdepth=8) w.write(PNG, PIXELS) # each number in the array becomes a pixel in the image. each array becomes a line. -sys.stdout.write("\n\n\r Writing to disk. Chunka-chunk-cka. Whirr.\n\n") -sys.stdout.flush() +print(" Writing to disk. Chunka-chunk-cka. Whirr...\n") DSK.close() # done with these files. close them. @@ -71,8 +75,38 @@ PNG.close() OUTPUTFILE = os.path.join(INPUTFILE + ".png") # set a destination file same as DSK, but with PNG extension -os.system('convert DiskImageTEMP.png -matte -virtual-pixel transparent -resize 1024x1024! -rotate 90 -distort Polar \'512 110 512,512 -180,180\' ' + OUTPUTFILE) - # convert the 4096x35px image to a square, rotate, then rotate around an axis. +os.system('convert '+TEMPFILENAME+' -matte -virtual-pixel transparent -resize 1024x1024! -rotate 90 -distort Polar "512 110 512,512 -180,180" "'+OUTPUTFILE+'"') + # Using ImageMagick, convert the 4096x35px image to a square, rotate, then rotate around an axis. + # NOTE: Windows command line needs to have Polar coordinates enquoted with " not ' + # NOTE: Windows has a native command called convert which does something very different + # from ImageMagick's convert command, so obviously this will fail if IM is not installed -os.system('open ' + OUTPUTFILE) # opens the resulting image in the default image viewer (Preview.app) +if 'win32' in sys.platform: + # Because the Windows "start" commandline command cannot take an enquoted file or pathname, + # which is necessary if the path has spaces, we have to obtain the "short" version of + # the file/path in the 8.3 format. There is no Python library to do this for us. + # Said another way: Windows is broken in that enquoting a file argument after their start + # command causes it to open a blank terminal. Boo! + # But we do this *after* the ImageMagick convert process above, because that will take an + # enquoted file just fine. + from ctypes import windll, create_unicode_buffer, sizeof + buf = create_unicode_buffer( 512 ) + if windll.kernel32.GetShortPathNameW( unicode(OUTPUTFILE), buf, sizeof(buf) ): + OUTPUTFILE = buf.value +else: + # Otherwise we enquote the output file becuase it may have spaces + OUTPUTFILE = '"' + OUTPUTFILE + '"' + +platform_commands = { + 'darwin' : 'open', # opens the resulting image in the default Mac image viewer (Preview.app) + 'linux' : 'xdg-open', # opens the resulting image in the default Linux image viewer (mime-determined); Python 2: 'linux2', Python 3: 'linux' + 'win32' : 'start' # opens the resulting image in the default Windows image viewer (Windows Photo Viewer, or...?) + } +# Open the .PNG in the default image viewer +for platform,command in platform_commands.items(): + if platform in sys.platform: + os.system(command + ' ' + OUTPUTFILE) + break +else: + print(" Your file is ready to view: " + OUTPUTFILE)