Bitmap/PPM conversion through a pipe: Difference between revisions
Content added Content deleted
mNo edit summary |
|||
Line 4: | Line 4: | ||
There are various utilities that can be used for this task, for example: '''cjpeg''' (package ''"jpeg-progs"'' on Linux, or ''"media-libs/libjpeg-turbo"'' on Gentoo), '''ppmtojpeg''' (package ''"netpbm"'' on Linux), '''convert''' (from ''ImageMagick'', multi-platform). |
There are various utilities that can be used for this task, for example: '''cjpeg''' (package ''"jpeg-progs"'' on Linux, or ''"media-libs/libjpeg-turbo"'' on Gentoo), '''ppmtojpeg''' (package ''"netpbm"'' on Linux), '''convert''' (from ''ImageMagick'', multi-platform). |
||
=={{header|ATS}}== |
|||
I use the <code>magick</code> command from ImageMagick. You need all the source files from [[Bitmap#ATS]], [[Bitmap/Read_a_PPM_file#ATS]], and [[Bitmap/Write_a_PPM_file#ATS]]. (You do ''not'' need the files from [[Grayscale_image#ATS]].) |
|||
<syntaxhighlight lang="ats"> |
|||
(* This program uses ImageMagick to convert an image, with the target |
|||
file specified according to the conventions of ImageMagick. That |
|||
allows such things as "gif:foobar.jpg" to mean a GIF named |
|||
"foobar.jpg". But, if you leave out the "gif:" prefix, ImageMagick |
|||
will make a JPEG. (I notice that one can also insert options to |
|||
magick, although this was an unexpected result of my design.) *) |
|||
(* |
|||
##myatsccdef=\ |
|||
patscc -std=gnu2x -g -O2 -DATS_MEMALLOC_LIBC \ |
|||
-o $fname($1) $1 \ |
|||
bitmap{,_{read,write}_ppm}_task.{s,d}ats |
|||
*) |
|||
#include "share/atspre_staload.hats" |
|||
staload "bitmap_task.sats" |
|||
staload "bitmap_read_ppm_task.sats" |
|||
staload "bitmap_write_ppm_task.sats" |
|||
staload _ = "bitmap_task.dats" |
|||
staload _ = "bitmap_read_ppm_task.dats" |
|||
staload _ = "bitmap_write_ppm_task.dats" |
|||
(*------------------------------------------------------------------*) |
|||
(* There is support for pipe-I/O in libats/libc, but I cannot (at |
|||
least when in a hurry) figure out how it is supposed to be |
|||
used. So, as elsewhere in the "raster graphics operations" |
|||
category, what is not in the prelude itself I implement with the |
|||
foreign function interfaces. :) Using FFI is a typical part of ATS |
|||
programming, and one should get used to doing it. |
|||
Anyway, here is some UNSAFE support for pipe-I/O. *) |
|||
typedef charstar = $extype"char *" |
|||
typedef FILEstar = $extype"FILE *" |
|||
fn {} |
|||
fileref_popen_unsafe (command : string, |
|||
mode : string) |
|||
: Option_vt FILEref = |
|||
let |
|||
val p = $extfcall (ptr, "popen", $UNSAFE.cast{charstar} command, |
|||
$UNSAFE.cast{charstar} mode) |
|||
in |
|||
if iseqz p then |
|||
None_vt () |
|||
else |
|||
Some_vt ($UNSAFE.cast{FILEref} p) |
|||
end |
|||
fn {} |
|||
fileref_pclose_unsafe (f : FILEref) |
|||
: int = (* Returns the exit status of the command. *) |
|||
$extfcall (int, "pclose", $UNSAFE.cast{FILEstar} f) |
|||
(*------------------------------------------------------------------*) |
|||
implement |
|||
main0 (argc, argv) = |
|||
let |
|||
val args = listize_argc_argv (argc, argv) |
|||
val nargs = length args |
|||
val inpf = |
|||
if nargs < 2 then |
|||
stdin_ref |
|||
else if args[1] = "-" then |
|||
stdin_ref |
|||
else |
|||
fileref_open_exn (args[1], file_mode_r) |
|||
val pix_opt = pixmap_read_ppm<rgb24> inpf |
|||
val () = fileref_close inpf |
|||
in |
|||
case+ pix_opt of |
|||
| ~ None_vt () => |
|||
begin |
|||
free args; |
|||
println! ("For some reason, I failed to read the image."); |
|||
exit 1 |
|||
end |
|||
| ~ Some_vt @(pfgc1 | pix1) => |
|||
let |
|||
val outf_name = if nargs < 3 then "-" else args[2] |
|||
val command = string_append ("magick ppm:- ", outf_name) |
|||
val () = free args |
|||
val pipe_opt = |
|||
(* Temporarily treating a strptr as a string, just to make a |
|||
function call of this sort, is not actually unsafe. *) |
|||
fileref_popen_unsafe ($UNSAFE.strptr2string command, "w") |
|||
val () = free command |
|||
in |
|||
case+ pipe_opt of |
|||
| ~ None_vt () => |
|||
begin |
|||
free (pfgc1 | pix1); |
|||
println! ("For some reason, I failed to open a pipe ", |
|||
"to magick."); |
|||
exit 3 |
|||
end |
|||
| ~ Some_vt outf => |
|||
let |
|||
val success = pixmap_write_ppm (outf, pix1) |
|||
in |
|||
ignoret (fileref_pclose_unsafe outf); |
|||
free (pfgc1 | pix1); |
|||
if ~success then |
|||
begin |
|||
println! ("For some reason, I failed to pipe the ", |
|||
"image to magick."); |
|||
exit 2 |
|||
end |
|||
end |
|||
end |
|||
end |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
Using SIPI test image 5.1.12: |
|||
<pre>$ myatscc bitmap_write_through_pipe_task.dats |
|||
$ ./bitmap_write_through_pipe_task 5.1.12.ppm bitmap_write_through_pipe_task_ATS.jpg</pre> |
|||
[[File:Bitmap write through pipe task ATS.jpg|alt=An alarm clock on a book on a book, and a diptych of family portraits. On a table or chest of drawers or some such. Monochrome photograph.]] |
|||
=={{header|C}}== |
=={{header|C}}== |
||
{{works with|POSIX|.1-2001}} |
{{works with|POSIX|.1-2001}} |
||
Line 45: | Line 175: | ||
In order to make it working, you must link it with the raster image functions given by the codes [[Bresenham's_line_algorithm#C|here]] and [[Basic_bitmap_storage#C|here]] |
In order to make it working, you must link it with the raster image functions given by the codes [[Bresenham's_line_algorithm#C|here]] and [[Basic_bitmap_storage#C|here]] |
||
=={{header|Go}}== |
=={{header|Go}}== |
||
{{works with|Go weekly.2011-12-14}} (Go 1 should be close) |
{{works with|Go weekly.2011-12-14}} (Go 1 should be close) |