Skip to content

Commit a301150

Browse files
authored
Merge pull request pklaus#16 from DL6ER/new/highres
Add high-res printing mode
2 parents a9c79a0 + 6a2a60a commit a301150

10 files changed

Lines changed: 75 additions & 12 deletions

File tree

app/labeldesigner/label.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ def _ensure_pil_image(self, img) -> Image.Image:
6161
except Exception:
6262
pass
6363
raise TypeError("Unsupported image type for resizing. Please provide a PIL.Image.Image or compatible object.")
64+
65+
6466
qr_correction_mapping = {
6567
'M': constants.ERROR_CORRECT_M,
6668
'L': constants.ERROR_CORRECT_L,
@@ -326,6 +328,7 @@ def generate(self, rotate = False):
326328
text_offset = horizontal_offset_text, vertical_offset_text
327329
image_offset = horizontal_offset_image, vertical_offset_image
328330

331+
logger.debug(f"Image resolution: {int(width)} x {int(height)} px")
329332
imgResult = Image.new('RGB', (int(width), int(height)), 'white')
330333

331334
if img is not None:

app/labeldesigner/printer.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,14 @@ def label_size(self):
4545
def label_size(self, value):
4646
self._label_size = value
4747

48-
def add_label_to_queue(self, label, count, cut_once=False):
48+
def add_label_to_queue(self, label, count, cut_once=False, high_res: bool = False):
4949
for cnt in range(0, count):
5050
cut = (cut_once == False) or (cut_once and cnt == count-1)
5151

5252
self._printQueue.append(
5353
{'label': label,
54-
'cut': cut
54+
'cut': cut,
55+
'high_res': high_res
5556
})
5657

5758
def process_queue(self) -> bool:
@@ -80,6 +81,7 @@ def process_queue(self) -> bool:
8081
red='red' in self.label_size,
8182
dither=dither,
8283
cut=queue_entry['cut'],
84+
dpi_600=queue_entry['high_res'],
8385
rotate=rotate)
8486

8587
self._printQueue.clear()

app/labeldesigner/routes.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,13 +120,14 @@ def print_label():
120120
if print_count < 1:
121121
raise ValueError("print_count must be greater than 0")
122122
cut_once = int(request.values.get('cut_once', 0)) == 1
123+
high_res = int(request.values.get('high_res', 0)) != 0
123124
except Exception as e:
124125
return_dict['message'] = str(e)
125126
current_app.logger.exception(e)
126127
# Generate error 400 response
127128
return make_response(jsonify(return_dict), 400)
128129

129-
printer.add_label_to_queue(label, print_count, cut_once)
130+
printer.add_label_to_queue(label, print_count, cut_once, high_res)
130131

131132
try:
132133
status = printer.process_queue()
@@ -184,12 +185,16 @@ def create_label_from_request(request):
184185
'image_bw_threshold': int(d.get('image_bw_threshold', 70)),
185186
'image_fit': int(d.get('image_fit', 1)) > 0,
186187
'print_color': d.get('print_color', 'black'),
187-
'timestamp': int(d.get('timestamp', 0))
188+
'timestamp': int(d.get('timestamp', 0)),
189+
'high_res': int(d.get('high_res', 0)) != 0
188190
}
189191

190-
def get_label_dimensions(label_size):
192+
def get_label_dimensions(label_size, high_res: bool = False):
191193
try:
192-
return [label.dots_printable for label in ALL_LABELS if label.identifier == label_size][0]
194+
dimensions = [label.dots_printable for label in ALL_LABELS if label.identifier == label_size][0]
195+
if high_res:
196+
return [2*dimensions[0], 2*dimensions[1]]
197+
return dimensions
193198
except KeyError:
194199
raise LookupError("Unknown label_size")
195200

@@ -254,7 +259,7 @@ def get_uploaded_image(image):
254259
else:
255260
label_type = LabelType.ROUND_DIE_CUT_LABEL
256261

257-
width, height = get_label_dimensions(context['label_size'])
262+
width, height = get_label_dimensions(context['label_size'], context['high_res'])
258263
if height > width:
259264
width, height = height, width
260265
if label_orientation == LabelOrientation.ROTATED:

app/labeldesigner/templates/labeldesigner.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
<div id="labelMismatch" class="form-text text-danger" style="display: none;">Label size mismatch detected!</div>
3939

4040
<label for="orientation" class="control-label input-group" style="margin-top: 10px; margin-bottom: 0">Label Orientation:</label>
41-
<div class="btn-group btn-group-toggle btn-block" data-toggle="buttons">
41+
<div class="btn-group btn-group-toggle btn-block mb-2" data-toggle="buttons">
4242
<label class="btn btn-secondary {% if default_orientation == 'standard' %}active{% endif %}" id="orientation_standard">
4343
<input type="radio" name="orientation" onchange="preview()" value="standard" aria-label="Standard" {% if
4444
default_orientation=='standard' %}checked data-default="1" {% endif %}>
@@ -50,6 +50,12 @@
5050
<span class="fas fa-ruler-vertical" aria-hidden="true"> Rotated
5151
</label>
5252
</div>
53+
<div class="form-check mb-2">
54+
<input class="form-check-input" type="checkbox" onchange="preview()" id="highResolutionCheckbox" data-default="0">
55+
<label class="form-check-label" for="highResolutionCheckbox">
56+
High-resolution printing (600 dpi)
57+
</label>
58+
</div>
5359
</div>
5460
<!-- class="card-body" -->
5561
</div>

app/static/js/main.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ function formData(cut_once = false) {
163163
border_roundness: $('#borderRoundness').val(),
164164
border_distance_x: $('#borderDistanceX').val(),
165165
border_distance_y: $('#borderDistanceY').val(),
166+
high_res: $('#highResolutionCheckbox').is(':checked') ? 1 : 0
166167
}
167168

168169
if (printer_status['red_support']) {
@@ -173,13 +174,17 @@ function formData(cut_once = false) {
173174
return data;
174175
}
175176

177+
function get_dpi() {
178+
return $('#highResolutionCheckbox').is(':checked') ? 600 : 300;
179+
}
180+
176181
function updatePreview(data) {
177182
setStatus({ 'preview': true });
178183
$('#previewImg').attr('src', 'data:image/png;base64,' + data);
179184
var img = $('#previewImg')[0];
180185
img.onload = function () {
181-
$('#labelWidth').html((img.naturalWidth / default_dpi * 2.54).toFixed(1));
182-
$('#labelHeight').html((img.naturalHeight / default_dpi * 2.54).toFixed(1));
186+
$('#labelWidth').html((img.naturalWidth / get_dpi() * 2.54).toFixed(1));
187+
$('#labelHeight').html((img.naturalHeight / get_dpi() * 2.54).toFixed(1));
183188
};
184189
}
185190

tests/_demo_image_highres.jpg

971 KB
Loading
1.3 MB
Loading

tests/image_highres_grayscale.png

2.4 MB
Loading

tests/simple_high_res.png

7.11 KB
Loading

tests/test_labeldesigner_api.py

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,34 @@ def test_generate_preview(client):
106106
verify_image(response.data, 'tests/simple.png')
107107

108108

109+
def test_generate_preview_high_res(client):
110+
data = EXAMPLE_FORMDATA.copy()
111+
data['high_res'] = 1
112+
data['text'] = json.dumps([
113+
{
114+
'family': 'DejaVu Sans',
115+
'style': 'Book',
116+
'text': 'Left',
117+
'size': '60',
118+
'align': 'left'
119+
},
120+
{
121+
'family': 'Droid Sans Mono',
122+
'style': 'Regular',
123+
'text': '-- LONG MONO TEXT --',
124+
'size': '50',
125+
'align': 'center'
126+
}
127+
])
128+
129+
response = client.post('/labeldesigner/api/preview', data=data)
130+
assert response.status_code == 200
131+
assert response.content_type in ['image/png']
132+
133+
# Check image
134+
verify_image(response.data, 'tests/simple_high_res.png')
135+
136+
109137
def test_generate_preview_inverted(client):
110138
data = EXAMPLE_FORMDATA.copy()
111139
data['text'] = json.dumps([
@@ -260,8 +288,13 @@ def test_generate_qr(client):
260288
verify_image(response.data, 'tests/qr.png')
261289

262290

263-
def image_test(client, image_path: str = "tests/_demo_image.jpg", rotated: bool = False, fit: bool = False, text: bool = False, image_mode: str = "grayscale"):
291+
def image_test(client, image_path: str|None = None, rotated: bool = False, fit: bool = False, text: bool = False, image_mode: str = "grayscale", high_res: bool = False):
264292
data = EXAMPLE_FORMDATA.copy()
293+
if image_path is None:
294+
if high_res:
295+
image_path = "tests/_demo_image_highres.jpg"
296+
else:
297+
image_path = "tests/_demo_image.jpg"
265298
my_file = FileStorage(
266299
stream=open(image_path, "rb"),
267300
filename=os.path.basename(image_path),
@@ -270,6 +303,7 @@ def image_test(client, image_path: str = "tests/_demo_image.jpg", rotated: bool
270303
data['print_type'] = 'image'
271304
data['image'] = my_file
272305
data['image_mode'] = image_mode
306+
data['high_res'] = 1 if high_res else 0
273307

274308
if image_mode == "black":
275309
data['image_bw_threshold'] = '128'
@@ -287,7 +321,7 @@ def image_test(client, image_path: str = "tests/_demo_image.jpg", rotated: bool
287321
}
288322
])
289323

290-
expected_img_path = "tests/image" + ("_rotated" if rotated else "") + ("_fit" if fit else "") + ("_text" if text else "") + "_" + image_mode + ".png"
324+
expected_img_path = "tests/image" + ("_rotated" if rotated else "") + ("_fit" if fit else "") + ("_text" if text else "") + ("_highres" if high_res else "") + "_" + image_mode + ".png"
291325

292326
response = client.post('/labeldesigner/api/preview', data=data)
293327
assert response.status_code == 200
@@ -341,6 +375,14 @@ def test_image_black_fit(client):
341375
image_test(client, image_mode="black", fit=True)
342376

343377

378+
def test_image_highres(client):
379+
image_test(client, high_res=True)
380+
381+
382+
def test_image_highres_fit(client):
383+
image_test(client, high_res=True, fit=True)
384+
385+
344386
def test_generate_template(client):
345387
data = EXAMPLE_FORMDATA.copy()
346388
# Mock current datetime.now

0 commit comments

Comments
 (0)