some old helper tools for rotation
Eli the Bearded <*@eli.users.panix.com> Wed, 20 May 2026 17:25:09 -0000 (UTC)
| Newsgroups | alt.ascii-art |
|---|---|
| Organization | Some absurd concept |
| Message-ID | <[email protected]> |
A few weeks ago I found these in an old backup of mine. There's four utilies, three of them using a compiled C heler tool and the fourth based on awk. Combined they provide a way to rotate ASCII art 90 degrees, 180 degrees, 270 degrees, and to left-right flip an image. The left-right flip is by Jef Poskanzer ( www.acme.com ) and clearly licensed. The others are of ambitious origin and have no clear license. I suspect the authors would be 100% okay with my sharing this old code for the purpose of hobbyists to use non-commercially. Code distributed in the old-school shell archive format. You can extract by hand easily enough or use `sh` to do it automatically. There was no makefile when I got this, but "make asciitool" worked for me. My only changes to the code were to add the #include lines above the comment in the C file and add line breaks to the C file usage message. Elijah ------ # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # notes # asciitool.c # ccw90 # cw90 # tb # lr # echo x - notes sed 's/^X//' >notes << 'END-of-notes' XDownloaded from X gopher://samuell.com:70/ Xsometime in June 2006 END-of-notes echo x - asciitool.c sed 's/^X//' >asciitool.c << 'END-of-asciitool.c' X#include <stdlib.h> X#include <stdio.h> X/* ********************************************************************** X asciitool.c An ASCII Rotation and Mirroring tool X Xcompile with: cc -o asciitool asciitool.c X XNot my code! (Joshua Bell, [email protected]) X XWell, some of it is, but not much. XChanges: - changed if/else if/else if/else if... to a switch X - fixed bug with -r270 (no longer requires rectangular images) X - made Infile and Outfile default to STDIN and STDOUT (for pipes) X - made incorrect calling syntax quit program X - reformatted the source to be more concise X Xasciitool -{mh|mv|r90|r180|r270} [Infile [Outfile]] X -mh Mirror horizontally X -mv Mirror vertically X -r90 Rotate 90 degrees counterclockwise X -r180 Rotate 90 degrees counterclockwise X -r270 Rotate 90 degrees counterclockwise X X********************************************************************** */ X X#include <stdio.h> X#include <string.h> X X#define NUM_FLAGS 5 X Xchar *FlagStrings[NUM_FLAGS] = { "-mv", "-mh", "-r90", "-r180", "-r270" }; Xenum { V_MIRROR, H_MIRROR, R90, R180, R270 }; X Xchar **GetFile(FilePtr, NumberOfLinesPtr, ErrorString) X FILE *FilePtr; X int *NumberOfLinesPtr; X char *ErrorString; X{ X char **FileLines; X char Buffer[255]; X int CurrentLine, c, Error; X X ErrorString[0] = '\0'; X X CurrentLine = 0; X Error = 0; X X while((c = fgetc(FilePtr)) != EOF) { X ungetc(c, FilePtr); X fgets(Buffer, sizeof(Buffer), FilePtr); X X if(CurrentLine == 0) { X if((FileLines = (char **)malloc(sizeof(char *))) == NULL) { X strcpy(ErrorString, "Memory Allocation Error: <malloc>"); X return(NULL); X } X X } else { X if((FileLines = X (char **)realloc(FileLines,(1 + CurrentLine) * sizeof(char *))) X == NULL) { X strcpy(ErrorString, "Memory Allocation Error: <realloc>\n"); X return(NULL); X } X } X X if((FileLines[CurrentLine] = (char *)malloc(strlen(Buffer) + 1)) == NULL) { X strcpy(ErrorString, "Memory Allocation Error: <malloc>\n"); X return(NULL); X } X X strcpy(FileLines[CurrentLine++], Buffer); X } X X *NumberOfLinesPtr = CurrentLine; X X return(FileLines); X X} /* GetFile */ X Xint main(argc, argv) X int argc; X char **argv; X{ X int i, j, k, Flag, NumberOfLines, Length, MaxLength; X FILE *Infile, *Outfile; X char String[255]; X char **FileLines, **NewFileLines, *CharPtr; X X if((argc < 2) | (argc > 4)) { X printf("Usage: %s -{mh|mv|r90|r180|r270} [Infile [Outfile]]\n", argv[0]); X printf(" -mh Mirror horizontally\n"); X printf(" -mv Mirror vertically\n"); X printf(" -r90 Rotate 90 degrees counterclockwise\n"); X printf(" -r180 Rotate 90 degrees counterclockwise\n"); X printf(" -r270 Rotate 90 degrees counterclockwise\n"); X return(-1); X } X X switch (argc) { X case 2: X Infile = stdin; X Outfile = stdout; X break; X case 3: X if((Infile = fopen(argv[2], "r")) == NULL) X { X printf("Could not open input file: %s\n", argv[1]); X return(-1); X } X Outfile = stdout; X break; X case 4: X if((Outfile = fopen(argv[3], "w")) == NULL) X { X printf("Could not open output file: %s\n", argv[2]); X return(-1); X } X break; X } X X X strcpy(String, argv[1]); X X for(i = 0; String[i]; i ++) X if(String[i] >= 'A' && String[i] <= 'Z') X String[i] += ('a' - 'A'); X X for(i = 0; i < NUM_FLAGS; i ++) X if(!strcmp(String, FlagStrings[i])) X break; X X if(i == NUM_FLAGS) X { X printf("Illegal flag: %s\n", argv[3]); X return(-1); X } X else X Flag = i; X X if((FileLines = GetFile(Infile, &NumberOfLines, String)) == NULL) { X printf("%s\n", String); X return(-1); X } X X for(i = 0; i < NumberOfLines; i ++) { X if((CharPtr = strrchr(FileLines[i], '\n')) != NULL) X *CharPtr = '\0'; X X Length = strlen(FileLines[i]); X X if(i == 0 || (Length > MaxLength)) X MaxLength = Length; X } X X switch (Flag) { X X case V_MIRROR: X for(i = NumberOfLines - 1; i >= 0; i --) X fprintf(Outfile, "%s\n", FileLines[i]); X break; X X case H_MIRROR: X for(i = 0; i < NumberOfLines; i ++) { X Length = strlen(FileLines[i]); X X for(j = 0; j < Length; j ++) X String[Length - j - 1] = FileLines[i][j]; X X String[j] = '\0'; X fprintf(Outfile, "%*s%s\n", MaxLength - Length, "", String); X } X break; X X case R180: X for(i = NumberOfLines - 1; i >= 0; i --) { X Length = strlen(FileLines[i]); X X for(j = 0; j < Length; j ++) X String[Length - j - 1] = FileLines[i][j]; X X String[j] = '\0'; X fprintf(Outfile, "%*s%s\n", MaxLength - Length, "", String); X } X break; X X/*** For "real" rotations, need extra code ***/ X X default: X X if((NewFileLines = X (char **)malloc(MaxLength * sizeof(char *))) == NULL) { X printf("Memory Allocation Error: <malloc>"); X return(-1); X } X X for(i = 0; i < MaxLength; i ++) { X if((NewFileLines[i] = X (char *)malloc((NumberOfLines + 1) * sizeof(char))) == NULL) { X printf("Memory Allocation Error: <malloc>"); X return(-1); X } X } X X switch (Flag) { X X case R90: X X for(i = 0; i < NumberOfLines; i ++) X { X for(j = 0; FileLines[i][j]; j ++) X NewFileLines[MaxLength - 1 - j][i] = FileLines[i][j]; X X while(j < MaxLength) { X NewFileLines[MaxLength - 1 - j][i] = ' '; X j++; X } X } X break; X X case R270: X X for(i = 0; i < NumberOfLines; i ++) { X Length = strlen(FileLines[i]); X X for(k = 0, j = MaxLength - 1; j >= 0; j --, k ++) X if (j >= Length) X NewFileLines[MaxLength - k - 1][NumberOfLines - i - 1] = ' '; X else X NewFileLines[MaxLength - k - 1][NumberOfLines - i - 1] = X FileLines[i][j]; X X while(k < MaxLength) { X NewFileLines[MaxLength - k - 1][NumberOfLines - i - 1] = ' '; X k++; X } X } X X break; X } X X for(j = 0; j < MaxLength; j ++) { X NewFileLines[j][NumberOfLines] = '\0'; X fprintf(Outfile, "%s\n", NewFileLines[j]); X } X } X X X for(i = 0; i < NumberOfLines; i ++) X free((void *)FileLines[i]); X X free((void *)FileLines); X X fclose(Infile), fclose(Outfile); X X return(0); X X} /* main */ END-of-asciitool.c echo x - ccw90 sed 's/^X//' >ccw90 << 'END-of-ccw90' X#!/bin/sh X# X# ccw90 - rotates ASCII pictures by 90 degrees counter clockwise X# X# by Joshua Bell <[email protected]>, July 1994 X# X# Requires the asciitool program is present in your search path. X# X# Inspiration from Jef Poskanzer's "lr" utility for left/right flips. X# X# Mapping is: _-~^<>v/\NZ!]|[()nu:;{}"'`,CUciIl17t=H X# to: |||<v^>\/ZN-~-_un()""_~:\/\U)u----r+H= X Xcat $* | X ./asciitool -r90 | X tr '_\-~^<>v/\\NZ!]|[()nu:;{}"'\''`,CUciIl17t=H' \ X '|||<v^>\\/ZN\-~\-_un()""_~:\\/\\U)u\-\-\-\-r+H=' | X sed 's/ *$//' X END-of-ccw90 echo x - cw90 sed 's/^X//' >cw90 << 'END-of-cw90' X#!/bin/sh X# X# cw90 - rotates ASCII pictures by 90 degrees clockwise X# X# by Joshua Bell <[email protected]>, July 1994 X# X# Requires the asciitool program is present in your search path. X# X# Inspiration from Jef Poskanzer's "lr" utility for left/right flips. X# X# Mapping is: _-~^<>v/\NZ!]|[()nu:;{}"'`,CUciIl1rt=H X# to: |||>^v<\/ZN-_-~nu)(""~_:\/\nCn----7+H= X Xcat $* | X ./asciitool -r270 | X tr '_\-~^<>v/\\NZ!]|[()nu:;{}"'\''`,CUciIl1rt=H' \ X '|||>^v<\\/ZN\-_\-~nu)(""~_:\\/\\nCn\-\-\-\-7+H=' | X sed 's/ *$//' X END-of-cw90 echo x - tb sed 's/^X//' >tb << 'END-of-tb' X#!/bin/sh X# X# tb - flips ASCII pictures top for bottom X# X# by Joshua Bell <[email protected]>, Feb 1994 X# X# Requires the asciitool program is present in your search path. X# X# Inspiration from Jef Poskanzer's "lr" utility for left/right flips. X# X# Mapping is: ;!~_`,.'"^/\AFJLMPSTUVWYZbfghimnpqrstuvwyz257 X# to: :i_~,`'..v\/VL7TWb2LAAMASPt6y!wubdtzfn^mhsSZJ X Xcat $* | X ./asciitool -mv | X tr ';!~_\140,.\047"^/\\AFJLMPSTUVWYZbfghimnpqrstuvwyz257' \ X ':i_~,\140\047..v\\/VL7TWb2LAAMASPt6y!wubdtzfn^mhsSZJ' | X sed 's/ *$//' X END-of-tb echo x - lr sed 's/^X//' >lr << 'END-of-lr' X#!/bin/sh X# X# lr - reverse ASCII pictures left for right X# X# Copyright (C) 1994 by Jef Poskanzer. X# X# Permission to use, copy, modify, and distribute this software and its X# documentation for any purpose and without fee is hereby granted, provided X# that the above copyright notice appear in all copies and that both that X# copyright notice and this permission notice appear in supporting X# documentation. This software is provided "as is" without express or X# implied warranty. X X# Translation of . -> , changed removed. Better to lose some symmetry than X# induce asymmetry, IMHO. (jsbell@acs) X Xcat $* | X expand | X awk '{printf "%s%s\n", $0, substr(" ", length)}' | X rev | X tr '()<>{}\[]/\\.,\140\047LJZSE3dbqp' ')(><}{]\[\\/..\047\140JLSZ3Ebdpq' | X sed 's/ *$//' END-of-lr exit