Initial data commit
This commit is contained in:
parent
72d218235f
commit
f23f22d71c
199087 changed files with 3378941 additions and 0 deletions
6
Task/Bitmap-Read-a-PPM-file/00-META.yaml
Normal file
6
Task/Bitmap-Read-a-PPM-file/00-META.yaml
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
category:
|
||||
- Input Output
|
||||
- E examples needing attention
|
||||
from: http://rosettacode.org/wiki/Bitmap/Read_a_PPM_file
|
||||
note: Raster graphics operations
|
||||
4
Task/Bitmap-Read-a-PPM-file/00-TASK.txt
Normal file
4
Task/Bitmap-Read-a-PPM-file/00-TASK.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
Using the data storage type defined [[Basic_bitmap_storage|on this page]] for raster images, read an image from a PPM file (binary P6 prefered).
|
||||
(Read [[wp:Netpbm_format|the definition of PPM file]] on Wikipedia.)
|
||||
|
||||
'''Task''': Use [[write ppm file]] solution and [[grayscale image]] solution with this one in order to convert a color image to grayscale one.
|
||||
98
Task/Bitmap-Read-a-PPM-file/11l/bitmap-read-a-ppm-file.11l
Normal file
98
Task/Bitmap-Read-a-PPM-file/11l/bitmap-read-a-ppm-file.11l
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
T Colour
|
||||
Byte r, g, b
|
||||
|
||||
F (r, g, b)
|
||||
.r = r
|
||||
.g = g
|
||||
.b = b
|
||||
|
||||
F ==(other)
|
||||
R .r == other.r & .g == other.g & .b == other.b
|
||||
|
||||
V black = Colour(0, 0, 0)
|
||||
V white = Colour(255, 255, 255)
|
||||
|
||||
T Bitmap
|
||||
Int width, height
|
||||
Colour background
|
||||
[[Colour]] map
|
||||
|
||||
F (width = 40, height = 40, background = white)
|
||||
assert(width > 0 & height > 0)
|
||||
.width = width
|
||||
.height = height
|
||||
.background = background
|
||||
.map = (0 .< height).map(h -> (0 .< @width).map(w -> @@background))
|
||||
|
||||
F fillrect(x, y, width, height, colour = black)
|
||||
assert(x >= 0 & y >= 0 & width > 0 & height > 0)
|
||||
L(h) 0 .< height
|
||||
L(w) 0 .< width
|
||||
.map[y + h][x + w] = colour
|
||||
|
||||
F set(x, y, colour = black)
|
||||
.map[y][x] = colour
|
||||
|
||||
F get(x, y)
|
||||
R .map[y][x]
|
||||
|
||||
F togreyscale()
|
||||
L(h) 0 .< .height
|
||||
L(w) 0 .< .width
|
||||
V (r, g, b) = .get(w, h)
|
||||
V l = Int(0.2126 * r + 0.7152 * g + 0.0722 * b)
|
||||
.set(w, h, Colour(l, l, l))
|
||||
|
||||
F writeppmp3()
|
||||
V magic = "P3\n"
|
||||
V comment = "# generated from Bitmap.writeppmp3\n"
|
||||
V s = magic‘’comment‘’("#. #.\n#.\n".format(.width, .height, 255))
|
||||
L(h) (.height - 1 .< -1).step(-1)
|
||||
L(w) 0 .< .width
|
||||
V (r, g, b) = .get(w, h)
|
||||
s ‘’= ‘ #3 #3 #3’.format(r, g, b)
|
||||
s ‘’= "\n"
|
||||
R s
|
||||
|
||||
F tokenize(fstr)
|
||||
[String] tokens
|
||||
L(line) fstr.split("\n")
|
||||
I !line.starts_with(‘#’)
|
||||
L(t) line.split(‘ ’, group_delimiters' 1B)
|
||||
tokens.append(t)
|
||||
R tokens
|
||||
|
||||
F ppmp3tobitmap(fstr)
|
||||
V tokens = tokenize(fstr)
|
||||
V tokeni = -1
|
||||
F nexttoken()
|
||||
@tokeni++
|
||||
R @tokens[@tokeni]
|
||||
assert(‘P3’ == nexttoken(), ‘Wrong filetype’)
|
||||
V width = Int(nexttoken())
|
||||
V height = Int(nexttoken())
|
||||
V maxval = Int(nexttoken())
|
||||
V bitmap = Bitmap(width, height, Colour(0, 0, 0))
|
||||
L(h) (height - 1 .< -1).step(-1)
|
||||
L(w) 0 .< width
|
||||
V r = Int(nexttoken())
|
||||
V g = Int(nexttoken())
|
||||
V b = Int(nexttoken())
|
||||
bitmap.set(w, h, Colour(r, g, b))
|
||||
|
||||
R bitmap
|
||||
|
||||
V ppmtxt = |‘P3
|
||||
# feep.ppm
|
||||
4 4
|
||||
15
|
||||
0 0 0 0 0 0 0 0 0 15 0 15
|
||||
0 0 0 0 15 7 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 15 7 0 0 0
|
||||
15 0 15 0 0 0 0 0 0 0 0 0
|
||||
’
|
||||
|
||||
V bitmap = ppmp3tobitmap(ppmtxt)
|
||||
print(‘Grey PPM:’)
|
||||
bitmap.togreyscale()
|
||||
print(bitmap.writeppmp3())
|
||||
12
Task/Bitmap-Read-a-PPM-file/ATS/bitmap-read-a-ppm-file-1.ats
Normal file
12
Task/Bitmap-Read-a-PPM-file/ATS/bitmap-read-a-ppm-file-1.ats
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#define ATS_PACKNAME "Rosetta_Code.bitmap_read_ppm_task"
|
||||
|
||||
staload "bitmap_task.sats"
|
||||
|
||||
fn {a : t@ype}
|
||||
pixmap_read_ppm :
|
||||
(* On failure to read, the return is None_vt(). I do not currently
|
||||
provide any indication of why the attempt failed, although in
|
||||
practice you probably would wish to add that. *)
|
||||
FILEref ->
|
||||
Option_vt ([w, h : pos] [p : addr | null < p]
|
||||
@(mfree_gc_v p | pixmap (a, w, h, p)))
|
||||
433
Task/Bitmap-Read-a-PPM-file/ATS/bitmap-read-a-ppm-file-2.ats
Normal file
433
Task/Bitmap-Read-a-PPM-file/ATS/bitmap-read-a-ppm-file-2.ats
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
(*------------------------------------------------------------------*)
|
||||
|
||||
#define ATS_DYNLOADFLAG 0
|
||||
#define ATS_PACKNAME "Rosetta_Code.bitmap_read_ppm_task"
|
||||
|
||||
#include "share/atspre_staload.hats"
|
||||
|
||||
staload "bitmap_task.sats"
|
||||
|
||||
(* You need to staload bitmap_task.dats, so the ATS compiler will have
|
||||
access to its implementations of templates. But we staload it
|
||||
anonymously, so the programmer will not have access. *)
|
||||
staload _ = "bitmap_task.dats"
|
||||
|
||||
staload "bitmap_read_ppm_task.sats"
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
|
||||
datavtype magic_number_vt =
|
||||
| Netpbm_magic_number of int
|
||||
| Unknown_magic_number of ()
|
||||
|
||||
fn {}
|
||||
read_magic_number (inpf : FILEref) : magic_number_vt =
|
||||
let
|
||||
val i = fileref_getc inpf
|
||||
in
|
||||
if i <> char2int0 'P' then
|
||||
Unknown_magic_number ()
|
||||
else
|
||||
let
|
||||
val i = fileref_getc inpf
|
||||
in
|
||||
if i < char2int0 '1' && char2int0 '7' < i then
|
||||
Unknown_magic_number ()
|
||||
else
|
||||
Netpbm_magic_number (i - char2int0 '0')
|
||||
end
|
||||
end
|
||||
|
||||
fn {}
|
||||
get_next_char (inpf : FILEref) : int =
|
||||
let
|
||||
fnx
|
||||
get_next () : int =
|
||||
let
|
||||
val i = fileref_getc inpf
|
||||
in
|
||||
if i = char2int0 '#' then
|
||||
skip_through_newline ()
|
||||
else
|
||||
i
|
||||
end
|
||||
and
|
||||
skip_through_newline () : int =
|
||||
let
|
||||
val i = fileref_getc inpf
|
||||
in
|
||||
if i < 0 then
|
||||
i
|
||||
else if i = char2int0 '\n' then
|
||||
get_next ()
|
||||
else
|
||||
skip_through_newline ()
|
||||
end
|
||||
in
|
||||
get_next ()
|
||||
end
|
||||
|
||||
(* The only tokens we need to scan for, in P1 through P6, are unsigned
|
||||
integers. P7 headers (Portable Arbitrary Map) have a completely
|
||||
different arrangement, but we are not handling that. *)
|
||||
fn {}
|
||||
get_next_integer (inpf : FILEref)
|
||||
(* A negative return value means we have reached the end. We do
|
||||
not distinguish whitespace characters from anything else that
|
||||
is not a digit or '#'. (Really I want to use intmax_t here,
|
||||
rather than llint, but there is no intmax_t support in the
|
||||
prelude. The ats2-xprelude package has support, but I am
|
||||
avoiding the dependency. *)
|
||||
: llint =
|
||||
let
|
||||
fnx
|
||||
look_for_digit () : llint =
|
||||
let
|
||||
val i = get_next_char inpf
|
||||
in
|
||||
if i < char2int0 '0' || char2int0 '9' < i then
|
||||
look_for_digit ()
|
||||
else
|
||||
read_digits (g0i2i (i - char2int0 '0'))
|
||||
end
|
||||
and
|
||||
read_digits (x : llint) : llint =
|
||||
let
|
||||
val i = get_next_char inpf
|
||||
in
|
||||
if i < char2int0 '0' || char2int0 '9' < i then
|
||||
(* I cannot find an "ungetc" in prelude/SATS/filebas.sats,
|
||||
so I will use the foreign function interface directly. *)
|
||||
let
|
||||
typedef FILEstar = $extype"FILE *"
|
||||
extern castfn FILEref2star : FILEref -<> FILEstar
|
||||
in
|
||||
ignoret ($extfcall (int, "ungetc", i, FILEref2star inpf));
|
||||
x
|
||||
end
|
||||
else
|
||||
let
|
||||
val digit : llint = g0i2i (i - char2int0 '0')
|
||||
in
|
||||
read_digits ((10LL * x) + digit)
|
||||
end
|
||||
end
|
||||
in
|
||||
look_for_digit ()
|
||||
end
|
||||
|
||||
fn {}
|
||||
read_ppm_header (inpf : FILEref)
|
||||
: Option_vt @(ullint, ullint, ullint) =
|
||||
let
|
||||
val width = get_next_integer inpf
|
||||
in
|
||||
if width < 0LL then
|
||||
None_vt ()
|
||||
else
|
||||
let
|
||||
val height = get_next_integer inpf
|
||||
in
|
||||
if height < 0LL then
|
||||
None_vt ()
|
||||
else
|
||||
let
|
||||
val maxval = get_next_integer inpf
|
||||
in
|
||||
if maxval < 0LL then
|
||||
None_vt ()
|
||||
else
|
||||
begin
|
||||
(* There is supposed to be a whitespace character (or
|
||||
comments and whitespace character) after the
|
||||
MAXVAL. We will accept anything, whitespace or
|
||||
not. *)
|
||||
ignoret (fileref_getc inpf);
|
||||
|
||||
Some_vt @(g0i2u width, g0i2u height, g0i2u maxval)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
fn {}
|
||||
get_next_single_byte (inpf : FILEref) : llint =
|
||||
let
|
||||
val i = fileref_getc inpf
|
||||
in
|
||||
if i < 0 then
|
||||
~1LL
|
||||
else
|
||||
g0i2i i
|
||||
end
|
||||
|
||||
fn {}
|
||||
get_next_double_byte (inpf : FILEref) : llint =
|
||||
let
|
||||
val i1 = fileref_getc inpf
|
||||
in
|
||||
if i1 < 0 then
|
||||
~1LL
|
||||
else
|
||||
let
|
||||
val i0 = fileref_getc inpf
|
||||
in
|
||||
if i0 < 0 then
|
||||
~1LL
|
||||
else
|
||||
let
|
||||
val i1 : llint = g0i2i i1
|
||||
and i0 : llint = g0i2i i0
|
||||
in
|
||||
(i1 * 256LL) + i0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
(* Implementation is provided only for rgb24. *)
|
||||
|
||||
extern castfn ull2sz : {i : int} ullint i -<> size_t i
|
||||
extern castfn ull2u : {i : int} ullint i -<> uint i
|
||||
extern castfn ull2u8 : ullint -<> uint8
|
||||
|
||||
extern fn {}
|
||||
read_raw_ppm_rgb24 : $d2ctype (pixmap_read_ppm<rgb24>)
|
||||
|
||||
extern fn {}
|
||||
read_plain_ppm_rgb24 : $d2ctype (pixmap_read_ppm<rgb24>)
|
||||
|
||||
extern fn {}
|
||||
read_general_ppm_rgb24 : $d2ctype (pixmap_read_ppm<rgb24>)
|
||||
|
||||
extern fn {}
|
||||
read_general$width () : [i : pos] size_t i
|
||||
|
||||
extern fn {}
|
||||
read_general$height () : [i : pos] size_t i
|
||||
|
||||
extern fn {}
|
||||
read_general$maxval () : [i : pos | i <= 65535] uint i
|
||||
|
||||
extern fn {}
|
||||
read_general$next_value : FILEref -> llint
|
||||
|
||||
implement
|
||||
pixmap_read_ppm<rgb24> inpf =
|
||||
case+ read_magic_number inpf of
|
||||
| ~ Unknown_magic_number () => None_vt ()
|
||||
| ~ Netpbm_magic_number num =>
|
||||
begin
|
||||
case+ num of
|
||||
| 6 => read_raw_ppm_rgb24 inpf
|
||||
| 3 => read_plain_ppm_rgb24 inpf
|
||||
| _ => None_vt
|
||||
end
|
||||
|
||||
implement {}
|
||||
read_raw_ppm_rgb24 inpf =
|
||||
case+ read_ppm_header inpf of
|
||||
| ~ None_vt () => None_vt ()
|
||||
| ~ Some_vt @(width, height, maxval) =>
|
||||
let
|
||||
val width = g1ofg0 width
|
||||
and height = g1ofg0 height
|
||||
and maxval = g1ofg0 maxval
|
||||
in
|
||||
if (width < 1LLU) + (height < 1LLU) +
|
||||
(maxval < 1LLU) + (65535LLU < maxval) then
|
||||
None_vt ()
|
||||
else
|
||||
let
|
||||
val w : Size_t = ull2sz width
|
||||
val h : Size_t = ull2sz height
|
||||
val maxval : uInt = ull2u maxval
|
||||
in
|
||||
if maxval = 255u then
|
||||
let
|
||||
val @(pfgc | pix) = pixmap_make<rgb24> (w, h)
|
||||
val success =
|
||||
load<rgb24> (inpf, pix, rgb24_make (255, 0, 0))
|
||||
in
|
||||
if ~success then
|
||||
begin
|
||||
free (pfgc | pix);
|
||||
None_vt ()
|
||||
end
|
||||
else
|
||||
Some_vt @(pfgc | pix)
|
||||
end
|
||||
else if maxval < 256u then
|
||||
let
|
||||
implement read_general$width<> () = w
|
||||
implement read_general$height<> () = h
|
||||
implement read_general$maxval<> () = maxval
|
||||
implement
|
||||
read_general$next_value<> inpf =
|
||||
get_next_single_byte inpf
|
||||
in
|
||||
read_general_ppm_rgb24<> inpf
|
||||
end
|
||||
else
|
||||
let
|
||||
implement read_general$width<> () = w
|
||||
implement read_general$height<> () = h
|
||||
implement read_general$maxval<> () = maxval
|
||||
implement
|
||||
read_general$next_value<> inpf =
|
||||
get_next_double_byte inpf
|
||||
in
|
||||
read_general_ppm_rgb24<> inpf
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
implement {}
|
||||
read_plain_ppm_rgb24 inpf =
|
||||
case+ read_ppm_header inpf of
|
||||
| ~ None_vt () => None_vt ()
|
||||
| ~ Some_vt @(width, height, maxval) =>
|
||||
let
|
||||
val width = g1ofg0 width
|
||||
and height = g1ofg0 height
|
||||
and maxval = g1ofg0 maxval
|
||||
in
|
||||
if (width < 1LLU) + (height < 1LLU) +
|
||||
(maxval < 1LLU) + (65535LLU < maxval) then
|
||||
None_vt ()
|
||||
else
|
||||
let
|
||||
val w : Size_t = ull2sz width
|
||||
val h : Size_t = ull2sz height
|
||||
val maxval : uInt = ull2u maxval
|
||||
implement read_general$width<> () = w
|
||||
implement read_general$height<> () = h
|
||||
implement read_general$maxval<> () = maxval
|
||||
implement
|
||||
read_general$next_value<> inpf =
|
||||
get_next_integer inpf
|
||||
in
|
||||
read_general_ppm_rgb24<> inpf
|
||||
end
|
||||
end
|
||||
|
||||
implement {}
|
||||
read_general_ppm_rgb24 inpf =
|
||||
let
|
||||
val [w : int] w = read_general$width<> ()
|
||||
and [h : int] h = read_general$height<> ()
|
||||
and maxval = read_general$maxval<> ()
|
||||
|
||||
fn
|
||||
scale_value (v : ullint) : uint8 =
|
||||
if maxval = 255u then
|
||||
ull2u8 v
|
||||
else
|
||||
let
|
||||
val maxval : ullint = g0u2u maxval
|
||||
val v = 255LLU * v
|
||||
val v1 = v / maxval
|
||||
and v0 = v mod maxval
|
||||
in
|
||||
if v0 + v0 < maxval then
|
||||
ull2u8 v1
|
||||
else if maxval < v0 + v0 then
|
||||
ull2u8 (succ v1)
|
||||
else if v1 mod 2LLU = 0LLU then
|
||||
ull2u8 v1
|
||||
else
|
||||
ull2u8 (succ v1)
|
||||
end
|
||||
|
||||
(* For easier programming, start with a fully initialized
|
||||
pixmap. The routine probably is I/O-bound, anyway. *)
|
||||
val @(pfgc | pix) =
|
||||
pixmap_make<rgb24> (w, h, rgb24_make (255, 0, 0))
|
||||
|
||||
macdef between (i, j, v) =
|
||||
let
|
||||
val v = ,(v)
|
||||
in
|
||||
(,(i) <= v) * (v <= ,(j))
|
||||
end
|
||||
|
||||
fun
|
||||
loop {x, y : nat | x <= w; y <= h}
|
||||
.<h - y, w - x>.
|
||||
(pix : !pixmap (rgb24, w, h),
|
||||
x : size_t x,
|
||||
y : size_t y)
|
||||
: bool (* success *) =
|
||||
if y = h then
|
||||
true
|
||||
else if x = w then
|
||||
loop (pix, i2sz 0, succ y)
|
||||
else
|
||||
let
|
||||
val maxv : llint = g0u2i maxval
|
||||
val vr = read_general$next_value<> inpf
|
||||
in
|
||||
if ~between (0LL, maxv, vr) then
|
||||
false
|
||||
else
|
||||
let
|
||||
val vg = read_general$next_value<> inpf
|
||||
in
|
||||
if ~between (0LL, maxv, vg) then
|
||||
false
|
||||
else
|
||||
let
|
||||
val vb = read_general$next_value<> inpf
|
||||
in
|
||||
if ~between (0LL, maxv, vb) then
|
||||
false
|
||||
else
|
||||
let
|
||||
val r = scale_value (g0i2u vr)
|
||||
and g = scale_value (g0i2u vg)
|
||||
and b = scale_value (g0i2u vb)
|
||||
in
|
||||
pix[x, y] := rgb24_make @(r, g, b);
|
||||
loop (pix, succ x, y)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
val success = loop (pix, i2sz 0, i2sz 0)
|
||||
in
|
||||
if ~success then
|
||||
begin
|
||||
free (pfgc | pix);
|
||||
None_vt ()
|
||||
end
|
||||
else
|
||||
Some_vt @(pfgc | pix)
|
||||
end
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
|
||||
#ifdef BITMAP_READ_PPM_TASK_TEST #then
|
||||
|
||||
staload "bitmap_write_ppm_task.sats"
|
||||
staload _ = "bitmap_write_ppm_task.dats"
|
||||
|
||||
(* The test program converts a PPM at standard input to a raw PPM with
|
||||
MAXVAL 255. *)
|
||||
implement
|
||||
main0 () =
|
||||
let
|
||||
val pix_opt = pixmap_read_ppm<rgb24> stdin_ref
|
||||
in
|
||||
case+ pix_opt of
|
||||
| ~ None_vt () => ()
|
||||
| ~ Some_vt @(pfgc | pix) =>
|
||||
begin
|
||||
ignoret (pixmap_write_ppm (stdout_ref, pix));
|
||||
free (pfgc | pix)
|
||||
end
|
||||
end
|
||||
|
||||
#endif
|
||||
|
||||
(*------------------------------------------------------------------*)
|
||||
79
Task/Bitmap-Read-a-PPM-file/ATS/bitmap-read-a-ppm-file-3.ats
Normal file
79
Task/Bitmap-Read-a-PPM-file/ATS/bitmap-read-a-ppm-file-3.ats
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
(* The program should be able to read a PPM in raw or plain format,
|
||||
with any valid Maxval. The output will be a grayscale raw PPM with
|
||||
Maxval=255.
|
||||
|
||||
Compile with "myatscc bitmap_read_ppm_task_program.dats", which
|
||||
should give you a program named "bitmap_read_ppm_task_program". *)
|
||||
|
||||
(*
|
||||
|
||||
##myatsccdef=\
|
||||
patscc -std=gnu2x -g -O2 -DATS_MEMALLOC_LIBC \
|
||||
-o $fname($1) $1 \
|
||||
bitmap{,_{{read,write}_ppm,grayscale}}_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_grayscale_task.sats"
|
||||
|
||||
staload _ = "bitmap_task.dats"
|
||||
staload _ = "bitmap_read_ppm_task.dats"
|
||||
staload _ = "bitmap_write_ppm_task.dats"
|
||||
staload _ = "bitmap_grayscale_task.dats"
|
||||
|
||||
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 @(pfgc2 | pix2) = pixmap_convert<rgb24,gray8> pix1
|
||||
val () = free (pfgc1 | pix1)
|
||||
val @(pfgc3 | pix3) = pixmap_convert<gray8,rgb24> pix2
|
||||
val () = free (pfgc2 | pix2)
|
||||
|
||||
val outf =
|
||||
if nargs < 3 then
|
||||
stdout_ref
|
||||
else if args[2] = "-" then
|
||||
stdout_ref
|
||||
else
|
||||
fileref_open_exn (args[2], file_mode_w)
|
||||
val success = pixmap_write_ppm<rgb24> (outf, pix3)
|
||||
val () = fileref_close outf
|
||||
|
||||
val () = free (pfgc3 | pix3)
|
||||
in
|
||||
free args;
|
||||
if ~success then
|
||||
begin
|
||||
println! ("For some reason, ",
|
||||
"I failed to write a new image.");
|
||||
exit 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
INCLUDE "H6:RGB2GRAY.ACT" ;from task Grayscale image
|
||||
|
||||
PROC DecodeSize(CHAR ARRAY s BYTE POINTER width,height)
|
||||
BYTE i
|
||||
|
||||
width^=ValB(s)
|
||||
i=1
|
||||
WHILE i<=s(0) AND s(i)#32
|
||||
DO
|
||||
s(i)=32
|
||||
i==+1
|
||||
OD
|
||||
height^=ValB(s)
|
||||
RETURN
|
||||
|
||||
PROC LoadHeader(RgbImage POINTER img
|
||||
CHAR ARRAY format BYTE dev)
|
||||
CHAR ARRAY line(255)
|
||||
BYTE header,size,max,width,height
|
||||
|
||||
header=0 size=0 max=0
|
||||
WHILE max=0
|
||||
DO
|
||||
InputSD(dev,line)
|
||||
IF line(0)>0 AND line(1)#'# THEN
|
||||
IF header=0 THEN
|
||||
IF SCompare(format,format)#0 THEN
|
||||
Break()
|
||||
FI
|
||||
header=1
|
||||
ELSEIF size=0 THEN
|
||||
DecodeSize(line,@width,@height)
|
||||
IF width=0 OR height=0 THEN
|
||||
Break()
|
||||
FI
|
||||
img.w=width img.h=height
|
||||
size=1
|
||||
ELSEIF max=0 THEN
|
||||
max=ValB(line)
|
||||
IF max#255 THEN
|
||||
Break()
|
||||
FI
|
||||
FI
|
||||
FI
|
||||
OD
|
||||
RETURN
|
||||
|
||||
PROC LoadPPM6(RgbImage POINTER img CHAR ARRAY path)
|
||||
BYTE dev=[1],x,y
|
||||
RGB c
|
||||
|
||||
Close(dev)
|
||||
Open(dev,path,4)
|
||||
LoadHeader(img,"P6",dev)
|
||||
FOR y=0 TO img.h-1
|
||||
DO
|
||||
FOR x=0 TO img.w-1
|
||||
DO
|
||||
c.r=GetD(dev)
|
||||
c.g=GetD(dev)
|
||||
c.b=GetD(dev)
|
||||
SetRgbPixel(img,x,y,c)
|
||||
OD
|
||||
OD
|
||||
Close(dev)
|
||||
RETURN
|
||||
|
||||
PROC SaveHeader(GrayImage POINTER img
|
||||
CHAR ARRAY format BYTE dev)
|
||||
|
||||
PrintDE(dev,format)
|
||||
PrintBD(dev,img.w)
|
||||
PutD(dev,32)
|
||||
PrintBDE(dev,img.h)
|
||||
PrintBDE(dev,255)
|
||||
RETURN
|
||||
|
||||
PROC SavePPM2(RgbImage POINTER img CHAR ARRAY path)
|
||||
BYTE dev=[1],x,y,c
|
||||
|
||||
Close(dev)
|
||||
Open(dev,path,8)
|
||||
SaveHeader(img,"P2",dev)
|
||||
FOR y=0 TO img.h-1
|
||||
DO
|
||||
FOR x=0 TO img.w-1
|
||||
DO
|
||||
c=GetGrayPixel(img,x,y)
|
||||
PrintBD(dev,c)
|
||||
IF x=img.w-1 THEN
|
||||
PutDE(dev)
|
||||
ELSE
|
||||
PutD(dev,32)
|
||||
FI
|
||||
OD
|
||||
OD
|
||||
Close(dev)
|
||||
RETURN
|
||||
|
||||
PROC Load(CHAR ARRAY path)
|
||||
CHAR ARRAY line(255)
|
||||
BYTE dev=[1]
|
||||
|
||||
Close(dev)
|
||||
Open(dev,path,4)
|
||||
WHILE Eof(dev)=0
|
||||
DO
|
||||
InputSD(dev,line)
|
||||
PrintE(line)
|
||||
OD
|
||||
Close(dev)
|
||||
RETURN
|
||||
|
||||
PROC Main()
|
||||
BYTE ARRAY rgbdata(300),graydata(100)
|
||||
RgbImage rgbimg
|
||||
GrayImage grayimg
|
||||
CHAR ARRAY path2="D:PPM2.PPM"
|
||||
CHAR ARRAY path6="D:PPM6.PPM"
|
||||
|
||||
Put(125) PutE() ;clear the screen
|
||||
InitRgbImage(rgbimg,0,0,rgbdata)
|
||||
InitRgbToGray()
|
||||
|
||||
PrintF("Loading %S...%E%E",path6)
|
||||
LoadPPM6(rgbimg,path6)
|
||||
|
||||
PrintF("Converting RGB to grayscale...%E%E")
|
||||
InitGrayImage(grayimg,rgbimg.w,rgbimg.h,graydata)
|
||||
RgbToGray(rgbimg,grayimg)
|
||||
|
||||
PrintF("Saving %S...%E%E",path2)
|
||||
SavePPM2(grayimg,path2)
|
||||
PrintF("Loading %S...%E%E",path2)
|
||||
Load(path2)
|
||||
RETURN
|
||||
70
Task/Bitmap-Read-a-PPM-file/Ada/bitmap-read-a-ppm-file-1.ada
Normal file
70
Task/Bitmap-Read-a-PPM-file/Ada/bitmap-read-a-ppm-file-1.ada
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
with Ada.Characters.Latin_1; use Ada.Characters.Latin_1;
|
||||
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
|
||||
with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
|
||||
|
||||
function Get_PPM (File : File_Type) return Image is
|
||||
use Ada.Characters.Latin_1;
|
||||
use Ada.Integer_Text_IO;
|
||||
|
||||
function Get_Line return String is -- Skips comments
|
||||
Byte : Character;
|
||||
Buffer : String (1..80);
|
||||
begin
|
||||
loop
|
||||
for I in Buffer'Range loop
|
||||
Character'Read (Stream (File), Byte);
|
||||
if Byte = LF then
|
||||
exit when Buffer (1) = '#';
|
||||
return Buffer (1..I - 1);
|
||||
end if;
|
||||
Buffer (I) := Byte;
|
||||
end loop;
|
||||
if Buffer (1) /= '#' then
|
||||
raise Data_Error;
|
||||
end if;
|
||||
end loop;
|
||||
end Get_Line;
|
||||
|
||||
Height : Integer;
|
||||
Width : Integer;
|
||||
begin
|
||||
if Get_Line /= "P6" then
|
||||
raise Data_Error;
|
||||
end if;
|
||||
declare
|
||||
Line : String := Get_Line;
|
||||
Start : Integer := Line'First;
|
||||
Last : Positive;
|
||||
begin
|
||||
Get (Line, Width, Last); Start := Start + Last;
|
||||
Get (Line (Start..Line'Last), Height, Last); Start := Start + Last;
|
||||
if Start <= Line'Last then
|
||||
raise Data_Error;
|
||||
end if;
|
||||
if Width < 1 or else Height < 1 then
|
||||
raise Data_Error;
|
||||
end if;
|
||||
end;
|
||||
if Get_Line /= "255" then
|
||||
raise Data_Error;
|
||||
end if;
|
||||
declare
|
||||
Result : Image (1..Height, 1..Width);
|
||||
Buffer : String (1..Width * 3);
|
||||
Index : Positive;
|
||||
begin
|
||||
for I in Result'Range (1) loop
|
||||
String'Read (Stream (File), Buffer);
|
||||
Index := Buffer'First;
|
||||
for J in Result'Range (2) loop
|
||||
Result (I, J) :=
|
||||
( R => Luminance (Character'Pos (Buffer (Index))),
|
||||
G => Luminance (Character'Pos (Buffer (Index + 1))),
|
||||
B => Luminance (Character'Pos (Buffer (Index + 2)))
|
||||
);
|
||||
Index := Index + 3;
|
||||
end loop;
|
||||
end loop;
|
||||
return Result;
|
||||
end;
|
||||
end Get_PPM;
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
declare
|
||||
F1, F2 : File_Type;
|
||||
begin
|
||||
Open (F1, In_File, "city.ppm");
|
||||
Create (F2, Out_File, "city_grayscale.ppm");
|
||||
Put_PPM (F2, Color (Grayscale (Get_PPM (F1))));
|
||||
Close (F1);
|
||||
Close (F2);
|
||||
end;
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
img := ppm_read("lena50.ppm") ;
|
||||
x := img[4,4] ; get pixel(4,4)
|
||||
y := img[24,24] ; get pixel(24,24)
|
||||
msgbox % x.rgb() " " y.rgb()
|
||||
img.write("lena50copy.ppm")
|
||||
return
|
||||
|
||||
ppm_read(filename, ppmo=0) ; only ppm6 files supported
|
||||
{
|
||||
if !ppmo ; if image not already in memory, read from filename
|
||||
fileread, ppmo, % filename
|
||||
|
||||
index := 1
|
||||
pos := 1
|
||||
|
||||
loop, parse, ppmo, `n, `r
|
||||
{
|
||||
if (substr(A_LoopField, 1, 1) == "#")
|
||||
continue
|
||||
loop,
|
||||
{
|
||||
if !pos := regexmatch(ppmo, "\d+", pixel, pos)
|
||||
break
|
||||
bitmap%A_Index% := pixel
|
||||
if (index == 4)
|
||||
Break
|
||||
pos := regexmatch(ppmo, "\s", x, pos)
|
||||
index ++
|
||||
}
|
||||
}
|
||||
|
||||
type := bitmap1
|
||||
width := bitmap2
|
||||
height := bitmap3
|
||||
maxcolor := bitmap4
|
||||
bitmap := Bitmap(width, height, color(0,0,0))
|
||||
index := 1
|
||||
i := 1
|
||||
j := 1
|
||||
bits := pos
|
||||
loop % width * height
|
||||
{
|
||||
bitmap[i, j, "r"] := numget(ppmo, 3 * A_Index + bits, "uchar")
|
||||
bitmap[i, j, "g"] := numget(ppmo, 3 * A_Index + bits + 1, "uchar")
|
||||
bitmap[i, j, "b"] := numget(ppmo, 3 * A_Index + bits + 2, "uchar")
|
||||
|
||||
if (j == width)
|
||||
{
|
||||
j := 1
|
||||
i += 1
|
||||
}
|
||||
else
|
||||
j++
|
||||
}
|
||||
return bitmap
|
||||
}
|
||||
#include bitmap_storage.ahk ; from http://rosettacode.org/wiki/Basic_bitmap_storage/AutoHotkey
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
f% = OPENIN("c:\lena.ppm")
|
||||
IF f%=0 ERROR 100, "Failed to open input file"
|
||||
|
||||
IF GET$#f% <> "P6" ERROR 101, "File is not in P6 format"
|
||||
REPEAT
|
||||
in$ = GET$#f%
|
||||
UNTIL LEFT$(in$,1) <> "#"
|
||||
size$ = in$
|
||||
max$ = GET$#f%
|
||||
|
||||
Width% = VAL(size$)
|
||||
space% = INSTR(size$, " ")
|
||||
Height% = VALMID$(size$, space%)
|
||||
|
||||
VDU 23,22,Width%;Height%;8,16,16,128
|
||||
|
||||
FOR y% = Height%-1 TO 0 STEP -1
|
||||
FOR x% = 0 TO Width%-1
|
||||
r% = BGET#f% : g% = BGET#f% : b% = BGET#f%
|
||||
l% = INT(0.3*r% + 0.59*g% + 0.11*b% + 0.5)
|
||||
PROCsetpixel(x%,y%,l%,l%,l%)
|
||||
NEXT
|
||||
NEXT y%
|
||||
END
|
||||
|
||||
DEF PROCsetpixel(x%,y%,r%,g%,b%)
|
||||
COLOUR 1,r%,g%,b%
|
||||
GCOL 1
|
||||
LINE x%*2,y%*2,x%*2,y%*2
|
||||
ENDPROC
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
using System.IO;
|
||||
class PPMReader
|
||||
{
|
||||
public static Bitmap ReadBitmapFromPPM(string file)
|
||||
{
|
||||
var reader = new BinaryReader(new FileStream(file, FileMode.Open));
|
||||
if (reader.ReadChar() != 'P' || reader.ReadChar() != '6')
|
||||
return null;
|
||||
reader.ReadChar(); //Eat newline
|
||||
string widths = "", heights = "";
|
||||
char temp;
|
||||
while ((temp = reader.ReadChar()) != ' ')
|
||||
widths += temp;
|
||||
while ((temp = reader.ReadChar()) >= '0' && temp <= '9')
|
||||
heights += temp;
|
||||
if (reader.ReadChar() != '2' || reader.ReadChar() != '5' || reader.ReadChar() != '5')
|
||||
return null;
|
||||
reader.ReadChar(); //Eat the last newline
|
||||
int width = int.Parse(widths),
|
||||
height = int.Parse(heights);
|
||||
Bitmap bitmap = new Bitmap(width, height);
|
||||
//Read in the pixels
|
||||
for (int y = 0; y < height; y++)
|
||||
for (int x = 0; x < width; x++)
|
||||
bitmap.SetPixel(x, y, new Bitmap.Color()
|
||||
{
|
||||
Red = reader.ReadByte(),
|
||||
Green = reader.ReadByte(),
|
||||
Blue = reader.ReadByte()
|
||||
});
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
1
Task/Bitmap-Read-a-PPM-file/C/bitmap-read-a-ppm-file-1.c
Normal file
1
Task/Bitmap-Read-a-PPM-file/C/bitmap-read-a-ppm-file-1.c
Normal file
|
|
@ -0,0 +1 @@
|
|||
image get_ppm(FILE *pf);
|
||||
38
Task/Bitmap-Read-a-PPM-file/C/bitmap-read-a-ppm-file-2.c
Normal file
38
Task/Bitmap-Read-a-PPM-file/C/bitmap-read-a-ppm-file-2.c
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#include "imglib.h"
|
||||
|
||||
#define PPMREADBUFLEN 256
|
||||
image get_ppm(FILE *pf)
|
||||
{
|
||||
char buf[PPMREADBUFLEN], *t;
|
||||
image img;
|
||||
unsigned int w, h, d;
|
||||
int r;
|
||||
|
||||
if (pf == NULL) return NULL;
|
||||
t = fgets(buf, PPMREADBUFLEN, pf);
|
||||
/* the code fails if the white space following "P6" is not '\n' */
|
||||
if ( (t == NULL) || ( strncmp(buf, "P6\n", 3) != 0 ) ) return NULL;
|
||||
do
|
||||
{ /* Px formats can have # comments after first line */
|
||||
t = fgets(buf, PPMREADBUFLEN, pf);
|
||||
if ( t == NULL ) return NULL;
|
||||
} while ( strncmp(buf, "#", 1) == 0 );
|
||||
r = sscanf(buf, "%u %u", &w, &h);
|
||||
if ( r < 2 ) return NULL;
|
||||
|
||||
r = fscanf(pf, "%u", &d);
|
||||
if ( (r < 1) || ( d != 255 ) ) return NULL;
|
||||
fseek(pf, 1, SEEK_CUR); /* skip one byte, should be whitespace */
|
||||
|
||||
img = alloc_img(w, h);
|
||||
if ( img != NULL )
|
||||
{
|
||||
size_t rd = fread(img->buf, sizeof(pixel), w*h, pf);
|
||||
if ( rd < w*h )
|
||||
{
|
||||
free_img(img);
|
||||
return NULL;
|
||||
}
|
||||
return img;
|
||||
}
|
||||
}
|
||||
16
Task/Bitmap-Read-a-PPM-file/C/bitmap-read-a-ppm-file-3.c
Normal file
16
Task/Bitmap-Read-a-PPM-file/C/bitmap-read-a-ppm-file-3.c
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#include <stdio.h>
|
||||
#include "imglib.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
image source;
|
||||
grayimage idest;
|
||||
|
||||
source = get_ppm(stdin);
|
||||
idest = tograyscale(source);
|
||||
free_img(source);
|
||||
source = tocolor(idest);
|
||||
output_ppm(stdout, source);
|
||||
free_img(source); free_img((image)idest);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
(in-package #:rgb-pixel-buffer)
|
||||
|
||||
(defparameter *whitespaces-chars* '(#\SPACE #\RETURN #\TAB #\NEWLINE #\LINEFEED))
|
||||
|
||||
(defun read-header-chars (stream &optional (delimiter-list *whitespaces-chars*))
|
||||
(do ((c (read-char stream nil :eof)
|
||||
(read-char stream nil :eof))
|
||||
(vals nil (if (or (null c) (char= c #\#)) vals (cons c vals)))) ;;don't collect comment chars
|
||||
((or (eql c :eof) (member c delimiter-list)) (map 'string #'identity (nreverse vals))) ;;return strings
|
||||
(when (char= c #\#) ;;skip comments
|
||||
(read-line stream))))
|
||||
|
||||
(defun read-ppm-file-header (file)
|
||||
(with-open-file (s file :direction :input)
|
||||
(do ((failure-count 0 (1+ failure-count))
|
||||
(tokens nil (let ((t1 (read-header-chars s)))
|
||||
(if (> (length t1) 0)
|
||||
(cons t1 tokens)
|
||||
tokens))))
|
||||
((>= (length tokens) 4) (values (nreverse tokens)
|
||||
(file-position s)))
|
||||
(when (>= failure-count 10)
|
||||
(error (format nil "File ~a does not seem to be a proper ppm file - maybe too many comment lines" file)))
|
||||
(when (= (length tokens) 1)
|
||||
(when (not (or (string= (first tokens) "P6") (string= (first tokens) "P3")))
|
||||
(error (format nil "File ~a is not a ppm file - wrong magic-number. Read ~a instead of P6 or P3 " file (first tokens))))))))
|
||||
|
||||
(defun read-ppm-image (file)
|
||||
(flet ((image-data-reader (stream start-position width height image-build-function read-function)
|
||||
(file-position stream start-position)
|
||||
(dotimes (row height)
|
||||
(dotimes (col width)
|
||||
(funcall image-build-function row col (funcall read-function stream))))))
|
||||
(multiple-value-bind (header file-pos) (read-ppm-file-header file)
|
||||
(let* ((image-type (first header))
|
||||
(width (parse-integer (second header) :junk-allowed t))
|
||||
(height (parse-integer (third header) :junk-allowed t))
|
||||
(max-value (parse-integer (fourth header) :junk-allowed t))
|
||||
(image (make-rgb-pixel-buffer width height)))
|
||||
(when (> max-value 255)
|
||||
(error "unsupported depth - convert to 1byte depth with pamdepth"))
|
||||
(cond ((string= "P6" image-type)
|
||||
(with-open-file (stream file :direction :input :element-type '(unsigned-byte 8))
|
||||
(image-data-reader stream
|
||||
file-pos
|
||||
width
|
||||
height
|
||||
#'(lambda (w h val)
|
||||
(setf (rgb-pixel image w h) val))
|
||||
#'(lambda (stream)
|
||||
(make-rgb-pixel (read-byte stream)
|
||||
(read-byte stream)
|
||||
(read-byte stream))))
|
||||
image))
|
||||
((string= "P3" image-type)
|
||||
(with-open-file (stream file :direction :input)
|
||||
(image-data-reader stream
|
||||
file-pos
|
||||
width
|
||||
height
|
||||
#'(lambda (w h val)
|
||||
(setf (rgb-pixel image w h) val))
|
||||
#'(lambda (stream)
|
||||
(make-rgb-pixel (read stream)
|
||||
(read stream)
|
||||
(read stream))))
|
||||
image))
|
||||
(t 'unsupported))
|
||||
image))))
|
||||
|
||||
(export 'read-ppm-image)
|
||||
|
|
@ -0,0 +1 @@
|
|||
(read-ppm-image "feep.ppm")
|
||||
127
Task/Bitmap-Read-a-PPM-file/Delphi/bitmap-read-a-ppm-file.delphi
Normal file
127
Task/Bitmap-Read-a-PPM-file/Delphi/bitmap-read-a-ppm-file.delphi
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
program BtmAndPpm;
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
{$R *.res}
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
System.Classes,
|
||||
Winapi.Windows,
|
||||
Vcl.Graphics;
|
||||
|
||||
type
|
||||
TBitmapHelper = class helper for TBitmap
|
||||
private
|
||||
public
|
||||
procedure SaveAsPPM(FileName: TFileName; useGrayScale: Boolean = False);
|
||||
procedure LoadFromPPM(FileName: TFileName; useGrayScale: Boolean = False);
|
||||
end;
|
||||
|
||||
function ColorToGray(Color: TColor): TColor;
|
||||
var
|
||||
L: Byte;
|
||||
begin
|
||||
L := round(0.2126 * GetRValue(Color) + 0.7152 * GetGValue(Color) + 0.0722 *
|
||||
GetBValue(Color));
|
||||
Result := RGB(L, L, L);
|
||||
end;
|
||||
|
||||
{ TBitmapHelper }
|
||||
|
||||
procedure TBitmapHelper.SaveAsPPM(FileName: TFileName; useGrayScale: Boolean = False);
|
||||
var
|
||||
i, j, color: Integer;
|
||||
Header: AnsiString;
|
||||
ppm: TMemoryStream;
|
||||
begin
|
||||
ppm := TMemoryStream.Create;
|
||||
try
|
||||
Header := Format('P6'#10'%d %d'#10'255'#10, [Self.Width, Self.Height]);
|
||||
writeln(Header);
|
||||
ppm.Write(Tbytes(Header), Length(Header));
|
||||
|
||||
for i := 0 to Self.Height - 1 do
|
||||
for j := 0 to Self.Width - 1 do
|
||||
begin
|
||||
if useGrayScale then
|
||||
color := ColorToGray(ColorToRGB(Self.Canvas.Pixels[i, j]))
|
||||
else
|
||||
color := ColorToRGB(Self.Canvas.Pixels[i, j]);
|
||||
ppm.Write(color, 3);
|
||||
end;
|
||||
ppm.SaveToFile(FileName);
|
||||
finally
|
||||
ppm.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBitmapHelper.LoadFromPPM(FileName: TFileName; useGrayScale: Boolean = False);
|
||||
var
|
||||
p: Integer;
|
||||
ppm: TMemoryStream;
|
||||
sW, sH: string;
|
||||
temp: AnsiChar;
|
||||
W, H: Integer;
|
||||
Color: TColor;
|
||||
|
||||
function ReadChar: AnsiChar;
|
||||
begin
|
||||
ppm.Read(Result, 1);
|
||||
end;
|
||||
|
||||
begin
|
||||
ppm := TMemoryStream.Create;
|
||||
ppm.LoadFromFile(FileName);
|
||||
if ReadChar + ReadChar <> 'P6' then
|
||||
exit;
|
||||
|
||||
repeat
|
||||
temp := ReadChar;
|
||||
if temp in ['0'..'9'] then
|
||||
sW := sW + temp;
|
||||
until temp = ' ';
|
||||
|
||||
repeat
|
||||
temp := ReadChar;
|
||||
if temp in ['0'..'9'] then
|
||||
sH := sH + temp;
|
||||
until temp = #10;
|
||||
|
||||
W := StrToInt(sW);
|
||||
H := StrToInt(sH);
|
||||
|
||||
if ReadChar + ReadChar + ReadChar <> '255' then
|
||||
exit;
|
||||
|
||||
ReadChar(); //skip newLine
|
||||
|
||||
SetSize(W, H);
|
||||
p := 0;
|
||||
while ppm.Read(Color, 3) > 0 do
|
||||
begin
|
||||
if useGrayScale then
|
||||
Color := ColorToGray(Color);
|
||||
Canvas.Pixels[p mod W, p div W] := Color;
|
||||
inc(p);
|
||||
end;
|
||||
ppm.Free;
|
||||
end;
|
||||
|
||||
begin
|
||||
with TBitmap.Create do
|
||||
begin
|
||||
// Load bmp
|
||||
LoadFromFile('Input.bmp');
|
||||
// Save as ppm
|
||||
SaveAsPPM('Output.ppm');
|
||||
|
||||
// Load as ppm and convert in grayscale
|
||||
LoadFromPPM('Output.ppm', True);
|
||||
|
||||
// Save as bmp
|
||||
SaveToFile('Output.bmp');
|
||||
|
||||
Free;
|
||||
end;
|
||||
end.
|
||||
55
Task/Bitmap-Read-a-PPM-file/E/bitmap-read-a-ppm-file-1.e
Normal file
55
Task/Bitmap-Read-a-PPM-file/E/bitmap-read-a-ppm-file-1.e
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
def chr := <import:java.lang.makeCharacter>.asChar
|
||||
|
||||
def readPPM(inputStream) {
|
||||
# Proper native-to-E stream IO facilities have not been designed and
|
||||
# implemented yet, so we are borrowing Java's. Poorly. This *will* be
|
||||
# improved eventually.
|
||||
|
||||
# Reads one header token, skipping comments and whitespace, and exactly
|
||||
# one trailing whitespace character
|
||||
def readToken() {
|
||||
var token := ""
|
||||
var c := chr(inputStream.read())
|
||||
while (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '#') {
|
||||
if (c == '#') {
|
||||
while (c != '\n') { c := chr(inputStream.read()) }
|
||||
}
|
||||
# skip over initial whitespace
|
||||
c := chr(inputStream.read())
|
||||
}
|
||||
while (!(c == ' ' || c == '\t' || c == '\r' || c == '\n')) {
|
||||
if (c == '#') {
|
||||
while (c != '\n') { c := chr(inputStream.read()) }
|
||||
} else {
|
||||
token += E.toString(c)
|
||||
c := chr(inputStream.read())
|
||||
}
|
||||
}
|
||||
return token
|
||||
}
|
||||
|
||||
# Header
|
||||
require(readToken() == "P6")
|
||||
def width := __makeInt(readToken())
|
||||
def height := __makeInt(readToken())
|
||||
def maxval := __makeInt(readToken())
|
||||
|
||||
def size := width * height * 3
|
||||
|
||||
# Body
|
||||
# See [[Basic bitmap storage]] for the definition and origin of sign()
|
||||
def data := <elib:tables.makeFlexList>.fromType(<type:java.lang.Byte>, size)
|
||||
if (maxval >= 256) {
|
||||
for _ in 1..size {
|
||||
data.push(sign((inputStream.read() * 256 + inputStream.read()) * 255 // maxval))
|
||||
}
|
||||
} else {
|
||||
for _ in 1..size {
|
||||
data.push(sign(inputStream.read() * 255 // maxval))
|
||||
}
|
||||
}
|
||||
|
||||
def image := makeImage(width, height)
|
||||
image.replace(data.snapshot())
|
||||
return image
|
||||
}
|
||||
6
Task/Bitmap-Read-a-PPM-file/E/bitmap-read-a-ppm-file-2.e
Normal file
6
Task/Bitmap-Read-a-PPM-file/E/bitmap-read-a-ppm-file-2.e
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
def readPPMTask(inputFile, outputFile) {
|
||||
makeGrayscale \
|
||||
.fromColor(readPPM(<import:java.io.makeFileInputStream>(inputFile))) \
|
||||
.toColor() \
|
||||
.writePPM(<import:java.io.makeFileOutputStream>(outputFile))
|
||||
}
|
||||
102
Task/Bitmap-Read-a-PPM-file/Erlang/bitmap-read-a-ppm-file-1.erl
Normal file
102
Task/Bitmap-Read-a-PPM-file/Erlang/bitmap-read-a-ppm-file-1.erl
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
% This module provides basic operations on ppm files:
|
||||
% Read from file, create ppm in memory (from generic bitmap) and save to file.
|
||||
% Writing PPM files was introduced in roseta code task 'Bitmap/Write a PPM file'
|
||||
% but the same code is included here to provide whole set of operations on ppm
|
||||
% needed for purposes of this task.
|
||||
|
||||
-module(ppm).
|
||||
|
||||
-export([ppm/1, write/2, read/1]).
|
||||
|
||||
% constants for writing ppm file
|
||||
-define(WHITESPACE, <<10>>).
|
||||
-define(SPACE, <<32>>).
|
||||
|
||||
% constants for reading ppm file
|
||||
-define(WHITESPACES, [9, 10, 13, 32]).
|
||||
-define(PPM_HEADER, "P6").
|
||||
|
||||
% data structure introduced in task Bitmap (module ros_bitmap.erl)
|
||||
-record(bitmap, {
|
||||
mode = rgb,
|
||||
pixels = nil,
|
||||
shape = {0, 0}
|
||||
}).
|
||||
|
||||
%%%%%%%%% API %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% read ppm file from file
|
||||
read(Filename) ->
|
||||
{ok, File} = file:read_file(Filename),
|
||||
parse(File).
|
||||
|
||||
% create ppm image from bitmap record
|
||||
ppm(Bitmap) ->
|
||||
{Width, Height} = Bitmap#bitmap.shape,
|
||||
Pixels = ppm_pixels(Bitmap),
|
||||
Maxval = 255, % original ppm format maximum
|
||||
list_to_binary([
|
||||
header(), width_and_height(Width, Height), maxval(Maxval), Pixels]).
|
||||
|
||||
% write bitmap as ppm file
|
||||
write(Bitmap, Filename) ->
|
||||
Ppm = ppm(Bitmap),
|
||||
{ok, File} = file:open(Filename, [binary, write]),
|
||||
file:write(File, Ppm),
|
||||
file:close(File).
|
||||
|
||||
%%%%%%%%% Reading PPM %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
parse(Binary) ->
|
||||
{?PPM_HEADER, Data} = get_next_token(Binary),
|
||||
{Width, HeightAndRest} = get_next_token(Data),
|
||||
{Height, MaxValAndRest} = get_next_token(HeightAndRest),
|
||||
{_MaxVal, RawPixels} = get_next_token(MaxValAndRest),
|
||||
Shape = {list_to_integer(Width), list_to_integer(Height)},
|
||||
Pixels = load_pixels(RawPixels),
|
||||
#bitmap{pixels=Pixels, shape=Shape}.
|
||||
|
||||
% load binary as a list of RGB triplets
|
||||
load_pixels(Binary) when is_binary(Binary)->
|
||||
load_pixels([], Binary).
|
||||
load_pixels(Acc, <<>>) ->
|
||||
array:from_list(lists:reverse(Acc));
|
||||
load_pixels(Acc, <<R, G, B, Rest/binary>>) ->
|
||||
load_pixels([<<R,G,B>>|Acc], Rest).
|
||||
|
||||
is_whitespace(Byte) ->
|
||||
lists:member(Byte, ?WHITESPACES).
|
||||
|
||||
% get next part of PPM file, skip whitespaces, and return the rest of a binary
|
||||
get_next_token(Binary) ->
|
||||
get_next_token("", true, Binary).
|
||||
get_next_token(CurrentToken, false, <<Byte, Rest/binary>>) ->
|
||||
case is_whitespace(Byte) of
|
||||
true ->
|
||||
{lists:reverse(CurrentToken), Rest};
|
||||
false ->
|
||||
get_next_token([Byte | CurrentToken], false, Rest)
|
||||
end;
|
||||
get_next_token(CurrentToken, true, <<Byte, Rest/binary>>) ->
|
||||
case is_whitespace(Byte) of
|
||||
true ->
|
||||
get_next_token(CurrentToken, true, Rest);
|
||||
false ->
|
||||
get_next_token([Byte | CurrentToken], false, Rest)
|
||||
end.
|
||||
|
||||
%%%%%%%%% Writing PPM %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
header() ->
|
||||
[<<"P6">>, ?WHITESPACE].
|
||||
|
||||
width_and_height(Width, Height) ->
|
||||
[encode_decimal(Width), ?SPACE, encode_decimal(Height), ?WHITESPACE].
|
||||
|
||||
maxval(Maxval) ->
|
||||
[encode_decimal(Maxval), ?WHITESPACE].
|
||||
|
||||
ppm_pixels(Bitmap) ->
|
||||
% 24 bit color depth
|
||||
array:to_list(Bitmap#bitmap.pixels).
|
||||
|
||||
encode_decimal(Number) ->
|
||||
integer_to_list(Number).
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
Colorful = ppm:read("colorful.ppm"),
|
||||
Gray = ros_bitmap:convert(ros_bitmap:convert(Colorful, grey), rgb),
|
||||
ppm:write(Gray, "gray.ppm"),
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
include get.e
|
||||
|
||||
function get2(integer fn)
|
||||
sequence temp
|
||||
temp = get(fn)
|
||||
return temp[2] - temp[1]*temp[1]
|
||||
end function
|
||||
|
||||
function read_ppm(sequence filename)
|
||||
sequence image, line
|
||||
integer dimx, dimy, maxcolor
|
||||
atom fn
|
||||
fn = open(filename, "rb")
|
||||
if fn < 0 then
|
||||
return -1 -- unable to open
|
||||
end if
|
||||
line = gets(fn)
|
||||
if not equal(line,"P6\n") then
|
||||
return -1 -- only ppm6 files are supported
|
||||
end if
|
||||
dimx = get2(fn)
|
||||
if dimx < 0 then
|
||||
return -1
|
||||
end if
|
||||
dimy = get2(fn)
|
||||
if dimy < 0 then
|
||||
return -1
|
||||
end if
|
||||
maxcolor = get2(fn)
|
||||
if maxcolor != 255 then
|
||||
return -1 -- maxcolors other then 255 are not supported
|
||||
end if
|
||||
image = repeat(repeat(0,dimy),dimx)
|
||||
for y = 1 to dimy do
|
||||
for x = 1 to dimx do
|
||||
image[x][y] = getc(fn)*#10000 + getc(fn)*#100 + getc(fn)
|
||||
end for
|
||||
end for
|
||||
close(fn)
|
||||
return image
|
||||
end function
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
sequence image
|
||||
image = read_ppm("image.ppm")
|
||||
image = to_gray(image)
|
||||
image = to_color(image)
|
||||
write_ppm("image_gray.ppm",image)
|
||||
18
Task/Bitmap-Read-a-PPM-file/FBSL/bitmap-read-a-ppm-file.fbsl
Normal file
18
Task/Bitmap-Read-a-PPM-file/FBSL/bitmap-read-a-ppm-file.fbsl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#ESCAPECHARS ON
|
||||
|
||||
DIM colored = ".\\Lena.ppm", grayscale = ".\\LenaGry.ppm"
|
||||
DIM head, tail, r, g, b, l, ptr, blobsize
|
||||
|
||||
FILEGET(FILEOPEN(colored, BINARY), FILELEN(colored)): FILECLOSE(FILEOPEN) ' Load buffer
|
||||
blobsize = INSTR(FILEGET, "\n255\n") + 4 ' Get sizeof PPM header
|
||||
head = @FILEGET + blobsize: tail = @FILEGET + FILELEN ' Set loop bounds
|
||||
|
||||
FOR ptr = head TO tail STEP 3 ' Transform color triplets
|
||||
r = PEEK(ptr + 0, 1) ' Read colors stored in RGB order
|
||||
g = PEEK(ptr + 1, 1)
|
||||
b = PEEK(ptr + 2, 1)
|
||||
l = 0.2126 * r + 0.7152 * g + 0.0722 * b ' Derive luminance
|
||||
POKE(ptr + 0, CHR(l))(ptr + 1, CHR)(ptr + 2, CHR) ' Write grayscale
|
||||
NEXT
|
||||
|
||||
FILEPUT(FILEOPEN(grayscale, BINARY_NEW), FILEGET): FILECLOSE(FILEOPEN) ' Save buffer
|
||||
38
Task/Bitmap-Read-a-PPM-file/Forth/bitmap-read-a-ppm-file.fth
Normal file
38
Task/Bitmap-Read-a-PPM-file/Forth/bitmap-read-a-ppm-file.fth
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
: read-ppm { fid -- bmp }
|
||||
pad dup 80 fid read-line throw 0= abort" Partial line"
|
||||
s" P6" compare abort" Only P6 supported."
|
||||
pad dup 80 fid read-line throw 0= abort" Partial line"
|
||||
0. 2swap >number
|
||||
1 /string \ skip space
|
||||
0. 2swap >number
|
||||
2drop drop nip ( w h )
|
||||
bitmap { bmp }
|
||||
pad dup 80 fid read-line throw 0= abort" Partial line"
|
||||
s" 255" compare abort" Only 8-bits per color channel supported"
|
||||
0 pad !
|
||||
bmp bdim
|
||||
0 do
|
||||
dup 0 do
|
||||
pad 3 fid read-file throw
|
||||
3 - abort" Not enough pixel data in file"
|
||||
pad @ i j bmp b!
|
||||
loop
|
||||
loop drop
|
||||
bmp ;
|
||||
|
||||
\ testing round-trip
|
||||
4 3 bitmap value test
|
||||
red test bfill
|
||||
green 1 2 test b!
|
||||
|
||||
s" red.ppm" w/o create-file throw
|
||||
test over write-ppm
|
||||
close-file throw
|
||||
|
||||
s" red.ppm" r/o open-file throw
|
||||
dup read-ppm value test2
|
||||
close-file throw
|
||||
|
||||
: bsize ( bmp -- len ) bdim * pixels bdata ;
|
||||
|
||||
test dup bsize test2 dup bsize compare . \ 0 if identical
|
||||
42
Task/Bitmap-Read-a-PPM-file/Fortran/bitmap-read-a-ppm-file.f
Normal file
42
Task/Bitmap-Read-a-PPM-file/Fortran/bitmap-read-a-ppm-file.f
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
subroutine read_ppm(u, img)
|
||||
integer, intent(in) :: u
|
||||
type(rgbimage), intent(out) :: img
|
||||
integer :: i, j, ncol, cc
|
||||
character(2) :: sign
|
||||
character :: ccode
|
||||
|
||||
img%width = 0
|
||||
img%height = 0
|
||||
nullify(img%red)
|
||||
nullify(img%green)
|
||||
nullify(img%blue)
|
||||
|
||||
read(u, '(A2)') sign
|
||||
read(u, *) img%width, img%height
|
||||
read(u, *) ncol
|
||||
|
||||
write(0,*) sign
|
||||
write(0,*) img%width, img%height
|
||||
write(0,*) ncol
|
||||
|
||||
if ( ncol /= 255 ) return
|
||||
|
||||
call alloc_img(img, img%width, img%height)
|
||||
|
||||
if ( valid_image(img) ) then
|
||||
do j=1, img%height
|
||||
do i=1, img%width
|
||||
read(u, '(A1)', advance='no', iostat=status) ccode
|
||||
cc = iachar(ccode)
|
||||
img%red(i,j) = cc
|
||||
read(u, '(A1)', advance='no', iostat=status) ccode
|
||||
cc = iachar(ccode)
|
||||
img%green(i,j) = cc
|
||||
read(u, '(A1)', advance='no', iostat=status) ccode
|
||||
cc = iachar(ccode)
|
||||
img%blue(i,j) = cc
|
||||
end do
|
||||
end do
|
||||
end if
|
||||
|
||||
end subroutine read_ppm
|
||||
68
Task/Bitmap-Read-a-PPM-file/Go/bitmap-read-a-ppm-file-1.go
Normal file
68
Task/Bitmap-Read-a-PPM-file/Go/bitmap-read-a-ppm-file-1.go
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package raster
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// ReadFrom constructs a Bitmap object from an io.Reader.
|
||||
func ReadPpmFrom(r io.Reader) (b *Bitmap, err error) {
|
||||
var all []byte
|
||||
all, err = ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
bss := rxHeader.FindSubmatch(all)
|
||||
if bss == nil {
|
||||
return nil, errors.New("unrecognized ppm header")
|
||||
}
|
||||
x, _ := strconv.Atoi(string(bss[3]))
|
||||
y, _ := strconv.Atoi(string(bss[6]))
|
||||
maxval, _ := strconv.Atoi(string(bss[9]))
|
||||
if maxval > 255 {
|
||||
return nil, errors.New("16 bit ppm not supported")
|
||||
}
|
||||
allCmts := append(append(append(bss[1], bss[4]...), bss[7]...), bss[10]...)
|
||||
b = NewBitmap(x, y)
|
||||
b.Comments = rxComment.FindAllString(string(allCmts), -1)
|
||||
b3 := all[len(bss[0]):]
|
||||
var n1 int
|
||||
for i := range b.px {
|
||||
b.px[i].R = byte(int(b3[n1]) * 255 / maxval)
|
||||
b.px[i].G = byte(int(b3[n1+1]) * 255 / maxval)
|
||||
b.px[i].B = byte(int(b3[n1+2]) * 255 / maxval)
|
||||
n1 += 3
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const (
|
||||
// single whitespace character
|
||||
ws = "[ \n\r\t\v\f]"
|
||||
// isolated comment
|
||||
cmt = "#[^\n\r]*"
|
||||
// comment sub expression
|
||||
cmts = "(" + ws + "*" + cmt + "[\n\r])"
|
||||
// number with leading comments
|
||||
num = "(" + cmts + "+" + ws + "*|" + ws + "+)([0-9]+)"
|
||||
)
|
||||
|
||||
var rxHeader = regexp.MustCompile("^P6" + num + num + num +
|
||||
"(" + cmts + "*" + ")" + ws)
|
||||
var rxComment = regexp.MustCompile(cmt)
|
||||
|
||||
// ReadFile writes binary P6 format PPM from the specified filename.
|
||||
func ReadPpmFile(fn string) (b *Bitmap, err error) {
|
||||
var f *os.File
|
||||
if f, err = os.Open(fn); err != nil {
|
||||
return
|
||||
}
|
||||
if b, err = ReadPpmFrom(f); err != nil {
|
||||
return
|
||||
}
|
||||
return b, f.Close()
|
||||
}
|
||||
28
Task/Bitmap-Read-a-PPM-file/Go/bitmap-read-a-ppm-file-2.go
Normal file
28
Task/Bitmap-Read-a-PPM-file/Go/bitmap-read-a-ppm-file-2.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package main
|
||||
|
||||
// Files required to build supporting package raster are found in:
|
||||
// * This task (immediately above)
|
||||
// * Bitmap
|
||||
// * Grayscale image
|
||||
// * Write a PPM file
|
||||
|
||||
import (
|
||||
"raster"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// (A file with this name is output by the Go solution to the task
|
||||
// "Bitmap/Read an image through a pipe," but of course any 8-bit
|
||||
// P6 PPM file should work.)
|
||||
b, err := raster.ReadPpmFile("pipein.ppm")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
b = b.Grmap().Bitmap()
|
||||
err = b.WritePpmFile("grayscale.ppm")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import Bitmap
|
||||
import Bitmap.RGB
|
||||
import Bitmap.Gray
|
||||
import Bitmap.Netpbm
|
||||
|
||||
import Control.Monad
|
||||
import Control.Monad.ST
|
||||
|
||||
main =
|
||||
(readNetpbm "original.ppm" :: IO (Image RealWorld RGB)) >>=
|
||||
stToIO . toGrayImage >>=
|
||||
writeNetpbm "new.pgm"
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
main =
|
||||
(readNetpbm "original.ppm" :: IO (Image RealWorld RGB)) >>=
|
||||
stToIO . (toRGBImage <=< toGrayImage) >>=
|
||||
writeNetpbm "new.ppm"
|
||||
10
Task/Bitmap-Read-a-PPM-file/J/bitmap-read-a-ppm-file-1.j
Normal file
10
Task/Bitmap-Read-a-PPM-file/J/bitmap-read-a-ppm-file-1.j
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
require 'files'
|
||||
|
||||
readppm=: monad define
|
||||
dat=. fread y NB. read from file
|
||||
msk=. 1 ,~ (*. 3 >: +/\) (LF&=@}: *. '#'&~:@}.) dat NB. mark field ends
|
||||
't wbyh maxval dat'=. msk <;._2 dat NB. parse
|
||||
'wbyh maxval'=. 2 1([ {. [: _99&". (LF,' ')&charsub)&.> wbyh;maxval NB. convert to numeric
|
||||
if. (_99 0 +./@e. wbyh,maxval) +. 'P6' -.@-: 2{.t do. _1 return. end.
|
||||
(a. i. dat) makeRGB |.wbyh NB. convert to basic bitmap format
|
||||
)
|
||||
3
Task/Bitmap-Read-a-PPM-file/J/bitmap-read-a-ppm-file-2.j
Normal file
3
Task/Bitmap-Read-a-PPM-file/J/bitmap-read-a-ppm-file-2.j
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
myimg=: readppm jpath '~temp/myimg.ppm'
|
||||
myimgGray=: toColor toGray myimg
|
||||
myimgGray writeppm jpath '~temp/myimgGray.ppm'
|
||||
137
Task/Bitmap-Read-a-PPM-file/Java/bitmap-read-a-ppm-file.java
Normal file
137
Task/Bitmap-Read-a-PPM-file/Java/bitmap-read-a-ppm-file.java
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class ReadPPMFile {
|
||||
|
||||
public static void main(String[] aArgs) throws IOException {
|
||||
// Using the file created in the Bitmap task
|
||||
String filePath = "output.ppm";
|
||||
|
||||
reader = new BufferedInputStream( new FileInputStream(filePath) );
|
||||
final char header1 = (char) reader.read();
|
||||
final char header2 = (char) reader.read();
|
||||
final char header3 = (char) reader.read();
|
||||
if ( header1 != 'P' || header2 != '6' || header3 != END_OF_LINE) {
|
||||
reader.close();
|
||||
throw new IllegalArgumentException("Not a valid P6 PPM file");
|
||||
}
|
||||
|
||||
final int width = processCharacters(SPACE_CHARACTER);
|
||||
final int height = processCharacters(END_OF_LINE);
|
||||
final int maxColorValue = processCharacters(END_OF_LINE);
|
||||
if ( maxColorValue < 0 || maxColorValue > 255 ) {
|
||||
reader.close();
|
||||
throw new IllegalArgumentException("Maximum color value is outside the range 0..255");
|
||||
}
|
||||
|
||||
// Remove any comments before reading data
|
||||
reader.mark(1);
|
||||
while ( reader.read() == START_OF_COMMENT ) {
|
||||
while ( reader.read() != END_OF_LINE );
|
||||
reader.mark(1);
|
||||
}
|
||||
reader.reset();
|
||||
|
||||
// Read data
|
||||
BasicBitmapStorage bitmap = new BasicBitmapStorage(width, height);
|
||||
|
||||
byte[] buffer = new byte[width * 3];
|
||||
for ( int y = 0; y < height; y++ ) {
|
||||
reader.read(buffer, 0, buffer.length);
|
||||
for ( int x = 0; x < width; x++ ) {
|
||||
Color color = new Color(Byte.toUnsignedInt(buffer[x * 3]),
|
||||
Byte.toUnsignedInt(buffer[x * 3 + 1]),
|
||||
Byte.toUnsignedInt(buffer[x * 3 + 2]));
|
||||
bitmap.setPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
reader.close();
|
||||
|
||||
// Convert to gray scale and save to a file
|
||||
bitmap.convertToGrayscale();
|
||||
File grayFile = new File("outputGray.jpg");
|
||||
ImageIO.write((RenderedImage) bitmap.getImage(), "jpg", grayFile);
|
||||
}
|
||||
|
||||
private static int processCharacters(char aChar) throws IOException {
|
||||
StringBuilder characters = new StringBuilder();
|
||||
char ch;
|
||||
while ( ( ch = (char) reader.read() ) != aChar ) {
|
||||
if ( ch == START_OF_COMMENT ) {
|
||||
while ( reader.read() != END_OF_LINE );
|
||||
continue;
|
||||
}
|
||||
characters.append(ch);
|
||||
}
|
||||
return Integer.valueOf(characters.toString());
|
||||
}
|
||||
|
||||
private static BufferedInputStream reader;
|
||||
|
||||
private static final char START_OF_COMMENT = '#';
|
||||
private static final char SPACE_CHARACTER = ' ';
|
||||
private static final char END_OF_LINE = '\n';
|
||||
|
||||
}
|
||||
|
||||
final class BasicBitmapStorage {
|
||||
|
||||
public BasicBitmapStorage(int aWidth, int aHeight) {
|
||||
image = new BufferedImage(aWidth, aHeight, BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
|
||||
public void fill(Color aColor) {
|
||||
Graphics graphics = image.getGraphics();
|
||||
graphics.setColor(aColor);
|
||||
graphics.fillRect(0, 0, image.getWidth(), image.getHeight());
|
||||
}
|
||||
|
||||
public Color getPixel(int aX, int aY) {
|
||||
return new Color(image.getRGB(aX, aY));
|
||||
}
|
||||
|
||||
public void setPixel(int aX, int aY, Color aColor) {
|
||||
image.setRGB(aX, aY, aColor.getRGB());
|
||||
}
|
||||
|
||||
public Image getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public void convertToGrayscale() {
|
||||
for ( int y = 0; y < image.getHeight(); y++ ) {
|
||||
for ( int x = 0; x < image.getWidth(); x++ ) {
|
||||
int color = image.getRGB(x, y);
|
||||
|
||||
int alpha = ( color >> 24 ) & 255;
|
||||
int red = ( color >> 16 ) & 255;
|
||||
int green = ( color >> 8 ) & 255;
|
||||
int blue = color & 255;
|
||||
|
||||
final int luminance = (int) ( 0.2126 * red + 0.7152 * green + 0.0722 * blue );
|
||||
|
||||
alpha = alpha << 24;
|
||||
red = luminance << 16;
|
||||
green = luminance << 8;
|
||||
blue = luminance;
|
||||
|
||||
color = alpha + red + green + blue;
|
||||
|
||||
image.setRGB(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final BufferedImage image;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
using Images, FileIO, Netpbm
|
||||
|
||||
rgbimg = load("data/bitmapInputTest.ppm")
|
||||
greyimg = Gray.(rgbimg)
|
||||
save("data/bitmapOutputTest.ppm", greyimg)
|
||||
130
Task/Bitmap-Read-a-PPM-file/Kotlin/bitmap-read-a-ppm-file.kotlin
Normal file
130
Task/Bitmap-Read-a-PPM-file/Kotlin/bitmap-read-a-ppm-file.kotlin
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
// Version 1.2.40
|
||||
|
||||
import java.awt.Color
|
||||
import java.awt.Graphics
|
||||
import java.awt.image.BufferedImage
|
||||
import java.io.FileInputStream
|
||||
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.ppm, created in the Bitmap/Write a PPM file task
|
||||
val pbis = PushbackInputStream(FileInputStream("output.ppm"), 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_gray.jpg")
|
||||
ImageIO.write(bbs.image, "jpg", grayFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Task/Bitmap-Read-a-PPM-file/Lua/bitmap-read-a-ppm-file.lua
Normal file
34
Task/Bitmap-Read-a-PPM-file/Lua/bitmap-read-a-ppm-file.lua
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
function Read_PPM( filename )
|
||||
local fp = io.open( filename, "rb" )
|
||||
if fp == nil then return nil end
|
||||
|
||||
local data = fp:read( "*line" )
|
||||
if data ~= "P6" then return nil end
|
||||
|
||||
repeat
|
||||
data = fp:read( "*line" )
|
||||
until string.find( data, "#" ) == nil
|
||||
|
||||
local image = {}
|
||||
local size_x, size_y
|
||||
|
||||
size_x = string.match( data, "%d+" )
|
||||
size_y = string.match( data, "%s%d+" )
|
||||
|
||||
data = fp:read( "*line" )
|
||||
if tonumber(data) ~= 255 then return nil end
|
||||
|
||||
for i = 1, size_x do
|
||||
image[i] = {}
|
||||
end
|
||||
|
||||
for j = 1, size_y do
|
||||
for i = 1, size_x do
|
||||
image[i][j] = { string.byte( fp:read(1) ), string.byte( fp:read(1) ), string.byte( fp:read(1) ) }
|
||||
end
|
||||
end
|
||||
|
||||
fp:close()
|
||||
|
||||
return image
|
||||
end
|
||||
|
|
@ -0,0 +1,169 @@
|
|||
Module Checkit {
|
||||
Function Bitmap {
|
||||
If match("NN") then {
|
||||
Read x as long, y as long
|
||||
} else.if Match("N") Then {
|
||||
\\ is a file?
|
||||
Read f
|
||||
if not Eof(f) then {
|
||||
Line Input #f, p3$
|
||||
If p3$="P3" Then {
|
||||
Line Input #f, Comment$
|
||||
if left$(Comment$,1)="#" then {
|
||||
Line Input #f, Dimension$
|
||||
} else Dimension$=Comment$
|
||||
long x=Val(piece$(Dimension$," ")(0))
|
||||
long y=Val(piece$(Dimension$," ")(1))
|
||||
do {
|
||||
Line Input #f, P255$
|
||||
} until left$(P255$, 1)<>"#"
|
||||
If not P255$="255" then Error "Not proper ppm format"
|
||||
}
|
||||
}
|
||||
} else Error "No proper arguments"
|
||||
|
||||
|
||||
if x<1 or y<1 then Error "Wrong dimensions"
|
||||
structure rgb {
|
||||
red as byte
|
||||
green as byte
|
||||
blue as byte
|
||||
}
|
||||
m=len(rgb)*x mod 4
|
||||
if m>0 then m=4-m ' add some bytes to raster line
|
||||
m+=len(rgb) *x
|
||||
Structure rasterline {
|
||||
{
|
||||
pad as byte*m
|
||||
}
|
||||
\\ union pad+hline
|
||||
hline as rgb*x
|
||||
}
|
||||
|
||||
Structure Raster {
|
||||
magic as integer*4
|
||||
w as integer*4
|
||||
h as integer*4
|
||||
lines as rasterline*y
|
||||
}
|
||||
Buffer Clear Image1 as Raster
|
||||
\\ 24 chars as header to be used from bitmap render build in functions
|
||||
Return Image1, 0!magic:="cDIB", 0!w:=Hex$(x,2), 0!h:=Hex$(y, 2)
|
||||
\\ fill white (all 255)
|
||||
\\ Str$(string) convert to ascii, so we get all characters from words width to byte width
|
||||
if not valid(f) then Return Image1, 0!lines:=Str$(String$(chrcode$(255), Len(rasterline)*y))
|
||||
Buffer Clear Pad as Byte*4
|
||||
SetPixel=Lambda Image1, Pad,aLines=Len(Raster)-Len(Rasterline), blines=-Len(Rasterline) (x, y, c) ->{
|
||||
where=alines+3*x+blines*y
|
||||
if c>0 then c=color(c)
|
||||
c-!
|
||||
Return Pad, 0:=c as long
|
||||
Return Image1, 0!where:=Eval(Pad, 2) as byte, 0!where+1:=Eval(Pad, 1) as byte, 0!where+2:=Eval(Pad, 0) as byte
|
||||
|
||||
}
|
||||
GetPixel=Lambda Image1,aLines=Len(Raster)-Len(Rasterline), blines=-Len(Rasterline) (x,y) ->{
|
||||
where=alines+3*x+blines*y
|
||||
=color(Eval(image1, where+2 as byte), Eval(image1, where+1 as byte), Eval(image1, where as byte))
|
||||
}
|
||||
StrDib$=Lambda$ Image1, Raster -> {
|
||||
=Eval$(Image1, 0, Len(Raster))
|
||||
}
|
||||
CopyImage=Lambda Image1 (image$) -> {
|
||||
if left$(image$,12)=Eval$(Image1, 0, 24 ) Then {
|
||||
Return Image1, 0:=Image$
|
||||
} Else Error "Can't Copy Image"
|
||||
}
|
||||
Export2File=Lambda Image1, x, y (f) -> {
|
||||
\\ use this between open and close
|
||||
Print #f, "P3"
|
||||
Print #f,"# Created using M2000 Interpreter"
|
||||
Print #f, x;" ";y
|
||||
Print #f, 255
|
||||
x2=x-1
|
||||
where=24
|
||||
For y1= 0 to y-1 {
|
||||
a$=""
|
||||
For x1=0 to x2 {
|
||||
Print #f, a$;Eval(Image1, where+2 as byte);" ";
|
||||
Print #f, Eval(Image1, where+1 as byte);" ";
|
||||
Print #f, Eval(Image1, where as byte);
|
||||
where+=3
|
||||
a$=" "
|
||||
}
|
||||
Print #f
|
||||
m=where mod 4
|
||||
if m<>0 then where+=4-m
|
||||
}
|
||||
}
|
||||
if valid(F) then {
|
||||
'load RGB values form file
|
||||
x0=x-1
|
||||
where=24
|
||||
For y1=y-1 to 0 {
|
||||
do {
|
||||
Line Input #f, aline$
|
||||
} until left$(aline$,1)<>"#"
|
||||
flush ' empty stack
|
||||
Stack aline$ ' place all values to stack as FIFO
|
||||
For x1=0 to x0 {
|
||||
\\ now read from stack using Number
|
||||
Return Image1, 0!where+2:=Number as byte, 0!where+1:=Number as byte, 0!where:=Number as byte
|
||||
where+=3
|
||||
}
|
||||
m=where mod 4
|
||||
if m<>0 then where+=4-m
|
||||
}
|
||||
}
|
||||
Group Bitmap {
|
||||
SetPixel=SetPixel
|
||||
GetPixel=GetPixel
|
||||
Image$=StrDib$
|
||||
Copy=CopyImage
|
||||
ToFile=Export2File
|
||||
}
|
||||
=Bitmap
|
||||
}
|
||||
A=Bitmap(10, 10)
|
||||
Call A.SetPixel(5,5, color(128,0,255))
|
||||
Open "A.PPM" for Output as #F
|
||||
Call A.ToFile(F)
|
||||
Close #f
|
||||
Open "A.PPM" for Input as #F
|
||||
Try {
|
||||
C=Bitmap(f)
|
||||
Copy 400*twipsx,200*twipsy use C.Image$()
|
||||
}
|
||||
Close #f
|
||||
' is the same as this one
|
||||
Open "A.PPM" for Input as #F
|
||||
Line Input #f, p3$
|
||||
If p3$="P3" Then {
|
||||
Line Input #f, Comment$
|
||||
if left$(Comment$,1)="#" then {
|
||||
Line Input #f, Dimension$
|
||||
} else Dimension$=Comment$
|
||||
Long x=Val(piece$(Dimension$," ")(0))
|
||||
Long y=Val(piece$(Dimension$," ")(1))
|
||||
do {
|
||||
Line Input #f, P255$
|
||||
} until left$(P255$, 1)<>"#"
|
||||
If not P255$="255" then Error "Not proper ppm format"
|
||||
B=Bitmap(x, y)
|
||||
x0=x-1
|
||||
For y1=y-1 to 0 {
|
||||
do {
|
||||
Line Input #f, aline$
|
||||
} until left$(aline$,1)<>"#"
|
||||
flush ' empty stack
|
||||
Stack aline$ ' place all values to stack as FIFO
|
||||
For x1=0 to x0 {
|
||||
\\ now read from stack
|
||||
Read red, green, blue
|
||||
Call B.setpixel(x1, y1, Color(red, green, blue))
|
||||
}
|
||||
}
|
||||
}
|
||||
Close #f
|
||||
If valid("B") then Copy 200*twipsx,200*twipsy use B.Image$()
|
||||
}
|
||||
Checkit
|
||||
|
|
@ -0,0 +1 @@
|
|||
Import["file.ppm","PPM"]
|
||||
91
Task/Bitmap-Read-a-PPM-file/Nim/bitmap-read-a-ppm-file.nim
Normal file
91
Task/Bitmap-Read-a-PPM-file/Nim/bitmap-read-a-ppm-file.nim
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
import strutils
|
||||
import bitmap
|
||||
import streams
|
||||
|
||||
type FormatError = object of CatchableError
|
||||
|
||||
# States used to parse the header.
|
||||
type State = enum waitingMagic, waitingWidth, waitingHeight, waitingColors
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
iterator tokens(f: Stream): tuple[value: string, lastInLine: bool] =
|
||||
## Yield the tokens in the header.
|
||||
for line in f.lines:
|
||||
if not line.startsWith('#'):
|
||||
let fields = line.splitWhitespace()
|
||||
for i, t in fields:
|
||||
yield (t, i == fields.high)
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
proc getInt(s: string): int {.inline.} =
|
||||
## Try to parse an int. Raise an exception if not an integer.
|
||||
try:
|
||||
result = s.parseInt()
|
||||
except ValueError:
|
||||
raise newException(FormatError, "Invalid value")
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
proc header(f: Stream): tuple[width, height: Index] =
|
||||
## Read the header and retrun the image width and height.
|
||||
var state = waitingMagic
|
||||
for (token, lastInLine) in f.tokens:
|
||||
case state
|
||||
of waitingMagic:
|
||||
if token != "P6":
|
||||
raise newException(FormatError, "Invalid file header")
|
||||
of waitingWidth:
|
||||
result.width = token.getInt()
|
||||
of waitingHeight:
|
||||
result.height = token.getInt()
|
||||
of waitingColors:
|
||||
if token.getInt() != 255:
|
||||
raise newException(FormatError, "Invalid number of colors")
|
||||
if not lastInLine:
|
||||
raise newException(FormatError, "Invalid data after number of colors")
|
||||
break
|
||||
state = succ(state)
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
proc readPPM*(f: Stream): Image =
|
||||
## Read a PPM file from a stream into an image.
|
||||
|
||||
let header = f.header()
|
||||
result = newImage(header.width, header.height)
|
||||
|
||||
var
|
||||
arr: array[256, int8]
|
||||
read = f.readData(addr(arr), 256)
|
||||
pos = 0
|
||||
|
||||
while read != 0:
|
||||
for i in 0 ..< read:
|
||||
case pos mod 3
|
||||
of 0: result.pixels[pos div 3].r = arr[i].uint8
|
||||
of 1: result.pixels[pos div 3].g = arr[i].uint8
|
||||
of 2: result.pixels[pos div 3].b = arr[i].uint8
|
||||
else: discard
|
||||
inc pos
|
||||
|
||||
read = f.readData(addr(arr), 256)
|
||||
|
||||
if pos != 3 * result.w * result.h:
|
||||
raise newException(FormatError, "Truncated file")
|
||||
|
||||
#---------------------------------------------------------------------------------------------------
|
||||
|
||||
proc readPPM*(filename: string): Image =
|
||||
## Load a PPM file into an image.
|
||||
|
||||
var file = openFileStream(filename, fmRead)
|
||||
result = file.readPPM()
|
||||
file.close()
|
||||
|
||||
#———————————————————————————————————————————————————————————————————————————————————————————————————
|
||||
|
||||
when isMainModule:
|
||||
let image = readPPM("output.ppm")
|
||||
echo image.h, " ", image.w
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
let read_ppm ~filename =
|
||||
let ic = open_in filename in
|
||||
let line = input_line ic in
|
||||
if line <> "P6" then invalid_arg "not a P6 ppm file";
|
||||
let line = input_line ic in
|
||||
let line =
|
||||
try if line.[0] = '#' (* skip comments *)
|
||||
then input_line ic
|
||||
else line
|
||||
with _ -> line
|
||||
in
|
||||
let width, height =
|
||||
Scanf.sscanf line "%d %d" (fun w h -> (w, h))
|
||||
in
|
||||
let line = input_line ic in
|
||||
if line <> "255" then invalid_arg "not a 8 bit depth image";
|
||||
let all_channels =
|
||||
let kind = Bigarray.int8_unsigned
|
||||
and layout = Bigarray.c_layout
|
||||
in
|
||||
Bigarray.Array3.create kind layout 3 width height
|
||||
in
|
||||
let r_channel = Bigarray.Array3.slice_left_2 all_channels 0
|
||||
and g_channel = Bigarray.Array3.slice_left_2 all_channels 1
|
||||
and b_channel = Bigarray.Array3.slice_left_2 all_channels 2
|
||||
in
|
||||
for y = 0 to pred height do
|
||||
for x = 0 to pred width do
|
||||
r_channel.{x,y} <- (input_byte ic);
|
||||
g_channel.{x,y} <- (input_byte ic);
|
||||
b_channel.{x,y} <- (input_byte ic);
|
||||
done;
|
||||
done;
|
||||
close_in ic;
|
||||
(all_channels,
|
||||
r_channel,
|
||||
g_channel,
|
||||
b_channel)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
let () =
|
||||
let img = read_ppm ~filename:"logo.ppm" in
|
||||
let img = to_color(to_grayscale ~img) in
|
||||
output_ppm ~oc:stdout ~img;
|
||||
;;
|
||||
84
Task/Bitmap-Read-a-PPM-file/Oz/bitmap-read-a-ppm-file-1.oz
Normal file
84
Task/Bitmap-Read-a-PPM-file/Oz/bitmap-read-a-ppm-file-1.oz
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
functor
|
||||
import
|
||||
Bitmap
|
||||
Open
|
||||
export
|
||||
Read
|
||||
%% Write
|
||||
define
|
||||
fun {Read Filename}
|
||||
F = {New Open.file init(name:Filename)}
|
||||
|
||||
fun {ReadColor8 _}
|
||||
Bytes = {F read(list:$ size:3)}
|
||||
in
|
||||
{List.toTuple color Bytes}
|
||||
end
|
||||
|
||||
fun {ReadColor16 _}
|
||||
Bytes = {F read(list:$ size:6)}
|
||||
in
|
||||
{List.toTuple color {Map {PairUp Bytes} FromBytes}}
|
||||
end
|
||||
in
|
||||
try
|
||||
Magic = {F read(size:2 list:$)}
|
||||
if Magic \= "P6" then raise bitmapIO(read unsupportedFormat(Magic)) end end
|
||||
Width = {ReadNumber F}
|
||||
Height = {ReadNumber F}
|
||||
MaxVal = {ReadNumber F}
|
||||
MaxVal =< 0xffff = true
|
||||
Reader = if MaxVal =< 0xff then ReadColor8 else ReadColor16 end
|
||||
B = {Bitmap.new Width Height}
|
||||
in
|
||||
{Bitmap.transform B Reader}
|
||||
B
|
||||
finally
|
||||
{F close}
|
||||
end
|
||||
end
|
||||
|
||||
fun {ReadNumber F}
|
||||
Ds
|
||||
in
|
||||
{SkipWS F}
|
||||
Ds = for collect:Collect break:Break do
|
||||
[C] = {F read(list:$ size:1)}
|
||||
in
|
||||
if {Char.isDigit C} then {Collect C}
|
||||
else {Break}
|
||||
end
|
||||
end
|
||||
{SkipWS F}
|
||||
{String.toInt Ds}
|
||||
end
|
||||
|
||||
proc {SkipWS F}
|
||||
[C] = {F read(list:$ size:1)}
|
||||
in
|
||||
if {Char.isSpace C} then {SkipWS F}
|
||||
elseif C == &# then
|
||||
{SkipLine F}
|
||||
else
|
||||
{F seek(whence:current offset:~1)}
|
||||
end
|
||||
end
|
||||
|
||||
proc {SkipLine F}
|
||||
[C] = {F read(list:$ size:1)}
|
||||
in
|
||||
if C \= &\n andthen C \= &\r then {SkipLine F} end
|
||||
end
|
||||
|
||||
fun {PairUp Xs}
|
||||
case Xs of X1|X2|Xr then [X1 X2]|{PairUp Xr}
|
||||
[] nil then nil
|
||||
end
|
||||
end
|
||||
|
||||
fun {FromBytes [C1 C2]}
|
||||
C1 * 0x100 + C2
|
||||
end
|
||||
|
||||
%% Omitted: Write
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
declare
|
||||
[BitmapIO Grayscale] = {Module.link ['BitmapIO.ozf' 'Grayscale.ozf']}
|
||||
|
||||
B = {BitmapIO.read "image.ppm"}
|
||||
G = {Grayscale.toGraymap B}
|
||||
in
|
||||
{BitmapIO.write {Grayscale.fromGraymap G} "greyimage.ppm"}
|
||||
64
Task/Bitmap-Read-a-PPM-file/PL-I/bitmap-read-a-ppm-file.pli
Normal file
64
Task/Bitmap-Read-a-PPM-file/PL-I/bitmap-read-a-ppm-file.pli
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/* BITMAP FILE: read in a file in PPM format, P6 (binary). 14/5/2010 */
|
||||
test: procedure options (main);
|
||||
declare (m, n, max_color, i, j) fixed binary (31);
|
||||
declare ch character (1), ID character (2);
|
||||
declare 1 pixel union,
|
||||
2 color bit(24) aligned,
|
||||
2 primary_colors,
|
||||
3 R char (1),
|
||||
3 G char (1),
|
||||
3 B char (1);
|
||||
declare in file record;
|
||||
|
||||
open file (in) title ('/IMAGE.PPM,TYPE(FIXED),RECSIZE(1)' ) input;
|
||||
|
||||
call get_char;
|
||||
ID = ch;
|
||||
call get_char;
|
||||
substr(ID, 2,1) = ch;
|
||||
/* Read in the dimensions of the image */
|
||||
call get_integer (m);
|
||||
call get_integer (n);
|
||||
|
||||
/* Read in the maximum color size used */
|
||||
call get_integer (max_color);
|
||||
/* The previous call reads in ONE line feed or CR or other terminator */
|
||||
/* character. */
|
||||
|
||||
begin;
|
||||
declare image (0:m-1,0:n-1) bit (24);
|
||||
|
||||
do i = 0 to hbound(image, 1);
|
||||
do j = 0 to hbound(image,2);
|
||||
read file (in) into (R);
|
||||
read file (in) into (G);
|
||||
read file (in) into (B);
|
||||
image(i,j) = color;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
get_char: procedure;
|
||||
do until (ch ^= ' ');
|
||||
read file (in) into (ch);
|
||||
end;
|
||||
end get_char;
|
||||
|
||||
get_integer: procedure (value);
|
||||
declare value fixed binary (31);
|
||||
|
||||
do until (ch = ' ');
|
||||
read file (in) into (ch);
|
||||
end;
|
||||
value = 0;
|
||||
do until (is_digit(ch));
|
||||
value = value*10 + ch;
|
||||
read file (in) into (ch);
|
||||
end;
|
||||
end get_integer;
|
||||
|
||||
is_digit: procedure (ch) returns (bit(1));
|
||||
declare ch character (1);
|
||||
return (index('0123456789', ch) > 0);
|
||||
end is_digit;
|
||||
end test;
|
||||
14
Task/Bitmap-Read-a-PPM-file/Perl/bitmap-read-a-ppm-file.pl
Normal file
14
Task/Bitmap-Read-a-PPM-file/Perl/bitmap-read-a-ppm-file.pl
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#! /usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use Image::Imlib2;
|
||||
|
||||
my $img = Image::Imlib2->load("out0.ppm");
|
||||
|
||||
# let's do something with it now
|
||||
$img->set_color(255, 255, 255, 255);
|
||||
$img->draw_line(0,0, $img->width,$img->height);
|
||||
$img->image_set_format("png");
|
||||
$img->save("out1.png");
|
||||
|
||||
exit 0;
|
||||
32
Task/Bitmap-Read-a-PPM-file/Phix/bitmap-read-a-ppm-file.phix
Normal file
32
Task/Bitmap-Read-a-PPM-file/Phix/bitmap-read-a-ppm-file.phix
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
-- demo\rosetta\Bitmap_read_ppm.exw (runnable version)
|
||||
|
||||
function read_ppm(string filename)
|
||||
sequence image, line
|
||||
integer dimx, dimy, maxcolor
|
||||
atom fn = open(filename, "rb")
|
||||
if fn<0 then
|
||||
return -1 -- unable to open
|
||||
end if
|
||||
line = gets(fn)
|
||||
if line!="P6\n" then
|
||||
return -1 -- only ppm6 files are supported
|
||||
end if
|
||||
line = gets(fn)
|
||||
{{dimx,dimy}} = scanf(line,"%d %d%s")
|
||||
line = gets(fn)
|
||||
{{maxcolor}} = scanf(line,"%d%s")
|
||||
image = repeat(repeat(0,dimy),dimx)
|
||||
for y=1 to dimy do
|
||||
for x=1 to dimx do
|
||||
image[x][y] = getc(fn)*#10000 + getc(fn)*#100 + getc(fn)
|
||||
end for
|
||||
end for
|
||||
close(fn)
|
||||
return image
|
||||
end function
|
||||
|
||||
--include ppm.e -- read_ppm(), write_ppm(), to_grey() (as distributed, instead of the above)
|
||||
|
||||
sequence img = read_ppm("Lena.ppm")
|
||||
img = to_grey(img)
|
||||
write_ppm("LenaGray.ppm",img)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
(de ppmRead (File)
|
||||
(in File
|
||||
(unless (and `(hex "5036") (rd 2)) # P6
|
||||
(quit "Wrong file format" File) )
|
||||
(rd 1)
|
||||
(let (DX 0 DY 0 Max 0 C)
|
||||
(while (>= 9 (setq C (- (rd 1) `(char "0"))) 0)
|
||||
(setq DX (+ (* 10 DX) C)) )
|
||||
(while (>= 9 (setq C (- (rd 1) `(char "0"))) 0)
|
||||
(setq DY (+ (* 10 DY) C)) )
|
||||
(while (>= 9 (setq C (- (rd 1) `(char "0"))) 0)
|
||||
(setq Max (+ (* 10 Max) C)) )
|
||||
(prog1
|
||||
(make (do DY (link (need DX))))
|
||||
(for Y @
|
||||
(map
|
||||
'((X) (set X (list (rd 1) (rd 1) (rd 1))))
|
||||
Y ) ) ) ) ) )
|
||||
|
|
@ -0,0 +1 @@
|
|||
(pgmWrite (ppm->pgm (ppmRead "img.ppm")) "img.pgm")
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
Structure PPMColor
|
||||
r.c
|
||||
g.c
|
||||
b.c
|
||||
EndStructure
|
||||
|
||||
Procedure LoadImagePPM(Image, file$)
|
||||
; Author Roger Rösch (Nickname Macros)
|
||||
IDFile = ReadFile(#PB_Any, file$)
|
||||
If IDFile
|
||||
If CreateImage(Image, 1, 1)
|
||||
Format$ = ReadString(IDFile)
|
||||
ReadString(IDFile) ; skip comment
|
||||
Dimensions$ = ReadString(IDFile)
|
||||
w = Val(StringField(Dimensions$, 1, " "))
|
||||
h = Val(StringField(Dimensions$, 2, " "))
|
||||
ResizeImage(Image, w, h)
|
||||
StartDrawing(ImageOutput(Image))
|
||||
max = Val(ReadString(IDFile)) ; Maximal Value for a color
|
||||
Select Format$
|
||||
Case "P3" ; File in ASCII format
|
||||
; Exract everey number remaining in th file into an array using an RegEx
|
||||
Stringlen = Lof(IDFile) - Loc(IDFile)
|
||||
content$ = Space(Stringlen)
|
||||
Dim color.s(0)
|
||||
ReadData(IDFile, @content$, Stringlen)
|
||||
CreateRegularExpression(1, "\d+")
|
||||
ExtractRegularExpression(1, content$, color())
|
||||
; Plot color information on our empty Image
|
||||
For y = 0 To h - 1
|
||||
For x = 0 To w - 1
|
||||
pos = (y*w + x)*3
|
||||
r=Val(color(pos))*255 / max
|
||||
g=Val(color(pos+1))*255 / max
|
||||
b=Val(color(pos+2))*255 / max
|
||||
Plot(x, y, RGB(r,g,b))
|
||||
Next
|
||||
Next
|
||||
Case "P6" ;File In binary format
|
||||
; Read whole bytes into a buffer because its faster than reading single ones
|
||||
Bufferlen = Lof(IDFile) - Loc(IDFile)
|
||||
*Buffer = AllocateMemory(Bufferlen)
|
||||
ReadData(IDFile, *Buffer, Bufferlen)
|
||||
; Plot color information on our empty Image
|
||||
For y = 0 To h - 1
|
||||
For x = 0 To w - 1
|
||||
*color.PPMColor = pos + *Buffer
|
||||
Plot(x, y, RGB(*color\r*255 / max, *color\g*255 / max, *color\b*255 / max))
|
||||
pos + 3
|
||||
Next
|
||||
Next
|
||||
EndSelect
|
||||
StopDrawing()
|
||||
; Return 1 if successfully loaded to behave as other PureBasic functions
|
||||
ProcedureReturn 1
|
||||
EndIf
|
||||
EndIf
|
||||
EndProcedure
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
Define file.s, file2.s, image = 3
|
||||
file = OpenFileRequester("Select source image file", "", "PPM image (*.ppm)|*.ppm", 0)
|
||||
If file And LCase(GetExtensionPart(file)) = "ppm"
|
||||
LoadImagePPM(image, file)
|
||||
ImageGrayout(image)
|
||||
file2 = Left(file, Len(file) - Len(GetExtensionPart(file))) + "_grayscale." + GetExtensionPart(file)
|
||||
SaveImageAsPPM(image, file2, 1)
|
||||
EndIf
|
||||
69
Task/Bitmap-Read-a-PPM-file/Python/bitmap-read-a-ppm-file.py
Normal file
69
Task/Bitmap-Read-a-PPM-file/Python/bitmap-read-a-ppm-file.py
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
# With help from http://netpbm.sourceforge.net/doc/ppm.html
|
||||
|
||||
# String masquerading as ppm file (version P3)
|
||||
import io
|
||||
|
||||
ppmtxt = '''P3
|
||||
# feep.ppm
|
||||
4 4
|
||||
15
|
||||
0 0 0 0 0 0 0 0 0 15 0 15
|
||||
0 0 0 0 15 7 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 15 7 0 0 0
|
||||
15 0 15 0 0 0 0 0 0 0 0 0
|
||||
'''
|
||||
|
||||
|
||||
def tokenize(f):
|
||||
for line in f:
|
||||
if line[0] != '#':
|
||||
for t in line.split():
|
||||
yield t
|
||||
|
||||
def ppmp3tobitmap(f):
|
||||
t = tokenize(f)
|
||||
nexttoken = lambda : next(t)
|
||||
assert 'P3' == nexttoken(), 'Wrong filetype'
|
||||
width, height, maxval = (int(nexttoken()) for i in range(3))
|
||||
bitmap = Bitmap(width, height, Colour(0, 0, 0))
|
||||
for h in range(height-1, -1, -1):
|
||||
for w in range(0, width):
|
||||
bitmap.set(w, h, Colour( *(int(nexttoken()) for i in range(3))))
|
||||
|
||||
return bitmap
|
||||
|
||||
print('Original Colour PPM file')
|
||||
print(ppmtxt)
|
||||
ppmfile = io.StringIO(ppmtxt)
|
||||
bitmap = ppmp3tobitmap(ppmfile)
|
||||
print('Grey PPM:')
|
||||
bitmap.togreyscale()
|
||||
ppmfileout = io.StringIO('')
|
||||
bitmap.writeppmp3(ppmfileout)
|
||||
print(ppmfileout.getvalue())
|
||||
|
||||
|
||||
'''
|
||||
The print statements above produce the following output:
|
||||
|
||||
Original Colour PPM file
|
||||
P3
|
||||
# feep.ppm
|
||||
4 4
|
||||
15
|
||||
0 0 0 0 0 0 0 0 0 15 0 15
|
||||
0 0 0 0 15 7 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 0 15 7 0 0 0
|
||||
15 0 15 0 0 0 0 0 0 0 0 0
|
||||
|
||||
Grey PPM:
|
||||
P3
|
||||
# generated from Bitmap.writeppmp3
|
||||
4 4
|
||||
11
|
||||
0 0 0 0 0 0 0 0 0 4 4 4
|
||||
0 0 0 11 11 11 0 0 0 0 0 0
|
||||
0 0 0 0 0 0 11 11 11 0 0 0
|
||||
4 4 4 0 0 0 0 0 0 0 0 0
|
||||
|
||||
'''
|
||||
36
Task/Bitmap-Read-a-PPM-file/REXX/bitmap-read-a-ppm-file.rexx
Normal file
36
Task/Bitmap-Read-a-PPM-file/REXX/bitmap-read-a-ppm-file.rexx
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/*REXX program reads a PPM formatted image file, and creates a gray─scale image of it. */
|
||||
parse arg iFN oFN /*obtain optional argument from the CL.*/
|
||||
if iFN=='' | iFN=="," then iFN= 'Lenna50' /*Not specified? Then use the default.*/
|
||||
if oFN=='' | oFN=="," then oFN= 'greyscale' /* " " " " " " */
|
||||
iFID= iFN'.ppm'; oFID= oFN'.ppm' /*complete the input and output FIDs.*/
|
||||
call charin iFID, 1, 0 /*set the position of the input file. */
|
||||
y=charin(iFID, , copies(9, digits() ) ) /*read the entire input file ───► X */
|
||||
parse var y id 3 c 4 3 width height # pixels /*extract header info from the PPM hdr.*/
|
||||
LF= 'a'x /*define a comment separator (in hdr).*/ /* ◄─── LF delimiters & comments*/
|
||||
if c==LF then do; commentEND=pos(LF, y, 4) /*point to the last char in the comment*/ /* ◄─── LF delimiters & comments*/
|
||||
parse var y =(commentEND) +1 width height # pixels /* ◄─── LF delimiters & comments*/
|
||||
end /* ◄─── LF delimiters & comments*/
|
||||
/* [↓] has an alternative delimiter? */ /* ◄─── LF delimiters & comments*/
|
||||
z=pos(LF, height); if z\==0 then parse var height height =(z) +1 # pixels /* ◄─── LF delimiters & comments*/
|
||||
z=pos(LF, # ); if z\==0 then parse var # # =(z) +1 pixels /* ◄─── LF delimiters & comments*/
|
||||
chunk=4000 /*chunk size to be written at one time.*/
|
||||
LenPixels= length(pixels)
|
||||
|
||||
do j=0 for 256; _=d2c(j); @._=j; @@.j=_ /*build two tables for fast conversions*/
|
||||
end /*j*/
|
||||
|
||||
call charout oFID, , 1 /*set the position of the output file. */
|
||||
call charout oFID, id || width height #' ' /*write the header followed by a blank.*/
|
||||
!=1
|
||||
do until !>=LenPixels; $= /*$: partial output string so far.*/
|
||||
do !=! by 3 for chunk /*chunk: # pixels converted at 1 time.*/
|
||||
parse var pixels =(!) r +1 g +1 b +1 /*obtain the next RGB of a PPM pixel.*/
|
||||
if r=='' then leave /*has the end─of─string been reached? */
|
||||
_=(.2126*@.r + .7152*@.g + .0722*@.b )%1 /*an integer RGB greyscale of a pixel. */
|
||||
$=$ || @@._ || @@._ || @@._ /*lump (grey) R G B pixels together. */
|
||||
end /*!*/ /* [↑] D2C converts decimal ───► char*/
|
||||
call charout oFID, $ /*write the next bunch of pixels. */
|
||||
end /*until*/
|
||||
|
||||
call charout oFID /*close the output file just to be safe*/
|
||||
say 'File ' oFID " was created." /*stick a fork in it, we're all done. */
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#lang racket
|
||||
(require racket/draw)
|
||||
|
||||
(define (read-ppm port)
|
||||
(parameterize ([current-input-port port])
|
||||
(define magic (read))
|
||||
(define width (read))
|
||||
(define height (read))
|
||||
(define maxcol (read))
|
||||
(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))
|
||||
(define green (read))
|
||||
(define blue (read))
|
||||
(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))
|
||||
36
Task/Bitmap-Read-a-PPM-file/Raku/bitmap-read-a-ppm-file.raku
Normal file
36
Task/Bitmap-Read-a-PPM-file/Raku/bitmap-read-a-ppm-file.raku
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
class Pixel { has UInt ($.R, $.G, $.B) }
|
||||
class Bitmap {
|
||||
has UInt ($.width, $.height);
|
||||
has Pixel @.data;
|
||||
}
|
||||
|
||||
role PGM {
|
||||
has @.GS;
|
||||
method P5 returns Blob {
|
||||
"P5\n{self.width} {self.height}\n255\n".encode('ascii')
|
||||
~ Blob.new: self.GS
|
||||
}
|
||||
}
|
||||
|
||||
sub load-ppm ( $ppm ) {
|
||||
my $fh = $ppm.IO.open( :enc('ISO-8859-1') );
|
||||
my $type = $fh.get;
|
||||
my ($width, $height) = $fh.get.split: ' ';
|
||||
my $depth = $fh.get;
|
||||
Bitmap.new( width => $width.Int, height => $height.Int,
|
||||
data => ( $fh.slurp.ords.rotor(3).map:
|
||||
{ Pixel.new(R => $_[0], G => $_[1], B => $_[2]) } )
|
||||
)
|
||||
}
|
||||
|
||||
sub grayscale ( Bitmap $bmp ) {
|
||||
$bmp.GS = map { (.R*0.2126 + .G*0.7152 + .B*0.0722).round(1) min 255 }, $bmp.data;
|
||||
}
|
||||
|
||||
my $filename = './camelia.ppm';
|
||||
|
||||
my Bitmap $b = load-ppm( $filename ) but PGM;
|
||||
|
||||
grayscale($b);
|
||||
|
||||
'./camelia-gs.pgm'.IO.open(:bin, :w).write: $b.P5;
|
||||
33
Task/Bitmap-Read-a-PPM-file/Ruby/bitmap-read-a-ppm-file.rb
Normal file
33
Task/Bitmap-Read-a-PPM-file/Ruby/bitmap-read-a-ppm-file.rb
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
class Pixmap
|
||||
# 'open' is a class method
|
||||
def self.open(filename)
|
||||
bitmap = nil
|
||||
File.open(filename, 'r') do |f|
|
||||
header = [f.gets.chomp, f.gets.chomp, f.gets.chomp]
|
||||
width, height = header[1].split.map {|n| n.to_i }
|
||||
if header[0] != 'P6' or header[2] != '255' or width < 1 or height < 1
|
||||
raise StandardError, "file '#{filename}' does not start with the expected header"
|
||||
end
|
||||
f.binmode
|
||||
bitmap = self.new(width, height)
|
||||
height.times do |y|
|
||||
width.times do |x|
|
||||
# read 3 bytes
|
||||
red, green, blue = f.read(3).unpack('C3')
|
||||
bitmap[x,y] = RGBColour.new(red, green, blue)
|
||||
end
|
||||
end
|
||||
end
|
||||
bitmap
|
||||
end
|
||||
end
|
||||
|
||||
# create an image: a green cross on a blue background
|
||||
colour_bitmap = Pixmap.new(20, 30)
|
||||
colour_bitmap.fill(RGBColour::BLUE)
|
||||
colour_bitmap.height.times {|y| [9,10,11].each {|x| colour_bitmap[x,y]=RGBColour::GREEN}}
|
||||
colour_bitmap.width.times {|x| [14,15,16].each {|y| colour_bitmap[x,y]=RGBColour::GREEN}}
|
||||
colour_bitmap.save('testcross.ppm')
|
||||
|
||||
# then, convert to grayscale
|
||||
Pixmap.open('testcross.ppm').to_grayscale!.save('testgray.ppm')
|
||||
282
Task/Bitmap-Read-a-PPM-file/Rust/bitmap-read-a-ppm-file.rust
Normal file
282
Task/Bitmap-Read-a-PPM-file/Rust/bitmap-read-a-ppm-file.rust
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
parser.rs:
|
||||
use super::{Color, ImageFormat};
|
||||
use std::str::from_utf8;
|
||||
use std::str::FromStr;
|
||||
|
||||
pub fn parse_version(input: &[u8]) -> nom::IResult<&[u8], ImageFormat> {
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::tag;
|
||||
use nom::character::complete::line_ending;
|
||||
use nom::combinator::map;
|
||||
use nom::sequence::terminated;
|
||||
|
||||
// starts with P3/P6 ends with a CR/LF
|
||||
terminated(
|
||||
alt((
|
||||
map(tag("P3".as_bytes()), |_| ImageFormat::P3),
|
||||
map(tag("P6".as_bytes()), |_| ImageFormat::P6),
|
||||
)),
|
||||
line_ending,
|
||||
)(input)
|
||||
}
|
||||
|
||||
pub fn parse_image_attributes(input: &[u8]) -> nom::IResult<&[u8], (usize, usize, usize)> {
|
||||
use nom::character::complete::line_ending;
|
||||
use nom::character::complete::{digit1, space1};
|
||||
use nom::sequence::terminated;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
// 3 numbers separated by spaces ends with a CR/LF
|
||||
terminated(tuple((digit1, space1, digit1, space1, digit1)), line_ending)(input).map(
|
||||
|(next_input, result)| {
|
||||
(
|
||||
next_input,
|
||||
(
|
||||
usize::from_str_radix(from_utf8(result.0).unwrap(), 10).unwrap(),
|
||||
usize::from_str_radix(from_utf8(result.2).unwrap(), 10).unwrap(),
|
||||
usize::from_str_radix(from_utf8(result.4).unwrap(), 10).unwrap(),
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn parse_color_binary(input: &[u8]) -> nom::IResult<&[u8], Color> {
|
||||
use nom::number::complete::u8 as nom_u8;
|
||||
use nom::sequence::tuple;
|
||||
|
||||
tuple((nom_u8, nom_u8, nom_u8))(input).map(|(next_input, res)| {
|
||||
(
|
||||
next_input,
|
||||
Color {
|
||||
red: res.0,
|
||||
green: res.1,
|
||||
blue: res.2,
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_data_binary(input: &[u8]) -> nom::IResult<&[u8], Vec<Color>> {
|
||||
use nom::multi::many0;
|
||||
many0(parse_color_binary)(input)
|
||||
}
|
||||
|
||||
pub fn parse_color_ascii(input: &[u8]) -> nom::IResult<&[u8], Color> {
|
||||
use nom::character::complete::{digit1, space0, space1};
|
||||
use nom::sequence::tuple;
|
||||
|
||||
tuple((digit1, space1, digit1, space1, digit1, space0))(input).map(|(next_input, res)| {
|
||||
(
|
||||
next_input,
|
||||
Color {
|
||||
red: u8::from_str(from_utf8(res.0).unwrap()).unwrap(),
|
||||
green: u8::from_str(from_utf8(res.2).unwrap()).unwrap(),
|
||||
blue: u8::from_str(from_utf8(res.4).unwrap()).unwrap(),
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_data_ascii(input: &[u8]) -> nom::IResult<&[u8], Vec<Color>> {
|
||||
use nom::multi::many0;
|
||||
many0(parse_color_ascii)(input)
|
||||
}
|
||||
|
||||
|
||||
lib.rs:
|
||||
extern crate nom;
|
||||
extern crate thiserror;
|
||||
mod parser;
|
||||
|
||||
use std::default::Default;
|
||||
use std::fmt;
|
||||
use std::io::{BufWriter, Error, Write};
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::{fs::File, io::Read};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Copy, Clone, Default, PartialEq, Debug)]
|
||||
pub struct Color {
|
||||
pub red: u8,
|
||||
pub green: u8,
|
||||
pub blue: u8,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum ImageFormat {
|
||||
P3,
|
||||
P6,
|
||||
}
|
||||
|
||||
impl From<&str> for ImageFormat {
|
||||
fn from(i: &str) -> Self {
|
||||
match i.to_lowercase().as_str() {
|
||||
"p3" => ImageFormat::P3,
|
||||
"p6" => ImageFormat::P6,
|
||||
_ => unimplemented!("no other formats supported"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ImageFormat {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
ImageFormat::P3 => {
|
||||
write!(f, "P3")
|
||||
}
|
||||
ImageFormat::P6 => {
|
||||
write!(f, "P6")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ImageError {
|
||||
#[error("File not found")]
|
||||
FileNotFound,
|
||||
#[error("File not readable")]
|
||||
FileNotReadable,
|
||||
#[error("Invalid header information")]
|
||||
InvalidHeader,
|
||||
#[error("Invalid information in the data block")]
|
||||
InvalidData,
|
||||
#[error("Invalid max color information")]
|
||||
InvalidMaxColor,
|
||||
#[error("File is incomplete")]
|
||||
IncompleteFile,
|
||||
#[error("unknown data store error")]
|
||||
Unknown,
|
||||
}
|
||||
pub struct Image {
|
||||
pub format: ImageFormat,
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
pub data: Vec<Color>,
|
||||
}
|
||||
|
||||
impl Image {
|
||||
#[must_use]
|
||||
pub fn new(width: usize, height: usize) -> Self {
|
||||
Self {
|
||||
format: ImageFormat::P6,
|
||||
width,
|
||||
height,
|
||||
data: vec![Color::default(); width * height],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fill(&mut self, color: Color) {
|
||||
for elem in &mut self.data {
|
||||
*elem = color;
|
||||
}
|
||||
}
|
||||
|
||||
/// # Errors
|
||||
///
|
||||
/// Will return `Error` if `filename` does not exist or the user does not have
|
||||
/// permission to write to it, or the write operation fails.
|
||||
pub fn write_ppm(&self, filename: &str) -> Result<(), Error> {
|
||||
let file = File::create(filename)?;
|
||||
let mut writer = BufWriter::new(file);
|
||||
writeln!(&mut writer, "{}", self.format.to_string())?;
|
||||
writeln!(&mut writer, "{} {} 255", self.width, self.height)?;
|
||||
match self.format {
|
||||
ImageFormat::P3 => {
|
||||
writer.write_all(
|
||||
&self
|
||||
.data
|
||||
.iter()
|
||||
.flat_map(|color| {
|
||||
vec![
|
||||
color.red.to_string(),
|
||||
color.green.to_string(),
|
||||
color.blue.to_string(),
|
||||
]
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.join(" ")
|
||||
.as_bytes(),
|
||||
)?;
|
||||
}
|
||||
ImageFormat::P6 => {
|
||||
writer.write_all(
|
||||
&self
|
||||
.data
|
||||
.iter()
|
||||
.flat_map(|color| vec![color.red, color.green, color.blue])
|
||||
.collect::<Vec<u8>>(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the format is not P6 or P3 PPM
|
||||
/// # Errors
|
||||
///
|
||||
/// Will return `Error` if `filename` does not exist or the user does not have
|
||||
/// permission to read it or the read operation fails, or the file format does not
|
||||
/// match the specification
|
||||
pub fn read_ppm(filename: &str) -> Result<Image, ImageError> {
|
||||
let mut file = File::open(filename).map_err(|_| ImageError::FileNotFound)?;
|
||||
let mut data: Vec<u8> = Vec::new();
|
||||
file.read_to_end(&mut data)
|
||||
.map_err(|_| ImageError::FileNotReadable)?;
|
||||
|
||||
let (i, format) = parser::parse_version(&data).map_err(|_| ImageError::InvalidHeader)?;
|
||||
let (i, (width, height, max_color)) =
|
||||
parser::parse_image_attributes(i).map_err(|_| ImageError::InvalidHeader)?;
|
||||
|
||||
if max_color != 255 {
|
||||
return Err(ImageError::InvalidMaxColor);
|
||||
}
|
||||
|
||||
let (_, data) = match format {
|
||||
ImageFormat::P3 => parser::parse_data_ascii(i).map_err(|_| ImageError::InvalidData)?,
|
||||
ImageFormat::P6 => parser::parse_data_binary(i).map_err(|_| ImageError::InvalidData)?,
|
||||
};
|
||||
|
||||
if data.len() != height * width {
|
||||
return Err(ImageError::IncompleteFile);
|
||||
};
|
||||
|
||||
Ok(Image {
|
||||
format,
|
||||
width,
|
||||
height,
|
||||
data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<(usize, usize)> for Image {
|
||||
type Output = Color;
|
||||
|
||||
fn index(&self, (x, y): (usize, usize)) -> &Color {
|
||||
&self.data[x + y * self.width]
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<(usize, usize)> for Image {
|
||||
fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Color {
|
||||
&mut self.data[x + y * self.width]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
use bitmap::Image;
|
||||
|
||||
// see read_ppm implementation in the bitmap library
|
||||
|
||||
pub fn main() {
|
||||
// read a PPM image, which was produced by the write-a-ppm-file task
|
||||
let image = Image::read_ppm("./test_image.ppm").unwrap();
|
||||
|
||||
println!("Read using nom parsing:");
|
||||
println!("Format: {:?}", image.format);
|
||||
println!("Dimensions: {} x {}", image.height, image.width);
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import scala.io._
|
||||
import scala.swing._
|
||||
import java.io._
|
||||
import java.awt.Color
|
||||
import javax.swing.ImageIcon
|
||||
|
||||
object Pixmap {
|
||||
private case class PpmHeader(format:String, width:Int, height:Int, maxColor:Int)
|
||||
|
||||
def load(filename:String):Option[RgbBitmap]={
|
||||
implicit val in=new BufferedInputStream(new FileInputStream(filename))
|
||||
val header=readHeader
|
||||
if(header.format=="P6")
|
||||
{
|
||||
val bm=new RgbBitmap(header.width, header.height);
|
||||
for(y <- 0 until bm.height; x <- 0 until bm.width; c=readColor)
|
||||
bm.setPixel(x, y, c)
|
||||
return Some(bm)
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
private def readHeader(implicit in:InputStream)={
|
||||
var format=readLine
|
||||
|
||||
var line=readLine
|
||||
while(line.startsWith("#")) //skip comments
|
||||
line=readLine
|
||||
|
||||
val parts=line.split("\\s")
|
||||
val width=parts(0).toInt
|
||||
val height=parts(1).toInt
|
||||
val maxColor=readLine.toInt
|
||||
|
||||
new PpmHeader(format, width, height, maxColor)
|
||||
}
|
||||
|
||||
private def readColor(implicit in:InputStream)=new Color(in.read, in.read, in.read)
|
||||
|
||||
private def readLine(implicit in:InputStream)={
|
||||
var out=""
|
||||
var b=in.read
|
||||
while(b!=0xA){out+=b.toChar; b=in.read}
|
||||
out
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
object PixmapTest {
|
||||
def main(args: Array[String]): Unit = {
|
||||
val img=Pixmap.load("image.ppm").get
|
||||
val grayImg=BitmapOps.grayscale(img);
|
||||
Pixmap.save(grayImg, "image_gray.ppm")
|
||||
|
||||
val mainframe=new MainFrame(){
|
||||
title="Test"
|
||||
visible=true
|
||||
contents=new Label(){
|
||||
icon=new ImageIcon(grayImg.image)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
$ include "seed7_05.s7i";
|
||||
include "draw.s7i";
|
||||
include "color.s7i";
|
||||
|
||||
const func PRIMITIVE_WINDOW: getPPM (in string: fileName) is func
|
||||
result
|
||||
var PRIMITIVE_WINDOW: aWindow is PRIMITIVE_WINDOW.value;
|
||||
local
|
||||
var file: ppmFile is STD_NULL;
|
||||
var string: line is "";
|
||||
var integer: width is 0;
|
||||
var integer: height is 0;
|
||||
var integer: x is 0;
|
||||
var integer: y is 0;
|
||||
var color: pixColor is black;
|
||||
begin
|
||||
ppmFile := open(fileName, "r");
|
||||
if ppmFile <> STD_NULL then
|
||||
if getln(ppmFile) = "P6" then
|
||||
repeat
|
||||
line := getln(ppmFile);
|
||||
until line = "" or line[1] <> '#';
|
||||
read(ppmFile, width);
|
||||
readln(ppmFile, height);
|
||||
aWindow := newPixmap(width, height);
|
||||
for y range 0 to pred(height) do
|
||||
for x range 0 to pred(width) do
|
||||
pixColor.redLight := ord(getc(ppmFile));
|
||||
pixColor.greenLight := ord(getc(ppmFile));
|
||||
pixColor.blueLight := ord(getc(ppmFile));
|
||||
end for;
|
||||
end for;
|
||||
end if;
|
||||
close(ppmFile);
|
||||
end if;
|
||||
end func;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package require Tk
|
||||
|
||||
proc readPPM {image file} {
|
||||
$image read $file -format ppm
|
||||
}
|
||||
21
Task/Bitmap-Read-a-PPM-file/Tcl/bitmap-read-a-ppm-file-2.tcl
Normal file
21
Task/Bitmap-Read-a-PPM-file/Tcl/bitmap-read-a-ppm-file-2.tcl
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package require Tk
|
||||
|
||||
proc grayscaleFile {filename {newFilename ""}} {
|
||||
set buffer [image create photo]
|
||||
if {$newFilename eq ""} {set newFilename $filename}
|
||||
try {
|
||||
$buffer read $filename -format ppm
|
||||
set w [image width $buffer]
|
||||
set h [image height $buffer]
|
||||
for {set x 0} {$x<$w} {incr x} {
|
||||
for {set y 0} {$y<$h} {incr y} {
|
||||
lassign [$buffer get $x $y] r g b
|
||||
set l [expr {int(0.2126*$r + 0.7152*$g + 0.0722*$b)}]
|
||||
$buffer put [format "#%02x%02x%02x" $l $l $l] -to $x $y
|
||||
}
|
||||
}
|
||||
$buffer write $newFilename -format ppm
|
||||
} finally {
|
||||
image delete $buffer
|
||||
}
|
||||
}
|
||||
12
Task/Bitmap-Read-a-PPM-file/Tcl/bitmap-read-a-ppm-file-3.tcl
Normal file
12
Task/Bitmap-Read-a-PPM-file/Tcl/bitmap-read-a-ppm-file-3.tcl
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
package require Tk
|
||||
|
||||
proc grayscaleFile {filename {newFilename ""}} {
|
||||
set buffer [image create photo]
|
||||
if {$newFilename eq ""} {set newFilename $filename}
|
||||
try {
|
||||
$buffer read $filename -format ppm
|
||||
$buffer write $newFilename -format ppm -grayscale
|
||||
} finally {
|
||||
image delete $buffer
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
function setrgb {
|
||||
_.r=$1
|
||||
_.g=$2
|
||||
_.b=$3
|
||||
}
|
||||
function grayscale {
|
||||
integer x=$(( round( 0.2126*_.r + 0.7152*_.g + 0.0722*_.b ) ))
|
||||
_.r=$x
|
||||
_.g=$x
|
||||
_.b=$x
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
function grayscale {
|
||||
RGBColor_t c
|
||||
for ((y=0; y<_.height; y++)); do
|
||||
for ((x=0; x<_.width; x++)); do
|
||||
c.setrgb ${_.data[y][x]}
|
||||
c.grayscale
|
||||
_.data[y][x]=$(c.to_s)
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
function read {
|
||||
exec 4<"$1"
|
||||
typeset filetype
|
||||
read -u4 filetype
|
||||
if [[ $filetype != "P3" ]]; then
|
||||
print -u2 "error: I can only read P3 type PPM files"
|
||||
else
|
||||
read -u4 _.width _.height
|
||||
integer maxval
|
||||
read -u4 maxval
|
||||
integer x y r g b
|
||||
typeset -a bytes
|
||||
for ((y=0; y<_.height; y++)); do
|
||||
read -u4 -A bytes
|
||||
for ((x=0; x<_.width; x++)); do
|
||||
r=${bytes[3*x+0]}
|
||||
g=${bytes[3*x+1]}
|
||||
b=${bytes[3*x+2]}
|
||||
if (( r > maxval || g > maxval || b > maxval )); then
|
||||
print -u2 "error: invalid color ($r $g $b), max=$maxval"
|
||||
return 1
|
||||
fi
|
||||
_.data[y][x]="$r $g $b"
|
||||
done
|
||||
done
|
||||
fi
|
||||
exec 4<&-
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
Bitmap_t c
|
||||
c.read "$HOME/tmp/bitmap.ppm"
|
||||
c.to_s
|
||||
|
||||
if [[ $(c.to_s) == $(cat "$HOME/tmp/bitmap.ppm") ]]; then
|
||||
echo looks OK
|
||||
else
|
||||
echo something is wrong
|
||||
fi
|
||||
|
||||
c.grayscale
|
||||
c.to_s
|
||||
c.write "$HOME/tmp/bitmap_g.ppm"
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
// Load a PPM file
|
||||
// @10 = filename
|
||||
// On return:
|
||||
// #10 points to buffer containing pixel data,
|
||||
// #11 = width, #12 = height.
|
||||
|
||||
:LOAD_PPM:
|
||||
File_Open(@10)
|
||||
BOF
|
||||
Search("|X", ADVANCE) // skip "P6"
|
||||
#11 = Num_Eval(ADVANCE) // #11 = width
|
||||
Match("|X", ADVANCE) // skip separator
|
||||
#12 = Num_Eval(ADVANCE) // #12 = height
|
||||
Match("|X", ADVANCE)
|
||||
Search("|X", ADVANCE) // skip maxval (assume 255)
|
||||
Del_Block(0,CP) // remove the header
|
||||
Return
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// Load RGB image
|
||||
Reg_Set(10, "|(USER_MACRO)\example.ppm")
|
||||
Call("LOAD_PPM")
|
||||
|
||||
// Convert to grayscale
|
||||
#10 = Buf_Num
|
||||
Call("RGB_TO_GRAYSCALE")
|
||||
Buf_Switch(#10) Buf_Quit(OK)
|
||||
|
||||
// Convert to RGB
|
||||
Call("GRAYSCALE_TO_RGB")
|
||||
|
||||
// Save the image
|
||||
Reg_Set(10, "|(USER_MACRO)\example_gray.ppm")
|
||||
Call("SAVE_PPM")
|
||||
|
||||
// Cleanup and exit
|
||||
Buf_Switch(#20) Buf_Quit(OK)
|
||||
return
|
||||
75
Task/Bitmap-Read-a-PPM-file/Wren/bitmap-read-a-ppm-file.wren
Normal file
75
Task/Bitmap-Read-a-PPM-file/Wren/bitmap-read-a-ppm-file.wren
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import "graphics" for Canvas, ImageData, Color
|
||||
import "dome" for Window, Process
|
||||
import "io" for FileSystem
|
||||
|
||||
class Bitmap {
|
||||
construct new(fileName, fileName2, width, height) {
|
||||
Window.title = "Bitmap - read PPM file"
|
||||
Window.resize(width, height)
|
||||
Canvas.resize(width, height)
|
||||
_w = width
|
||||
_h = height
|
||||
_fn2 = fileName2
|
||||
loadPPMFile(fileName)
|
||||
}
|
||||
|
||||
init() {
|
||||
toGrayScale()
|
||||
// display images side by side
|
||||
_bmp.draw(0, 0)
|
||||
_bmp2.draw(536, 0)
|
||||
// save gray scale image to file
|
||||
_bmp2.saveToFile(_fn2)
|
||||
}
|
||||
|
||||
loadPPMFile(fileName) {
|
||||
var ppm = FileSystem.load(fileName)
|
||||
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("Lenna100.ppm", "Lenna100_gs.jpg", 1048, 512)
|
||||
45
Task/Bitmap-Read-a-PPM-file/XPL0/bitmap-read-a-ppm-file.xpl0
Normal file
45
Task/Bitmap-Read-a-PPM-file/XPL0/bitmap-read-a-ppm-file.xpl0
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
include c:\cxpl\codes; \intrinsic 'code' declarations
|
||||
|
||||
func OpenInFile; \Open for input the file typed on command line
|
||||
int CpuReg, Handle;
|
||||
char CmdTail($80);
|
||||
[CpuReg:= GetReg;
|
||||
Blit(CpuReg(11), $81, CpuReg(12), CmdTail, $7F); \get copy of command line
|
||||
Trap(false); \turn off error trapping
|
||||
Handle:= FOpen(CmdTail, 0); \open named file for input
|
||||
FSet(Handle, ^I); \assign file to input device 3
|
||||
OpenI(3); \initialize input buffer pointers
|
||||
if GetErr then return false;
|
||||
Trap(true);
|
||||
return true;
|
||||
];
|
||||
|
||||
int C, X, Y, Width, Height, Max, Lum;
|
||||
real Red, Green, Blue;
|
||||
[if not OpenInFile then [Text(0, "File not found"); exit];
|
||||
if ChIn(3)#^P or ChIn(3)#^6 then [Text(0, "Not P6 PPM file"); exit];
|
||||
repeat loop [C:= ChIn(3);
|
||||
if C # ^# then quit;
|
||||
repeat C:= ChIn(3) until C=$0A\EOL\;
|
||||
];
|
||||
until C>=^0 & C<=^9;
|
||||
Backup; \back up so IntIn re-reads first digit
|
||||
Width:= IntIn(3); \(skips any whitespace)
|
||||
Height:= IntIn(3);
|
||||
Max:= IntIn(3) + 1; \(255/15=17; 256/16=16)
|
||||
case of
|
||||
Width<= 640 & Height<=480: SetVid($112);
|
||||
Width<= 800 & Height<=600: SetVid($115);
|
||||
Width<=1024 & Height<=768: SetVid($118)
|
||||
other SetVid($11B); \1280x1024
|
||||
for Y:= 0 to Height-1 do
|
||||
for X:= 0 to Width-1 do
|
||||
[Red := float(ChIn(3)*256/Max) * 0.21; \convert color to grayscale
|
||||
Green:= float(ChIn(3)*256/Max) * 0.72;
|
||||
Blue := float(ChIn(3)*256/Max) * 0.07;
|
||||
Lum:= fix(Red) + fix(Green) + fix(Blue);
|
||||
Point(X, Y, Lum<<16 + Lum<<8 + Lum);
|
||||
];
|
||||
X:= ChIn(1); \wait for keystroke
|
||||
SetVid(3); \restore normal text display
|
||||
]
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
sub readPPM(f$)
|
||||
local ff, x, y, t$, dcol$, wid, hei
|
||||
|
||||
if f$ = "" print "No PPM file name indicate." : return false
|
||||
|
||||
ff = open (f$, "rb")
|
||||
if not ff print "File ", f$, " not found." : return false
|
||||
|
||||
input #ff t$, wid, hei, dcol$
|
||||
|
||||
if t$ = "P6" then
|
||||
open window wid, hei
|
||||
|
||||
for x = 0 to hei - 1
|
||||
for y = 0 to wid - 1
|
||||
color peek(#ff), peek(#ff), peek(#ff)
|
||||
dot y, x
|
||||
next y
|
||||
next x
|
||||
|
||||
close #ff
|
||||
else
|
||||
print "File is NOT PPM P6 type." : return false
|
||||
end if
|
||||
|
||||
return true
|
||||
end sub
|
||||
11
Task/Bitmap-Read-a-PPM-file/Zkl/bitmap-read-a-ppm-file.zkl
Normal file
11
Task/Bitmap-Read-a-PPM-file/Zkl/bitmap-read-a-ppm-file.zkl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
//24-bpp P6 PPM solution:
|
||||
image:=File("lena.ppm","rb").read();
|
||||
start:=image.find("\n255\n")+5; // Get sizeof PPM header
|
||||
|
||||
foreach n in ([start..image.len()-1,3]){ // Transform color triplets
|
||||
r,g,b:=image[n,3]; // Read colors stored in RGB order
|
||||
l:=(0.2126*r + 0.7152*g + 0.0722*b).toInt(); // Derive luminance
|
||||
image[n,3]=T(l,l,l);
|
||||
}
|
||||
|
||||
File("lenaGrey.ppm","wb").write(image);
|
||||
Loading…
Add table
Add a link
Reference in a new issue