Grid for artists is a project that seeks to satisfy the needs of both novice and new artists who are looking for a grid guide to facilitate the drawing process.
What the program does is to take an image and the dimensions of your painting canvas and then generate the necessary grids to make a perfect drawing, it will give you the margins and the size that the squares should have.
Grid for artists was designed in MecSimCalc, which facilitates both the input of the necessary information (images, options, text) and the handling of the data, which generates outputs that are understandable to any audience, as well as a user-friendly interface.
First, you must enter an image in the section where it says upload the file. You can drag and drop or select.
Second, you must fill in the information related to your painting canvas, which consists of both the width and length of your painting canvas, but without leaving out the two universal measurements, the inch (American) and the centimeter (Latin American), keep in mind that you can only enter integer values, which will affect the accuracy of the calculations if you do not choose an indicated measurement.
Third, choose the amount of horizontal squares that the grid will have, this is a small standard that makes it universal to choose the aspect of the grid, keep in mind that as you make more squares, your drawing will be more precise, BUT YOU WILL BECOME A PERSON DEPENDENT ON THE GRIDS, it is recommended to vary the amount of squares.
The output consists of three parts, first you will get the image with the grid already designed, an Embed part and another part to save it in your device, second you will get a pre-visualization of the grid that your painting canvas should have, as well as a link to download and third you will have the instructions to build the grid inside your painting canvas.
And now... TO PAINT
The implemented code is simple, we will only consider images and draw on them, the first image is the one to which the grid will be created, the second is a canvas generated with Pillow, which will simulate the canvas that the artist has in his house or workplace.
def main(inputs): [meta, data] = inputs['file'].split(";base64,") . . . # Decode the file data file_data = io.BytesIO(base64.b64decode(data)) # Convert the file data into a Pillow's Image img = Image.open(file_data) # Manipulate the image img = create_grid(img, amount) # Creating canvas canvas = Image.new(mode="L", size=(width, height), color=255) canvas_w, canvas_h, square, canvas = create_grid(canvas, amount, True) . . .
On the other hand, the program is based on a function, which is perfectly documented in the code, this function will be in charge of creating the grid, the basis and foundation of the program.
def create_grid(image, amount, canvas=False): image = image rotate = False if image.width > image.height: rotate = True image = image.transpose(Image.Transpose.ROTATE_90) image_aspect = image.width / image.height # Calculate the width and height times of cubes times_width = amount image_cube = int(image.width / times_width) times_height = int(image.height / image_cube) # Compare margin (ONLY CANVAS MODE) if canvas: # Pre charge margin image_width = (image.width - (image_cube * times_width)) / 2 image_height = (image.height - (times_height * image_cube)) / 2 if image_height < 50 or image_width < 50: image_cube -= 50 # Calculate the margin image_width = (image.width - (image_cube * times_width)) / 2 image_height = (image.height - (times_height * image_cube)) / 2 # Draw some lines draw = ImageDraw.Draw(image) y_start = image_height y_end = y_start + (image_cube * times_height) x_start = image_width x_end = x_start + (image_cube * times_width) for ix in range(0, times_height + 1): static_y = image_height + (image_cube * ix) line = ((x_start, static_y), (x_end, static_y)) draw.line(line, fill=128, width=int(5 * image_aspect)) for iy in range(0, times_width + 1): static_x = image_width + (image_cube * iy) line = ((static_x, y_start), (static_x, y_end)) draw.line(line, fill=128, width=int(5 * image_aspect)) del draw if rotate: image = image.transpose(Image.Transpose.ROTATE_270) if canvas: return x_start, y_start, image_cube, image return image
This is the basis and foundation of the program, it is simple, but it fulfills the mission, which is to create a grid.
First we will check if it is centimeters or inches, if it is inches we will do a conversion, since the program is based on centimeters, but note that we are always multiplying by 100 and returning integers, this because in order to create the canvas we need integers, so by multiplying it by 100 we are decreasing the loss of accuracy (also because, unless you use a super rare canvas developed by yourself, the program will always work exactly).
if option == "Inches": width = int(round(width * 2.54, 0)) height = int(round(height * 2.54, 0)) . . . if option == "Inches": margin_lr, margin_tb, square_in = round(canvas_w / 2.54, 2), round(canvas_h / 2.54, 2), round(square / 2.54, 2)
Second, what we do is to check where the canvas will start and where it will end, this has in between the amount of horizontal grids, which are the ones that are received as input, and then generate the amount of vertical ones.
# Calculate the width and height times of cubes times_width = amount image_cube = int(image.width / times_width) times_height = int(image.height / image_cube) # Compare margin (ONLY CANVAS MODE) if canvas: # Pre charge margin image_width = (image.width - (image_cube * times_width)) / 2 image_height = (image.height - (times_height * image_cube)) / 2 if image_height < 50 or image_width < 50: image_cube -= 50 # Calculate the margin image_width = (image.width - (image_cube * times_width)) / 2 image_height = (image.height - (times_height * image_cube)) / 2
Third, from the number of grids to generate and the margin from which it will generate, then we start to cycle through each of the lines to be drawn on our canvas.
# Draw some lines draw = ImageDraw.Draw(image) y_start = image_height y_end = y_start + (image_cube * times_height) x_start = image_width x_end = x_start + (image_cube * times_width) for ix in range(0, times_height + 1): static_y = image_height + (image_cube * ix) line = ((x_start, static_y), (x_end, static_y)) draw.line(line, fill=128, width=int(5 * image_aspect)) for iy in range(0, times_width + 1): static_x = image_width + (image_cube * iy) line = ((static_x, y_start), (static_x, y_end)) draw.line(line, fill=128, width=int(5 * image_aspect))
Also note that in case there is more height than width, what we will do is to rotate in order not to lose consistency in the program.
. . . rotate = False if image.width > image.height: rotate = True image = image.transpose(Image.Transpose.ROTATE_90) . . . if rotate: image = image.transpose(Image.Transpose.ROTATE_270)
On the other hand, we also have functions to generate HTML output.
def Image_File(data, extension, filename): return "Download Image" def Image_Embed(data): return ""
Copyright © MecSimCalc 2024
Terms | Privacy