From 4a1356046a61b06e516080503f8f2787a8e4bdf3 Mon Sep 17 00:00:00 2001 From: Ilya Razmanov Date: Thu, 18 Apr 2024 14:51:37 +0300 Subject: [PATCH] 2.8.1 self-calling functions --- README.RU.md | 26 +++- README.md | 20 ++- bsk.ico | Bin 72566 -> 0 bytes g.ico | Bin 72566 -> 0 bytes geo.ico | Bin 72566 -> 0 bytes img2mesh-OBJ.py | 226 ---------------------------- img2mesh-POV.py | 308 -------------------------------------- img2mesh-STL.py | 358 --------------------------------------------- img2mesh.py | 101 +++++++++++++ img2obj.py | 249 +++++++++++++++++++++++++++++++ img2pov.py | 359 +++++++++++++++++++++++++++++++++++++++++++++ img2stl.py | 382 ++++++++++++++++++++++++++++++++++++++++++++++++ vaba.ico | Bin 0 -> 72566 bytes 13 files changed, 1126 insertions(+), 903 deletions(-) delete mode 100644 bsk.ico delete mode 100644 g.ico delete mode 100644 geo.ico delete mode 100644 img2mesh-OBJ.py delete mode 100644 img2mesh-POV.py delete mode 100644 img2mesh-STL.py create mode 100644 img2mesh.py create mode 100644 img2obj.py create mode 100644 img2pov.py create mode 100644 img2stl.py create mode 100644 vaba.ico diff --git a/README.RU.md b/README.RU.md index 422523b..851d8e7 100644 --- a/README.RU.md +++ b/README.RU.md @@ -2,23 +2,35 @@ # Конвертер из растровых картинок в 3D-сетку треугольников -Программа на Python для трассировки карты высот в графическом формате ([PNG](http://www.libpng.org/pub/png/)) в трёхмерную векторную сетку треугольников (triangle meash) в формате [POVRay](https://www.povray.org/). Координаты x, y пикселя соответствуют координатам x, y узлов сетки, яркость пикселя соответствует высоте (z) узла сетки. В случае исходных графических файлов с низким разрешением полученная при трассировке 3D-сетка обеспечивает лучшее визуальное качество рендеринга, нежели исходные графические файлы при их использовании в качестве heightfield напрямую. +Программа на Python для трассировки карты высот в графическом формате ([PNG](http://www.libpng.org/pub/png/)) в трёхмерную векторную сетку треугольников (triangle meash) в форматах [POVRay](https://www.povray.org/) POV, Wavefront OBJ, а также STL для 3D-принтеров. Координаты x, y пикселя соответствуют координатам x, y узлов сетки, яркость пикселя соответствует высоте (z) узла сетки. В случае исходных графических файлов с низким разрешением полученная при трассировке 3D-сетка обеспечивает лучшее визуальное качество рендеринга, нежели исходные графические файлы при их использовании в качестве heightfield напрямую. ![Example of img2mesh output rendering](https://dnyarri.github.io/imgmesh/640/img2mesh.png) -В данной директории находится наиболее свежая версия программы; несколько более старых закопаны в *"old_versions"* для археологов будущего. +Содержимое: + +- **img2mesh** - удобный GUI, импортирующий все функции из программ ниже. + +- **img2pov** - конвертер PNG в POVRay scene. Полученная сцена содержит 3D-сетку, объект box (CSG intersection), создающий боковые стенки и дно, свет и камеру. Текстуры заявлены в declare отдельно для удобства редактирования. + +- **img2obj** - конвертер PNG в Wavefront OBJ. Экспортированный файл содержит только 3D-сетку. -**Update:** В рамках крупного обновления, помимо полной переделки экспорта в POVRay, также добавлены экспорт в Wavefront OBJ и STL для 3D-принтеров. +- **img2stl** - конвертер PNG в STL. Экспортированный файл содержит 3D-сетку и боковые и нижнюю поверхности в виде сетки, поскольку они необходимы 3D-принтеру. + +Следует заметить, что img2pov, img2obj и img2stl могут как работать самостоятельно по отдельности, так и быть удобно импортированы во внешнюю программу (как это сделано в img2mesh). + +![Preview of img2mesh output files in one folder](https://dnyarri.github.io/imgmesh/printscreen.png) + +В данной директории находится наиболее свежая версия программы; несколько более старых закопаны в *"old_versions"* для археологов будущего. -*Зависимости от внешних библиотек:* [PyPNG](https://gitlab.com/drj11/pypng), Tkinter. Первая лежит рядом с программой в репозитории, и, слава Создателю, способна работать в таком виде без установки; вторая входит во все типовые дистрибутивы Python. +*Зависимости от внешних библиотек:* [PyPNG](https://gitlab.com/drj11/pypng), Tkinter. Первая лежит рядом с программой в репозитории, и, слава cоздателю, способна работать в таком виде без установки; вторая входит во все типовые дистрибутивы Python. -*Инструкция по эксплуатации:* программы оборудованы минималистическим GUI, в результате всё, что вы должны сделать после запуска программы, это с помощью окна "Open..." выбрать и открыть файл PNG, с помощью окна "Save..." выбрать POV-файл для сохранения, подождать, пока программа отработает и закроется, затем открыть полученный POV-файл в POVRay и нажать кнопочку "Render". Экспортированная сцена содержит необходимый минимум глобальных переменных и объектов (камера, свет) для ознакомительного рендеринга без редактирования. Текстуры объекта и параметры камеры и т.п. записаны в максимально общем виде с комментариями, и должны быть просты для понимания и редактирования. +*Инструкция по эксплуатации:* программы оборудованы минималистическим GUI, в результате всё, что вы должны сделать после запуска программы, это с помощью окна "Open..." выбрать и открыть файл PNG, с помощью окна "Save..." выбрать файл для сохранения, подождать, пока программа отработает и закроется, затем открыть полученный файл в подходящей программе. Прочие программы: -[Dnyarri website](https://dnyarri.github.io/) +[Вебсайт Жабы Огромной Умственной Силы](https://dnyarri.github.io/) -Во избежание санкций проект зеркалится: +Во избежание перебоев проект зеркалится: [github Dnyarri](https://github.com/Dnyarri/img2mesh) diff --git a/README.md b/README.md index 4ce5fe4..77e3a5d 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,29 @@ # Bitmap to POVRay 3D triangle mesh converter -Python program for conversion of bitmap heightfield (in [PNG format](http://www.libpng.org/pub/png/)) to 3D triangle mesh in [POVRay](https://www.povray.org/) format. Resulting triangle mesh provides better rendering in case of low-res source files as compared to using source bitmaps as a heightfield directly. +Python program for conversion of bitmap heightfield (in [PNG format](http://www.libpng.org/pub/png/)) to 3D triangle mesh in [POVRay](https://www.povray.org/) POV, Wavefront OBJ and stereolithography (3D printer) STL format. Resulting triangle mesh provides better rendering in case of low-res source files as compared to using source bitmaps as a heightfield directly. ![Example of img2mesh output rendering](https://dnyarri.github.io/imgmesh/640/img2mesh.png) -Current dir contain most recent version of img2mesh program. Some previous versions are saved in *"old_versions"* for future alien archeologist to dig. +Project content: + +- **img2mesh** - suitable GUI frontend linked to all programs below. + +- **img2pov** - PNG to POVRay scene converter. Exported scene contains 3D mesh, bounding box (CSG intersection) to make it solid object with interior, camera and light. Textures are declared separately and easy to edit. + +- **img2obj** - PNG to Wavefront OBJ converter. Exported file contains 3D mesh only. -**Update:** As a part of major update, beside complete rewriting of POVRay export, Wavefront OBJ and stereolithography STL (for 3D-printing) exports were also added. +- **img2stl** - PNG to STL converter. Exported file contain 3D mesh with side and bottom meshes necessary for 3D printer software. + +Note that img2pov, img2obj and img2stl may be both run as standalone programs and be imported into some other software (currently in main img2mesh). + +![Preview of img2mesh output files in one folder](https://dnyarri.github.io/imgmesh/printscreen.png) + +Current dir contain most recent version of img2mesh program. Some previous versions are saved in *"old_versions"* for future alien archeologist to dig. *Dependencies:* [PyPNG](https://gitlab.com/drj11/pypng), Tkinter. The former is placed in this repo and, thank the Maker, will work right after downloading; the latter included in all typical Python installation. -*Usage:* program equipped with minimal GUI, so all you have to do after starting the program is use standard "Open..." GUI to open image file, then use standard "Save..." GUI to set POVRay scene file to be created, then wait while program does the job, then open resulting POV file with POVRay and render the scene. Scene contains enough basic stuff (globals, light, camera) to be rendered successfully right after exporting without any editing. +*Usage:* programs are equipped with minimal GUI, so all you have to do after starting the program is use standard "Open..." dialog to open image file, then use standard "Save..." to name exported file to be created, then wait while program does the job, then open resulting file with suitable software and render the scene. More software at: diff --git a/bsk.ico b/bsk.ico deleted file mode 100644 index 88b96f117ecc48bd615bea4a33b2a8555b55eb78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72566 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 diff --git a/geo.ico b/geo.ico deleted file mode 100644 index 0eca9f2e69933ad079b8875774ae97baf8eaa719..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72566 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 CGbP{v diff --git a/img2mesh-OBJ.py b/img2mesh-OBJ.py deleted file mode 100644 index cd39849..0000000 --- a/img2mesh-OBJ.py +++ /dev/null @@ -1,226 +0,0 @@ -#!/usr/bin/env python - -''' -IMG2MESH OBJ - Program for conversion of image heightfield to triangle mesh in OBJ format ------------------------------------------------------------------------------------------ - -Created by: Ilya Razmanov (mailto:ilyarazmanov@gmail.com) - aka Ilyich the Toad (mailto:amphisoft@gmail.com) -History: -1.0.0.0 Initial production release - - Main site: - https://dnyarri.github.io - - Project mirrored at: - https://github.com/Dnyarri/img2mesh - https://gitflic.ru/project/dnyarri/img2mesh - -''' - -__author__ = "Ilya Razmanov" -__copyright__ = "(c) 2024 Ilya Razmanov" -__credits__ = "Ilya Razmanov" -__license__ = "unlicense" -__version__ = "1.0.0.0" -__maintainer__ = "Ilya Razmanov" -__email__ = "ilyarazmanov@gmail.com" -__status__ = "Production" - -from tkinter import Tk -from tkinter import Label -from tkinter import filedialog - -from pathlib import Path - -from png import Reader # I/O with PyPNG from: https://gitlab.com/drj11/pypng - -# -------------------------------------------------------------- -# Creating dialog - -iconpath = Path(__file__).resolve().parent / 'g.ico' -iconname = str(iconpath) -useicon = iconpath.exists() # Check if icon file really exist. If False, it will not be used later. - -sortir = Tk() -sortir.title('PNG to OBJ conversion') -if useicon: - sortir.iconbitmap(iconname) # Replacement for simple sortir.iconbitmap('name.ico') - ugly but stable. -sortir.geometry('+200+100') -zanyato = Label(sortir, text='Allons-y!', font=("arial", 14), padx=16, pady=10, justify='center') -zanyato.pack() -sortir.withdraw() - -# Main dialog created and hidden -# -------------------------------------------------------------- - -# -------------------------------------------------------------- -# Open source image -sourcefilename = filedialog.askopenfilename( - title='Open source PNG file', filetypes=[('PNG', '.png')], defaultextension=('PNG', '.png') -) -if sourcefilename == '': - quit() - -source = Reader(filename=sourcefilename) # starting PyPNG - -X, Y, pixels, info = source.asDirect() # Opening image, iDAT comes to "pixels" as bytearray, to be tuple'd later - -Z = info['planes'] # Maximum CHANNEL NUMBER -imagedata = tuple((pixels)) # Attempt to fix all bytearrays into something solid - -if info['bitdepth'] == 8: - maxcolors = 255 # Maximal value for 8-bit channel -if info['bitdepth'] == 16: - maxcolors = 65535 # Maximal value for 16-bit channel - -# Open export file -resultfile = filedialog.asksaveasfile( - mode='w', - title='Save Wavefront OBJ file', - filetypes=[ - ('Wavefront OBJ file', '*.obj'), - ('All Files', '*.*'), - ], - defaultextension=('Wavefront OBJ file', '.obj'), -) -if resultfile == '': - quit() -# Both files opened -# -------------------------------------------------------------- - -# -------------------------------------------------------------- -# Functions block: -# -# src a-la FM style src(x,y,z) -# Image should be opened as "imagedata" by main program before -# Note that X, Y, Z are not determined in function, you have to determine it in main program - - -def src(x, y, z): - ''' - Analog of src from FilterMeister, force repeat edge instead of out of range - ''' - cx = x - cy = y - cx = max(0, cx) - cx = min((X - 1), cx) - cy = max(0, cy) - cy = min((Y - 1), cy) - - position = (cx * Z) + z # Here is the main magic of turning two x, z into one array position - channelvalue = int(((imagedata[cy])[position])) - - return channelvalue - - -# end of src function - - -def srcY(x, y): - ''' - Converting to greyscale, returns Yntensity, force repeat edge instead of out of range - ''' - cx = x - cy = y - cx = max(0, cx) - cx = min((X - 1), cx) - cy = max(0, cy) - cy = min((Y - 1), cy) - - if info['planes'] < 3: # supposedly L and LA - Yntensity = src(x, y, 0) - else: # supposedly RGB and RGBA - Yntensity = int(0.2989 * src(x, y, 0) + 0.587 * src(x, y, 1) + 0.114 * src(x, y, 2)) - - return Yntensity - - -# end of srcY function -# -# end of Functions block -# -------------------------------------------------------------- - -# Global positioning and scaling to tweak. - -xOffset = -0.5*float(X-1) # To be added BEFORE rescaling to center object. -yOffset = -0.5*float(Y-1) # To be added BEFORE rescaling to center object -zOffset = 0.0 - -xRescale = 1.0 / float(max(X, Y)) # To fit object into 1,1,1 cube -yRescale = xRescale -zRescale = 1.0 / float(maxcolors) - -# WRITING OBJ FILE, finally - -resultfile.write('o pryanik_nepechatnyj\n') # opening object - -# Now going to cycle through image and build mesh - -for y in range(0, Y, 1): - - message = 'Processing row ' + str(y) + ' of ' + str(Y) + '...' - sortir.deiconify() - zanyato.config(text=message) - sortir.update() - sortir.update_idletasks() - - for x in range(0, X, 1): - - # Since I was unable to find clear declaration of coordinate system, I'll plug a coordinate switch here - - # Reading switch: - xRead = x - yRead = (Y - 1 - y) # 'yRead = Y - y' coordinate mirror to mimic Photoshop coordinate system; +/- 1 steps below are inverted correspondingly vs. original img2mesh - - # Remains of Writing switch. No longer used since v. 0.1.0.2 but var names remained so dummy plug must be here. - xWrite = x - yWrite = y - - v9 = srcY(xRead, yRead) # Current pixel to process and write. Then going to neighbours - v1 = 0.25 * (v9 + srcY((xRead - 1), yRead) + srcY((xRead - 1), (yRead + 1)) + srcY(xRead, (yRead + 1))) - v3 = 0.25 * (v9 + srcY(xRead, (yRead + 1)) + srcY((xRead + 1), (yRead + 1)) + srcY((xRead + 1), yRead)) - v5 = 0.25 * (v9 + srcY((xRead + 1), yRead) + srcY((xRead + 1), (yRead - 1)) + srcY(xRead, (yRead - 1))) - v7 = 0.25 * (v9 + srcY(xRead, (yRead - 1)) + srcY((xRead - 1), (yRead - 1)) + srcY((xRead - 1), yRead)) - - # finally going to pyramid building - - # top part begins - resultfile.writelines( - [ - f'v {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', - f'v {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', - f'v {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', - 'f -3 -2 -1\n', # triangle 2 - - f'v {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', - f'v {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', - f'v {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', - 'f -3 -2 -1\n', # triangle 4 - - f'v {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', - f'v {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', - f'v {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', - f'f -3 -2 -1\n', # triangle 6 - - f'v {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', - f'v {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', - f'v {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', - f'f -3 -2 -1\n', # triangle 8 - ] - ) - # top part ends - -resultfile.write('# end pryanik_nepechatnyj') # closing object - -# Close output -resultfile.close() - -# -------------------------------------------------------------- -# Destroying dialog - -sortir.destroy() -sortir.mainloop() - -# Dialog destroyed and closed -# -------------------------------------------------------------- diff --git a/img2mesh-POV.py b/img2mesh-POV.py deleted file mode 100644 index dfeba79..0000000 --- a/img2mesh-POV.py +++ /dev/null @@ -1,308 +0,0 @@ -#!/usr/bin/env python - -''' -IMG2MESH-POV - Program for conversion of image heightfield to triangle mesh in POVRay format ---------------------------------------------------------------------------------------------- - -Created by: Ilya Razmanov (mailto:ilyarazmanov@gmail.com) - aka Ilyich the Toad (mailto:amphisoft@gmail.com) -History: -001 Abandoned img2mesh v.1 and turned to img2mesh v.2 with completely different mesh structure. -005 Replaced Pillow I/O with PyPNG from: https://gitlab.com/drj11/pypng - Support for 16 bit/channel PNGs added. Added mesh encapsulation with cubic box - to provide solid walls and bottom. Restructured output for easy reading. - Extended POVRay camera description. -007 Output cleanup and generalization. GUI improved to show progress during long processing. - Reducing unnecessary import. -2.7.1.0 Significant code cleanup with .writelines. Versioning more clear. -2.8.0.0 Total rewrite to remove all transforms from POVRay. - - Main site: - https://dnyarri.github.io - - Project mirrored at: - https://github.com/Dnyarri/img2mesh - https://gitflic.ru/project/dnyarri/img2mesh - -''' - -__author__ = "Ilya Razmanov" -__copyright__ = "(c) 2023-2024 Ilya Razmanov" -__credits__ = "Ilya Razmanov" -__license__ = "unlicense" -__version__ = "2.8.0.0" -__maintainer__ = "Ilya Razmanov" -__email__ = "ilyarazmanov@gmail.com" -__status__ = "Production" - -from tkinter import Tk -from tkinter import Label -from tkinter import filedialog - -from time import time -from time import ctime - -from pathlib import Path - -from png import Reader # I/O with PyPNG from: https://gitlab.com/drj11/pypng - -# -------------------------------------------------------------- -# Creating dialog - -iconpath = Path(__file__).resolve().parent / 'bsk.ico' -iconname = str(iconpath) -useicon = iconpath.exists() # Check if icon file really exist. If False, it will not be used later. - -sortir = Tk() -sortir.title('PNG to POV conversion') -if useicon: - sortir.iconbitmap(iconname) # Replacement for simple sortir.iconbitmap('name.ico') - ugly but stable. -sortir.geometry('+200+100') -zanyato = Label(sortir, text = 'Starting...', font=("arial", 14), padx=16, pady=10, justify='center') -zanyato.pack() -sortir.withdraw() - -# Main dialog created and hidden -# -------------------------------------------------------------- - -# Open source image -sourcefilename = filedialog.askopenfilename(title='Open source PNG file', filetypes=[('PNG','.png')], defaultextension = ('PNG','.png')) -if (sourcefilename == ''): - quit() - -source = Reader(filename = sourcefilename) # starting PyPNG - -X,Y,pixels,info = source.asDirect() # Opening image, iDAT comes to "pixels" as bytearray, to be tuple'd later - -Z = (info['planes']) # Maximum CHANNEL NUMBER -imagedata = tuple((pixels)) # Attempt to fix all bytearrays - -if (info['bitdepth'] == 8): - maxcolors = 255 # Maximal value for 8-bit channel -if (info['bitdepth'] == 16): - maxcolors = 65535 # Maximal value for 16-bit channel - -# Open export file -resultfile = filedialog.asksaveasfile(mode='w', title='Save resulting POV file', filetypes = - [ - ('POV-Ray scene file', '*.pov'), - ('All Files', '*.*'), - ], - defaultextension = ('POV-Ray scene file','.pov')) -if (resultfile == ''): - quit() -# Both files opened - -# src a-la FM style src(x,y,z) -# Image should be opened as "imagedata" by main program before -# Note that X, Y, Z are not determined in function, you have to determine it in main program - -def src(x, y, z): - ''' - Analog src from FM, force repeat edge instead of out of range - ''' - cx = x; cy = y - cx = max(0,cx); cx = min((X-1),cx) - cy = max(0,cy); cy = min((Y-1),cy) - - position = (cx*Z) + z # Here is the main magic of turning two x, z into one array position - channelvalue = int(((imagedata[cy])[position])) - - return channelvalue -# end of src function - -def srcY(x, y): - ''' - Converting to greyscale, returns Yntensity, force repeat edge instead of out of range - ''' - cx = x; cy = y - cx = max(0,cx); cx = min((X-1),cx) - cy = max(0,cy); cy = min((Y-1),cy) - - if (info['planes'] < 3): # supposedly L and LA - Yntensity = src(x, y, 0) - else: # supposedly RGB and RGBA - Yntensity = int(0.2989*src(x, y, 0) + 0.587*src(x, y, 1) + 0.114*src(x, y, 2)) - - return Yntensity -# end of srcY function - -# WRITING POV FILE - -# ------------ -# POV header -# ------------ - -resultfile.writelines( - [ - '/*\n', - 'Persistence of Vision Ray Tracer Scene Description File\n', - 'Version: 3.7\n', - 'Description: A triangle mesh scene file converted from image heightfield\n', - 'Author: Automatically generated by img2mesh program\n', - ' https://github.com/Dnyarri/img2mesh\n', - ' https://gitflic.ru/project/dnyarri/img2mesh\n', - 'developed by Ilya Razmanov aka Ilyich the Toad\n', - ' https://dnyarri.github.io/\n', - ' mailto:ilyarazmanov@gmail.com\n', - '*/\n\n', - ] -) - -resultfile.write(f'// Converted from: {sourcefilename} ') -seconds = time() -localtime = ctime(seconds) -resultfile.write(f'at: {localtime}\n// Source info: {info}\n\n') - -# Statements - -resultfile.writelines( - [ - '\n', - '#version 3.7;\n\n', - 'global_settings{\n', - ' max_trace_level 3 // Set low to speed up rendering. May need to be increased for metals and glasses\n', - ' adc_bailout 0.01 // Set high to speed up rendering. May need to be decreased to 1/256 for better quality\n', - ' ambient_light <0.5,0.5,0.5>\n', - ' assumed_gamma 1.0\n}\n\n', - - '#include "colors.inc"\n', - '#include "finish.inc"\n', - '#include "metals.inc"\n', - '#include "golds.inc"\n\n', - - '#declare thethingtexturebottom =\n', - ' texture {\n', - ' pigment {\n', - ' gradient z\n', - ' colour_map {\n', - ' [0, Red]\n', - ' [0.5 Blue]\n', - ' [1, White]\n', - ' }\n', - ' }\n', - ' }\n', - - '#declare thethingtexturetop =\n', - ' texture {\n', - ' pigment {\n', - ' gradient z\n', - ' colour_map {\n', - ' [0.00, rgbt <0,0,0,1>]\n', - ' [0.48, rgbt <0,0,0,1>]\n', - ' [0.50, rgbt <0,0,0,0>]\n', - ' [0.52, rgbt <0,0,0,1>]\n', - ' [1.00, rgbt <0,0,0,1>]\n', - ' }\n', - ' }\n', - ' scale 0.2\n', - ' }\n', - ] -) - -# Mesh - -# Global positioning and scaling to tweak. - -xOffset = -0.5*float(X-1) # To be added BEFORE rescaling to center object. -yOffset = -0.5*float(Y-1) # To be added BEFORE rescaling to center object -zOffset = 0.0 - -xRescale = 1.0 / float(max(X, Y)) # To fit object into 1,1,1 cube -yRescale = xRescale -zRescale = 1.0 / float(maxcolors) - - -resultfile.write('\n\n#declare thething = mesh {\n') # Opening mesh object "thething" - -# Now going to cycle through image and build mesh - -for y in range(0, Y, 1): - - message = ('Processing row ' + str(y) +' of ' + str(Y) + '...') - sortir.deiconify() - zanyato.config(text = message) - sortir.update() - sortir.update_idletasks() - - resultfile.write(f'\n\n // Row {y}\n') - - for x in range(0, X, 1): - - # Reading switch: - xRead = (X - 1 - x) - yRead = (Y - 1 - y) - - # Last remains of writing switch. No longer used but var names remained active so dummy plug must be here. - xWrite = x - yWrite = y - - v9 = srcY(xRead, yRead) # Current pixel to process and write. Then going to neighbours - v1 = 0.25 * (v9 + srcY((xRead + 1), yRead) + srcY((xRead + 1), (yRead + 1)) + srcY(xRead, (yRead + 1))) - v3 = 0.25 * (v9 + srcY(xRead, (yRead + 1)) + srcY((xRead - 1), (yRead + 1)) + srcY((xRead - 1), yRead)) - v5 = 0.25 * (v9 + srcY((xRead - 1), yRead) + srcY((xRead - 1), (yRead - 1)) + srcY(xRead, (yRead - 1))) - v7 = 0.25 * (v9 + srcY(xRead, (yRead - 1)) + srcY((xRead + 1), (yRead - 1)) + srcY((xRead + 1), yRead)) - - # finally going to pyramid building - - resultfile.write(f'\n triangle{{<{xRescale*(xWrite-0.5+xOffset)}, {yRescale*(yWrite-0.5+yOffset)}, {zRescale*v1}> <{xRescale*(xWrite+xOffset)}, {yRescale*(yWrite+yOffset)}, {zRescale*v9}> <{xRescale*(xWrite+0.5+xOffset)}, {yRescale*(yWrite-0.5+yOffset)}, {zRescale*v3}>}}') # Triangle 2 1-9-3 - - resultfile.write(f'\n triangle{{<{xRescale*(xWrite+0.5+xOffset)}, {yRescale*(yWrite-0.5+yOffset)}, {zRescale*v3}> <{xRescale*(xWrite+xOffset)}, {yRescale*(yWrite+yOffset)}, {zRescale*v9}> <{xRescale*(xWrite+0.5+xOffset)}, {yRescale*(yWrite+0.5+yOffset)}, {zRescale*v5}>}}') # Triangle 4 3-9-5 - - resultfile.write(f'\n triangle{{<{xRescale*(xWrite+0.5+xOffset)}, {yRescale*(yWrite+0.5+yOffset)}, {zRescale*v5}> <{xRescale*(xWrite+xOffset)}, {yRescale*(yWrite+yOffset)}, {zRescale*v9}> <{xRescale*(xWrite-0.5+xOffset)}, {yRescale*(yWrite+0.5+yOffset)}, {zRescale*v7}>}}') # Triangle 6 5-9-7 - - resultfile.write(f'\n triangle{{<{xRescale*(xWrite-0.5+xOffset)}, {yRescale*(yWrite+0.5+yOffset)}, {zRescale*v7}> <{xRescale*(xWrite+xOffset)}, {yRescale*(yWrite+yOffset)}, {zRescale*v9}> <{xRescale*(xWrite-0.5+xOffset)}, {yRescale*(yWrite-0.5+yOffset)}, {zRescale*v1}>}}') # Triangle 8 7-9-1 - - # completed pyramid. Ave me! - -resultfile.write('\n\n inside_vector <0, 0, 1>\n\n') - -# Sample texture of textures -resultfile.writelines( - [ - ' texture {thethingtexturebottom}\n', - ' texture {thethingtexturetop}\n', - '}\n// Closed thething\n\n', - '#declare boxedthing = object{\n', - ' intersection {\n', - ' box {<-0.5, -0.5, 0>, <0.5, 0.5, 1.0>\n', - ' pigment {rgb <0.5, 0.5, 5>}\n', - ' }\n', - ' thething\n', - ' }\n', - '}', - '// Constructed CGS "boxedthing" of mesh plus bounding box thus adding side walls and bottom\n\n', - 'object {boxedthing}\n\n', - ] -) # Closing solids - -# Camera -proportions = max(X,Y)/X -resultfile.writelines( - [ - '#declare camera_height = 3.0;\n\n', - 'camera{\n', - '// orthographic\n', - ' location <0.0, 0.0, camera_height>\n', - ' right x*image_width/image_height\n' - ' up y\n' - ' direction <0, 0, 1>\n', - f' angle 2.0*(degrees(atan2({0.5 * proportions}, camera_height-1.0))) // Supposed to fit object\n', - ' look_at <0.0, 0.0, 0.0>\n}\n\n', - ] -) - -# Light -resultfile.write('light_source {0*x\n color rgb <1.0, 1.0, 1.0>\n translate <20, 20, 20>\n}\n') -resultfile.write('\n/*\n\nhappy rendering\n\n 0~0\n (---)\n(.>|<.)\n-------\n\n*/') -# Close output -resultfile.close() - -# -------------------------------------------------------------- -# Destroying dialog - -sortir.destroy() -sortir.mainloop() - -# Dialog destroyed and closed -# -------------------------------------------------------------- diff --git a/img2mesh-STL.py b/img2mesh-STL.py deleted file mode 100644 index 2486fa7..0000000 --- a/img2mesh-STL.py +++ /dev/null @@ -1,358 +0,0 @@ -#!/usr/bin/env python - -''' -IMG2MESH STL - Program for conversion of image heightfield to triangle mesh in STL format ------------------------------------------------------------------------------------------ - -Created by: Ilya Razmanov (mailto:ilyarazmanov@gmail.com) - aka Ilyich the Toad (mailto:amphisoft@gmail.com) -History: -1.0.0.0 Initial production release - - Main site: - https://dnyarri.github.io - - Project mirrored at: - https://github.com/Dnyarri/img2mesh - https://gitflic.ru/project/dnyarri/img2mesh - -''' - -__author__ = "Ilya Razmanov" -__copyright__ = "(c) 2024 Ilya Razmanov" -__credits__ = "Ilya Razmanov" -__license__ = "unlicense" -__version__ = "1.0.0.0" -__maintainer__ = "Ilya Razmanov" -__email__ = "ilyarazmanov@gmail.com" -__status__ = "Production" - -from tkinter import Tk -from tkinter import Label -from tkinter import filedialog - -from pathlib import Path - -from png import Reader # I/O with PyPNG from: https://gitlab.com/drj11/pypng - -# -------------------------------------------------------------- -# Creating dialog - -iconpath = Path(__file__).resolve().parent / 'geo.ico' -iconname = str(iconpath) -useicon = iconpath.exists() # Check if icon file really exist. If False, it will not be used later. - -sortir = Tk() -sortir.title('PNG to STL conversion') -if useicon: - sortir.iconbitmap(iconname) # Replacement for simple sortir.iconbitmap('name.ico') - ugly but stable. -sortir.geometry('+200+100') -zanyato = Label(sortir, text='Allons-y!', font=("arial", 14), padx=16, pady=10, justify='center') -zanyato.pack() -sortir.withdraw() - -# Main dialog created and hidden -# -------------------------------------------------------------- - -# -------------------------------------------------------------- -# Open source image -sourcefilename = filedialog.askopenfilename( - title='Open source PNG file', filetypes=[('PNG', '.png')], defaultextension=('PNG', '.png') -) -if sourcefilename == '': - quit() - -source = Reader(filename=sourcefilename) # starting PyPNG - -X, Y, pixels, info = source.asDirect() # Opening image, iDAT comes to "pixels" as bytearray, to be tuple'd later - -Z = info['planes'] # Maximum CHANNEL NUMBER -imagedata = tuple((pixels)) # Attempt to fix all bytearrays into something solid - -if info['bitdepth'] == 8: - maxcolors = 255 # Maximal value for 8-bit channel -if info['bitdepth'] == 16: - maxcolors = 65535 # Maximal value for 16-bit channel - -# Open export file -resultfile = filedialog.asksaveasfile( - mode='w', - title='Save StereoLithography file', - filetypes=[ - ('StereoLithography object file', '*.stl'), - ('All Files', '*.*'), - ], - defaultextension=('StereoLithography object file', '.stl'), -) -if resultfile == '': - quit() -# Both files opened -# -------------------------------------------------------------- - -# -------------------------------------------------------------- -# Functions block: -# -# src a-la FM style src(x,y,z) -# Image should be opened as "imagedata" by main program before -# Note that X, Y, Z are not determined in function, you have to determine it in main program - - -def src(x, y, z): - ''' - Analog of src from FilterMeister, force repeat edge instead of out of range - ''' - cx = x - cy = y - cx = max(0, cx) - cx = min((X - 1), cx) - cy = max(0, cy) - cy = min((Y - 1), cy) - - position = (cx * Z) + z # Here is the main magic of turning two x, z into one array position - channelvalue = int(((imagedata[cy])[position])) - - return channelvalue - - -# end of src function - - -def srcY(x, y): - ''' - Converting to greyscale, returns Yntensity, force repeat edge instead of out of range - ''' - cx = x - cy = y - cx = max(0, cx) - cx = min((X - 1), cx) - cy = max(0, cy) - cy = min((Y - 1), cy) - - if info['planes'] < 3: # supposedly L and LA - Yntensity = src(x, y, 0) - else: # supposedly RGB and RGBA - Yntensity = int(0.2989 * src(x, y, 0) + 0.587 * src(x, y, 1) + 0.114 * src(x, y, 2)) - - return Yntensity - - -# end of srcY function -# -# end of Functions block -# -------------------------------------------------------------- - -# Global positioning and scaling to tweak. Offset supposed to make everyone feeling positive, rescale supposed to scale anything to [0..1.0] regardless of what the units are - -xOffset = 1.0 # To be added BEFORE rescaling to compensate 0.5 X expansion -yOffset = 1.0 # To be added BEFORE rescaling to compensate 0.5 Y expansion -zOffset = 0.0 # To be added AFTER rescaling just in case there should be something to fix - -xRescale = 1.0 / float(max(X, Y)) # To fit object into 1,1,1 cube -yRescale = xRescale -zRescale = 1.0 / float(maxcolors) - -# WRITING STL FILE, finally - -resultfile.write('solid pryanik_nepechatnyj\n') # opening object - -# Now going to cycle through image and build mesh - -for y in range(0, Y, 1): - - message = 'Processing row ' + str(y) + ' of ' + str(Y) + '...' - sortir.deiconify() - zanyato.config(text=message) - sortir.update() - sortir.update_idletasks() - - for x in range(0, X, 1): - - # Since I was unable to find clear declaration of coordinate system, I'll plug a coordinate switch here - - # Reading switch: - xRead = x - yRead = (Y - 1 - y) # 'yRead = Y - y' coordinate mirror to mimic Photoshop coordinate system; +/- 1 steps below are inverted correspondingly vs. original img2mesh - - # Remains of Writing switch. No longer used since v. 0.1.0.2 but var names remained so dummy plug must be here. - xWrite = x - yWrite = y - - v9 = srcY(xRead, yRead) # Current pixel to process and write. Then going to neighbours - v1 = 0.25 * (v9 + srcY((xRead - 1), yRead) + srcY((xRead - 1), (yRead + 1)) + srcY(xRead, (yRead + 1))) - v3 = 0.25 * (v9 + srcY(xRead, (yRead + 1)) + srcY((xRead + 1), (yRead + 1)) + srcY((xRead + 1), yRead)) - v5 = 0.25 * (v9 + srcY((xRead + 1), yRead) + srcY((xRead + 1), (yRead - 1)) + srcY(xRead, (yRead - 1))) - v7 = 0.25 * (v9 + srcY(xRead, (yRead - 1)) + srcY((xRead - 1), (yRead - 1)) + srcY((xRead - 1), yRead)) - - # finally going to pyramid building - - # top part begins - resultfile.writelines( - [ - ' facet normal 0 0 1\n', # triangle 2 normal up - ' outer loop\n', # 1 - 9 - 3 - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', - f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', - ' endloop\n', - ' endfacet\n', - ' facet normal 0 0 1\n', # triangle 4 normal up - ' outer loop\n', # 3 - 9 - 5 - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', - f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', - ' endloop\n', - ' endfacet\n', - ' facet normal 0 0 1\n', # triangle 6 normal up - ' outer loop\n', # 5 - 9 - 7 - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', - f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', - ' endloop\n', - ' endfacet\n', - ' facet normal 0 0 1\n', # triangle 8 normal up - ' outer loop\n', # 7 - 9 - 1 - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', - f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', - ' endloop\n', - ' endfacet\n', - ] - ) - # top part ends - - # left side begins - if x == 0: - resultfile.writelines( - [ - ' facet normal -1 0 0\n', # triangle 8- normal left - ' outer loop\n', # 1 - down1 - 7 - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', - ' endloop\n', - ' endfacet\n', - ' facet normal -1 0 0\n', # triangle 8- normal left - ' outer loop\n', # down1 - down7 - 7 - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', - ' endloop\n', - ' endfacet\n', - ] - ) - # left side ends - - # right side begins - if x == (X - 1): - resultfile.writelines( - [ - ' facet normal 1 0 0\n', # triangle 4+ normal left - ' outer loop\n', # 5 - down5 - 3 - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', - ' endloop\n', - ' endfacet\n', - ' facet normal 1 0 0\n', # triangle 4+ normal left - ' outer loop\n', # 3 - down5 - down3 - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', - ' endloop\n', - ' endfacet\n', - ] - ) - # right side ends - - # far side begins - if y == 0: - resultfile.writelines( - [ - ' facet normal 0 -1 0\n', # triangle 2- normal far - ' outer loop\n', # 3 - down - 1 - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', - ' endloop\n', - ' endfacet\n', - ' facet normal 0 -1 0\n', # triangle 2- normal far - ' outer loop\n', # down - down - 1 - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', - ' endloop\n', - ' endfacet\n', - ] - ) - # far side ends - - # close side begins - if y == (Y - 1): - resultfile.writelines( - [ - ' facet normal 0 1 0\n', # triangle 6+ normal close - ' outer loop\n', # 7 - down - 5 - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', - ' endloop\n', - ' endfacet\n', - ' facet normal 0 1 0\n', # triangle 6+ normal close - ' outer loop\n', # down - down - 5 - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', - ' endloop\n', - ' endfacet\n', - ] - ) - # close side ends - - # bottom part begins - resultfile.writelines( - [ - ' facet normal 0 0 -1\n', # triangle 2 normal up - ' outer loop\n', # 1 - 9 - 3 - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', - ' endloop\n', - ' endfacet\n', - ' facet normal 0 0 -1\n', # triangle 4 normal up - ' outer loop\n', # 3 - 9 - 5 - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', - ' endloop\n', - ' endfacet\n', - ' facet normal 0 0 -1\n', # triangle 6 normal up - ' outer loop\n', # 5 - 9 - 7 - f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', - ' endloop\n', - ' endfacet\n', - ' facet normal 0 0 -1\n', # triangle 8 normal up - ' outer loop\n', # 7 - 9 - 1 - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+0.0):e}\n', - f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', - ' endloop\n', - ' endfacet\n', - ] - ) - # bottom part ends - -resultfile.write('endsolid pryanik_nepechatnyj') # closing object - -# Close output -resultfile.close() - -# -------------------------------------------------------------- -# Destroying dialog - -sortir.destroy() -sortir.mainloop() - -# Dialog destroyed and closed -# -------------------------------------------------------------- diff --git a/img2mesh.py b/img2mesh.py new file mode 100644 index 0000000..212f46a --- /dev/null +++ b/img2mesh.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python +''' +IMG2MESH - Program for conversion of image heightfield to triangle mesh in different formats +--------------------------------------------------------------------------------------------- +Common GUI shell for img2pov, img2obj and img2stl modules. + +Created by: Ilya Razmanov (mailto:ilyarazmanov@gmail.com) + aka Ilyich the Toad (mailto:amphisoft@gmail.com) +History: + +1.0.0.0 Initial production release. + + Main site: + https://dnyarri.github.io + + Project mirrored at: + https://github.com/Dnyarri/img2mesh + https://gitflic.ru/project/dnyarri/img2mesh + +''' + +__author__ = "Ilya Razmanov" +__copyright__ = "(c) 2024 Ilya Razmanov" +__credits__ = "Ilya Razmanov" +__license__ = "unlicense" +__version__ = "1.0.0.0" +__maintainer__ = "Ilya Razmanov" +__email__ = "ilyarazmanov@gmail.com" +__status__ = "Production" + +from tkinter import Tk +from tkinter import Label, Button, TOP, BOTTOM, X + +from pathlib import Path + +from img2pov import img2pov +from img2obj import img2obj +from img2stl import img2stl + +# ACHTUNG! User break definition below. Take care. +DyeDye = False # Variable for breaking program anywhere upon conditions + + +def DisMiss(): # Kill dialog and continue + global DyeDye + DyeDye = False + stopper.destroy() + + +def DyeDyeMyDarling(): # Kill dialog and kill program + global DyeDye + DyeDye = True + stopper.destroy() + quit() + + +# -------------------------------------------------------------- +# Creating startup dialog (stopper) + +iconpath = Path(__file__).resolve().parent / 'vaba.ico' +iconname = str(iconpath) +useicon = iconpath.exists() # Check if icon file really exist. If False, it will not be used later. + +stopper = Tk() +stopper.title('IMG2MESH') +if useicon: + stopper.iconbitmap(iconname) +stopper.geometry('+200+100') +stopper.minsize(300, 300) +stopper.maxsize(400, 400) + +preved01 = Label(stopper, text = 'img2mesh', font=("arial", 36), padx=16, pady=10, justify='center') +preved01.pack(side=TOP, fill=X) + +preved02 = Label(stopper, text = 'PNG height fields to 3D mesh converter', font=("arial", 12), padx=16, pady=10, justify='center') +preved02.pack(side=TOP, fill=X) + +butt01 = Button(stopper, text='PNG to POV...', font=('arial', 16), cursor='hand2', justify='center', command=img2pov +) +butt01.pack(side=TOP, padx=4, pady=2, fill=X) + +butt02 = Button(stopper, text='PNG to OBJ...', font=('arial', 16), cursor='hand2', justify='center', command=img2obj +) +butt02.pack(side=TOP, padx=4, pady=2, fill=X) + +butt03 = Button(stopper, text='PNG to STL...', font=('arial', 16), cursor='hand2', justify='center', command=img2stl +) +butt03.pack(side=TOP, padx=4, pady=2, fill=X) + +butt04 = Button( + stopper, text='Exit', font=('arial', 16), cursor='hand2', justify='center', command=DyeDyeMyDarling +) +butt04.pack(side=BOTTOM, padx=4, pady=2, fill=X) + +stopper.mainloop() + +# Startup dialog created, used and killed +# -------------------------------------------------------------- + +if DyeDye: + quit() # Kill program if "Quit" was pressed in stopper diff --git a/img2obj.py b/img2obj.py new file mode 100644 index 0000000..343e39e --- /dev/null +++ b/img2obj.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python + +''' +IMG2OBJ - Program for conversion of image heightfield to triangle mesh in OBJ format +----------------------------------------------------------------------------------------- + +Created by: Ilya Razmanov (mailto:ilyarazmanov@gmail.com) + aka Ilyich the Toad (mailto:amphisoft@gmail.com) +History: +1.0.0.0 Initial production release. +1.0.1.0 Program converted into self-calling function to have a possibility to import it. + + Main site: + https://dnyarri.github.io + + Project mirrored at: + https://github.com/Dnyarri/img2mesh + https://gitflic.ru/project/dnyarri/img2mesh + +''' + +__author__ = "Ilya Razmanov" +__copyright__ = "(c) 2024 Ilya Razmanov" +__credits__ = "Ilya Razmanov" +__license__ = "unlicense" +__version__ = "1.0.1.0" +__maintainer__ = "Ilya Razmanov" +__email__ = "ilyarazmanov@gmail.com" +__status__ = "Production" + +from tkinter import Tk +from tkinter import Label +from tkinter import filedialog + +from pathlib import Path + +from png import Reader # I/O with PyPNG from: https://gitlab.com/drj11/pypng + +# ACHTUNG! Starting a whole-program procedure! + +def img2obj(): + ''' + Procedure for opening PNG heightfield and creating Wavefront .obj 3D mesh file from it. + + ''' + + # -------------------------------------------------------------- + # Creating dialog + + iconpath = Path(__file__).resolve().parent / 'vaba.ico' + iconname = str(iconpath) + useicon = iconpath.exists() # Check if icon file really exist. If False, it will not be used later. + + sortir = Tk() + sortir.title('PNG to OBJ conversion') + if useicon: + sortir.iconbitmap(iconname) # Replacement for simple sortir.iconbitmap('name.ico') - ugly but stable. + sortir.geometry('+200+100') + zanyato = Label(sortir, text='Allons-y!', font=("arial", 14), padx=16, pady=10, justify='center') + zanyato.pack() + sortir.withdraw() + + # Main dialog created and hidden + # -------------------------------------------------------------- + + + # Open source image + sourcefilename = filedialog.askopenfilename( + title='Open source PNG file', filetypes=[('PNG', '.png')], defaultextension=('PNG', '.png') + ) + # Source file name taken + + if (sourcefilename == '') or (sourcefilename == None): + return None + # break if user press 'Cancel' + + source = Reader(filename=sourcefilename) + # opening file with PyPNG + + X, Y, pixels, info = source.asDirect() + # Opening image, iDAT comes to "pixels" as bytearray, to be tuple'd later + + Z = info['planes'] # Maximum CHANNEL NUMBER + imagedata = tuple((pixels)) # Attempt to fix all bytearrays + + if info['bitdepth'] == 8: + maxcolors = 255 # Maximal value for 8-bit channel + if info['bitdepth'] == 16: + maxcolors = 65535 # Maximal value for 16-bit channel + + # source file opened, initial data received + + # opening result file, first get name + resultfilename = filedialog.asksaveasfilename( + title='Save Wavefront OBJ file', + filetypes=[ + ('Wavefront OBJ file', '*.obj'), + ('All Files', '*.*'), + ], + defaultextension=('Wavefront OBJ file', '.obj'), + ) + + if (resultfilename == '') or (sourcefilename == None): + return None + # break if user press 'Cancel' + # return doesn't seem to work well with .asksaveasfile + + resultfile = open(resultfilename, 'w') + # result file opened + + # Both files opened + + # -------------------------------------------------------------- + # Functions block: + # + # src a-la FM style src(x,y,z) + # Image should be opened as "imagedata" by main program before + # Note that X, Y, Z are not determined in function, you have to determine it in main program + + def src(x, y, z): + ''' + Analog of src from FilterMeister, force repeat edge instead of out of range + ''' + cx = x + cy = y + cx = max(0, cx) + cx = min((X - 1), cx) + cy = max(0, cy) + cy = min((Y - 1), cy) + + position = (cx * Z) + z # Here is the main magic of turning two x, z into one array position + channelvalue = int(((imagedata[cy])[position])) + + return channelvalue + + + # end of src function + + + def srcY(x, y): + ''' + Converting to greyscale, returns Yntensity, force repeat edge instead of out of range + ''' + cx = x + cy = y + cx = max(0, cx) + cx = min((X - 1), cx) + cy = max(0, cy) + cy = min((Y - 1), cy) + + if info['planes'] < 3: # supposedly L and LA + Yntensity = src(x, y, 0) + else: # supposedly RGB and RGBA + Yntensity = int(0.2989 * src(x, y, 0) + 0.587 * src(x, y, 1) + 0.114 * src(x, y, 2)) + + return Yntensity + + # end of srcY function + + # end of Functions block + # -------------------------------------------------------------- + + # Global positioning and scaling to tweak. + + xOffset = -0.5*float(X-1) # To be added BEFORE rescaling to center object. + yOffset = -0.5*float(Y-1) # To be added BEFORE rescaling to center object + zOffset = 0.0 + + xRescale = 1.0 / float(max(X, Y)) # To fit object into 1,1,1 cube + yRescale = xRescale + zRescale = 1.0 / float(maxcolors) + + # WRITING OBJ FILE, finally + + resultfile.write('o pryanik_nepechatnyj\n') # opening object + + # Now going to cycle through image and build mesh + + for y in range(0, Y, 1): + + message = 'Processing row ' + str(y) + ' of ' + str(Y) + '...' + sortir.deiconify() + zanyato.config(text=message) + sortir.update() + sortir.update_idletasks() + + for x in range(0, X, 1): + + # Since I was unable to find clear declaration of coordinate system, I'll plug a coordinate switch here + + # Reading switch: + xRead = x + yRead = (Y - 1 - y) # 'yRead = Y - y' coordinate mirror to mimic Photoshop coordinate system; +/- 1 steps below are inverted correspondingly vs. original img2mesh + + # Remains of Writing switch. No longer used since v. 0.1.0.2 but var names remained so dummy plug must be here. + xWrite = x + yWrite = y + + v9 = srcY(xRead, yRead) # Current pixel to process and write. Then going to neighbours + v1 = 0.25 * (v9 + srcY((xRead - 1), yRead) + srcY((xRead - 1), (yRead + 1)) + srcY(xRead, (yRead + 1))) + v3 = 0.25 * (v9 + srcY(xRead, (yRead + 1)) + srcY((xRead + 1), (yRead + 1)) + srcY((xRead + 1), yRead)) + v5 = 0.25 * (v9 + srcY((xRead + 1), yRead) + srcY((xRead + 1), (yRead - 1)) + srcY(xRead, (yRead - 1))) + v7 = 0.25 * (v9 + srcY(xRead, (yRead - 1)) + srcY((xRead - 1), (yRead - 1)) + srcY((xRead - 1), yRead)) + + # finally going to pyramid building + + # top part begins + resultfile.writelines( + [ + f'v {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', + f'v {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', + f'v {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', + 'f -3 -2 -1\n', # triangle 2 + + f'v {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', + f'v {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', + f'v {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', + 'f -3 -2 -1\n', # triangle 4 + + f'v {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', + f'v {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', + f'v {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', + f'f -3 -2 -1\n', # triangle 6 + + f'v {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', + f'v {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', + f'v {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', + f'f -3 -2 -1\n', # triangle 8 + ] + ) + # top part ends + + resultfile.write('# end pryanik_nepechatnyj') # closing object + + # Close output + resultfile.close() + + # -------------------------------------------------------------- + # Destroying dialog + + sortir.destroy() + sortir.mainloop() + + # Dialog destroyed and closed + # -------------------------------------------------------------- + +# Procedure ended, the program begins +if __name__ == "__main__": + img2obj() \ No newline at end of file diff --git a/img2pov.py b/img2pov.py new file mode 100644 index 0000000..05b248d --- /dev/null +++ b/img2pov.py @@ -0,0 +1,359 @@ +#!/usr/bin/env python + +''' +IMG2POV - Program for conversion of image heightfield to triangle mesh in POVRay format +--------------------------------------------------------------------------------------------- + +Created by: Ilya Razmanov (mailto:ilyarazmanov@gmail.com) + aka Ilyich the Toad (mailto:amphisoft@gmail.com) +History: + +001 Abandoned img2mesh v.1 and turned to img2mesh v.2 with completely different mesh structure. +005 Replaced Pillow I/O with PyPNG from: https://gitlab.com/drj11/pypng + Support for 16 bit/channel PNGs added. Added mesh encapsulation box. + Extended POVRay camera description. + Restructured output for easy reading. +007 Output cleanup and generalization. GUI improved to show progress during long processing. + Reducing unnecessary import. +2.7.1.0 Significant code cleanup with .writelines. Versioning more clear. +2.8.0.0 Total rewrite to remove all transforms from POVRay. +2.8.1.0 Program converted into self-calling function to have a possibility to import it. + + Main site: + https://dnyarri.github.io + + Project mirrored at: + https://github.com/Dnyarri/img2mesh + https://gitflic.ru/project/dnyarri/img2mesh + +''' + +__author__ = "Ilya Razmanov" +__copyright__ = "(c) 2023-2024 Ilya Razmanov" +__credits__ = "Ilya Razmanov" +__license__ = "unlicense" +__version__ = "2.8.1.0" +__maintainer__ = "Ilya Razmanov" +__email__ = "ilyarazmanov@gmail.com" +__status__ = "Production" + +from tkinter import Tk +from tkinter import Label +from tkinter import filedialog + +from time import time +from time import ctime + +from pathlib import Path + +from png import Reader # I/O with PyPNG from: https://gitlab.com/drj11/pypng + +# ACHTUNG! Starting a whole-program procedure! + + +def img2pov(): + ''' + Procedure for opening PNG heightfield and creating POVRay .pov 3D mesh file from it. + + ''' + + # -------------------------------------------------------------- + # Creating dialog + + iconpath = Path(__file__).resolve().parent / 'vaba.ico' + iconname = str(iconpath) + useicon = iconpath.exists() # Check if icon file really exist. If False, it will not be used later. + + sortir = Tk() + sortir.title('PNG to POV conversion') + if useicon: + sortir.iconbitmap(iconname) # Replacement for simple sortir.iconbitmap('name.ico') - ugly but stable. + sortir.geometry('+200+100') + zanyato = Label(sortir, text='Starting...', font=("arial", 14), padx=16, pady=10, justify='center') + zanyato.pack() + sortir.withdraw() + + # Main dialog created and hidden + # -------------------------------------------------------------- + + # Open source image + sourcefilename = filedialog.askopenfilename( + title='Open source PNG file', filetypes=[('PNG', '.png')], defaultextension=('PNG', '.png') + ) + # Source file name taken + + if (sourcefilename == '') or (sourcefilename == None): + return None + # break if user press 'Cancel' + + source = Reader(filename=sourcefilename) + # opening file with PyPNG + + X, Y, pixels, info = source.asDirect() + # Opening image, iDAT comes to "pixels" as bytearray, to be tuple'd later + + Z = info['planes'] # Maximum CHANNEL NUMBER + imagedata = tuple((pixels)) # Attempt to fix all bytearrays + + if info['bitdepth'] == 8: + maxcolors = 255 # Maximal value for 8-bit channel + if info['bitdepth'] == 16: + maxcolors = 65535 # Maximal value for 16-bit channel + + # source file opened, initial data received + + # opening result file, first get name + resultfilename = filedialog.asksaveasfilename( + title='Save POVRay scene file', + filetypes=[ + ('POV-Ray scene file', '*.pov'), + ('All Files', '*.*'), + ], + defaultextension=('POV-Ray scene file', '.pov'), + ) + + if (resultfilename == '') or (sourcefilename == None): + return None + # break if user press 'Cancel' + # return doesn't seem to work well with .asksaveasfile + + resultfile = open(resultfilename, 'w') + # result file opened + + # Both files opened + + # -------------------------------------------------------------- + # Functions block: + # + # src a-la FM style src(x,y,z) + # Image should be opened as "imagedata" by main program before + # Note that X, Y, Z are not determined in function, you have to determine it in main program + + def src(x, y, z): + ''' + Analog src from FM, force repeat edge instead of out of range + ''' + cx = x + cy = y + cx = max(0, cx) + cx = min((X - 1), cx) + cy = max(0, cy) + cy = min((Y - 1), cy) + + position = (cx * Z) + z # Here is the main magic of turning two x, z into one array position + channelvalue = int(((imagedata[cy])[position])) + + return channelvalue + + # end of src function + + def srcY(x, y): + ''' + Converting to greyscale, returns Yntensity, force repeat edge instead of out of range + ''' + cx = x + cy = y + cx = max(0, cx) + cx = min((X - 1), cx) + cy = max(0, cy) + cy = min((Y - 1), cy) + + if info['planes'] < 3: # supposedly L and LA + Yntensity = src(x, y, 0) + else: # supposedly RGB and RGBA + Yntensity = int(0.2989 * src(x, y, 0) + 0.587 * src(x, y, 1) + 0.114 * src(x, y, 2)) + + return Yntensity + + # end of srcY function + + # WRITING POV FILE + + # ------------ + # POV header + # --- + + resultfile.writelines( + [ + '/*\n', + 'Persistence of Vision Ray Tracer Scene Description File\n', + 'Version: 3.7\n', + 'Description: A triangle mesh scene file converted from image heightfield\n', + 'Author: Automatically generated by img2mesh program\n', + ' https://github.com/Dnyarri/img2mesh\n', + ' https://gitflic.ru/project/dnyarri/img2mesh\n', + 'developed by Ilya Razmanov aka Ilyich the Toad\n', + ' https://dnyarri.github.io/\n', + ' mailto:ilyarazmanov@gmail.com\n', + '*/\n\n', + ] + ) + + resultfile.write(f'// Converted from: {sourcefilename} ') + seconds = time() + localtime = ctime(seconds) + resultfile.write(f'at: {localtime}\n// Source info: {info}\n\n') + + # Statements + + resultfile.writelines( + [ + '\n', + '#version 3.7;\n\n', + 'global_settings{\n', + ' max_trace_level 3 // Set low to speed up rendering. May need to be increased for metals and glasses\n', + ' adc_bailout 0.01 // Set high to speed up rendering. May need to be decreased to 1/256 for better quality\n', + ' ambient_light <0.5,0.5,0.5>\n', + ' assumed_gamma 1.0\n}\n\n', + '#include "colors.inc"\n', + '#include "finish.inc"\n', + '#include "metals.inc"\n', + '#include "golds.inc"\n\n', + '#declare thethingtexturebottom =\n', + ' texture {\n', + ' pigment {\n', + ' gradient z\n', + ' colour_map {\n', + ' [0.0, Red]\n', + ' [0.5, Blue]\n', + ' [1.0, White]\n', + ' }\n', + ' }\n', + ' finish {phong 1.0}\n', + ' }\n', + '\n', + '#declare thethingtexturetop =\n', + ' texture {\n', + ' pigment {\n', + ' gradient z\n', + ' colour_map {\n', + ' [0.00, rgbt <0,0,0,1>]\n', + ' [0.48, rgbt <0,0,0,1>]\n', + ' [0.50, rgbt <0,0,0,0>]\n', + ' [0.52, rgbt <0,0,0,1>]\n', + ' [1.00, rgbt <0,0,0,1>]\n', + ' }\n', + ' }\n', + ' scale 0.2\n', + ' }\n', + ] + ) + + # Mesh + + # Global positioning and scaling to tweak. + + xOffset = -0.5 * float(X - 1) # To be added BEFORE rescaling to center object. + yOffset = -0.5 * float(Y - 1) # To be added BEFORE rescaling to center object + zOffset = 0.0 + + xRescale = 1.0 / float(max(X, Y)) # To fit object into 1,1,1 cube + yRescale = xRescale + zRescale = 1.0 / float(maxcolors) + + resultfile.write('\n\n#declare thething = mesh {\n') # Opening mesh object "thething" + + # Now going to cycle through image and build mesh + + for y in range(0, Y, 1): + + message = 'Processing row ' + str(y) + ' of ' + str(Y) + '...' + sortir.deiconify() + zanyato.config(text=message) + sortir.update() + sortir.update_idletasks() + + resultfile.write(f'\n\n // Row {y}\n') + + for x in range(0, X, 1): + + # Reading switch: + xRead = X - 1 - x + yRead = Y - 1 - y + + # Last remains of writing switch. No longer used but var names remained active so dummy plug must be here. + xWrite = x + yWrite = y + + v9 = srcY(xRead, yRead) # Current pixel to process and write. Then going to neighbours + v1 = 0.25 * (v9 + srcY((xRead + 1), yRead) + srcY((xRead + 1), (yRead + 1)) + srcY(xRead, (yRead + 1))) + v3 = 0.25 * (v9 + srcY(xRead, (yRead + 1)) + srcY((xRead - 1), (yRead + 1)) + srcY((xRead - 1), yRead)) + v5 = 0.25 * (v9 + srcY((xRead - 1), yRead) + srcY((xRead - 1), (yRead - 1)) + srcY(xRead, (yRead - 1))) + v7 = 0.25 * (v9 + srcY(xRead, (yRead - 1)) + srcY((xRead + 1), (yRead - 1)) + srcY((xRead + 1), yRead)) + + # finally going to pyramid building + + resultfile.write( + f'\n triangle{{<{xRescale*(xWrite-0.5+xOffset)}, {yRescale*(yWrite-0.5+yOffset)}, {zRescale*v1}> <{xRescale*(xWrite+xOffset)}, {yRescale*(yWrite+yOffset)}, {zRescale*v9}> <{xRescale*(xWrite+0.5+xOffset)}, {yRescale*(yWrite-0.5+yOffset)}, {zRescale*v3}>}}' + ) # Triangle 2 1-9-3 + + resultfile.write( + f'\n triangle{{<{xRescale*(xWrite+0.5+xOffset)}, {yRescale*(yWrite-0.5+yOffset)}, {zRescale*v3}> <{xRescale*(xWrite+xOffset)}, {yRescale*(yWrite+yOffset)}, {zRescale*v9}> <{xRescale*(xWrite+0.5+xOffset)}, {yRescale*(yWrite+0.5+yOffset)}, {zRescale*v5}>}}' + ) # Triangle 4 3-9-5 + + resultfile.write( + f'\n triangle{{<{xRescale*(xWrite+0.5+xOffset)}, {yRescale*(yWrite+0.5+yOffset)}, {zRescale*v5}> <{xRescale*(xWrite+xOffset)}, {yRescale*(yWrite+yOffset)}, {zRescale*v9}> <{xRescale*(xWrite-0.5+xOffset)}, {yRescale*(yWrite+0.5+yOffset)}, {zRescale*v7}>}}' + ) # Triangle 6 5-9-7 + + resultfile.write( + f'\n triangle{{<{xRescale*(xWrite-0.5+xOffset)}, {yRescale*(yWrite+0.5+yOffset)}, {zRescale*v7}> <{xRescale*(xWrite+xOffset)}, {yRescale*(yWrite+yOffset)}, {zRescale*v9}> <{xRescale*(xWrite-0.5+xOffset)}, {yRescale*(yWrite-0.5+yOffset)}, {zRescale*v1}>}}' + ) # Triangle 8 7-9-1 + + # completed pyramid. Ave me! + + resultfile.write('\n\n inside_vector <0, 0, 1>\n\n') + + # Sample texture of textures + resultfile.writelines( + [ + ' texture{thethingtexturebottom}\n', + ' texture{thethingtexturetop}\n', + '}\n// Closed thething\n\n', + '#declare boxedthing = object{\n', + ' intersection {\n', + ' box {<-0.5, -0.5, 0>, <0.5, 0.5, 1.0>\n', + ' pigment {rgb <0.5, 0.5, 5>}\n', + ' }\n', + ' thething\n', + ' }\n', + '}', + '// Constructed CGS "boxedthing" of mesh plus bounding box thus adding side walls and bottom\n\n', + 'object{boxedthing}\n\n', + ] + ) # Closing solids + + # Camera + proportions = max(X, Y) / X + resultfile.writelines( + [ + '#declare camera_height = 3.0;\n\n', + 'camera{\n', + '// orthographic\n', + ' location <0.0, 0.0, camera_height>\n', + ' right x*image_width/image_height\n' ' up y\n' ' direction <0, 0, 1>\n', + f' angle 2.0*(degrees(atan2({0.5 * proportions}, camera_height-1.0))) // Supposed to fit object\n', + ' look_at <0.0, 0.0, 0.0>\n}\n\n', + ] + ) + + # Light + resultfile.write('light_source{0*x\n color rgb <1.0, 1.0, 1.0>\n translate <20, 20, 20>\n}\n') + resultfile.write('\n/*\n\nhappy rendering\n\n 0~0\n (---)\n(.>|<.)\n-------\n\n*/') + # Close output + resultfile.close() + + # -------------------------------------------------------------- + # Destroying dialog + + sortir.destroy() + sortir.mainloop() + + # Dialog destroyed and closed + # -------------------------------------------------------------- + + return None + + +# Procedure ended, the program begins +if __name__ == "__main__": + img2pov() diff --git a/img2stl.py b/img2stl.py new file mode 100644 index 0000000..71baa04 --- /dev/null +++ b/img2stl.py @@ -0,0 +1,382 @@ +#!/usr/bin/env python + +''' +IMG2STL - Program for conversion of image heightfield to triangle mesh in STL format +----------------------------------------------------------------------------------------- + +Created by: Ilya Razmanov (mailto:ilyarazmanov@gmail.com) + aka Ilyich the Toad (mailto:amphisoft@gmail.com) +History: +1.0.0.0 Initial production release. +1.0.1.0 Program converted into self-calling function to have a possibility to import it. + + Main site: + https://dnyarri.github.io + + Project mirrored at: + https://github.com/Dnyarri/img2mesh + https://gitflic.ru/project/dnyarri/img2mesh + +''' + +__author__ = "Ilya Razmanov" +__copyright__ = "(c) 2024 Ilya Razmanov" +__credits__ = "Ilya Razmanov" +__license__ = "unlicense" +__version__ = "1.0.1.0" +__maintainer__ = "Ilya Razmanov" +__email__ = "ilyarazmanov@gmail.com" +__status__ = "Production" + +from tkinter import Tk +from tkinter import Label +from tkinter import filedialog + +from pathlib import Path + +from png import Reader # I/O with PyPNG from: https://gitlab.com/drj11/pypng + +# ACHTUNG! Starting a whole-program procedure! + +def img2stl(): + ''' + Procedure for opening PNG heightfield and creating stereolithography .stl 3D mesh file from it. + + ''' + + # -------------------------------------------------------------- + # Creating dialog + + iconpath = Path(__file__).resolve().parent / 'vaba.ico' + iconname = str(iconpath) + useicon = iconpath.exists() # Check if icon file really exist. If False, it will not be used later. + + sortir = Tk() + sortir.title('PNG to STL conversion') + if useicon: + sortir.iconbitmap(iconname) # Replacement for simple sortir.iconbitmap('name.ico') - ugly but stable. + sortir.geometry('+200+100') + zanyato = Label(sortir, text='Allons-y!', font=("arial", 14), padx=16, pady=10, justify='center') + zanyato.pack() + sortir.withdraw() + + # Main dialog created and hidden + # -------------------------------------------------------------- + + # Open source image + sourcefilename = filedialog.askopenfilename( + title='Open source PNG file', filetypes=[('PNG', '.png')], defaultextension=('PNG', '.png') + ) + # Source file name taken + + if (sourcefilename == '') or (sourcefilename == None): + return None + # break if user press 'Cancel' + + source = Reader(filename=sourcefilename) + # opening file with PyPNG + + X, Y, pixels, info = source.asDirect() + # Opening image, iDAT comes to "pixels" as bytearray, to be tuple'd later + + Z = info['planes'] # Maximum CHANNEL NUMBER + imagedata = tuple((pixels)) # Attempt to fix all bytearrays + + if info['bitdepth'] == 8: + maxcolors = 255 # Maximal value for 8-bit channel + if info['bitdepth'] == 16: + maxcolors = 65535 # Maximal value for 16-bit channel + + # source file opened, initial data received + + # opening result file, first get name + resultfilename = filedialog.asksaveasfilename( + title='Save stereolithography STL file', + filetypes=[ + ('3D object file', '*.stl'), + ('All Files', '*.*'), + ], + defaultextension=('3D object file', '.stl'), + ) + + if (resultfilename == '') or (sourcefilename == None): + return None + # break if user press 'Cancel' + # return doesn't seem to work well with .asksaveasfile + + resultfile = open(resultfilename, 'w') + # result file opened + + # Both files opened + + # -------------------------------------------------------------- + # Functions block: + # + # src a-la FM style src(x,y,z) + # Image should be opened as "imagedata" by main program before + # Note that X, Y, Z are not determined in function, you have to determine it in main program + + + def src(x, y, z): + ''' + Analog of src from FilterMeister, force repeat edge instead of out of range + ''' + cx = x + cy = y + cx = max(0, cx) + cx = min((X - 1), cx) + cy = max(0, cy) + cy = min((Y - 1), cy) + + position = (cx * Z) + z # Here is the main magic of turning two x, z into one array position + channelvalue = int(((imagedata[cy])[position])) + + return channelvalue + + + # end of src function + + + def srcY(x, y): + ''' + Converting to greyscale, returns Yntensity, force repeat edge instead of out of range + ''' + cx = x + cy = y + cx = max(0, cx) + cx = min((X - 1), cx) + cy = max(0, cy) + cy = min((Y - 1), cy) + + if info['planes'] < 3: # supposedly L and LA + Yntensity = src(x, y, 0) + else: # supposedly RGB and RGBA + Yntensity = int(0.2989 * src(x, y, 0) + 0.587 * src(x, y, 1) + 0.114 * src(x, y, 2)) + + return Yntensity + + + # end of srcY function + # + # end of Functions block + # -------------------------------------------------------------- + + # Global positioning and scaling to tweak. Offset supposed to make everyone feeling positive, rescale supposed to scale anything to [0..1.0] regardless of what the units are + + xOffset = 1.0 # To be added BEFORE rescaling to compensate 0.5 X expansion + yOffset = 1.0 # To be added BEFORE rescaling to compensate 0.5 Y expansion + zOffset = 0.0 # To be added AFTER rescaling just in case there should be something to fix + + xRescale = 1.0 / float(max(X, Y)) # To fit object into 1,1,1 cube + yRescale = xRescale + zRescale = 1.0 / float(maxcolors) + + # WRITING STL FILE, finally + + resultfile.write('solid pryanik_nepechatnyj\n') # opening object + + # Now going to cycle through image and build mesh + + for y in range(0, Y, 1): + + message = 'Processing row ' + str(y) + ' of ' + str(Y) + '...' + sortir.deiconify() + zanyato.config(text=message) + sortir.update() + sortir.update_idletasks() + + for x in range(0, X, 1): + + # Since I was unable to find clear declaration of coordinate system, I'll plug a coordinate switch here + + # Reading switch: + xRead = x + yRead = (Y - 1 - y) # 'yRead = Y - y' coordinate mirror to mimic Photoshop coordinate system; +/- 1 steps below are inverted correspondingly vs. original img2mesh + + # Remains of Writing switch. No longer used since v. 0.1.0.2 but var names remained so dummy plug must be here. + xWrite = x + yWrite = y + + v9 = srcY(xRead, yRead) # Current pixel to process and write. Then going to neighbours + v1 = 0.25 * (v9 + srcY((xRead - 1), yRead) + srcY((xRead - 1), (yRead + 1)) + srcY(xRead, (yRead + 1))) + v3 = 0.25 * (v9 + srcY(xRead, (yRead + 1)) + srcY((xRead + 1), (yRead + 1)) + srcY((xRead + 1), yRead)) + v5 = 0.25 * (v9 + srcY((xRead + 1), yRead) + srcY((xRead + 1), (yRead - 1)) + srcY(xRead, (yRead - 1))) + v7 = 0.25 * (v9 + srcY(xRead, (yRead - 1)) + srcY((xRead - 1), (yRead - 1)) + srcY((xRead - 1), yRead)) + + # finally going to pyramid building + + # top part begins + resultfile.writelines( + [ + ' facet normal 0 0 1\n', # triangle 2 normal up + ' outer loop\n', # 1 - 9 - 3 + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', + f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', + ' endloop\n', + ' endfacet\n', + ' facet normal 0 0 1\n', # triangle 4 normal up + ' outer loop\n', # 3 - 9 - 5 + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', + f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', + ' endloop\n', + ' endfacet\n', + ' facet normal 0 0 1\n', # triangle 6 normal up + ' outer loop\n', # 5 - 9 - 7 + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', + f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', + ' endloop\n', + ' endfacet\n', + ' facet normal 0 0 1\n', # triangle 8 normal up + ' outer loop\n', # 7 - 9 - 1 + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', + f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+zRescale*v9):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', + ' endloop\n', + ' endfacet\n', + ] + ) + # top part ends + + # left side begins + if x == 0: + resultfile.writelines( + [ + ' facet normal -1 0 0\n', # triangle 8- normal left + ' outer loop\n', # 1 - down1 - 7 + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', + ' endloop\n', + ' endfacet\n', + ' facet normal -1 0 0\n', # triangle 8- normal left + ' outer loop\n', # down1 - down7 - 7 + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', + ' endloop\n', + ' endfacet\n', + ] + ) + # left side ends + + # right side begins + if x == (X - 1): + resultfile.writelines( + [ + ' facet normal 1 0 0\n', # triangle 4+ normal left + ' outer loop\n', # 5 - down5 - 3 + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', + ' endloop\n', + ' endfacet\n', + ' facet normal 1 0 0\n', # triangle 4+ normal left + ' outer loop\n', # 3 - down5 - down3 + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', + ' endloop\n', + ' endfacet\n', + ] + ) + # right side ends + + # far side begins + if y == 0: + resultfile.writelines( + [ + ' facet normal 0 -1 0\n', # triangle 2- normal far + ' outer loop\n', # 3 - down - 1 + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v3):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', + ' endloop\n', + ' endfacet\n', + ' facet normal 0 -1 0\n', # triangle 2- normal far + ' outer loop\n', # down - down - 1 + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+zRescale*v1):e}\n', + ' endloop\n', + ' endfacet\n', + ] + ) + # far side ends + + # close side begins + if y == (Y - 1): + resultfile.writelines( + [ + ' facet normal 0 1 0\n', # triangle 6+ normal close + ' outer loop\n', # 7 - down - 5 + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v7):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', + ' endloop\n', + ' endfacet\n', + ' facet normal 0 1 0\n', # triangle 6+ normal close + ' outer loop\n', # down - down - 5 + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+zRescale*v5):e}\n', + ' endloop\n', + ' endfacet\n', + ] + ) + # close side ends + + # bottom part begins + resultfile.writelines( + [ + ' facet normal 0 0 -1\n', # triangle 2 normal up + ' outer loop\n', # 1 - 9 - 3 + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', + ' endloop\n', + ' endfacet\n', + ' facet normal 0 0 -1\n', # triangle 4 normal up + ' outer loop\n', # 3 - 9 - 5 + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', + ' endloop\n', + ' endfacet\n', + ' facet normal 0 0 -1\n', # triangle 6 normal up + ' outer loop\n', # 5 - 9 - 7 + f' vertex {(xRescale*(xWrite+0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', + ' endloop\n', + ' endfacet\n', + ' facet normal 0 0 -1\n', # triangle 8 normal up + ' outer loop\n', # 7 - 9 - 1 + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite+0.5+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite+xOffset)):e} {(yRescale*(yWrite+yOffset)):e} {(zOffset+0.0):e}\n', + f' vertex {(xRescale*(xWrite-0.5+xOffset)):e} {(yRescale*(yWrite-0.5+yOffset)):e} {(zOffset+0.0):e}\n', + ' endloop\n', + ' endfacet\n', + ] + ) + # bottom part ends + + resultfile.write('endsolid pryanik_nepechatnyj') # closing object + + # Close output + resultfile.close() + + # -------------------------------------------------------------- + # Destroying dialog + + sortir.destroy() + sortir.mainloop() + + # Dialog destroyed and closed + # -------------------------------------------------------------- + +# Procedure ended, the program begins +if __name__ == "__main__": + img2stl() \ No newline at end of file diff --git a/vaba.ico b/vaba.ico new file mode 100644 index 0000000000000000000000000000000000000000..9cf974bafac79589d4a93d4554d28be60d4282bd GIT binary patch literal 72566 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%0D-B64pa46ivt#|9&+KyNo?})i^Z-$7yb>9#T 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 literal 0 HcmV?d00001