Bitmap/PPM conversion through a pipe
From Rosetta Code
Using the data storage type defined on this page for raster images, delegate writing a JPEG file through a pipe using the output_ppm function defined on this other page.
There are various utilities that can be used for this task, for example: cjpeg (package "jpeg-progs" on Linux), ppmtojpeg (package "netpbm" on Linux), convert (from ImageMagick, multi-platform).
Contents |
[edit] C
Works with: POSIX version .1-2001 This one uses the ImageMagick convert tool.
/* interface */
void print_jpg(image img, int qual);
#define MAXCMDBUF 100
void print_jpg(image img, int qual)
{
char buf[MAXCMDBUF];
unsigned int n;
FILE *pipe;
snprintf(buf, MAXCMDBUF, "convert ppm:- -quality %d jpg:-", qual);
pipe = popen(buf, "w");
if ( pipe != NULL )
{
fprintf(pipe, "P6\n%d %d\n255\n", img->width, img->height);
n = img->width * img->height;
fwrite(img->buf, sizeof(pixel), n, pipe);
pclose(pipe);
}
}
The code that writes to the pipe is the same of output_ppm of course. A complete example is
#include "imglib.h"
int main()
{
image img;
img = alloc_img(100,100);
fill_img(img, 50, 20, 200);
draw_line(img, 0, 0, 80, 80, 255, 0, 0);
print_jpg(img, 75);
free_img(img);
}
In order to make it working, you must link it with the raster image functions given by the codes here and here
[edit] OCaml
let print_jpeg ~img ?(quality=96) () =
let cmd = Printf.sprintf "cjpeg -quality %d" quality in
(*
let cmd = Printf.sprintf "ppmtojpeg -quality %d" quality in
let cmd = Printf.sprintf "convert ppm:- -quality %d jpg:-" quality in
*)
let ic, oc = Unix.open_process cmd in
output_ppm ~img ~oc;
try
while true do
let c = input_char ic in
print_char c
done
with End_of_file -> ()
;;
[edit] Ruby
Extends Write ppm file#Ruby. Uses the ImageMagick convert tool.
Additionally, for debugging, allow writing in pixmap P3 (ascii) format.
class Pixmap
PIXMAP_FORMATS = ["P3", "P6"] # implemented output formats
PIXMAP_BINARY_FORMATS = ["P6"] # implemented output formats which are binary
def write_ppm(ios, format="P6")
if not PIXMAP_FORMATS.include?(format)
raise NotImplementedError, "pixmap format #{format} has not been implemented"
end
ios.puts format, "#{@width} #{@height}", "255"
ios.binmode if PIXMAP_BINARY_FORMATS.include?(format)
@height.times do |y|
@width.times do |x|
case format
when "P3" then ios.print @data[x][y].values.join(" "),"\n"
when "P6" then ios.print @data[x][y].values.pack('C3')
end
end
end
end
def save(filename, opts={:format=>"P6"})
File.open(filename, 'w') do |f|
write_ppm(f, opts[:format])
end
end
def print(opts={:format=>"P6"})
write_ppm($stdout, opts[:format])
end
def save_as_jpeg(filename, quality=75)
pipe = IO.popen("convert ppm:- -quality #{quality} jpg:#{filename}", 'w')
write_ppm(pipe)
pipe.close
end
end
image = Pixmap.open('file.ppm')
image.save_as_jpeg('file.jpg')
[edit] Tcl
Referring to Write ppm file#Tcl and Basic bitmap storage#Tcl
Library: Tk
package require Tk
proc output_jpeg {image filename {quality 75}} {
set f [open |[list convert ppm:- -quality $quality jpg:- > $filename] w]
fconfigure $f -translation binary
puts -nonewline $f [$image data -format ppm]
close $f
}
However, it is more normal to do this directly with the Library: TkImg which is bundled with many Tcl distributions.
package require Tk
package require img::jpeg
proc output_jpeg {image filename} {
$image write $filename -format jpeg
}
set img [image create photo -filename filename.ppm]
output_jpeg $img filename.jpg







