Bitmap/Read an image through a pipe: Difference between revisions

→‎{{header|Wren}}: Fixed a potential timing issue with FileSystem.load.
No edit summary
(→‎{{header|Wren}}: Fixed a potential timing issue with FileSystem.load.)
 
(30 intermediate revisions by 16 users not shown)
Line 1:
{{task|Raster graphics operations}}
[[Category:Input Output]]
[[Category:Less Than 20 Examples]]
{{task|Raster graphics operations}}
 
This task is the ''opposite'' of the [[PPM conversion through a pipe]]. In this task, using a delegate tool (like '''cjpeg''', one of the netpbm package, or '''convert''' of the ImageMagick package) we read an image file and load it into the data storage type [[Basic bitmap storage|defined here]]. We can also use the code from [[Read ppm file]], so that we can use PPM format like a (natural) bridge between the foreign image format and our simple data storage.
=={{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]].)
 
Because I wrote this program by modifying [[Bitmap/PPM_conversion_through_a_pipe#ATS]], it both reads ''and writes'' the file by piping through the <code>magick</code> command of ImageMagick. The comments at the top of the earlier program thus apply doubly here.
 
<syntaxhighlight lang="ats">
(* I both read AND write the image through pipes connected to
ImageMagick. One can also pass options and such but I won't go into
the details. *)
 
(*
 
##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_name = if nargs < 2 then "-" else args[1]
val command = string_append ("magick ", inpf_name, " ppm:-")
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, "r")
val () = free command
in
case+ pipe_opt of
| ~ None_vt () =>
begin
free args;
println! ("For some reason, I failed to open a pipe ",
"for reading from magick.");
exit 1
end
| ~ Some_vt inpf =>
let
val pix_opt = pixmap_read_ppm<rgb24> inpf
in
ignoret (fileref_pclose_unsafe inpf);
case+ pix_opt of
| ~ None_vt () =>
begin
free args;
println! ("For some reason, I failed to pipe the image ",
"from magick.");
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 ",
"for writing to magick.");
exit 3
end
| ~ Some_vt outf =>
let
val success = pixmap_write_ppm<rgb24> (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
end
</syntaxhighlight>
 
{{out}}
 
Using SIPI test image 4.1.07:
 
<pre>$ myatscc bitmap_read_through_pipe_task.dats
$ ./bitmap_read_through_pipe_task 4.1.07.tiff > 4.1.07.ppm
$ file 4.1.07.ppm
4.1.07.ppm: Netpbm image data, size = 256 x 256, rawbits, pixmap
$ ./bitmap_read_through_pipe_task 4.1.07.tiff 4.1.07.jpg
$ file 4.1.07.jpg
4.1.07.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, 256x256, components 3</pre>
 
Notice that, when I did not specify an output file, I got a PPM (PPM being what was sent through the output pipe to magick). Both times, though, the input pipe converts a TIFF image to PPM, which then is read into the internal <code>pixmap</code> type.
 
Here is the JPEG that was outputted:
[[File:Bitmap read through pipe task ATS.jpg|none|alt=SIPI test image of jellybeans.]]
 
=={{header|AutoHotkey}}==
{{works with | AutoHotkey_L}}
Uses [http://www.autohotkey.com/forum/viewtopic.php?t=16823 StdoutTovar.ahk]
<langsyntaxhighlight AutoHotkeylang="autohotkey">ppm := Run("cmd.exe /c convert lena50.jpg ppm:-")
; pipe in from imagemagick
img := ppm_read("", ppm) ;
Line 67 ⟶ 222:
#include bitmap_storage.ahk ; from http://rosettacode.org/wiki/Basic_bitmap_storage/AutoHotkey
#include run.ahk ; http://www.autohotkey.com/forum/viewtopic.php?t=16823
</syntaxhighlight>
</lang>
 
=={{header|C}}==
Line 73 ⟶ 228:
Here I've used '''convert''' by ImageMagick. It is up to the program to ''understand'' the source file type; in this way, we can read theoretically any image format ImageMagick can handle. The <tt>get_ppm</tt> function defined in [[Read ppm file]] is used.
 
<langsyntaxhighlight lang="c">image read_image(const char *name);</langsyntaxhighlight>
 
<langsyntaxhighlight lang="c">#include "imglib.h"
 
#define MAXCMDBUF 100
Line 102 ⟶ 257:
}
return NULL;
}</langsyntaxhighlight>
 
=={{header|Go}}==
This example uses convert to convert the test image for the flood fill task. It reads through the pipe as required for this task, then writes as a .ppm file convenient for the flood fill task.
{{works with|Go weekly.2011-12-14}}
<syntaxhighlight lang="go">package main
Using djpeg:
<lang go>package main
 
// Files required to build supporting package raster are found in:
Line 115 ⟶ 268:
 
import (
"fmtlog"
"os/exec"
"raster"
Line 121 ⟶ 274:
 
func main() {
c := exec.Command("convert", "Unfilledcirc.png", "-depth", "1", "ppm:-")
// (A file with this name is output by the Go solution to the task
// "Bitmap/PPM conversion through a pipe," but of course any handy
// jpeg should work.)
c := exec.Command("djpeg", "pipeout.jpg")
pipe, err := c.StdoutPipe()
if err != nil {
fmtlog.PrintlnFatal(err)
return
}
if err = c.Start(); err != nil {
if err != nil {log.Fatal(err)
fmt.Println(err)
return
}
b, err := raster.ReadPpmFrom(pipe)
if err != nil {
fmtlog.PrintlnFatal(err)
return
}
if err = b.WritePpmFile("pipeinUnfilledcirc.ppm"); err != nil {
if err != nil {log.Fatal(err)
fmt.Println(err)
}
}</langsyntaxhighlight>
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
<syntaxhighlight lang="julia">using Images, FileIO
 
img = load("data/bitmapOutputTest.jpg")
save("data/bitmapOutputTest.ppm", img)</syntaxhighlight>
=={{header|Kotlin}}==
{{works with|Ubuntu 16.04}}
The code for this is similar to that for the [[Bitmap/Read a PPM file]] task except that the .jpg file is converted via a pipe to .ppm format using the ImageMagick 'convert' tool and stored in a BasicBitmapStorage object. It is then converted to grayscale and saved back to disk as a .jpg file.
<syntaxhighlight lang="scala">// Version 1.2.40
 
import java.awt.Color
import java.awt.Graphics
import java.awt.image.BufferedImage
import java.io.PushbackInputStream
import java.io.File
import javax.imageio.ImageIO
 
class BasicBitmapStorage(width: Int, height: Int) {
val image = BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR)
 
fun fill(c: Color) {
val g = image.graphics
g.color = c
g.fillRect(0, 0, image.width, image.height)
}
 
fun setPixel(x: Int, y: Int, c: Color) = image.setRGB(x, y, c.getRGB())
 
fun getPixel(x: Int, y: Int) = Color(image.getRGB(x, y))
 
fun toGrayScale() {
for (x in 0 until image.width) {
for (y in 0 until image.height) {
var rgb = image.getRGB(x, y)
val red = (rgb shr 16) and 0xFF
val green = (rgb shr 8) and 0xFF
val blue = rgb and 0xFF
val lumin = (0.2126 * red + 0.7152 * green + 0.0722 * blue).toInt()
rgb = (lumin shl 16) or (lumin shl 8) or lumin
image.setRGB(x, y, rgb)
}
}
}
}
 
fun PushbackInputStream.skipComment() {
while (read().toChar() != '\n') {}
}
 
fun PushbackInputStream.skipComment(buffer: ByteArray) {
var nl: Int
while (true) {
nl = buffer.indexOf(10) // look for newline at end of comment
if (nl != -1) break
read(buffer) // read another buffer full if newline not yet found
}
val len = buffer.size
if (nl < len - 1) unread(buffer, nl + 1, len - nl - 1)
}
 
fun Byte.toUInt() = if (this < 0) 256 + this else this.toInt()
 
fun main(args: Array<String>) {
// use file, output_piped.jpg, created in the
// Bitmap/PPM conversion through a pipe task
val pb = ProcessBuilder("convert", "output_piped.jpg", "ppm:-")
pb.directory(null)
pb.redirectOutput(ProcessBuilder.Redirect.PIPE)
val proc = pb.start()
val pStdOut = proc.inputStream
val pbis = PushbackInputStream(pStdOut, 80)
pbis.use {
with (it) {
val h1 = read().toChar()
val h2 = read().toChar()
val h3 = read().toChar()
if (h1 != 'P' || h2 != '6' || h3 != '\n') {
println("Not a P6 PPM file")
System.exit(1)
}
val sb = StringBuilder()
while (true) {
val r = read().toChar()
if (r == '#') { skipComment(); continue }
if (r == ' ') break // read until space reached
sb.append(r.toChar())
}
val width = sb.toString().toInt()
sb.setLength(0)
while (true) {
val r = read().toChar()
if (r == '#') { skipComment(); continue }
if (r == '\n') break // read until new line reached
sb.append(r.toChar())
}
val height = sb.toString().toInt()
sb.setLength(0)
while (true) {
val r = read().toChar()
if (r == '#') { skipComment(); continue }
if (r == '\n') break // read until new line reached
sb.append(r.toChar())
}
val maxCol = sb.toString().toInt()
if (maxCol !in 0..255) {
println("Maximum color value is outside the range 0..255")
System.exit(1)
}
var buffer = ByteArray(80)
// get rid of any more opening comments before reading data
while (true) {
read(buffer)
if (buffer[0].toChar() == '#') {
skipComment(buffer)
}
else {
unread(buffer)
break
}
}
// read data
val bbs = BasicBitmapStorage(width, height)
buffer = ByteArray(width * 3)
var y = 0
while (y < height) {
read(buffer)
for (x in 0 until width) {
val c = Color(
buffer[x * 3].toUInt(),
buffer[x * 3 + 1].toUInt(),
buffer[x * 3 + 2].toUInt()
)
bbs.setPixel(x, y, c)
}
y++
}
// convert to grayscale and save to a file
bbs.toGrayScale()
val grayFile = File("output_piped_gray.jpg")
ImageIO.write(bbs.image, "jpg", grayFile)
}
}
}</syntaxhighlight>
=={{header|Lua}}==
Uses Bitmap class [[Bitmap#Lua|here]], with an RGB tuple pixel representation, and the rudimentary PPM support [[Bitmap/Flood_fill#Lua|here]], and the Lenna image [[:File:Lenna100.jpg|here]].
 
First, the <code>loadPPM()</code> method is altered to allow passing an existing file handle:
<syntaxhighlight lang="lua">function Bitmap:loadPPM(filename, fp)
if not fp then fp = io.open(filename, "rb") end
if not fp then return end
local head, width, height, depth, tail = fp:read("*line", "*number", "*number", "*number", "*line")
self.width, self.height = width, height
self:alloc()
for y = 1, self.height do
for x = 1, self.width do
self.pixels[y][x] = { string.byte(fp:read(1)), string.byte(fp:read(1)), string.byte(fp:read(1)) }
end
end
fp:close()
end</syntaxhighlight>
Then, for the actual "read-from-pipe" task, a Lua environment that supports <code>io.popen()</code> is required:
<syntaxhighlight lang="lua">local bitmap = Bitmap(0,0)
fp = io.popen("magick Lenna100.jpg ppm:-", "rb")
bitmap:loadPPM(nil, fp)
 
bitmap:savePPM("Lenna100.ppm") -- just as "proof"</syntaxhighlight>
=={{header|Mathematica}}/{{header|Wolfram Language}}==
Based off the Julia program.
<syntaxhighlight lang="mathematica">Export["data/bitmapOutputTest.ppm",Import["data/bitmapOutputTest.jpg"]];</syntaxhighlight>
=={{header|Nim}}==
Using "jpegtopnm" from Netpbm suite. Input is a JPEG file and result (the PPM file) is sent to stdout. The procedure "readPPM" reads directly from the stream and build the image container.
 
<syntaxhighlight lang="nim">import bitmap
import osproc
import ppm_read
import streams
 
# Launch Netpbm "jpegtopnm".
# Input is taken from "input.jpeg" and result sent to stdout.
let p = startProcess("jpegtopnm", args = ["input.jpeg"], options = {poUsePath})
let stream = FileStream(p.outputStream())
let image = stream.readPPM()
echo image.w, " ", image.h
p.close()</syntaxhighlight>
=={{header|OCaml}}==
The <code>read_ppm</code> function of the page [[read ppm file]] and used by the code below would need to be changed to take as parameter an input channel instead of the filename.
<langsyntaxhighlight lang="ocaml">let read_image ~filename =
if not(Sys.file_exists filename)
then failwith(Printf.sprintf "the file %s does not exist" filename);
Line 155 ⟶ 485:
let img = read_ppm ~ic in
(img)
;;</langsyntaxhighlight>
=={{header|Perl}}==
<syntaxhighlight lang="perl"># 20211226 Perl programming solution
 
use strict;
use warnings;
 
use Imager;
 
my $raw;
 
open my $fh, '-|', 'cat Lenna50.jpg' or die;
binmode $fh;
while ( sysread $fh , my $chunk , 1024 ) { $raw .= $chunk }
close $fh;
 
my $enable = $Imager::formats{"jpeg"}; # some kind of tie ?
 
my $IO = Imager::io_new_buffer $raw or die;
my $im = Imager::File::JPEG::i_readjpeg_wiol $IO or die;
 
open my $fh2, '>', 'output.ppm' or die;
binmode $fh2;
my $IO2 = Imager::io_new_fd(fileno $fh2);
Imager::i_writeppm_wiol $im, $IO2 ;
close $fh2;
undef($im);</syntaxhighlight>
{{out}}
<pre>file output.ppm
output.ppm: Netpbm PPM "rawbits" image data, size = 512 x 512
magick identify output.ppm
output.ppm PPM 512x512 512x512+0+0 8-bit sRGB 786464B 0.000u 0:00.014</pre>
=={{header|Phix}}==
Uses the demo\rosetta\viewppm.exw utility to accomplish this task.<br>
The returned data is raw binary, so you can either write it direct or chuck it through read_ppm/write_ppm.
<!--<syntaxhighlight lang="phix">(notonline)-->
<span style="color: #000080;font-style:italic;">-- demo\rosetta\Bitmap_Read_an_image_through_a_pipe.exw</span>
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- file i/o, system_exec(), pipes[!!]</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">pipeio</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">include</span> <span style="color: #000000;">ppm</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- read_ppm(), write_ppm()</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">pipes</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">pipes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">PIPOUT</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">create_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">INHERIT_READ</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- Create the child process, with replacement stdout. </span>
<span style="color: #004080;">string</span> <span style="color: #000000;">cmd</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%s viewppm -load test.jpg"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">get_interpreter</span><span style="color: #0000FF;">(</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)})</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">hProc</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">system_exec</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cmd</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pipes</span><span style="color: #0000FF;">),</span>
<span style="color: #000000;">hPipe</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">pipes</span><span style="color: #0000FF;">[</span><span style="color: #000000;">PIPOUT</span><span style="color: #0000FF;">][</span><span style="color: #000000;">READ_PIPE</span><span style="color: #0000FF;">]</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">ppm</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">read_from_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hProc</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">chunk</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">read_from_pipe</span><span style="color: #0000FF;">(</span><span style="color: #000000;">hPipe</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">hProc</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">chunk</span><span style="color: #0000FF;">=-</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #000000;">ppm</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">chunk</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">pipes</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">close_handles</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pipes</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">img</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">read_ppm</span><span style="color: #0000FF;">(</span><span style="color: #000000;">ppm</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bText</span><span style="color: #0000FF;">:=</span><span style="color: #004600;">true</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">write_ppm</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Lenapipe.ppm"</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">img</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span> <span style="color: #000080;font-style:italic;">-- or</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">fn</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">open</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Lenapipe.ppm"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"wb"</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ppm</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fn</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #0000FF;">?</span><span style="color: #008000;">"done"</span>
<span style="color: #0000FF;">{}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">wait_key</span><span style="color: #0000FF;">()</span>
<!--</syntaxhighlight>-->
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(setq *Ppm (ppmRead '("convert" "img.jpg" "ppm:-")))</langsyntaxhighlight>
=={{header|Python}}==
<syntaxhighlight lang="python">
"""
Adapted from https://stackoverflow.com/questions/26937143/ppm-to-jpeg-jpg-conversion-for-python-3-4-1
Requires pillow-5.3.0 with Python 3.7.1 32-bit on Windows.
Sample ppm graphics files from http://www.cs.cornell.edu/courses/cs664/2003fa/images/
"""
 
from PIL import Image
 
# boxes_1.jpg is the jpg version of boxes_1.ppm
 
im = Image.open("boxes_1.jpg")
im.save("boxes_1v2.ppm")
</syntaxhighlight>
Does not need to pipe through a conversion utility
because the Pillow module does the conversion.
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">
 
(define (read-ppm port)
(parameterize ([current-input-port port])
(define magic (read-line))
(match-define (list w h) (string-split (read-line) " "))
(define width (string->number w))
(define height (string->number h))
(define maxcol (string->number (read-line)))
(define bm (make-object bitmap% width height))
(define dc (new bitmap-dc% [bitmap bm]))
(send dc set-smoothing 'unsmoothed)
(define (adjust v) (* 255 (/ v maxcol)))
(for/list ([x width])
(for/list ([y height])
(define red (read-byte))
(define green (read-byte))
(define blue (read-byte))
(define color (make-object color% (adjust red) (adjust green) (adjust blue)))
(send dc set-pen color 1 'solid)
(send dc draw-point x y)))
bm))
 
(define (image->bmp filename)
(define command (format "convert ~a ppm:-" filename))
Line 170 ⟶ 606:
bmp)
 
(image->bmp "input.jpg")</langsyntaxhighlight>
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2017.09}}
Uses pieces from [[Bitmap#Raku| Bitmap]] and [[Bitmap/Read_a_PPM_file#Raku| Read a PPM file]] tasks. Included here to make a complete, runnable program.
 
Uses imagemagick convert to pipe the image in.
 
<syntaxhighlight lang="raku" line>class Pixel { has UInt ($.R, $.G, $.B) }
class Bitmap {
has UInt ($.width, $.height);
has Pixel @.data;
}
 
role PPM {
method P6 returns Blob {
"P6\n{self.width} {self.height}\n255\n".encode('ascii')
~ Blob.new: flat map { .R, .G, .B }, self.data
}
}
 
sub getline ( $proc ) {
my $line = '#'; # skip comment when reading a .png
$line = $proc.out.get while $line.substr(0,1) eq '#';
$line;
}
 
my $filename = './camelia.png';
 
my $proc = run 'convert', $filename, 'ppm:-', :enc('ISO-8859-1'), :out;
 
my $type = getline($proc);
my ($width, $height) = getline($proc).split: ' ';
my $depth = getline($proc);
 
my Bitmap $b = Bitmap.new( width => $width.Int, height => $height.Int) but PPM;
 
$b.data = $proc.out.slurp.ords.rotor(3).map:
{ Pixel.new(R => .[0], G => .[1], B => .[2]) };
 
'./camelia.ppm'.IO.open(:bin, :w).write: $b.P6;</syntaxhighlight>
 
See [https://github.com/thundergnat/rc/blob/master/img/camelia.png camelia image here].
=={{header|Ruby}}==
Uses [[Raster graphics operations/Ruby]].
Extending [[Read ppm file#Ruby]] and [[PPM conversion through a pipe#Ruby]]. Uses the ImageMagick <code>convert</code> tool.
 
<syntaxhighlight lang="ruby"># frozen_string_literal: true
 
require_relative 'raster_graphics'
 
<lang ruby>class Pixmap
def self.read_ppm(ios)
format = ios.gets.chomp
width, height = ios.gets.chomp.split.map {|n| n.(&:to_i })
max_colour = ios.gets.chomp
 
if (not !PIXMAP_FORMATS.include?(format)) or ||
(width < 1) or|| (height < 1) or||
(max_colour != '255')
then
ios.close
raise StandardError, "file '#{filename}' does not start with the expected header"
Line 190 ⟶ 670:
ios.binmode if PIXMAP_BINARY_FORMATS.include?(format)
 
bitmap = self.new(width, height)
height.times do |y|
width.times do |x|
# read 3 bytes
red, green, blue = case format
when 'P3' then ios.gets.chomp.split
when 'P6' then ios.read(3).unpack('C3')
end
bitmap[x, y] = RGBColour.new(red, green, blue)
end
end
Line 214 ⟶ 694:
end
 
bitmap = Pixmap.open_from_jpeg('filefoto.jpg')</lang>
bitmap.save('foto.ppm')
 
</syntaxhighlight>
=={{header|Tcl}}==
{{works with|Tcl|8.6}}
{{libheader|Tk}}
<langsyntaxhighlight lang="tcl">package require Tk
 
proc magickalReadImage {bufferImage fileName} {
Line 228 ⟶ 709:
close $f
}
}</langsyntaxhighlight>
=={{header|Wren}}==
{{libheader|DOME}}
As DOME doesn't have a method for calling an external process (''ImageMagick'' in this case), we re-use the small plug-in (''pipeconv.so'') we created in the 'PPM conversion through a pipe' task
to add this functionality.
 
We can now use this plug-in in the following script which calls ''ImageMagick'' to convert the ''output_piped.jpg'' file to a ''ppm'' file so that we can load the latter, convert it to a gray scale image, display it and save it to a .jpg file.
 
<syntaxhighlight lang="wren">import "graphics" for Canvas, ImageData, Color
import "dome" for Window, Process
import "io" for FileSystem
import "plugin" for Plugin
 
Plugin.load("pipeconv")
 
import "pipeconv" for PipeConv
 
class Bitmap {
construct new(fileName, fileName2, fileName3, width, height) {
Window.title = "Bitmap - read image via pipe"
Window.resize(width, height)
Canvas.resize(width, height)
_w = width
_h = height
_fn3 = fileName3
// convert .jpg file to .ppm via a pipe
PipeConv.convert(fileName, fileName2)
// load the .ppm file
loadPPMFile(fileName2)
}
 
init() {
toGrayScale()
// display gray scale image
_bmp2.draw(0, 0)
// save it to file
_bmp2.saveToFile(_fn3)
}
 
loadPPMFile(fileName) {
var ppm = FileSystem.load(fileName)
var count = ppm.count //ensure file is fully loaded before proceeding
if (ppm[0..1] != "P6") {
System.print("The loaded file is not a P6 file.")
Process.exit()
}
var lines = ppm.split("\n")
if (Num.fromString(lines[2]) > 255) {
System.print("The maximum color value can't exceed 255.")
Process.exit()
}
var wh = lines[1].split(" ")
var w = Num.fromString(wh[0])
var h = Num.fromString(wh[1])
_bmp = ImageData.create(fileName, w, h)
var bytes = ppm.bytes
var i = bytes.count - 3 * w * h
for (y in 0...h) {
for (x in 0...w) {
var r = bytes[i]
var g = bytes[i+1]
var b = bytes[i+2]
var c = Color.rgb(r, g, b)
pset(x, y, c)
i = i + 3
}
}
}
 
toGrayScale() {
_bmp2 = ImageData.create("gray scale", _bmp.width, _bmp.height)
for (x in 0..._bmp.width) {
for (y in 0..._bmp.height) {
var c1 = _bmp.pget(x, y)
var lumin = (0.2126 * c1.r + 0.7152 * c1.g + 0.0722 * c1.b).floor
var c2 = Color.rgb(lumin, lumin,lumin, c1.a)
_bmp2.pset(x, y, c2)
}
}
}
 
pset(x, y, col) { _bmp.pset(x, y, col) }
 
pget(x, y) { _bmp.pget(x, y) }
 
update() {}
 
draw(alpha) {}
}
 
var Game = Bitmap.new("output_piped.jpg", "output_piped.ppm", "output_piped_gs.jpg", 350, 350)</syntaxhighlight>
 
=={{header|zkl}}==
{{trans|C}}
Uses the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl
 
Using the convert utility by ImageMagick:
<syntaxhighlight lang="zkl">p:=System.popen(0'|convert "fractalTree.jpg" ppm:-|,"r");
img:=PPM.readPPM(p); p.close();</syntaxhighlight>
{{omit from|PARI/GP}}
{{omit from|TI-83 BASIC}} {{omit from|TI-89 BASIC}} <!-- Does not have an external OS/command processor. -->
{{omit from|TI-89 BASIC}} <!-- Does not have an external OS/command processor. -->
[[Category:Less Than 20 Examples]]
9,476

edits