Data update

This commit is contained in:
Ingy döt Net 2026-04-30 12:34:36 -04:00
parent 4bb20c9b71
commit cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions

View file

@ -0,0 +1,106 @@
procedure Flood_Fill
( Picture : in out Image;
From : Point;
Fill : Pixel;
Replace : Pixel;
Distance : Luminance := 20
) is
function Diff (A, B : Luminance) return Luminance is
pragma Inline (Diff);
begin
if A > B then
return A - B;
else
return B - A;
end if;
end Diff;
function "-" (A, B : Pixel) return Luminance is
pragma Inline ("-");
begin
return Luminance'Max (Luminance'Max (Diff (A.R, B.R), Diff (A.G, B.G)), Diff (A.B, B.B));
end "-";
procedure Column (From : Point);
procedure Row (From : Point);
Visited : array (Picture'Range (1), Picture'Range (2)) of Boolean :=
(others => (others => False));
procedure Column (From : Point) is
X1 : Positive := From.X;
X2 : Positive := From.X;
begin
Visited (From.X, From.Y) := True;
for X in reverse Picture'First (1)..From.X - 1 loop
exit when Visited (X, From.Y);
declare
Color : Pixel renames Picture (X, From.Y);
begin
Visited (X, From.Y) := True;
exit when Color - Replace > Distance;
Color := Fill;
X1 := X;
end;
end loop;
for X in From.X + 1..Picture'Last (1) loop
exit when Visited (X, From.Y);
declare
Color : Pixel renames Picture (X, From.Y);
begin
Visited (X, From.Y) := True;
exit when Color - Replace > Distance;
Color := Fill;
X2 := X;
end;
end loop;
for X in X1..From.X - 1 loop
Row ((X, From.Y));
end loop;
for X in From.X + 1..X2 loop
Row ((X, From.Y));
end loop;
end Column;
procedure Row (From : Point) is
Y1 : Positive := From.Y;
Y2 : Positive := From.Y;
begin
Visited (From.X, From.Y) := True;
for Y in reverse Picture'First (2)..From.Y - 1 loop
exit when Visited (From.X, Y);
declare
Color : Pixel renames Picture (From.X, Y);
begin
Visited (From.X, Y) := True;
exit when Color - Replace > Distance;
Color := Fill;
Y1 := Y;
end;
end loop;
for Y in From.Y + 1..Picture'Last (2) loop
exit when Visited (From.X, Y);
declare
Color : Pixel renames Picture (From.X, Y);
begin
Visited (From.X, Y) := True;
exit when Color - Replace > Distance;
Color := Fill;
Y2 := Y;
end;
end loop;
for Y in Y1..From.Y - 1 loop
Column ((From.X, Y));
end loop;
for Y in From.Y + 1..Y2 loop
Column ((From.X, Y));
end loop;
end Row;
Color : Pixel renames Picture (From.X, From.Y);
begin
if Color - Replace <= Distance then
Visited (From.X, From.Y) := True;
Color := Fill;
Column (From);
end if;
end Flood_Fill;

View file

@ -0,0 +1,19 @@
declare
File : File_Type;
begin
Open (File, In_File, "Unfilledcirc.ppm");
declare
Picture : Image := Get_PPM (File);
begin
Close (File);
Flood_Fill
( Picture => Picture,
From => (122, 30),
Fill => (255,0,0),
Replace => White
);
Create (File, Out_File, "Filledcirc.ppm");
Put_PPM (File, Picture);
Close (File);
end;
end;

View file

@ -1,55 +1,55 @@
#NoEnv
#SingleInstance, Force
SetBatchLines, -1
CoordMode, Mouse
CoordMode, Pixel
SetBatchLines, -1
CoordMode, Mouse
CoordMode, Pixel
return
CapsLock::
KeyWait, CapsLock
MouseGetPos, X, Y
PixelGetColor, color, X, Y
FloodFill(x, y, color, 0x000000, 1, "Esc")
MsgBox Done!
KeyWait, CapsLock
MouseGetPos, X, Y
PixelGetColor, color, X, Y
FloodFill(x, y, color, 0x000000, 1, "Esc")
MsgBox Done!
Return
FloodFill( 0x, 0y, target, replacement, mode=1, key="" )
{
VarSetCapacity(Rect, 16, 0)
hDC := DllCall("GetDC", UInt, 0)
hBrush := DllCall("CreateSolidBrush", UInt, replacement)
l := 0
while l >= 0
{
if getkeystate(key, "P")
return
x := %l%x, y := %l%y
%l%p++
p := %l%p
PixelGetColor, color, x, y
if (color = target)
{
NumPut(x, Rect, 0)
NumPut(y, Rect, 4)
NumPut(x+1, Rect, 8)
NumPut(y+1, Rect, 12)
DllCall("FillRect", UInt, hDC, Str, Rect, UInt, hBrush)
}
else if (p = 1)
{
%l%x := %l%y := %l%p := "", l--
continue
}
if (p < 5)
ol := l++
, %l%x := %ol%x + (p = 1 ? 1 : p = 2 ? -1 : 0)
, %l%y := %ol%y + (p = 3 ? 1 : p = 4 ? -1 : 0)
else
%l%x := %l%y := %l%p := "", l--
}
DllCall("ReleaseDC", UInt, 0, UInt, hDC)
DllCall("DeleteObject", UInt, hBrush)
VarSetCapacity(Rect, 16, 0)
hDC := DllCall("GetDC", UInt, 0)
hBrush := DllCall("CreateSolidBrush", UInt, replacement)
l := 0
while l >= 0
{
if getkeystate(key, "P")
return
x := %l%x, y := %l%y
%l%p++
p := %l%p
PixelGetColor, color, x, y
if (color = target)
{
NumPut(x, Rect, 0)
NumPut(y, Rect, 4)
NumPut(x+1, Rect, 8)
NumPut(y+1, Rect, 12)
DllCall("FillRect", UInt, hDC, Str, Rect, UInt, hBrush)
}
else if (p = 1)
{
%l%x := %l%y := %l%p := "", l--
continue
}
if (p < 5)
ol := l++
, %l%x := %ol%x + (p = 1 ? 1 : p = 2 ? -1 : 0)
, %l%y := %ol%y + (p = 3 ? 1 : p = 4 ? -1 : 0)
else
%l%x := %l%y := %l%p := "", l--
}
DllCall("ReleaseDC", UInt, 0, UInt, hDC)
DllCall("DeleteObject", UInt, hBrush)
}

View file

@ -16,25 +16,25 @@ void FloodFillAlgorithm::flood(Point startPoint, Mat* tgtMat) {
if (image->at<Vec3b>(startPoint) == srcColor) {
queue<Point> pointQueue;
pointQueue.push(startPoint);
pointQueue.push(startPoint);
while (!pointQueue.empty()) {
Point p = pointQueue.front();
pointQueue.pop();
while (!pointQueue.empty()) {
Point p = pointQueue.front();
pointQueue.pop();
if (insideImage(p)) {
if (insideImage(p)) {
if ((image->at<Vec3b>(p) == srcColor)) {
image->at<Vec3b>(p) = tgtMat->at<Vec3b>(p);
if ((image->at<Vec3b>(p) == srcColor)) {
image->at<Vec3b>(p) = tgtMat->at<Vec3b>(p);
pointQueue.push(Point(p.x + 1, p.y));
pointQueue.push(Point(p.x - 1, p.y));
pointQueue.push(Point(p.x, p.y + 1));
pointQueue.push(Point(p.x, p.y - 1));
}
}
pointQueue.push(Point(p.x + 1, p.y));
pointQueue.push(Point(p.x - 1, p.y));
pointQueue.push(Point(p.x, p.y + 1));
pointQueue.push(Point(p.x, p.y - 1));
}
}
}
}
}
}

View file

@ -5,5 +5,5 @@ typedef struct {
typedef rgb_color *rgb_color_p;
void floodfill(image img, int px, int py,
rgb_color_p bankscolor,
rgb_color_p rcolor);
rgb_color_p bankscolor,
rgb_color_p rcolor);

View file

@ -29,8 +29,8 @@ inline void _ffill_enqueue(_ffill_queue *q, int px, int py)
inline double color_distance( rgb_color_p a, rgb_color_p b )
{
return sqrt( (double)(a->red - b->red)*(a->red - b->red) +
(double)(a->green - b->green)*(a->green - b->green) +
(double)(a->blue - b->blue)*(a->blue - b->blue) ) / (256.0*sqrt(3.0));
(double)(a->green - b->green)*(a->green - b->green) +
(double)(a->blue - b->blue)*(a->blue - b->blue) ) / (256.0*sqrt(3.0));
}
inline void _ffill_rgbcolor(image img, rgb_color_p tc, int px, int py)
@ -41,25 +41,25 @@ inline void _ffill_rgbcolor(image img, rgb_color_p tc, int px, int py)
}
#define NSOE(X,Y) do { \
if ( ((X)>=0)&&((Y)>=0) && ((X)<img->width)&&((Y)<img->height)) { \
_ffill_rgbcolor(img, &thisnode, (X), (Y)); \
if ( color_distance(&thisnode, bankscolor) > tolerance ) { \
if (color_distance(&thisnode, rcolor) > 0.0) { \
put_pixel_unsafe(img, (X), (Y), rcolor->red, \
rcolor->green, \
rcolor->blue); \
_ffill_enqueue(&head, (X), (Y)); \
pixelcount++; \
} \
} \
} \
#define NSOE(X,Y) do { \
if ( ((X)>=0)&&((Y)>=0) && ((X)<img->width)&&((Y)<img->height)) { \
_ffill_rgbcolor(img, &thisnode, (X), (Y)); \
if ( color_distance(&thisnode, bankscolor) > tolerance ) { \
if (color_distance(&thisnode, rcolor) > 0.0) { \
put_pixel_unsafe(img, (X), (Y), rcolor->red, \
rcolor->green, \
rcolor->blue); \
_ffill_enqueue(&head, (X), (Y)); \
pixelcount++; \
} \
} \
} \
} while(0)
unsigned int floodfill(image img, int px, int py,
rgb_color_p bankscolor,
rgb_color_p rcolor)
rgb_color_p bankscolor,
rgb_color_p rcolor)
{
_ffill_queue head;
rgb_color thisnode;

View file

@ -0,0 +1,37 @@
require "./pixmap"
class Pixmap
def flood_fill (x, y, color)
old_color = self[x, y]
queue = Deque(Int32).new
width = @width
size = @data.size
idx = y * width + x
queue << idx
until queue.empty?
idx = queue.shift
next unless @data[idx] == old_color
start = idx
# go left
limit = start // width * width
while idx >= limit && @data[idx] == old_color
@data[idx] = color
up, dn = idx - width, idx + width
queue << up if up >= 0 && @data[up] == old_color
queue << dn if dn < size && @data[dn] == old_color
idx -= 1
end
# go right
limit = (start + width) // width * width
idx = start + 1
while idx < limit && @data[idx] == old_color
@data[idx] = color
up, dn = idx - width, idx + width
queue << up if up >= 0 && @data[up] == old_color
queue << dn if dn < size && @data[dn] == old_color
idx += 1
end
end
end
end

View file

@ -0,0 +1,22 @@
require "./circle"
require "./flood_fill"
require "./write_ppm"
require "./load_ppm"
img = Pixmap.new 120, 80, Color::WHITE
img.circle 60, 40, 35, Color::BLACK
img.circle 100, 20, 18, Color::RED
img.flood_fill 10, 10, Color.new(210, 230, 0)
img.flood_fill 60, 40, Color.new(255, 128, 76)
img.write "crystal_flood_fill.ppm"
img = Pixmap.load "Unfilledcirc.ppm"
img.flood_fill 10, 10, Color.new(0, 128, 240)
img.flood_fill img.width-1, img.height-1, Color.new(0, 128, 240)
img.flood_fill 10, img.height//2, Color.new(240, 180, 10)
img.flood_fill 100, 100, Color.new(255, 60, 10)
img.write "crystal_filledcirc.ppm"

View file

@ -15,23 +15,23 @@ FBSL.GETCLIENTRECT(ME, 0, 0, Breadth, Height)
DrawCircles() ' Initialize circles
BEGIN EVENTS
SELECT CASE CBMSG
CASE WM_LBUTTONDOWN: FillCircles() ' Flood fill circles
CASE WM_CLOSE: FBSL.RELEASEDC(ME, FBSL.GETDC) ' Clean up
END SELECT
SELECT CASE CBMSG
CASE WM_LBUTTONDOWN: FillCircles() ' Flood fill circles
CASE WM_CLOSE: FBSL.RELEASEDC(ME, FBSL.GETDC) ' Clean up
END SELECT
END EVENTS
SUB FillCircles()
FILL(FBSL.GETDC, Breadth / 2, Height / 2, &HFFFF) ' Yellow: flood fill using intrinsics
FOR DIM x = 0 TO Breadth / 2 ' Red: flood fill iteratively
FOR DIM y = 0 TO Height / 2
IF NOT POINT(FBSL.GETDC, x, y) THEN PSET(FBSL.GETDC, x, y, &HFF)
NEXT
NEXT
FBSLSETTEXT(ME, "After Flood Fill") ' Reset form caption
FILL(FBSL.GETDC, Breadth / 2, Height / 2, &HFFFF) ' Yellow: flood fill using intrinsics
FOR DIM x = 0 TO Breadth / 2 ' Red: flood fill iteratively
FOR DIM y = 0 TO Height / 2
IF NOT POINT(FBSL.GETDC, x, y) THEN PSET(FBSL.GETDC, x, y, &HFF)
NEXT
NEXT
FBSLSETTEXT(ME, "After Flood Fill") ' Reset form caption
END SUB
SUB DrawCircles() ' Concatenate function calls
CIRCLE(FBSL.GETDC, Breadth / 2, Height / 2, 85, &HFFFFFF, 0, 360, 1, TRUE) _ ' White
(FBSL.GETDC, Breadth / 3, Height / 3, 30, 0, 0, 360, 1, TRUE) ' Black
CIRCLE(FBSL.GETDC, Breadth / 2, Height / 2, 85, &HFFFFFF, 0, 360, 1, TRUE) _ ' White
(FBSL.GETDC, Breadth / 3, Height / 3, 30, 0, 0, 360, 1, TRUE) ' Black
END SUB

View file

@ -1,18 +1,18 @@
floodFill = function(bmp, x, y, targetColor, replacementColor)
// Check if pixel is outside the bounds
if not(0 < x < bmp.width) or not(0 < y < bmp.height) then return
// Check the current pixel color
currentColor = bmp.pixel(x, y)
if currentColor != targetColor then return
// Replace the color
bmp.setPixel x, y, replacementColor
// Recursively apply to adjacent pixels
floodFill(bmp, x + 1, y, targetColor, replacementColor)
floodFill(bmp, x - 1, y, targetColor, replacementColor)
floodFill(bmp, x, y + 1, targetColor, replacementColor)
floodFill(bmp, x, y - 1, targetColor, replacementColor)
// Check if pixel is outside the bounds
if not(0 < x < bmp.width) or not(0 < y < bmp.height) then return
// Check the current pixel color
currentColor = bmp.pixel(x, y)
if currentColor != targetColor then return
// Replace the color
bmp.setPixel x, y, replacementColor
// Recursively apply to adjacent pixels
floodFill(bmp, x + 1, y, targetColor, replacementColor)
floodFill(bmp, x - 1, y, targetColor, replacementColor)
floodFill(bmp, x, y + 1, targetColor, replacementColor)
floodFill(bmp, x, y - 1, targetColor, replacementColor)
end function
clear
img = file.loadImage("Unfilledcirc.png")

View file

@ -23,20 +23,20 @@ sub floodfill
if ( colordistance(\@tcol, \@col) > $distparameter ) { return; }
push @queue, [$x, $y];
while ( @queue ) {
my $pointref = shift(@queue);
( $x, $y ) = @$pointref;
if ( ($x < 0) || ($y < 0) || ( $x >= $img->width ) || ( $y >= $img->height ) ) { next; }
if ( ! exists($visited{"$x,$y"}) ) {
@col = $img->query_pixel($x, $y);
if ( colordistance(\@tcol, \@col) <= $distparameter ) {
$img->draw_point($x, $y);
$visited{"$x,$y"} = 1;
push @queue, [$x+1, $y];
push @queue, [$x-1, $y];
push @queue, [$x, $y+1];
push @queue, [$x, $y-1];
}
}
my $pointref = shift(@queue);
( $x, $y ) = @$pointref;
if ( ($x < 0) || ($y < 0) || ( $x >= $img->width ) || ( $y >= $img->height ) ) { next; }
if ( ! exists($visited{"$x,$y"}) ) {
@col = $img->query_pixel($x, $y);
if ( colordistance(\@tcol, \@col) <= $distparameter ) {
$img->draw_point($x, $y);
$visited{"$x,$y"} = 1;
push @queue, [$x+1, $y];
push @queue, [$x-1, $y];
push @queue, [$x, $y+1];
push @queue, [$x, $y-1];
}
}
}
}

View file

@ -4,16 +4,16 @@ class Bitmap {
has Pixel @.data;
method pixel(
$i where ^$!width,
$j where ^$!height
--> Pixel
$i where ^$!width,
$j where ^$!height
--> Pixel
) is rw { @!data[$i + $j * $!width] }
}
role PPM {
method P6 returns Blob {
"P6\n{self.width} {self.height}\n255\n".encode('ascii')
~ Blob.new: flat map { .R, .G, .B }, self.data
"P6\n{self.width} {self.height}\n255\n".encode('ascii')
~ Blob.new: flat map { .R, .G, .B }, self.data
}
}

View file

@ -0,0 +1,64 @@
Rebol [
title: "Rosetta code: Bitmap/Flood fill"
file: %Bitmap-Flood_fill.r3
url: https://rosettacode.org/wiki/Bitmap/Bitmap-Flood_fill
]
flood-fill: function [
image [image! file! url!]
position [pair!] "Start position"
color1 [tuple!] "Target color to replace"
color2 [tuple!] "Replacement color"
][
unless image? image [image: load image] ;; Load image if not already loaded
xsize: image/size/x
ysize: image/size/y
color2/4: color1/4: 255 ;; Ensure both colors are fully opaque
que: copy []
if image/:position != color1 [return image] ;; Bail if seed pixel isn't target color
append que position
while [not empty? que][
position: take que ;; Dequeue next position to process
if image/:position == color1 [ ;; Skip if already recolored
W: position
;; Scan west, recoloring pixels until we leave the target-color region
while [image/:W == color1][
image/:W: color2
next: W + 0x1 ;; Pixel south of W
if all [next/y < ysize color1 == image/:next][append que next]
next: W - 0x1 ;; Pixel north of W
if all [next/y > 0 color1 == image/:next][append que next]
next: W - 1x0 ;; Step west
either next/x > 1 [W: next][break] ;; Stop at left edge
]
E: position + 1x0 ;; Start east scan one step right of seed
if E/x < xsize [
;; Scan east, recoloring pixels until we leave the target-color region
while [image/:E == color1][
image/:E: color2
next: E + 0x1 ;; Pixel south of E
if all [next/y < ysize color1 == image/:next][append que next]
next: E - 0x1 ;; Pixel north of E
if all [next/y > 0 color1 == image/:next][append que next]
next: E + 1x0 ;; Step east
either next/x < xsize [E: next][break] ;; Stop at right edge
]
]
]
]
image ;; Return the modified image
]
;; Download the test image if not already cached locally
unless exists? file: %Unfilledcirc.png [
write file read https://static.wikitide.net/rosettacodewiki/0/0f/Unfilledcirc.png
]
img: load %Unfilledcirc.png
img: flood-fill img 200x200 white red
img: flood-fill img 100x100 black blue
browse save %Filledcirc.png img ;; Save result and open in browser

View file

@ -0,0 +1,12 @@
# Drop a png onto this pane, then Run.
&p$"Found a _" °img&frab "image.png"
≡≡⊢ # Convert to greyscale.
Sensitivity ← 0.3 # Lower is finer.
N₄ ← [1_0 0_1 ¯ 1_0 0_¯1]
[40_40]⊙0.8 # Starting point, fill colour.
Good ← >Sensitivity⌵-⬚0.5⊡⊢ # Needs filling. Simple edges-check.
# Take first of list. If needs fill, do so and then add
# its four neighbours into queue. Repeat until queue is empty.
⍢(⨬(↘1|◴⊂+N₄¤°⊂ ⊃(⋅∘|∘|⋅⋅⋅∘)◡(⍜(⊡|⋅∘)⊢))◡Good
| >0⧻)
⋅⊙⋅

View file

@ -4,11 +4,11 @@ fcn flood(pixmap, x,y, repl){ // slow!
while(stack){
x,y:=stack.pop();
if((0<=y<h) and (0<=x<w)){
p:=pixmap[x,y];
if(p==targ){
pixmap[x,y]=repl;
stack.append( T(x-1,y), T(x+1,y), T(x, y-1), T(x, y+1) );
}
p:=pixmap[x,y];
if(p==targ){
pixmap[x,y]=repl;
stack.append( T(x-1,y), T(x+1,y), T(x, y-1), T(x, y+1) );
}
}
}
}