RosettaCodeData/Task/Grayscale-image/M2000-Interpreter/grayscale-image.m2000
2025-06-11 20:16:52 -04:00

202 lines
5.6 KiB
Text

Module P6P5 {
Class Bitmap {
{ // from version 14
Var x As long, y As long, Import As boolean, P5 As boolean
If match("NN") Then
Read x, y
Else.if Match("N") Then
Read f As long
buffer whitespace As Byte
if not Eof(f) Then
get #f, whitespace :P6$=eval$(whitespace)
get #f, whitespace : P6$+=eval$(whitespace)
boolean getW=true, getH=true, getV=true
long v
P5=p6$=str$("P5")
If p6$=str$("P6") or P5 Then
do
get #f, whitespace
if Eval$(whitespace)=str$("#") Then
do
get #f, whitespace
until eval(whitespace)=10
Else
select case eval(whitespace)
case 32, 9, 13, 10
{
if getW and x<>0 Then
getW=false
Else.if getH and y<>0 Then
getH=false
Else.if getV and v<>0 Then
getV=false
End If
}
case 48 To 57
{
if getW Then
x*=10
x+=eval(whitespace, 0)-48
Else.if getH Then
y*=10
y+=eval(whitespace, 0)-48
Else.if getV Then
v*=10
v+=eval(whitespace, 0)-48
End If
}
End Select
End If
iF eof(f) Then Error "Not a ppm file"
until getV=false
Else
Error "Not a P6 ppm or P5 ppm file"
End If
Import=True
End if
Else
Error "No proper arguments"
End If
if x<1 or y<1 Then Error "Wrong dimensions"
Buffer Clear Pad1 As Byte*3
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
}
hline As rgb*x
}
Structure Raster {
magic As integer*4
w As integer*4
h As integer*4
{
linesB As Byte*len(rasterline)*y
}
lines As rasterline*y
}
Buffer Clear Image1 As Raster
Return Image1, 0!magic:="cDIB", 0!w:=Hex$(x,2), 0!h:=Hex$(y, 2)
if not Import Then Return Image1, 0!lines:=Str$(String$(chrcode$(255), Len(rasterline)*y))
Buffer Clear Pad As Byte*4
aLines=Len(Raster)-Len(Rasterline)-Raster("linesB")
blines=-Len(Rasterline)
if Import Then
x0=x-1 : where=0
Buffer Pad1 As Byte*3
Buffer Pad2 As Byte
local rasterline=x*3
m=rasterline mod 4 : if m<>0 Then rasterline+=4-m
For y1=y-1 To 0
where=rasterline*y1
For x1=0 To x0
if p5 Then
Get #f, Pad2: m=eval(Pad2,0) : Return pad1, 0:=m, 1:=m, 2:=m
Else
Get #f, Pad1 : Push Eval(pad1, 2) : Return pad1, 2:=Eval(pad1, 0), 0:=Number
End if
Image1|linesB[where]=Pad1[0, 3] : where+=3
Next
Next
End if
}
SetPixel=Lambda Image1, Pad, aLines, blines (x, y, c) ->{
if c>0 Then c=color(c)
c-!
Return Pad, 0:=c As long
Push pad[2] : pad[2]=pad[0]: pad[0]=Number
Image1|linesB[alines+3*x+blines*y]=Pad[0, 3]
}
GetPixel=Lambda Image1,aLines, blines, Pad1 (x,y) ->{
Pad1[0]=Image1|linesB[alines+3*x+blines*y, 3]
=color(Pad1[2], Pad1[1],Pad1[0])
}
GetPixelGray=Lambda Image1,aLines, blines, Pad1 (x,y) ->{
Pad1[0]=Image1|linesB[alines+3*x+blines*y, 3]
grayval=round(0.2126*Pad1[2] + 0.7152*Pad1[1] + 0.0722*Pad1[0], 0)
=color(grayval,grayval,grayval)
}
Image$=Lambda$ Image1, Raster ->Eval$(Image1, 0, Len(Raster))
Copy=Lambda Image1 (image$) -> {
if left$(image$,12)=Image1[0, 24] Then
Return Image1, 0:=Image$
Else
Error "Can't Copy Image"
End if
}
ToFile=Lambda Image1, x, y (f) -> {
Print #f, "P6";chr$(10);"# Created using M2000 Interpreter";chr$(10);
Print #f, x;" ";y;" 255";chr$(10);
x2=x-1 : where=0 : rasterline=x*3
m=rasterline mod 4 : if m<>0 Then rasterline+=4-m
Buffer pad As Byte*3
For y1=y-1 To 0
where=rasterline*y1
For x1=0 To x2
pad[0]=image1|linesB[where, 3]
Push pad[2] : pad[2]=pad[0]: pad[0]=Number
Put #f, pad : where+=3
Next
Next
}
ToFileGray=Lambda Image1, x, y (f) -> {
Print #f, "P5";chr$(10);"# Created using M2000 Interpreter";chr$(10);
Print #f, x;" ";y;" 255";chr$(10);
x2=x-1 : where=0 : rasterline=x*3
m=rasterline mod 4 : if m<>0 Then rasterline+=4-m
Buffer pad As Byte*3
Buffer bytepad As Byte
const R=0.2126, G=0.7152, B=0.0722
For y1=y-1 To 0
where=rasterline*y1
For x1=0 To x2
Return pad, 0:=eval$(image1, 0!linesB!where, 3)
Return bytepad, 0:=round(R*Eval(pad, 2) + G*Eval(pad, 1) + B*Eval(pad, 0), 0)
Put #f, bytepad : where+=3
Next
Next
}
}
Cls 5,0
A=Bitmap(15,10)
B=Bitmap(15,10)
c1=color(100, 200, 255)
c2=color(180, 250, 128)
For i=0 To 8
Call A.SetPixel(i, i, c1)
Call A.SetPixel(9, i,c2)
Next
Call A.SetPixel(i,i,c1)
// make a new one GrayScale (but 24bit) As B
For i=0 To 14 { For J=0 To 9 {Call B.SetPixel(i, j, A.GetPixelGray(i,j))}}
// place image A at 200 pixel from left margin, 100 pixel from top margin
Copy 200*twipsX, 100*twipsY use A.Image$(), 0, 800 ' zoom 800%, angle 0
// place image B at 400 pixel from left margin, 100 pixel from top margin
Copy 400*twipsX, 100*twipsY use B.Image$(), 0, 800 ' zoom 800%
Try {
Open "P6example.ppm" For Output As #f
Call A.Tofile(f)
Close #f
Open "P5example.ppm" For Output As #f
Call A.TofileGray(f)
Close #f
Open "P5example.ppm" For Input As #f
C=Bitmap(f)
close #f
Copy 600*twipsX, 100*twipsY use C.Image$(), 0, 800 ' zoom 800%
Open "P6example.ppm" For Input As #f
C=Bitmap(f)
close #f
// use of Top clause To make the border color transparent at rotation
Copy 800*twipsX, 100*twipsY top C.Image$(), 30, 800 ' zoom 800%, angle 30 degree
}
Print "Done"
}
P6P5