Draw dots based on (x,y) locations

Viewed 475

So I got .txt file with around 200 lines, each contains a (x,y) location ranging from 0 to 255. I want to draw dot, or "," at each location.. so (0,5) will draw 5 spaces in first line and then the ",".

Using python, is there a way to print it to the terminal that way? if not, is there a way to create .txt file with the "image" or any other way to view the resulting "image" (its just bunch of ","'s) thanks.

EDIT:

The .txt file is something I extracted from challenge. The challenege was to decode the output of given binary file. This is the original file: https://elbitcareer.hunterhrms.com/wp-content/uploads/elbitsystems.elbit

This is the .txt coords I managed to extract from the file: https://easyupload.io/imtbdn

And this is what it looks like when I print it to the terminal: enter image description here

It looks like the right direction (SYSCO..?) but something is off.. Any ideas on what is the problem?

EDIT2: So my .txt file was missing some points and my terminal window needed some resizing.. now it kinda workds! thanks all.

3 Answers

Here is a little function using ANSI escape codes to do that.

def print_at(x, y, txt):
    """
    Print txt on a specific coordinate of the terminal screen.
    """
    print(f"\033[{y};{x}H{txt}")

I wrote some code and the output seems to be just like yours but a little more. So the problem must be in the console size. I used out.txt file and this code:

import numpy as np

xmax = 0
ymax = 0
with open('out.txt', 'r') as f:
    while f.readline() !='':
        line = f.readline()
        if line and "," in line:
            x, y = line.split(',')
        x = int(x)
        y = int(y)
        if x > xmax:
            xmax = x
        if y > ymax:
            ymax = y
f.close()

pic = np.zeros((xmax+1,ymax+1))

with open('out.txt', 'r') as f:
    while f.readline() !='':
        line = f.readline()
        if line and "," in line:
            x, y = line.split(',')
        x = int(x)
        y = int(y)
        pic[x][y] = 1
        
print(xmax,ymax)

with open('picture.txt', 'w') as f:
    for y in range(ymax):
        for x in range(xmax):
            if pic[x][y] == 1:
                f.write('.')
            else:
                f.write(' ')
        f.write('\n')

This code works in 4 steps:

  1. Looking for max values of the picture.
  2. Creates matrix filled with zeros with this size.
  3. Fill the matrix with ones according to x,y coordinates from out.txt
  4. Iterate through the matrix and write to picture.txt dot '.' if there is 1 and spaces if 0.

The output file is picture.txt and looks like this: enter image description here

try to change size of your terminal console and will be good :)

Updated Answer

Now that your file has the format:

colourIndex, x, y

you can make a PNG image like this:

#!/usr/bin/env python3

import numpy as np
from PIL import Image

# Unpack CSV into three Numpy arrays
colour, x, y = np.loadtxt('out.txt', dtype=np.int, delimiter=',', unpack=True)

# Find height and width of "image", i.e. maximum y and x
h = np.max(y)
w = np.max(x)
print(f'Width: {w}, height: {h}')

# Make empty (black) 3-channel RGB image right size
im = np.zeros((h,w,3), dtype=np.uint8)

# Choose some colours for the colour indices
colmap = {0:[255,0,255],    # 0 -> magenta
          1:[128,128,128]}  # 1 -> grey

# Fill in points in colour
for col,thisx,thisy in zip(colour,x,y):
    im[thisy-1, thisx-1] = colmap[col]

# Make into "PIL Image" and save
Image.fromarray(im).save('result.png')

enter image description here

Original Answer

As your question mentions "or other way", I thought I'd make a PNG image from your data:

#!/usr/bin/env python3

import re
import numpy as np
from PIL import Image

# Open file with rather pesky parentheses, carriage returns and linefeeds
with open('out.txt', 'r') as f:
    c = f.read()

# Find all things that look like numbers and make into Numnpy array of 2 columns
points = np.array(re.findall('\d+',c), dtype=np.int).reshape(-1,2)

# Find height and width of "image", i.e. maximum x and y
w, h = np.max(points, axis=0)
print(f'Width: {w}, height: {h}')

# Make empty (black) image right size
im = np.zeros((h,w), dtype=np.uint8)

# Fill in white points
im[points[...,1]-1,points[...,0]-1] = 255

# Make into "PIL Image" and save
Image.fromarray(im).save('result.png')

Note that the code is twice as long as it needs to be as a result of all the unnecessary parentheses and Windows-y CR+LF at the line ends (Carriage Return and Linefeeds) in your input file.

enter image description here

Note that I scaled the image vertically because characters in a Terminal are generally taller than they are wide - unlike bitmapped images where pixels are square.

Related