po/src/include/print.printer.php

247 lines
7.9 KiB
PHP

<?php
// Copyright (C) 2017 Solomon Peachy (pizza@shaftnet.org)
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
include_once "config.php";
include_once "common.php";
include_once "site.php";
function photo_print_queue_one($database, $photo, $version, $printer) {
global $strings;
global $po_user;
global $passwords;
$output = "";
$photo_data = pg_fetch_assoc(pg_query($database, "select users, hide_original, title, can_access_photo(photo.identifier, $po_user[id], '{".$passwords."}') as ok from photo where identifier = $photo"));
/* Make sure we can access it! */
if (($photo_data['users'] != $po_user['id']) &&
!($po_user['type'] == PO_USER_TYPE_ADMIN)) {
if (($photo_data['ok'] != 't') || ($photo_data['hide_original'] != 't')) {
return "XXX permission denied: $photo \n";
}
}
$element = array();
$element['version'] = $version;
$element['photo'] = $photo;
$element['title'] = $photo_data['title'];
$element['user'] = $po_user;
$element['owner'] = $photo_data['users'];
$element['printer'] = $printer;
$element['size'] = 4;
$serialized = base64_encode(serialize($element));
/* This is implicitly ROW EXCLUSIVE locked */
pg_query($database, "INSERT INTO pending_prints(identifier, users, version, print_data)
VALUES (nextval('pending_prints_sequence'), $po_user[id],
$version, '$serialized')");
return $output;
}
function photo_print_single($database, $single) {
global $strings;
global $image_repository_path;
global $sys_convert;
global $sys_gm;
global $use_gm;
global $sys_lp;
global $tmp_volume_path;
global $icc_profiles;
$retval = FALSE;
$output = "";
$rotate = FALSE;
$crop_factor_x = 0;
$crop_factor_y = 0;
$printer = $single['printer'];
$version = $single['version'];
$title = $single['title'];
if ($title == "")
$title = $strings['photo_no_title'] ." - $single[photo]";
$query = "select f.path as original_path, v.original_image_name, f.x_res, f.y_res, v.colorspace
from photo_version v, files f
where v.identifier = $version and v.identifier = f.version and (f.size = $single[size] or f.size = 0) order by f.size desc";
# print "-- $query\n";
$photo_version_data = pg_query($database, $query);
$photo_version_single = pg_fetch_assoc($photo_version_data, 0);
$file_name = $image_repository_path."/".$photo_version_single['original_path'];
$native_x = $photo_version_single['x_res'];
$native_y = $photo_version_single['y_res'];
$original_name = $photo_version_single['original_image_name'];
$colorspace = $photo_version_single['colorspace'];
if (($printer['target_x'] > $printer['target_y'] && $native_x < $native_y) ||
($printer['target_x'] < $printer['target_y'] && $native_x > $native_y)) {
$rotate = TRUE;
}
/* check for the source file's existence */
if (!is_file($file_name)) {
$output .= err_str($strings['errors_file_not_found'] ." : ". sprintf($strings['export_skipped'],emit_a(generate_link('photo', $single['photo']), $title)));
return $output . "<br>\n";
}
$output .= "<li>Printing $original_name - $single[photo]:$single[version]:$single[size] on $printer[queue_name] at $printer[target_x]x$printer[target_y]</li>\n";
# Figure out scaling factor so we can crop sanely.
if ($rotate)
$in_ratio = $native_y / $native_x;
else
$in_ratio = $native_x / $native_y;
if ($in_ratio < 1) {
$target_min = $printer['target_x'];
$target_max = $printer['target_y'];
} else {
$in_ratio = 1 / $in_ratio;
$target_min = $printer['target_y'];
$target_max = $printer['target_x'];
}
# $output .= "<li>$native_x $native_y $target_min $target_max $in_ratio</li>";
# generate sane filename
$tmp_filename = tempnam($tmp_volume_path, "po.print.");
unlink($tmp_filename);
$tmp_filename .= ".ppm";
# set up processing
if ($use_gm) {
$cmdline = "$sys_gm convert ";
} else {
$cmdline = "$sys_convert";
}
$cmdline .= " " . escapeshellarg($file_name) ." ";
# rotate if needed
if ($rotate) {
$cmdline .= " -rotate 90 ";
}
# scale to fill the target area
$cmdline .= " -resize ".$printer['target_x']."x".$printer['target_y']."^";
# crop to final
$cmdline .= " -gravity center -extent ".$printer['target_x']."x".$printer['target_y'];
# sharpen as needed
$cmdline .= " -unsharp ". escapeshellarg("0x". $printer['sharpen_sigma'] ."+". $printer['sharpen_amount'] ."+". $printer['sharpen_threshold']) . " ";
# Apply color correction
if (isset($printer['icc_profile']) &&
strlen($printer['icc_profile'])) {
$iccname = "im/" . $printer['icc_profile'];
if (is_file($iccname)) {
if ($colorspace != 99) {
$cmdline .= " +profile icm -profile " . escapeshellarg($icc_profiles[$colorspace]['file']);
}
$cmdline .= " -profile ". escapeshellarg($iccname) . " +profile icm ";
}
}
# Output filename
$cmdline .= " " . escapeshellarg($tmp_filename);
# $output .= "<pre>$cmdline</pre>\n";
system($cmdline, $retval);
if ($retval) {
$output .= err_str("FAILED: >>><pre>$cmdline</pre><<< $retval\n");
return $output;
}
# Set up printing.
$cmdline = "$sys_lp";
if ($printer['hostname']) {
$cmdline .= " -h $printer[hostname] ";
}
$cmdline .= " -d '$printer[queue_name]' ";
$cmdline .= " -t '$single[photo]:$single[version]:$original_name' ";
$cmdline .= " -o PageSize=$printer[pagesize] -o PageRegion=$printer[pagesize] -o ImageableArea=$printer[pagesize] -o PaperDimension=$printer[pagesize] ";
foreach ($printer['options'] as $opt) {
$cmdline .= " -o '$opt' ";
}
$cmdline .= " $tmp_filename ";
if (!$retval) {
# $output .= "<pre>$cmdline</pre>\n";
system($cmdline, $retval);
if ($retval) {
$output .= err_str("FAILED: >>><pre>$cmdline</pre><<< $retval\n");
return $output;
}
}
unlink($tmp_filename);
return $output;
}
function photo_print_worker($database, $userid = FALSE, $background = TRUE) {
while (TRUE) {
$output = '';
$add = '';
if ($userid !== FALSE) {
$add = " where users = $userid ";
}
/* Obtain a row from the database */
pg_query($database, "BEGIN");
$result = pg_query($database, "LOCK TABLE pending_prints IN SHARE ROW EXCLUSIVE MODE");
if ($result === FALSE) {
pg_query($database, "ABORT");
break;
}
$data = pg_query($database, "select identifier, print_data from pending_prints $add order by identifier LIMIT 1");
if ($data !== FALSE && pg_num_rows($data) >= 1) {
$row = pg_fetch_row($data);
pg_query($database, "delete from pending_prints where identifier = $row[0]");
$result = pg_query($database, "COMMIT");
} else {
$result = pg_query($database, "ABORT");
break;
}
if ($result === FALSE) # Just in case!
break;
$single = unserialize(base64_decode($row[1]));
$output .= photo_print_single($database, $single);
if ($background) {
$po_user = $single['user'];
$output = pg_escape_string($database, $output);
$foo = pg_query($database, "insert into print_results(users, log_data) values ($po_user[id], '$output')");
} else {
print $output;
}
}
}