Inaccurate results from ImageMagick function queryFontMetrics - imagemagick

Imagick::queryFontMetrics does not seem to be working. When I use the metrics provided by queryFontMetrics to size the image, some fonts are still being cut off. Any ideas?
Here's my code:
if (!file_exists($cache['dirname'].'/'.$cache['basename'])) {
try {
$draw = new ImagickDraw();
$draw->setFont($font_path['dirname'].'/'.$font_path['basename']);
$draw->setFontSize($size);
$draw->setGravity(Imagick::GRAVITY_CENTER);
$draw->setFillColor($color);
$canvas = new Imagick();
$metrics = $canvas->queryFontMetrics($draw, $text);
$canvas->newImage($metrics['textWidth'], $metrics['textHeight'], "transparent", "png");
$canvas->annotateImage($draw, 0, 0, 0, $text);
$canvas->setImageFormat('PNG');
mkdir($cache['dirname'], 0777, true);
$canvas->writeImage($cache['dirname'].'/'.$cache['basename']);
header("Content-Type: image/png");
echo $canvas;
$canvas->clear();
$canvas->destroy();
$draw->clear();
$draw->destroy();
} catch(Exception $e) {
// Output an error message
echo 'Error: ', $e->getMessage(), "";
}
} else {
// Output the image
$canvas = new Imagick($cache['dirname'].'/'.$cache['basename']);
header("Content-Type: image/png");
echo $canvas;
}

Okay, it looks like I'll be answering this one myself. After quite a bit of research, I've discovered that it's basically impossible to get correct metrics from the font itself. This is because each font designer could potentially define the metrics differently. The best way to proceed is to simply make the image much larger than necessary (to ensure that no clipping occurs) and then use the trim command: http://www.php.net/manual/en/imagick.trimimage.php.

Related

SWT: Integrate clickable link into StyledText

With the help of this question I was able to figure out how I can display a link inside a StyledText widget in SwT. The color is correct and even the cursor changes shape when hovering over the link.
So far so good, but the link is not actually clickable. Although the cursor changes its shape, nothing happens if clicking on the link. Therefore I am asking how I can make clicking the link to actually open it in the browser.
I thought of using a MouseListener, tracking the click-location back to the respective text the click has been performed on and then deciding whether to open the link or not. However that seems way too complicated given that there already is some routine going on for changing the cursor accordingly. I believe that there is some easy way to do this (and assuring that the clicking-behavior is actually consistent to when the cursor changes its shape).
Does anyone have any suggestions?
Here's an MWE demonstrating what I have done so far:
public static void main(String[] args) throws MalformedURLException {
final URL testURL = new URL("https://stackoverflow.com/questions/1494337/can-html-style-links-be-added-to-swt-styledtext");
Display display = new Display();
Shell shell = new Shell(display);
shell.setLayout(new GridLayout(1, true));
StyledText sTextWidget = new StyledText(shell, SWT.READ_ONLY);
final String firstPart = "Some text before ";
String msg = firstPart + testURL.toString() + " some text after";
sTextWidget.setText(msg);
sTextWidget.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
StyleRange linkStyleRange = new StyleRange(firstPart.length(), testURL.toString().length(), null, null);
linkStyleRange.underline = true;
linkStyleRange.underlineStyle = SWT.UNDERLINE_LINK;
linkStyleRange.data = testURL.toString();
sTextWidget.setStyleRange(linkStyleRange);
shell.open();
while(!shell.isDisposed()) {
display.readAndDispatch();
}
}
Okay I was being a little too fast on posting this question... There's a snippet that deals with exactly this problem and it shows, that one indeed has to use an extra MouseListener in order to get things working.
The snippet can be found here and this is the relevant part setting up the listener:
styledText.addListener(SWT.MouseDown, event -> {
// It is up to the application to determine when and how a link should be activated.
// In this snippet links are activated on mouse down when the control key is held down
if ((event.stateMask & SWT.MOD1) != 0) {
int offset = styledText.getOffsetAtLocation(new Point (event.x, event.y));
if (offset != -1) {
StyleRange style1 = null;
try {
style1 = styledText.getStyleRangeAtOffset(offset);
} catch (IllegalArgumentException e) {
// no character under event.x, event.y
}
if (style1 != null && style1.underline && style1.underlineStyle == SWT.UNDERLINE_LINK) {
System.out.println("Click on a Link");
}
}
}
});

Brother Label printer printing Dark image

I am using Label printer QL-700 from Brother and trying to print a label with image on it.
I am using the following test code :
string templatePath = TEMPLATE_DIRECTORY;
// None decoration frame
if (cmbTemplate.SelectedIndex == 0)
{
templatePath += TEMPLATE_SIMPLE;
}
// Decoration frame
else
{
templatePath += TEMPLATE_FRAME;
}
bpac.DocumentClass doc = new DocumentClass();
if (doc.Open(templatePath) != false)
{
try
{
//doc.GetObject("objCompany").Text = txtCompany.Text;
//doc.GetObject("objName").Text = txtName.Text;
// doc.SetMediaById(doc.Printer.GetMediaId(), true);
doc.SetPrinter("Brother QL-700", true);
bpac.Object ob = doc.GetObject("Photo");
//ob.SetData(0, #"C:\Photo\635466380534236711.png", 4);
doc.StartPrint("", PrintOptionConstants.bpoDefault);
doc.PrintOut(1, PrintOptionConstants.bpoDefault);
doc.EndPrint();
doc.Close();
}
catch(Exception ex)
{
}
}
I have a template and at the runtime I set the image. But the thing is its printing the image too dark. Can anybody suggest how can I fix it ?
I tried
- Changing the brightness of the Printer Properties
- Tried changing the Brightness of the image in the Default image on the Template.
Nothing worked.
Anybody, anything - please suggest.

How to catch .exe not start or fail exception MVC

I try to export chart images to png or pdf with the code below.(I use Asp.Net MVC, Telerik Kendo, Inskcape)
Every user needs to have installed Inkscape software on their computers to get charts exported. I mean, if user doesn't have Inkscape, user can not get image.
So i want to control if user have Inkscape or not. If there is no installed Inkscape, i want to show exception message to related View like "Please install Inkscape to your computers"
How can i do it? With try, catch? If else? I can't get the logic about what i should.
private string DoExport(string svgFile, KendoChartExport.Models.ExportFormat format)
{
var extension = format == KendoChartExport.Models.ExportFormat.PNG ? "png" : "pdf";
var outFile = TempFileName() + "." + extension;
var inkscape = new System.Diagnostics.Process();
inkscape.StartInfo.FileName = INKSCAPE_PATH;
inkscape.StartInfo.Arguments =
String.Format("--file \"{0}\" --export-{1} \"{2}\" --export-width {3} --export-height {4}",
svgFile, extension, outFile, WIDTH, HEIGHT);
inkscape.StartInfo.UseShellExecute = true;
inkscape.Start();
inkscape.WaitForExit();
return outFile;
}
I want to someting like that:
try
{
inkscape.Start();
}
catch (Exception)
{
throw ViewBag.Error = "Please Install Inkscape";
}
Any idea to help?

nicUpload says "Invalid Upload ID", cant make it works

Im trying to implement nicEdit with the nicupload plugin, but when I select a file to upload it says "Failed to upload image", and the server response says "Invalid Upload ID".
This is the code that calls the script and initializes:
<script src="http://js.nicedit.com/nicEdit-latest.js" type="text/javascript"></script>
<script type="text/javascript">//<![CDATA[
bkLib.onDomLoaded(function() {
new nicEditor({uploadURI : '../../nicedit/nicUpload.php'}).panelInstance('area1');
});
//]]>
</script>
The path to nicUpload.php is correct, and the code is the one that can be found in the documentation: http://nicedit.com/src/nicUpload/nicUpload.js
I made the upload folder changes, and set write permissions. According to the documentation (http://wiki.nicedit.com/w/page/515/Configuration%20Options), thats all, but i keep getting errors. Any ideas?
After looking for an solution a long time (lot of posts without real solution), i now fixed the code myself. I'm now able to upload an image to my own server. Thx to firebug and eclipse ;-)
The main problem is that the nicUpload.php is old and not working with the current nicEdit-Upload function.
Missing is the error handling, feel free to add this...
Add the nicEditor to your php file and configure it to use the nicEdit.php:
new nicEditor({iconsPath : 'pics/nicEditorIcons.gif', uploadURI : 'script/nicUpload.php'}
Download the nicEdit.js uncompressed and change the following lines in nicEdit.js:
uploadFile : function() {
var file = this.fileInput.files[0];
if (!file || !file.type.match(/image.*/)) {
this.onError("Only image files can be uploaded");
return;
}
this.fileInput.setStyle({ display: 'none' });
this.setProgress(0);
var fd = new FormData();
fd.append("image", file);
fd.append("key", "b7ea18a4ecbda8e92203fa4968d10660");
var xhr = new XMLHttpRequest();
xhr.open("POST", this.ne.options.uploadURI || this.nicURI);
xhr.onload = function() {
try {
var res = JSON.parse(xhr.responseText);
} catch(e) {
return this.onError();
}
//this.onUploaded(res.upload); // CHANGE HERE
this.onUploaded(res);
}.closure(this);
xhr.onerror = this.onError.closure(this);
xhr.upload.onprogress = function(e) {
this.setProgress(e.loaded / e.total);
}.closure(this);
xhr.send(fd);
},
onUploaded : function(options) {
this.removePane();
//var src = options.links.original; // CHANGE HERE
var src = options['url'];
if(!this.im) {
this.ne.selectedInstance.restoreRng();
//var tmp = 'javascript:nicImTemp();';
this.ne.nicCommand("insertImage", src);
this.im = this.findElm('IMG','src', src);
}
var w = parseInt(this.ne.selectedInstance.elm.getStyle('width'));
if(this.im) {
this.im.setAttributes({
src : src,
width : (w && options.image.width) ? Math.min(w, options.image.width) : ''
});
}
}
Change the nicUpload.php like this
<?php
/* NicEdit - Micro Inline WYSIWYG
* Copyright 2007-2009 Brian Kirchoff
*
* NicEdit is distributed under the terms of the MIT license
* For more information visit http://nicedit.com/
* Do not remove this copyright message
*
* nicUpload Reciever Script PHP Edition
* #description: Save images uploaded for a users computer to a directory, and
* return the URL of the image to the client for use in nicEdit
* #author: Brian Kirchoff <briankircho#gmail.com>
* #sponsored by: DotConcepts (http://www.dotconcepts.net)
* #version: 0.9.0
*/
/*
* #author: Christoph Pahre
* #version: 0.1
* #description: different modification, so that this php file is working with the newest nicEdit.js (needs also modification - #see)
* #see http://stackoverflow.com/questions/11677128/nicupload-says-invalid-upload-id-cant-make-it-works
*/
define('NICUPLOAD_PATH', '../images/uploadedImages'); // Set the path (relative or absolute) to
// the directory to save image files
define('NICUPLOAD_URI', '../images/uploadedImages'); // Set the URL (relative or absolute) to
// the directory defined above
$nicupload_allowed_extensions = array('jpg','jpeg','png','gif','bmp');
if(!function_exists('json_encode')) {
die('{"error" : "Image upload host does not have the required dependicies (json_encode/decode)"}');
}
if($_SERVER['REQUEST_METHOD']=='POST') { // Upload is complete
$file = $_FILES['image'];
$image = $file['tmp_name'];
$id = $file['name'];
$max_upload_size = ini_max_upload_size();
if(!$file) {
nicupload_error('Must be less than '.bytes_to_readable($max_upload_size));
}
$ext = strtolower(substr(strrchr($file['name'], '.'), 1));
#$size = getimagesize($image);
if(!$size || !in_array($ext, $nicupload_allowed_extensions)) {
nicupload_error('Invalid image file, must be a valid image less than '.bytes_to_readable($max_upload_size));
}
$filename = $id;
$path = NICUPLOAD_PATH.'/'.$filename;
if(!move_uploaded_file($image, $path)) {
nicupload_error('Server error, failed to move file');
}
$status = array();
$status['done'] = 1;
$status['width'] = $size[0];
$rp = realpath($path);
$status['url'] = NICUPLOAD_URI ."/".$id;
nicupload_output($status, false);
exit;
}
// UTILITY FUNCTIONS
function nicupload_error($msg) {
echo nicupload_output(array('error' => $msg));
}
function nicupload_output($status, $showLoadingMsg = false) {
$script = json_encode($status);
$script = str_replace("\\/", '/', $script);
echo $script;
exit;
}
function ini_max_upload_size() {
$post_size = ini_get('post_max_size');
$upload_size = ini_get('upload_max_filesize');
if(!$post_size) $post_size = '8M';
if(!$upload_size) $upload_size = '2M';
return min( ini_bytes_from_string($post_size), ini_bytes_from_string($upload_size) );
}
function ini_bytes_from_string($val) {
$val = trim($val);
$last = strtolower($val[strlen($val)-1]);
switch($last) {
// The 'G' modifier is available since PHP 5.1.0
case 'g':
$val *= 1024;
case 'm':
$val *= 1024;
case 'k':
$val *= 1024;
}
return $val;
}
function bytes_to_readable( $bytes ) {
if ($bytes<=0)
return '0 Byte';
$convention=1000; //[1000->10^x|1024->2^x]
$s=array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB');
$e=floor(log($bytes,$convention));
return round($bytes/pow($convention,$e),2).' '.$s[$e];
}
?>
You can manually pass an id to your script: e.g nicUpload.php?id=introPicHeader and it will become introPicHeader.jpg (or appropriate extension) in the images folder you defined.
However, I have noticed that this script is broken and cannot access the configuration option uploadURI if specified directly in nicEdit.js during the nicEditorAdvancedButton.extend({. This causes access to an relatively pathed "Unknown" resource, causing an error.
The documentation implies otherwise and the fact that the nicURI was specified here for imgur.com (maybe as a default) gave me the impression I could also add a uploadURI reference to the nicUpload.php script in a single place rather than on every editor instantiation.
Update
This works if you pass it during instantiation, which I guess does allow for easy dynamic id population.
Unfortunately, the nicUpload.php is riddled with errors and it's output is not JSON. The editor expects to parse JSON and finds a script tag and errors with unexpected token "<".
There are a raft of other errors which I will attempt to identify:
In nicEdit.js
A.append("image") should be infact A.append("nicImage")
this.onUploaded(D.upload) should become this.onUploaded(D)
this.onUploaded(D) should be moved to within the try block after var D=JSON.parse(C.responseText) to fix variable scope issues
B.image.width needs to become B.width
In nicUpload.php
JSON output is not formed correctly, comment out html output and output just json_encode($status).
JSON output needs to return a key/value pair named links rather than url although renaming the var D=B.links to var D=B.url in nicEdit.js would also suffice as a fix.
Both php and javascript code leaves a lot to be desired, I get many errors regularly and have been fixing them myself.

How to work with Images in Dart lang

I'm post a question here before( How to load an image in Dart ) and get answer, but same time get more questions.
Why I'm can draw image only this way:
image.on.load.add((e) {
context.drawImage(image, 0, 0);
});
but if I'm write something like:
ImageElement image = new ImageElement();
image.src = 'myImage.png';
context.drawImage(image, 0, 0);
^^^ this don't work and don't draw image. Why?
bool loaded = false;
ImageElement image = new ImageElement();
image.src = 'myImage.png';
image.on.load.add((e) {
loaded = true;
});
print(loaded); // on console get - false
^^^ why I'm get false? I'm created if image loaded variable loaded become true, but loaded don't become true.
Sorry for my bad English language. Thanks!
As for your first question, if you leave out
image.onLoad.listen((e) {
context.drawImage(image, 0, 0);
});
then no code will be executed when the image is loaded.
The on.load.add(...) construction basically assigns a function (often referred to as a handler) that will be executed when the browser loads the image. If no such function is assigned then nothing happens when the image is loaded and consequently context.drawImage(image, 0, 0) will not work.
Your second questions is related to this function. Loading an image is an asynchronous process, meaning your on load handler (on.load.add(...)) is first fired when the client has successfully loaded the image. This means that after assininging your on load handler execution continues to your next call: print(loaded) which will be false as the image is not loaded yet.
Newer image onload syntax:
readFile() {
ImageElement image = new ImageElement(src: "plant.png");
document.body.nodes.add(image);
image.onLoad.listen(
onData,
onError: onError,
onDone: onDone,
cancelOnError: true
);
}
onData(Event e) {
print("success");
}
onError(Event e) {
print("error: $e");
}
onDone() {
print("done");
}

Resources