CloudFlare suffered a massive security issue affecting all of its customers, including Rosetta Code. All passwords not changed since February 19th 2017 have been expired, and session cookie longevity will be reduced until late March.--Michael Mol (talk) 05:15, 25 February 2017 (UTC)

Bitmap/PPM conversion through a pipe

From Rosetta Code
Task
Bitmap/PPM conversion through a pipe
You are encouraged to solve this task according to the task description, using any language you may know.

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).

C[edit]

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

Go[edit]

(Go 1 should be close)

Using cjpeg:

package main
 
// Files required to build supporting package raster are found in:
// * Bitmap
// * Write a PPM file
 
import (
"fmt"
"math/rand"
"os/exec"
"raster"
)
 
func main() {
b := raster.NewBitmap(400, 300)
// a little extravagant, this draws a design of dots and lines
b.FillRgb(0xc08040)
for i := 0; i < 2000; i++ {
b.SetPxRgb(rand.Intn(400), rand.Intn(300), 0x804020)
}
for x := 0; x < 400; x++ {
for y := 240; y < 245; y++ {
b.SetPxRgb(x, y, 0x804020)
}
for y := 260; y < 265; y++ {
b.SetPxRgb(x, y, 0x804020)
}
}
for y := 0; y < 300; y++ {
for x := 80; x < 85; x++ {
b.SetPxRgb(x, y, 0x804020)
}
for x := 95; x < 100; x++ {
b.SetPxRgb(x, y, 0x804020)
}
}
 
// pipe logic
c := exec.Command("cjpeg", "-outfile", "pipeout.jpg")
pipe, err := c.StdinPipe()
if err != nil {
fmt.Println(err)
return
}
err = c.Start()
if err != nil {
fmt.Println(err)
return
}
err = b.WritePpmTo(pipe)
if err != nil {
fmt.Println(err)
return
}
err = pipe.Close()
if err != nil {
fmt.Println(err)
}
}

Mathematica[edit]

This example is untested. Please check that it's correct, debug it as necessary, and remove this message.


convert[img_, out_] := 
Module[{pipe =
StartProcess[{"WolframKernel", "-noinit", "-noprompt", "-run",
"Export[\"out.jpg\",ImportString[InputString[],\"PPM\"]]"}]},
WriteString[pipe, ExportString[Image[Graphics[]], "PPM"]];
Close[pipe];];

OCaml[edit]

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 -> ()
;;

PicoLisp[edit]

# Create an empty image of 120 x 90 pixels
(setq *Ppm (make (do 90 (link (need 120)))))
 
# Fill background with green color
(ppmFill *Ppm 0 255 0)
 
# Draw a diagonal line
(for I 80 (ppmSetPixel *Ppm I I 0 0 0))
 
# Write to "img.jpg" through a pipe
(ppmWrite *Ppm '("convert" "-" "img.jpg"))


Racket[edit]

 
(define (ppm->jpeg bitmap [jpg-file "output"] [quality 75])
(define command (format "convert ppm:- -quality ~a jpg:~a.jpg" quality jpg-file))
(match-define (list in out pid err ctrl) (process command))
(bitmap->ppm bitmap out)
(close-input-port in)
(close-output-port out))
 
(ppm->jpeg bm)

Ruby[edit]

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, "[email protected]} [email protected]}", "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')

Tcl[edit]

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

zkl[edit]

Translation of: C

Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

Using the convert utility by ImageMagick:

img:=PPM.readPPMFile("fractal.ppm");
p:=System.popen(0'|convert ppm:- jpg:"fractal.jpg"|,"w");
img.write(p); p.close();