Compare commits
10 commits
30d1cc8e3d
...
864dcb8160
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
864dcb8160 | ||
|
|
cd4df840b6 | ||
|
|
c4436d040b | ||
|
|
117efa3589 | ||
|
|
80bf0cf4e8 | ||
|
|
1d0f5cf199 | ||
|
|
78456105ac | ||
|
|
10d218bfba | ||
|
|
bd1c7ed477 | ||
|
|
29e254434f |
49 changed files with 642 additions and 482 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -1,5 +1,6 @@
|
||||||
*.so
|
*.so
|
||||||
|
*.h
|
||||||
*.swp
|
*.swp
|
||||||
*/__pycache__
|
__pycache__
|
||||||
flask/static
|
static
|
||||||
*/output.png
|
*output.png
|
||||||
|
|
|
||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
[submodule "flask/epson"]
|
|
||||||
path = flask/epson
|
|
||||||
url = https://mid-kid.root.sx/git/mid-kid/epson.git
|
|
||||||
2
Makefile
2
Makefile
|
|
@ -1,4 +1,4 @@
|
||||||
build:
|
build:
|
||||||
cd faxmachine &&\
|
cd epson/faxmachine &&\
|
||||||
go build -o ../library_bridge.so -buildmode=c-shared ../library_bridge.go
|
go build -o ../library_bridge.so -buildmode=c-shared ../library_bridge.go
|
||||||
|
|
||||||
|
|
|
||||||
209
app.py
Normal file
209
app.py
Normal file
|
|
@ -0,0 +1,209 @@
|
||||||
|
from flask import Flask, render_template, request, redirect, url_for, session, send_from_directory
|
||||||
|
from PIL import Image
|
||||||
|
from gen_image import gen_image
|
||||||
|
from printer_info import *
|
||||||
|
from datetime import datetime
|
||||||
|
from print import *
|
||||||
|
from format_image import *
|
||||||
|
from file_handler import *
|
||||||
|
from colorama import Fore, Style
|
||||||
|
import os
|
||||||
|
|
||||||
|
generated_image_filename = "generated.png"
|
||||||
|
uploaded_image_filename = "uploaded" #extention is depended on uploaded file format
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
app.secret_key = "blahaj"
|
||||||
|
|
||||||
|
templates = {
|
||||||
|
"DNH": {
|
||||||
|
"text1": {
|
||||||
|
"string": "Do Not Hack",
|
||||||
|
"size": 50,
|
||||||
|
"pos": 0
|
||||||
|
},
|
||||||
|
"text2": {
|
||||||
|
"string": "bottom text",
|
||||||
|
"size": 25,
|
||||||
|
"pos": 55
|
||||||
|
},
|
||||||
|
"cut": True
|
||||||
|
},
|
||||||
|
"Food": {
|
||||||
|
"text1": {
|
||||||
|
"string": "Nickname",
|
||||||
|
"size": 50,
|
||||||
|
"pos": 0
|
||||||
|
},
|
||||||
|
"text2": {
|
||||||
|
"string": "",
|
||||||
|
"size": 25,
|
||||||
|
"pos": 55
|
||||||
|
},
|
||||||
|
"cut": True
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/', methods=['GET', 'POST'])
|
||||||
|
def base():
|
||||||
|
check_for_new_user(session)
|
||||||
|
return render_template('base.html')
|
||||||
|
|
||||||
|
|
||||||
|
# gets triggered when the user_data folder for the user is created
|
||||||
|
@new_user_handler
|
||||||
|
def on_new_user(session):
|
||||||
|
print(Fore.BLUE + "new user with ID:", session["ID"], Style.RESET_ALL)
|
||||||
|
|
||||||
|
session["text image path"] = None
|
||||||
|
session["uploaded image path"] = None
|
||||||
|
session["cut"] = True
|
||||||
|
session["text1"] = templates["DNH"]["text1"]
|
||||||
|
session["text2"] = templates["DNH"]["text2"]
|
||||||
|
session["cut"] = templates["DNH"]["cut"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/image', methods=['GET', 'POST'])
|
||||||
|
def image():
|
||||||
|
check_for_new_user(session)
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
if 'image' not in request.files:
|
||||||
|
return redirect(request.url)
|
||||||
|
file = request.files['image']
|
||||||
|
|
||||||
|
if file.filename == '':
|
||||||
|
return redirect(request.url)
|
||||||
|
if file:
|
||||||
|
extension = os.path.splitext(file.filename)[1]
|
||||||
|
session["uploaded image path"] = uploaded_image_filename+extension
|
||||||
|
|
||||||
|
filepath = get_file_path(session, session["uploaded image path"])
|
||||||
|
file.save(filepath)
|
||||||
|
|
||||||
|
format_image(filepath).save(filepath)
|
||||||
|
|
||||||
|
return render_template('image.html', filename=session["uploaded image path"], cut=session["cut"])
|
||||||
|
|
||||||
|
|
||||||
|
#TODO: maybe merge some stuff with text-print
|
||||||
|
@app.route('/image-print', methods=['GET', 'POST'])
|
||||||
|
def image_print():
|
||||||
|
check_for_new_user(session)
|
||||||
|
|
||||||
|
if session["uploaded image path"] == None:
|
||||||
|
print(Fore.YELLOW + "Warning, file doesn't exist" + Style.RESET_ALL)
|
||||||
|
return render_template('image.html', filename=session["uploaded image path"], cut=session["cut"])
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
image = format_image_to_label(get_file_path(session, session["uploaded image path"]))
|
||||||
|
print_image(image)
|
||||||
|
|
||||||
|
if 'cut' in request.form:
|
||||||
|
print("printing and cutting")
|
||||||
|
cut_paper()
|
||||||
|
session["cut"] = True;
|
||||||
|
else:
|
||||||
|
print("printing")
|
||||||
|
session["cut"] = False;
|
||||||
|
|
||||||
|
return render_template('image.html', filename=session["uploaded image path"], cut=session["cut"])
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/text-template', methods=['GET', 'POST'])
|
||||||
|
def text_template():
|
||||||
|
check_for_new_user(session)
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
template = templates[request.form["template"]]
|
||||||
|
if request.form["template"] == "Food":
|
||||||
|
template["text2"]["string"] = datetime.now().strftime('%Y-%m-%d')
|
||||||
|
|
||||||
|
session["text1"] = template["text1"]
|
||||||
|
session["text2"] = template["text2"]
|
||||||
|
session["cut"] = template["cut"]
|
||||||
|
|
||||||
|
return render_template('text.html', filename="text.png", text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/text-form', methods=['GET', 'POST'])
|
||||||
|
def text_form():
|
||||||
|
check_for_new_user(session)
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
session["text1"] = {
|
||||||
|
"string": request.form["string1"],
|
||||||
|
"size": int(request.form["size1"]),
|
||||||
|
"pos": int(request.form["pos1"]),
|
||||||
|
}
|
||||||
|
session["text2"] = {
|
||||||
|
"string": request.form["string2"],
|
||||||
|
"size": int(request.form["size2"]),
|
||||||
|
"pos": int(request.form["pos2"]),
|
||||||
|
}
|
||||||
|
|
||||||
|
img = gen_image(label_width, session["text1"], session["text2"])
|
||||||
|
|
||||||
|
get_folder_path(session)
|
||||||
|
|
||||||
|
session["text image path"] = generated_image_filename
|
||||||
|
img.save(get_file_path(session, session["text image path"]))
|
||||||
|
print()
|
||||||
|
print(session["text image path"])
|
||||||
|
|
||||||
|
return render_template('text.html', filename=session["text image path"], text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/text', methods=['GET', 'POST'])
|
||||||
|
def text():
|
||||||
|
check_for_new_user(session)
|
||||||
|
|
||||||
|
return render_template('text.html', filename=session["text image path"], text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/text-print', methods=['GET', 'POST'])
|
||||||
|
def text_print():
|
||||||
|
check_for_new_user(session)
|
||||||
|
|
||||||
|
if request.method == 'POST':
|
||||||
|
if session["text image path"] == None:
|
||||||
|
print(Fore.YELLOW + "Warning, file doesn't exist" + Style.RESET_ALL)
|
||||||
|
return render_template('text.html', filename=session["text image path"], text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
||||||
|
|
||||||
|
|
||||||
|
image = format_image_to_label(get_file_path(session, session["text image path"]))
|
||||||
|
print_image(image)
|
||||||
|
|
||||||
|
if 'cut' in request.form:
|
||||||
|
print("printing and cutting")
|
||||||
|
cut_paper()
|
||||||
|
session["cut"] = True;
|
||||||
|
else:
|
||||||
|
print("printing")
|
||||||
|
session["cut"] = False;
|
||||||
|
|
||||||
|
return render_template('text.html', filename=session["text image path"], text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/user_data/<filename>')
|
||||||
|
def user_data(filename):
|
||||||
|
return send_from_directory(get_folder_path(session), filename)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/uploads/<filename>')
|
||||||
|
def uploaded_file(filename):
|
||||||
|
return redirect(url_for('static', filename='uploads/' + filename))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/text/<filename>')
|
||||||
|
def generated_file(filename):
|
||||||
|
return redirect(url_for('static', filename='text/' + filename))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(debug=True)
|
||||||
|
|
||||||
128
epson/library_bridge.go
Normal file
128
epson/library_bridge.go
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
_ "time"
|
||||||
|
"image"
|
||||||
|
_ "image/gif"
|
||||||
|
_ "image/jpeg"
|
||||||
|
_ "image/png"
|
||||||
|
"log"
|
||||||
|
"unsafe"
|
||||||
|
"bytes"
|
||||||
|
|
||||||
|
_ "github.com/jbuchbinder/gopnm"
|
||||||
|
_ "golang.org/x/image/webp"
|
||||||
|
|
||||||
|
"git.sr.ht/~guacamolie/faxmachine/escpos"
|
||||||
|
"git.sr.ht/~guacamolie/faxmachine/escpos/protocol"
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
const red = "\033[31m"
|
||||||
|
const reset = "\033[0m"
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
func printer_init(path string, speed int) (*escpos.Printer, error) {
|
||||||
|
p, err := escpos.StartUSBPrinter(path, protocol.TMT88IV, escpos.FlagNone)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%sError: failed to start printer: %v%s\n", red, err, reset)
|
||||||
|
return p, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := p.EnableASB(protocol.ASBReportAll); err != nil {
|
||||||
|
p.Close()
|
||||||
|
fmt.Printf("%sError: failed enable ASB: %v%s\n", red, err, reset)
|
||||||
|
return p, err
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for status := range p.ASBStatus() {
|
||||||
|
log.Printf("received ASB status: %#v\n", status)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := p.SetPrintSpeed(speed); err != nil {
|
||||||
|
fmt.Printf("%sError: Failed to set print speed: %v%s\n", red, err, reset)
|
||||||
|
return p, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func printer_close(p *escpos.Printer) (error) {
|
||||||
|
if err = p.Wait(); err != nil {
|
||||||
|
fmt.Printf("%sError: Failed to print: %v%s\n", red, err, reset)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = p.Close(); err != nil {
|
||||||
|
fmt.Printf("%sError: Failed close printer: %v%s\n", red, err, reset)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Print("printer closed\n");
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//export cut
|
||||||
|
func cut(path *C.char) {
|
||||||
|
fmt.Print("Starting cut\n");
|
||||||
|
p, err := printer_init(C.GoString(path), 1)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = p.CutPaper(); err != nil {
|
||||||
|
fmt.Printf("%sError: Failed to cut paper: %v%s\n", red, err, reset)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
printer_close(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export print_text
|
||||||
|
func print_text(path *C.char, str *C.char) {
|
||||||
|
p, err := printer_init(C.GoString(path), 1)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(p, C.GoString(str))
|
||||||
|
fmt.Fprint(p, "\n")
|
||||||
|
|
||||||
|
printer_close(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
//export print_image
|
||||||
|
func print_image(path *C.char, data *C.uchar, size C.int) {
|
||||||
|
p, err := printer_init(C.GoString(path), 1)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for status := range p.ASBStatus() {
|
||||||
|
log.Printf("received ASB status: %#v\n", status)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
byteData := C.GoBytes(unsafe.Pointer(data), C.int(size))
|
||||||
|
imgReader := bytes.NewReader(byteData)
|
||||||
|
img, _, err := image.Decode(imgReader)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("%sError: Failed get decode image: %v%s\n", red, err, reset)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := p.PrintImage(img); err != nil {
|
||||||
|
fmt.Printf("%sError: Failed print image: %v%s\n", red, err, reset)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
printer_close(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func main() {}
|
||||||
76
file_handler.py
Normal file
76
file_handler.py
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
import random
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import time
|
||||||
|
|
||||||
|
user_data_lifetime_seconds = 2*60*60
|
||||||
|
data_path = "user_data"
|
||||||
|
users = dict([])
|
||||||
|
|
||||||
|
if os.path.exists(data_path):
|
||||||
|
shutil.rmtree(data_path)
|
||||||
|
|
||||||
|
def delete_old_users(session):
|
||||||
|
for ID in users.copy():
|
||||||
|
elapsed = time.time() - users[ID]["last accessed"]
|
||||||
|
|
||||||
|
if (elapsed > user_data_lifetime_seconds):
|
||||||
|
print(ID, "Hasn't accessed their files in", elapsed, "seconds, removing all user data")
|
||||||
|
|
||||||
|
shutil.rmtree(users[ID]["path"])
|
||||||
|
del users[ID]
|
||||||
|
|
||||||
|
new_user_handler_func = None
|
||||||
|
|
||||||
|
|
||||||
|
def new_user_handler(func):
|
||||||
|
global new_user_handler_func
|
||||||
|
new_user_handler_func = func
|
||||||
|
return func
|
||||||
|
|
||||||
|
|
||||||
|
def new_user(session):
|
||||||
|
while(True):
|
||||||
|
ID = random.randint(0, 100000000)
|
||||||
|
if not ID in users:
|
||||||
|
break
|
||||||
|
|
||||||
|
users[ID] = {
|
||||||
|
"path": data_path + "/" + str(ID),
|
||||||
|
"last accessed": time.time()
|
||||||
|
}
|
||||||
|
|
||||||
|
session["ID"] = ID
|
||||||
|
|
||||||
|
os.makedirs(users[session["ID"]]["path"])
|
||||||
|
|
||||||
|
if new_user_handler_func:
|
||||||
|
new_user_handler_func(session)
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_path(session, filename):
|
||||||
|
return os.path.join(get_folder_path(session), filename)
|
||||||
|
|
||||||
|
|
||||||
|
def file_exists(session, filename):
|
||||||
|
return os.path.exists(get_file_path(session, filename))
|
||||||
|
|
||||||
|
|
||||||
|
def check_for_new_user(session):
|
||||||
|
if not "ID" in session:
|
||||||
|
new_user(session)
|
||||||
|
elif not session["ID"] in users:
|
||||||
|
new_user(session)
|
||||||
|
|
||||||
|
delete_old_users(session)
|
||||||
|
|
||||||
|
|
||||||
|
def get_folder_path(session):
|
||||||
|
check_for_new_user(session)
|
||||||
|
ID = session["ID"]
|
||||||
|
user = users[ID]
|
||||||
|
|
||||||
|
user["last accessed"] = time.time()
|
||||||
|
|
||||||
|
return user["path"]
|
||||||
|
|
||||||
157
flask/app.py
157
flask/app.py
|
|
@ -1,157 +0,0 @@
|
||||||
from flask import Flask, render_template, request, redirect, url_for, session
|
|
||||||
from PIL import Image
|
|
||||||
from gen_image import gen_image
|
|
||||||
from printer_info import *
|
|
||||||
from datetime import datetime
|
|
||||||
from print import *
|
|
||||||
from format_image import *
|
|
||||||
import os
|
|
||||||
|
|
||||||
valid_height=800
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
app.config['UPLOAD_FOLDER'] = 'static/uploads'
|
|
||||||
app.config['TEXT_FOLDER'] = 'static/text'
|
|
||||||
app.secret_key = "blahaj"
|
|
||||||
|
|
||||||
# Ensure the upload directory exists
|
|
||||||
if not os.path.exists(app.config['UPLOAD_FOLDER']):
|
|
||||||
os.makedirs(app.config['UPLOAD_FOLDER'])
|
|
||||||
if not os.path.exists(app.config['TEXT_FOLDER']):
|
|
||||||
os.makedirs(app.config['TEXT_FOLDER'])
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/image', methods=['GET', 'POST'])
|
|
||||||
def image():
|
|
||||||
if request.method == 'POST':
|
|
||||||
if 'image' not in request.files:
|
|
||||||
return redirect(request.url)
|
|
||||||
file = request.files['image']
|
|
||||||
|
|
||||||
if file.filename == '':
|
|
||||||
return redirect(request.url)
|
|
||||||
if file:
|
|
||||||
extension = os.path.splitext(file.filename)[1]
|
|
||||||
filepath = os.path.join(app.config['UPLOAD_FOLDER'], "upload" + extension)
|
|
||||||
|
|
||||||
file.save(filepath)
|
|
||||||
|
|
||||||
# Process image #
|
|
||||||
height = Image.open(filepath).height
|
|
||||||
|
|
||||||
valid = False
|
|
||||||
if height == valid_height:
|
|
||||||
valid = True
|
|
||||||
#################
|
|
||||||
|
|
||||||
return render_template('image.html', filename="upload"+extension, height=height, valid=valid)
|
|
||||||
|
|
||||||
return render_template('image.html')
|
|
||||||
|
|
||||||
templates = {
|
|
||||||
"DNH": {
|
|
||||||
"text1": {
|
|
||||||
"string": "Do Not Hack",
|
|
||||||
"size": 50,
|
|
||||||
"pos": 0
|
|
||||||
},
|
|
||||||
"text2": {
|
|
||||||
"string": "bottom text",
|
|
||||||
"size": 25,
|
|
||||||
"pos": 55
|
|
||||||
},
|
|
||||||
"cut": True
|
|
||||||
},
|
|
||||||
"Food": {
|
|
||||||
"text1": {
|
|
||||||
"string": "Nickname",
|
|
||||||
"size": 50,
|
|
||||||
"pos": 0
|
|
||||||
},
|
|
||||||
"text2": {
|
|
||||||
"string": "",
|
|
||||||
"size": 25,
|
|
||||||
"pos": 55
|
|
||||||
},
|
|
||||||
"cut": True
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@app.route('/text-template', methods=['GET', 'POST'])
|
|
||||||
def text_template():
|
|
||||||
if request.method == 'POST':
|
|
||||||
template = templates[request.form["template"]]
|
|
||||||
if request.form["template"] == "Food":
|
|
||||||
template["text2"]["string"] = datetime.now().strftime('%Y-%m-%d')
|
|
||||||
|
|
||||||
session["text1"] = template["text1"]
|
|
||||||
session["text2"] = template["text2"]
|
|
||||||
session["cut"] = template["cut"]
|
|
||||||
|
|
||||||
return render_template('text.html', filename="text.png", text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
|
||||||
|
|
||||||
return render_template('text.html', filename="text.png", text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
|
||||||
|
|
||||||
@app.route('/text-form', methods=['GET', 'POST'])
|
|
||||||
def text_form():
|
|
||||||
if request.method == 'POST':
|
|
||||||
session["text1"] = {
|
|
||||||
"string": request.form["string1"],
|
|
||||||
"size": int(request.form["size1"]),
|
|
||||||
"pos": int(request.form["pos1"]),
|
|
||||||
}
|
|
||||||
session["text2"] = {
|
|
||||||
"string": request.form["string2"],
|
|
||||||
"size": int(request.form["size2"]),
|
|
||||||
"pos": int(request.form["pos2"]),
|
|
||||||
}
|
|
||||||
|
|
||||||
img = gen_image(label_width, session["text1"], session["text2"])
|
|
||||||
filepath = os.path.join(app.config['TEXT_FOLDER'], "text.png")
|
|
||||||
img.save(filepath)
|
|
||||||
print(session)
|
|
||||||
|
|
||||||
return render_template('text.html', filename="text.png", text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
|
||||||
|
|
||||||
return render_template('text.html', filename="text.png", text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/text', methods=['GET', 'POST'])
|
|
||||||
def text():
|
|
||||||
session["text1"] = templates["DNH"]["text1"]
|
|
||||||
session["text2"] = templates["DNH"]["text2"]
|
|
||||||
session["cut"] = templates["DNH"]["cut"]
|
|
||||||
return render_template('text.html', filename="text.png", text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/text-print', methods=['GET', 'POST'])
|
|
||||||
def tex_print():
|
|
||||||
if request.method == 'POST':
|
|
||||||
image = format_image("static/text/text.png")
|
|
||||||
print_image(image)
|
|
||||||
|
|
||||||
if 'cut' in request.form:
|
|
||||||
print("printing and cutting")
|
|
||||||
cut_paper()
|
|
||||||
session["cut"] = True;
|
|
||||||
else:
|
|
||||||
print("printing")
|
|
||||||
session["cut"] = False;
|
|
||||||
|
|
||||||
return render_template('text.html', filename="text.png", text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
|
||||||
|
|
||||||
return render_template('text.html', filename="text.png", text1=session["text1"], text2=session["text2"], cut=session["cut"])
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/uploads/<filename>')
|
|
||||||
def uploaded_file(filename):
|
|
||||||
return redirect(url_for('static', filename='uploads/' + filename))
|
|
||||||
|
|
||||||
@app.route('/text/<filename>')
|
|
||||||
def generated_file(filename):
|
|
||||||
return redirect(url_for('static', filename='text/' + filename))
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app.run(debug=True)
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 37ab1729e6cdb212619bd4c12097ef0d926c0c2c
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
from PIL import Image
|
|
||||||
|
|
||||||
def format_image(path):
|
|
||||||
image = Image.open(path)
|
|
||||||
image = image.rotate(-90, expand=True)
|
|
||||||
|
|
||||||
new_image = Image.new('1', (512, image.height), 1)
|
|
||||||
new_image.paste(image, (0, 0))
|
|
||||||
|
|
||||||
return new_image
|
|
||||||
|
|
||||||
#format_image("static/text/text.png").save("output.png")
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
dev_path="/dev/usb/lp0"
|
|
||||||
from format_image import format_image
|
|
||||||
from PIL import Image
|
|
||||||
import os
|
|
||||||
|
|
||||||
def print_text(text):
|
|
||||||
stream = open('/dev/usb/lp0', 'wb')
|
|
||||||
stream.write(text.encode('utf-8'))
|
|
||||||
stream.close()
|
|
||||||
|
|
||||||
def cut_paper():
|
|
||||||
stream = open('/dev/usb/lp0', 'wb')
|
|
||||||
stream.write(b'\x1DV\x41\0')
|
|
||||||
stream.close()
|
|
||||||
|
|
||||||
def print_image(image):
|
|
||||||
image.save("/tmp/image.png")
|
|
||||||
|
|
||||||
# I'm sorry
|
|
||||||
os.system("cd epson/; ./print_image.sh /tmp/image.png; cd ..")
|
|
||||||
|
|
||||||
#image = format_image("static/text/text.png")
|
|
||||||
#image.save("/tmp/image.png")
|
|
||||||
#print_image(image)
|
|
||||||
#cut_paper()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
label_width = 100
|
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Image Upload</title>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.box {
|
|
||||||
flex: 1;
|
|
||||||
background-color: lightgray;
|
|
||||||
text-align: center;
|
|
||||||
margin: 1px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
{% block head %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<div class="box">Text</div>
|
|
||||||
<div class="box">Image</div>
|
|
||||||
<div class="box">QR</div>
|
|
||||||
<div class="box">Barcode</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h1>Upload Image</h1>
|
|
||||||
<form method="POST" enctype="multipart/form-data">
|
|
||||||
<input type="file" name="image">
|
|
||||||
<input type="submit" value="Upload">
|
|
||||||
</form>
|
|
||||||
|
|
||||||
{% if filename %}
|
|
||||||
<h2>Uploaded Image:</h2>
|
|
||||||
<img src="{{ url_for('uploaded_file', filename=filename) }}" alt="Uploaded Image" style="max-width:300px;">
|
|
||||||
{% if valid %}
|
|
||||||
<p style="color: green;">Height: {{ height }} px</p>
|
|
||||||
{% else %}
|
|
||||||
<p style="color: red;">Height: {{ height }} px</p>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
27
format_image.py
Normal file
27
format_image.py
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
from PIL import Image
|
||||||
|
from printer_info import *
|
||||||
|
|
||||||
|
def format_image_to_label(path):
|
||||||
|
image = Image.open(path)
|
||||||
|
image = image.rotate(-90, expand=True)
|
||||||
|
|
||||||
|
new_image = Image.new('1', (printer_width, image.height), 1)
|
||||||
|
new_image.paste(image, (0, 0))
|
||||||
|
|
||||||
|
return new_image
|
||||||
|
|
||||||
|
def format_image(path):
|
||||||
|
image = Image.open(path)
|
||||||
|
|
||||||
|
if (image.height != label_width):
|
||||||
|
print("resizing image")
|
||||||
|
new_height = label_width
|
||||||
|
new_width = int(label_width * image.width / image.height)
|
||||||
|
|
||||||
|
image = image.resize((new_width, new_height))
|
||||||
|
|
||||||
|
image = image.convert('1', dither=Image.FLOYDSTEINBERG)
|
||||||
|
return image
|
||||||
|
|
||||||
|
|
||||||
|
#format_image("static/uploads/upload.png").save("output.png")
|
||||||
|
|
@ -2,9 +2,11 @@ from PIL import Image, ImageDraw, ImageFont
|
||||||
from colorama import Fore, Style
|
from colorama import Fore, Style
|
||||||
from printer_info import *
|
from printer_info import *
|
||||||
|
|
||||||
|
font = "resources/ComicMono.ttf"
|
||||||
|
|
||||||
def gen_image(height, text1, text2):
|
def gen_image(height, text1, text2):
|
||||||
font1 = ImageFont.truetype("ComicMono.ttf", size=text1["size"])
|
font1 = ImageFont.truetype(font, size=text1["size"])
|
||||||
font2 = ImageFont.truetype("ComicMono.ttf", size=text2["size"])
|
font2 = ImageFont.truetype(font, size=text2["size"])
|
||||||
|
|
||||||
text1["string"] = text1["string"].replace("\r\n", "\n")
|
text1["string"] = text1["string"].replace("\r\n", "\n")
|
||||||
text2["string"] = text2["string"].replace("\r\n", "\n")
|
text2["string"] = text2["string"].replace("\r\n", "\n")
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
_ "image"
|
|
||||||
_ "image/gif"
|
|
||||||
_ "image/jpeg"
|
|
||||||
_ "image/png"
|
|
||||||
"log"
|
|
||||||
_ "os"
|
|
||||||
|
|
||||||
_ "github.com/jbuchbinder/gopnm"
|
|
||||||
_ "golang.org/x/image/webp"
|
|
||||||
|
|
||||||
_ "github.com/lestrrat-go/dither"
|
|
||||||
_ "github.com/nfnt/resize"
|
|
||||||
|
|
||||||
"git.sr.ht/~guacamolie/faxmachine/escpos"
|
|
||||||
"git.sr.ht/~guacamolie/faxmachine/escpos/protocol"
|
|
||||||
)
|
|
||||||
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
func printer_init(path string, speed int) (*escpos.Printer) {
|
|
||||||
p, err := escpos.StartUSBPrinter(path, protocol.TMT88IV, escpos.FlagNone)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to start printer: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := p.EnableASB(protocol.ASBReportAll); err != nil {
|
|
||||||
p.Close()
|
|
||||||
log.Fatalf("failed to enable ASB: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
for status := range p.ASBStatus() {
|
|
||||||
log.Printf("received ASB status: %#v\n", status)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
if err := p.SetPrintSpeed(speed); err != nil {
|
|
||||||
log.Fatalf("failed to set print speed: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
//export cut
|
|
||||||
func cut(path *C.char) {
|
|
||||||
p := printer_init(C.GoString(path), 1)
|
|
||||||
|
|
||||||
if err = p.CutPaper(); err != nil {
|
|
||||||
log.Fatalf("failed to cut paper: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = p.Wait(); err != nil {
|
|
||||||
log.Fatalf("failed to print: %v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//export print_text
|
|
||||||
func print_text(path *C.char, str *C.char) {
|
|
||||||
p := printer_init(C.GoString(path), 1)
|
|
||||||
|
|
||||||
fmt.Fprint(p, C.GoString(str))
|
|
||||||
fmt.Fprint(p, "\n")
|
|
||||||
|
|
||||||
if err = p.Wait(); err != nil {
|
|
||||||
log.Fatalf("failed to print: %v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printimg(path *C.char) {
|
|
||||||
p, err := escpos.StartUSBPrinter("/dev/usb/lp0", protocol.TMT88IV, escpos.FlagNone)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to start printer: %v\n", err)
|
|
||||||
}
|
|
||||||
defer p.Close()
|
|
||||||
|
|
||||||
if err := p.EnableASB(protocol.ASBReportAll); err != nil {
|
|
||||||
log.Fatalf("failed to enable ASB: %v\n", err)
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
for status := range p.ASBStatus() {
|
|
||||||
log.Printf("received ASB status: %#v\n", status)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
//img, _, err := image.Decode(os.Stdin)
|
|
||||||
//if err != nil {
|
|
||||||
// log.Fatalf("failed to get decode image: %v\n", err)
|
|
||||||
//}
|
|
||||||
//img = resize.Resize(512, 0, img, resize.Lanczos3)
|
|
||||||
//img = dither.Monochrome(dither.FloydSteinberg, img, 1.18)
|
|
||||||
|
|
||||||
// if err := p.SetEncoding(escpos.CharPagePC427); err != nil {
|
|
||||||
// log.Fatalf("failed to set encoding: %v\n", err)
|
|
||||||
// }
|
|
||||||
if err := p.SetPrintSpeed(1); err != nil {
|
|
||||||
log.Fatalf("failed to set print speed: %v\n", err)
|
|
||||||
}
|
|
||||||
//if err := p.PrintImage(img); err != nil {
|
|
||||||
// log.Fatalf("failed to print image: %v\n", err)
|
|
||||||
//}
|
|
||||||
|
|
||||||
//if len(os.Args) > 2 && os.Args[2] != "" {
|
|
||||||
// fmt.Fprintf(p, "\n%s\n", os.Args[2])
|
|
||||||
//}
|
|
||||||
|
|
||||||
fmt.Fprint(p, "\n\n\n")
|
|
||||||
|
|
||||||
if err := p.CutPaper(); err != nil {
|
|
||||||
log.Fatalf("failed to cut paper: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := p.Wait(); err != nil {
|
|
||||||
log.Fatalf("failed to print: %v\n", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {}
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
/* Code generated by cmd/cgo; DO NOT EDIT. */
|
|
||||||
|
|
||||||
/* package command-line-arguments */
|
|
||||||
|
|
||||||
|
|
||||||
#line 1 "cgo-builtin-export-prolog"
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#ifndef GO_CGO_EXPORT_PROLOGUE_H
|
|
||||||
#define GO_CGO_EXPORT_PROLOGUE_H
|
|
||||||
|
|
||||||
#ifndef GO_CGO_GOSTRING_TYPEDEF
|
|
||||||
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Start of preamble from import "C" comments. */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of preamble from import "C" comments. */
|
|
||||||
|
|
||||||
|
|
||||||
/* Start of boilerplate cgo prologue. */
|
|
||||||
#line 1 "cgo-gcc-export-header-prolog"
|
|
||||||
|
|
||||||
#ifndef GO_CGO_PROLOGUE_H
|
|
||||||
#define GO_CGO_PROLOGUE_H
|
|
||||||
|
|
||||||
typedef signed char GoInt8;
|
|
||||||
typedef unsigned char GoUint8;
|
|
||||||
typedef short GoInt16;
|
|
||||||
typedef unsigned short GoUint16;
|
|
||||||
typedef int GoInt32;
|
|
||||||
typedef unsigned int GoUint32;
|
|
||||||
typedef long long GoInt64;
|
|
||||||
typedef unsigned long long GoUint64;
|
|
||||||
typedef GoInt64 GoInt;
|
|
||||||
typedef GoUint64 GoUint;
|
|
||||||
typedef size_t GoUintptr;
|
|
||||||
typedef float GoFloat32;
|
|
||||||
typedef double GoFloat64;
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#include <complex.h>
|
|
||||||
typedef _Fcomplex GoComplex64;
|
|
||||||
typedef _Dcomplex GoComplex128;
|
|
||||||
#else
|
|
||||||
typedef float _Complex GoComplex64;
|
|
||||||
typedef double _Complex GoComplex128;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
static assertion to make sure the file is being used on architecture
|
|
||||||
at least with matching size of GoInt.
|
|
||||||
*/
|
|
||||||
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];
|
|
||||||
|
|
||||||
#ifndef GO_CGO_GOSTRING_TYPEDEF
|
|
||||||
typedef _GoString_ GoString;
|
|
||||||
#endif
|
|
||||||
typedef void *GoMap;
|
|
||||||
typedef void *GoChan;
|
|
||||||
typedef struct { void *t; void *v; } GoInterface;
|
|
||||||
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* End of boilerplate cgo prologue. */
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern void cut(char* path);
|
|
||||||
extern void print_text(char* path, char* str);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
48
print.py
Normal file
48
print.py
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
dev_path="/dev/usb/lp0"
|
||||||
|
from format_image import *
|
||||||
|
from PIL import Image
|
||||||
|
import ctypes
|
||||||
|
import io
|
||||||
|
import time
|
||||||
|
|
||||||
|
printer = ctypes.CDLL('./epson/library_bridge.so')
|
||||||
|
|
||||||
|
def print_text(text):
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
printer.print_text(b"/dev/usb/lp0", text.encode('utf-8'))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
|
||||||
|
def cut_paper():
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
printer.cut(b"/dev/usb/lp0")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
def print_image(image):
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
Bytes = io.BytesIO()
|
||||||
|
image.save(Bytes, format='PNG')
|
||||||
|
Bytes = Bytes.getvalue()
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
printer.print_image(b"/dev/usb/lp0", Bytes, len(Bytes))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
|
|
||||||
|
# I'm sorry
|
||||||
|
#os.system("cd epson/; ./print_image.sh /tmp/image.png; cd ..")
|
||||||
|
|
||||||
|
#image = format_image("static/text/text.png")
|
||||||
|
#image.save("/tmp/image.png")
|
||||||
|
#print_image(image)
|
||||||
|
#cut_paper()
|
||||||
|
|
||||||
|
|
||||||
2
printer_info.py
Normal file
2
printer_info.py
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
label_width = 100
|
||||||
|
printer_width = 512
|
||||||
22
resources/LICENSE
Normal file
22
resources/LICENSE
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Original work Copyright (c) 2018 Shannon Miwa
|
||||||
|
Modified work Copyright (c) 2019 dtinth
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
94
templates/base.html
Normal file
94
templates/base.html
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Image Upload</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box {
|
||||||
|
flex: 1;
|
||||||
|
text-align: center;
|
||||||
|
margin: 1px;
|
||||||
|
padding: 20px;
|
||||||
|
color: white;
|
||||||
|
background-color: #ff69b4; /* Pink */
|
||||||
|
border: 2px solid #55cdfc; /* Light blue */
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.box:hover {
|
||||||
|
background-color: #f7a8b8; /* Softer pink on hover */
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ff69b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="submit"], select, textarea, input[type="number"] {
|
||||||
|
background-color: #55cdfc;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="submit"]:hover, input[type="number"]:hover, select:hover, textarea:hover {
|
||||||
|
background-color: #f7a8b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: #ff69b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 3px solid #55cdfc;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 2px solid #ff69b4;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<a href="text" class="box">
|
||||||
|
<div>Text</div>
|
||||||
|
</a>
|
||||||
|
<a href="image" class="box">
|
||||||
|
<div>Image</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
25
templates/image.html
Normal file
25
templates/image.html
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>Upload Image</h1>
|
||||||
|
<form method="POST" action="/image" enctype="multipart/form-data">
|
||||||
|
<input type="file" name="image">
|
||||||
|
<input type="submit" value="Upload">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{% if filename %}
|
||||||
|
<br><br>
|
||||||
|
<img src="user_data/{{filename}}" alt="Uploaded image">
|
||||||
|
|
||||||
|
<form method="POST" action="/image-print">
|
||||||
|
{% if cut %}
|
||||||
|
<input type="checkbox" name="cut" value="cut" checked>
|
||||||
|
{%else %}
|
||||||
|
<input type="checkbox" name="cut" value="cut">
|
||||||
|
{%endif%}
|
||||||
|
<label for="cut"> Cut paper after printing </label><br>
|
||||||
|
|
||||||
|
<input type="submit" value="Print" style="font-size: 2em; padding: 20px 40px;">
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
|
@ -33,8 +33,7 @@
|
||||||
|
|
||||||
{% if filename %}
|
{% if filename %}
|
||||||
<br><br>
|
<br><br>
|
||||||
<img style="border: 1px solid blueviolet;"
|
<img src="user_data/{{filename}}" alt="Generated Image">
|
||||||
src="{{ url_for('generated_file', filename=filename) }}" alt="Uploaded Image">
|
|
||||||
|
|
||||||
<form method="POST" action="/text-print">
|
<form method="POST" action="/text-print">
|
||||||
{% if cut %}
|
{% if cut %}
|
||||||
|
|
@ -44,7 +43,7 @@
|
||||||
{%endif%}
|
{%endif%}
|
||||||
<label for="cut"> Cut paper after printing </label><br>
|
<label for="cut"> Cut paper after printing </label><br>
|
||||||
|
|
||||||
<input type="submit" value="Print">
|
<input type="submit" value="Print" style="font-size: 2em; padding: 20px 40px;">
|
||||||
</form>
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
9
test.py
9
test.py
|
|
@ -1,9 +0,0 @@
|
||||||
import ctypes
|
|
||||||
|
|
||||||
mylib = ctypes.CDLL('./library_bridge.so')
|
|
||||||
|
|
||||||
mylib.print_text("/dev/usb/lp0".encode('utf-8'), "test\n".encode('utf-8'))
|
|
||||||
mylib.print_text("/dev/usb/lp0".encode('utf-8'), "test\n".encode('utf-8'))
|
|
||||||
mylib.print_text("/dev/usb/lp0".encode('utf-8'), "test\n".encode('utf-8'))
|
|
||||||
|
|
||||||
mylib.cut("/dev/usb/lp0".encode('utf-8'))
|
|
||||||
Loading…
Reference in a new issue