How do I fix this error with ImageMagick? - php

I'm using ImageMagick to convert a RAW file (*.nef extension) into a JPEG image. I'm actually doing this from within PHP, but not using the IMagick extension (I spent too much time banging my head against a wall trying to get that working that eventually I just gave up). Instead, I'm using PHP's exec() function to call ImageMagick from the command line and just do the manipulations there.
Anyways, I wrote a simple PHP script to do this -- to convert the NEF image into a JPEG image -- and it worked! I ran it through a number of tests. When the JPEG didn't exist, it created it. When the JPEG already did exist, it overwrote it. Perfect!
Until today. I made that script last Friday. Today (Monday), when it tried to use it, it stopped working. I literally changed nothing about it, but a couple days later it's failing all the same tests that I ran on Friday. I can retrieve the output from the command line, and these are the errors it's encountering this time around:
Magick: `%s' (%d) dcraw.exe -4 -w -O "C:/Windows/TEMP/magick-iDvVnHw-.ppm" "C:/Windows/TEMP/magick-hYeYwWRd" # error/utility.c/SystemCommand/2094.
Magick: delegate failed `dcraw.exe -4 -w -O "%u.ppm" "%i"' # error/delegate.c/InvokeDelegate/1058.
Magick: unable to open image `C:/Windows/TEMP/magick-iDvVnHw-.ppm': No such file or directory # error/blob.c/OpenBlob/2588.
Magick: missing an image filename `E:\test.jpg' # error/convert.c/ConvertImageCommand/3015.
These errors didn't show up on Friday. Why are they showing up now? What do they mean? And what can I do about them? Thanks in advance.

I had a similar error on linux:
No such file or directory # error/blob.c/OpenBlob/2709. convert: no images defined `/tmp/transform_5c88983-1.jpg' # error/convert.c/ConvertImageComman
The problem was a special character in my german picturename:
images/1/14/Ministerium-für-Bildung.jpg
I went into the folder and created a symlink without the character:
ln -s Ministerium-für-Bildung.jpg Ministerium-fr-Bildung.jpg

Well, I was able to solve it. I did two things, and I'm not entirely sure that the first thing had any impact or not, but I'll mention both for anyone else struggling. First, since it seemed to be having trouble with a temp file, I changed the Windows security/permissions on the C:\Windows\TEMP folder to explicitly allow IIS_USER full control, as well as Everyone.
But secondly, and more importantly, I changed the command I was passing into exec(). Previously my command looked something like this:
$cmd = 'C: & "C:\\Program Files (x86)\\ImageMagick\\convert.exe" ';
$cmd .= '"E:\\test.nef" "E:\\test.jpg" 2>&1';
exec($cmd, $output, $return);
So instead I specified a new "temp" directory, and set the current path, like so:
$cmd = 'SET MAGICK_TMPDIR=E:\\Temp&SET path=C:\\Program Files (x86)\\;%path%& ';
$cmd .= '"C:\\Program Files (x86)\\ImageMagick\\convert.exe" ';
$cmd .= '"E:\\test.nef" "E:\\test.jpg" 2>&1';
exec($cmd, $output, $return);
And that did the trick! The script is working again.

Related

php magick (not imagick library) using ufraw-batch conversion from raw to jpeg not working

I am trying to convert a variety of raw images into jpeg files using php, an exec call directly to magick and have the delegate ufraw convert the image.
I'm doing it this way because the imagick library didn't give me the results I wanted.
This is my script:
exec('/usr/local/bin/magick /path/to/image/CRW_7864.CRW -compress jpeg -quality 50 /path/to/image/CRW_7864.jpeg 2>&1', $output);
var_dump($output);
The dump is so that I can see all the outputs. The call in the delegates.xml file for imagemagick doesn't have --silence so that I can see all the output for it. The delegate line looks like this:
<delegate decode="dng:decode" command="/usr/local/bin/ufraw-batch --out-type=jpeg "--output=%u" "%i""/>
The conversion fails:
array(3) { [0]=> string(53) "ufraw-batch: Loaded /var/tmp/magick-36451MMV_GgkGDl9p" [1]=> string(193) "ufraw-batch: overwrite '/var/tmp/magick-36451iMjYJmSd4yhV'? [y/N] magick: delegate failed `/usr/local/bin/ufraw-batch --out-type=jpeg '--output=%u' '%i'' # error/delegate.c/InvokeDelegate/1897." [2]=> string(125) "magick: unable to open image '/var/tmp/magick-36451iMjYJmSd4yhV.ppm': No such file or directory # error/blob.c/OpenBlob/3496." }
Now here's the weird thing, the code for ufraw (in delegates.xml) works when I input it directly into terminal.
I have set the permissions so that the user (set in my .htdoc) has access to all relevant image files
From what I can tell, ufraw takes the image sent by magick to it and accepts it. Then it tries to move it to somewhere and overwrite another temp file? Then falls down.
I have spent 3-4 days on this now and I am stumped. Any help or clarity would be greatly appreciated.
Running:
Apache 2.4.43
php 7.4.6_1
imagemagick 7.0.10-18
I had an epiphany late last night.
when ufraw saves the temp file it takes from Magick, it uses the name it gets from Magick. However, Magick then looks for a file with the filetype '.ppm'
Therefore I have to force the overwrite, and change the delegate command so that ufraw saves the temp file with the '.ppm' at the end
<delegate decode="dng:decode" command="/usr/local/bin/ufraw-batch --out-type=jpeg --overwrite "--output=%u.ppm" "%i""/>
This worked. I can now run the original exec command and convert the '.CRW' to '.JPEG'.
Some things to point out that I learned from all this:
ImageMagick delegates command code needs to be tested in command line before you rely on it. If the delegate falls over, you won't know why, it will just fail.
Feedback is essential. in the exec call, have the stdout and stderr output so you can see what is going on. Add 2>&1 to the end of the call. (See original exec call)
Add --verbose to the exec call to see more information about what is going on.
Remove `--silence' from the ufraw delegate command (in imagemagick) when testing it in command line. This gives you more feedback.
Be mindful of your permissions (who owns what and who can do what to which), file types (what different programs are looking for) and naming.
Use full paths to programs within programs.
UPDATE
I continued to work on this for other RAW types (ARW, NEF, etc) and I found that ufraw was struggling to identfy some of these (temp files don't have the extensions). It was treating them as .tiff files and not being able to handle the conversion.
The answer to this was given to me by a user on here. Uploading of camera RAW files to a web server. File type issue. Is there a work around?
Basically, when you call imageMagick on a temp file you should prefix the file type to the call. This will tell ImageMagick what delegate to use for it.
exec('/usr/local/bin/magick ARW:/path/to/image/tempfile -verbose -compress jpeg -quality 50 /path/to/image/filename.jpeg 2>&1', $output);

PHP exec() with Pygments for PHP

I'm currently using the Pygments for PHP plugin that is located here: http://derek.simkowiak.net/pygments-for-php/.
The line that actually calls Pygments from that code is an exec() passed: pygmentize -f html $extra_opts -l $language $temp_name as the command. This all works fine, and I get back the output and it is formatted by the plugin.
What I would like to happen at the same time is for Pygments to create an image of it, so I pass exec() a similar command: pygmentize -f png $extra_opts -l $language -o $full_image_path/$output_file.png $temp_name This is where I run into a problem. The image never shows up in the expected folder.
However, if I var_dump() that command string before I exec() it and take it and run it straight from the command line, it works fine.
I have tried echoing exec('whoami') which tells me that the PHP user is www-data. I've tried giving permissions to www-data and changing ownership to www-data on the folder where I store the images. I've also tried changing permissions to 777 just to see what would happen, and the answer is nothing.
Is there something I'm missing? I'm running out of ideas to try. Thank you!
Edit: Another thing that I've checked is the output from the exec command, and the return value. It outputs an empty array, and it returns 1 as the return value.
Edit 2: After seeing that that directory should be writeable/readable for the PHP user, is it possible that pygments doesn't have permission to write it as a specific user? I'm not sure this makes sense, as when I run it myself it works fine, and in fact, when PHP runs it with the HTML lexer, it is able to run. I'm not very experienced in Python, so I don't know if this is a potential issue.
I guess you cannot do it like this.
$output_file.png
Try
$file = $output_file.".png"
and substitute in the exec
Ended up being an issue with the font that was installed for use by the www-root user. Apparently the one that is used by default for Pygments was installed only for the user that I was running as when I use the command line.
The way I was able to figure this out, was running
exec("$command 2>&1", $out, $code);.
The extra 2>&1 redirects stderr into the output for me to see the issue.
The $out parameter showed the FontNotFound error that pygments was throwing.
I changed the font that Pygments used via the command line using: full,style=manni,cssclass=pygmentize_kbOKBd,font_name='DejaVu Sans Mono' -l php -o /srv/www/path/to/images/uploads/2513732976ad4b7.02729290.png /tmp/pygmentize_kbOKBd after finding which fonts I had available to me.
To see which fonts I had available to me as the user running the script, I just ran fc-list in an exec() command for Ubuntu, and checked the output of that for the list of available fonts.

File not found, but files are present

I'm working on a server where users should be able to run protein sequences against a database, and it uses an executable called blastall. The server generates an executable which it should then run using batch. However, it doesn't appear to be running. Here is an example of an executable is generates (cmd.sh):
#!/usr/bin/env sh
cd /var/www/dbCAN
php -q /var/www/dbCAN/tools/blast.php -e -w /var/www/dbCAN/data/blast/20121019135548
Where the crazy number at the end of that is an auto-generated job ID based on when the job was submitted. There are 2 issues, and I'm trying to solve one at a time. The first issue is that when manually executed (by me simply running ./cmd.sh), I get the following errors:
sh: 1: /var/www/dbCAN/tools/blast/bin/blastall: not found
sh: 1: /var/www/dbCAN/tools/blast/bin/blastall: not found
sh: 1: -t: not found
But this doesn't really make sense to me, as the directory specified does in fact contain blastall. It has full rwx permissions and every directory along the way has appropriate permissions.
The blast.php file in tools looks like this:
try {
do_blast($opts["w"]);
$info['status'] = 'done';
$fp = fopen("$opts['w']/info.yaml","w")
fwrite($fp, Sypc::YAMLDump($info)); fclose($fp);
}
With of course variable declarations above it, and the do_blast function looks like this (again with variables declared above it and a cd so the directories work out):
function do_blast($workdir)
{
system("/var/www/dbCAN/tools/blast/bin/blastall -d data/blast/all.seq.fa -m 9 -p blastp -i $workdir/input.faa -o $workdir/output.txt")
system("/var/www/dbCAN/tools/blast/bin/blastall -d data/blast/all.seq.fa -p blastp -i $workdir/input.faa -o $workdir/output2.txt")
}
Any idea what may be causing this issue? I thought it may be because I'm running it and it was created by apache, but rwx is allowed for all users. I can include more information if needed, but I chose not to at this point because the original person who wrote the PHP split up everything into tons of little files, so it's difficult to pinpoint where the problem is exactly. Any ideas (if not complete solutions) are very appreciated.
EDIT: Solution found. As it turns out, the blastall executable had been compiled on a different linux system. Switched to a different executable and it ran flawlessly.
Could it be an issue with relative paths in your script? See my answer here, maybe it helps:
finding a file in php that is 4 directories up
The solution was to recompile the blastall executable. It had been compiled for Redhat and I am using Ubuntu. Unfortunately I assumed the executable I was given was for my system, not the previous one.

Exec command doesn't work as expected

I'm trying to launch a CLI command from a PHP script:
in particular I wanna use this command convert a.png a.tif to convert an image to tiff.
When I launch this command from CLI it works as expected but if I launch from a PHP script with the following code it doesn't create any tiff image in my folder:
$exec = "convert a.png a.tif";
exec($exec,$yaks,$err);
echo "<pre>";
print_r($yaks);
echo "$err";
echo "</pre>";
Moreover $yaks is empty and $err is set to 127.
I'm not an expert, why this doesn't work as expected?
Best regards
UPDATE
I used this command instead $exec = "convert 4.png 4.tif 2>&1"; and I got in return [0] => sh: convert: command not found
This seems to me strange since I can use it from CLI!
FINAL UPDATE
Thanks a lot guys!
$exec = "/usr/local/bin/convert a.png a.tif";
This command solved the problem!
You're great.
you should enter fullpath to "convert" and may be files.
err 127 - file not found
It looks like the 'convert' binary isn't in any of the directories on the PATH PHP is using. You could try using the full path, e.g. /opt/local/bin/convert or whatever the path is.
You could also modify the PATH used by PHP (but I don't know how).
The PHP script probably doesn't know where to find these things you're referring to in the exec command. When you run this from the command line, the shell will look for them in the directory you are in at that point in time; but when you run it from PHP, it probably defaults to the PHP dir and not the specific dir in which your files are. So write out the full path.

Problems when trying to exectue exec("unix2dos xxx") in PHP/Apache

In a previous post, I was trying to update the encoding for a download file from php. One of the suggestions was to run the unix2dos command before sending the file to the user. This works great when I run the command on the linux box, but when I try and run the command from php I get nothing. Here is what I tried:
$cmd = "unix2dos -n $fullPath $downloadFile";
echo exec($cmd, $out, $retVal);
This displays nothing to the screen, $retVal is 0, and $out is an empty string.
echo system($cmd, $retVal);
This displays nothing to the screen, $retVal is 0.
echo shell_exec($cmd);
This displays nothing to the screen.
I have also tried escaping the command and it parameters like:
$cmd = escapeshellcmd($cmd);
and
$cmd = "unix2dos ". escapeshellarg("-n \"$fullPath\" \"$downloadFile\"");
Please let me know if you see something that I am doing wrong.
Thanks!
Edit: Here is some info that may be helpful.
unix2dos version: 2.2 (1995.03.31)
php version 5.2.9
Running in apache 2 on in Redhat Enterprise Linux 4
Have you considered a pure PHP solution?
<?php
$unixfile = file_get_content('/location/of/file/');
$dosfile= str_replace("\n", "\r\n", $unixfile );
file_put_contents('/location/of/file/', $dosfile);
?>
Something like that should do it, although untested :)
Shadi
See which user the PHP exec command is running as:
<?php system('whoami'); ?>
If this command fails then you likely do not have permission to use exec() or system(), so check your INI files. But be sure to check the correct ones! On Debian systems there are separate Apache and CLI INI files stored at /etc/php5/apache/php.ini and /etc/php5/cli/php.ini respectively. Sorry I do not know the locations for RedHat.
If the whoami command succeeds, make sure that the unix2dos command can be run by the user that is shown, and that the same user is allowed to make changes to the files in question by using chmod or chown.
Are you using the full path to unix2dos? Perhaps the executable is in your path for your shell but not in the path that PHP is using.
My implementation of unix2dos produces no output. If the return value is 0 then the command succeeded and your file has been updated.
The only other thing I see is the -n option which my version doesn't seem to have. You should probably check your man page to see what options it supports
unix2dos does not display the file it converts. Therefor you must display it yourself. A very basic way to do it could be :
$cmd = "unix2dos -n $fullPath $downloadFile";
echo exec($cmd, $out, $retVal);
include "$fullPath."/".$downloadFile;
Using include is pretty dirty but quick and easy. A cleaner way would be to use fopen and read the file then display it.
You'd better create a function that enclose all the operation : conversion + display so you'll have everything at hands.
But, If I were you, I'd prefer to not use exec at all and use FileIterator with a trim on every line so you will not have to care about the carriage return nor deal with a hazardous shell binding.
Not sure about your exact problem, but debugging suggestion:
Try first setting $cmd to ls. See if that works. Then try using /bin/ls (use the full path.)
If those don't work, then there might be a problem with your PHP configuration - there might be a safemode parameter or something which disallows the use of exec(), shell_exec(), or system() functions.
I got the source code from here.
http://www.sfr-fresh.com/linux/misc/unix2dos-2.2.src.tar.gz
I compiled it and then ran the tool. This was my output:
rascher#danish:~/unix2dos$ ./a.out -n 1.txt 2.txt
unix2dos: converting file 1.txt to file 2.txt in DOS format ...
I think the problem is this: the program writes all of its output to stderr, rather than stdout. If you look at the source code, you can see "fprintf(stderr, ...)"
As far as I know, PHP will only read the part of your program's output that is sent to STDOUT. So to overcome this, it seems like you have to redirect the output of your program (unix2dos uses stderr) to stdout. To do this, try something like:
$cmd = "unix2dos -n $fullPath $downloadFile 2>&1"
The "2>" means "redirect stderr" and "&1" means "to stdout".
In either case, I would imagine that the file was converting properly, but since you weren't getting any of the expected output, you thought it was failing. Before making the change, check on the output file to see if it is in DOS or UNIX format.

Categories