September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -1,106 +1,107 @@
// http://commons.wikimedia.org/wiki/File:Julia_immediate_basin_1_3.png
unsigned int f(unsigned int _iX, unsigned int _iY)
/*
gives position of point (iX,iY) in 1D array ; uses also global variables
it does not check if index is good so memory error is possible
*/
{return (_iX + (iYmax-_iY-1)*iXmax );}
* RosettaCode: Bitmap/Flood fill, language C, dialects C89, C99, C11.
*
* This is an implementation of the recursive algorithm. For the sake of
* simplicity, instead of reading files as JPEG, PNG, etc., the program
* read and write Portable Bit Map (PBM) files in plain text format.
* Portable Bit Map files can also be read and written with GNU GIMP.
*
* The program is just an example, so the image size is limited to 2048x2048,
* the image can only be black and white, there is no run-time validation.
*
* Data is read from a standard input stream, the results are written to the
* standard output file.
*
* In order for this program to work properly it is necessary to allocate
* enough memory for the program stack. For example, in Microsoft Visual Studio,
* the option /stack:134217728 declares a 128MB stack instead of the default
* size of 1MB.
*/
#define _CRT_SECURE_NO_WARNINGS /* Unlock printf etc. in MSVC */
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 2048
#define BYTE unsigned char
int FillContour(int iXseed, int iYseed, unsigned char color, unsigned char _data[])
static int width, height;
static BYTE bitmap[MAXSIZE][MAXSIZE];
static BYTE oldColor;
static BYTE newColor;
void floodFill(int i, int j)
{
/*
fills contour with black border ( color = iJulia) using seed point inside contour
and horizontal lines
it starts from seed point, saves max right( iXmaxLocal) and max left ( iXminLocal) interior points of horizontal line,
in new line ( iY+1 or iY-1) it computes new interior point : iXmidLocal=iXminLocal + (iXmaxLocal-iXminLocal)/2;
result is stored in _data array : 1D array of 1-bit colors ( shades of gray)
it does not check if index of _data array is good so memory error is possible
*/
int iX, /* seed integer coordinate */
iY=iYseed,
/* most interior point of line iY */
iXmidLocal=iXseed,
/* min and max of interior points of horizontal line iY */
iXminLocal,
iXmaxLocal;
int i ; /* index of _data array */;
/* --------- move up --------------- */
do{
iX=iXmidLocal;
i =f(iX,iY); /* index of _data array */;
/* move to right */
while (_data[i]==iInterior)
{ _data[i]=color;
iX+=1;
i=f(iX,iY);
}
iXmaxLocal=iX-1;
/* move to left */
iX=iXmidLocal-1;
i=f(iX,iY);
while (_data[i]==iInterior)
{ _data[i]=color;
iX-=1;
i=f(iX,iY);
}
iXminLocal=iX+1;
iY+=1; /* move up */
iXmidLocal=iXminLocal + (iXmaxLocal-iXminLocal)/2; /* new iX inside contour */
i=f(iXmidLocal,iY); /* index of _data array */;
if ( _data[i]==iJulia) break; /* it should not cross the border */
} while (iY<iYmax);
/* ------ move down ----------------- */
iXmidLocal=iXseed;
iY=iYseed-1;
do{
iX=iXmidLocal;
i =f(iX,iY); /* index of _data array */;
/* move to right */
while (_data[i]==iInterior) /* */
{ _data[i]=color;
iX+=1;
i=f(iX,iY);
}
iXmaxLocal=iX-1;
/* move to left */
iX=iXmidLocal-1;
i=f(iX,iY);
while (_data[i]==iInterior) /* */
{ _data[i]=color;
iX-=1; /* move to right */
i=f(iX,iY);
}
iXminLocal=iX+1;
iY-=1; /* move down */
iXmidLocal=iXminLocal + (iXmaxLocal-iXminLocal)/2; /* new iX inside contour */
i=f(iXmidLocal,iY); /* index of _data array */;
if ( _data[i]==iJulia) break; /* it should not cross the border */
} while (0<iY);
/* mark seed point by big pixel */
const int iSide =iXmax/500; /* half of width or height of big pixel */
for(iY=iYseed-iSide;iY<=iYseed+iSide;++iY){
for(iX=iXseed-iSide;iX<=iXseed+iSide;++iX){
i= f(iX,iY); /* index of _data array */
_data[i]=10;}}
return 0;
if ( 0 <= i && i < height
&& 0 <= j && j < width
&& bitmap[i][j] == oldColor )
{
bitmap[i][j] = newColor;
floodFill(i-1,j);
floodFill(i+1,j);
floodFill(i,j-1);
floodFill(i,j+1);
}
}
/* *****************************************************************************
* Input/output routines.
*/
void skipLine(FILE* file)
{
while(!ferror(file) && !feof(file) && fgetc(file) != '\n')
;
}
void skipCommentLines(FILE* file)
{
int c;
int comment = '#';
while ((c = fgetc(file)) == comment)
skipLine(file);
ungetc(c,file);
}
readPortableBitMap(FILE* file)
{
int i,j;
skipLine(file);
skipCommentLines(file); fscanf(file,"%d",&width);
skipCommentLines(file); fscanf(file,"%d",&height);
skipCommentLines(file);
if ( width <= MAXSIZE && height <= MAXSIZE )
for ( i = 0; i < height; i++ )
for ( j = 0; j < width; j++ )
fscanf(file,"%1d",&(bitmap[i][j]));
else exit(EXIT_FAILURE);
}
void writePortableBitMap(FILE* file)
{
int i,j;
fprintf(file,"P1\n");
fprintf(file,"%d %d\n", width, height);
for ( i = 0; i < height; i++ )
{
for ( j = 0; j < width; j++ )
fprintf(file,"%1d", bitmap[i][j]);
fprintf(file,"\n");
}
}
/* *****************************************************************************
* The main entry point.
*/
int main(void)
{
oldColor = 1;
newColor = oldColor ? 0 : 1;
readPortableBitMap(stdin);
floodFill(height/2,width/2);
writePortableBitMap(stdout);
return EXIT_SUCCESS;
}

View file

@ -1,9 +1,106 @@
/* #include <sys/queue.h> */
typedef struct {
color_component red, green, blue;
} rgb_color;
typedef rgb_color *rgb_color_p;
// http://commons.wikimedia.org/wiki/File:Julia_immediate_basin_1_3.png
void floodfill(image img, int px, int py,
rgb_color_p bankscolor,
rgb_color_p rcolor);
unsigned int f(unsigned int _iX, unsigned int _iY)
/*
gives position of point (iX,iY) in 1D array ; uses also global variables
it does not check if index is good so memory error is possible
*/
{return (_iX + (iYmax-_iY-1)*iXmax );}
int FillContour(int iXseed, int iYseed, unsigned char color, unsigned char _data[])
{
/*
fills contour with black border ( color = iJulia) using seed point inside contour
and horizontal lines
it starts from seed point, saves max right( iXmaxLocal) and max left ( iXminLocal) interior points of horizontal line,
in new line ( iY+1 or iY-1) it computes new interior point : iXmidLocal=iXminLocal + (iXmaxLocal-iXminLocal)/2;
result is stored in _data array : 1D array of 1-bit colors ( shades of gray)
it does not check if index of _data array is good so memory error is possible
*/
int iX, /* seed integer coordinate */
iY=iYseed,
/* most interior point of line iY */
iXmidLocal=iXseed,
/* min and max of interior points of horizontal line iY */
iXminLocal,
iXmaxLocal;
int i ; /* index of _data array */;
/* --------- move up --------------- */
do{
iX=iXmidLocal;
i =f(iX,iY); /* index of _data array */;
/* move to right */
while (_data[i]==iInterior)
{ _data[i]=color;
iX+=1;
i=f(iX,iY);
}
iXmaxLocal=iX-1;
/* move to left */
iX=iXmidLocal-1;
i=f(iX,iY);
while (_data[i]==iInterior)
{ _data[i]=color;
iX-=1;
i=f(iX,iY);
}
iXminLocal=iX+1;
iY+=1; /* move up */
iXmidLocal=iXminLocal + (iXmaxLocal-iXminLocal)/2; /* new iX inside contour */
i=f(iXmidLocal,iY); /* index of _data array */;
if ( _data[i]==iJulia) break; /* it should not cross the border */
} while (iY<iYmax);
/* ------ move down ----------------- */
iXmidLocal=iXseed;
iY=iYseed-1;
do{
iX=iXmidLocal;
i =f(iX,iY); /* index of _data array */;
/* move to right */
while (_data[i]==iInterior) /* */
{ _data[i]=color;
iX+=1;
i=f(iX,iY);
}
iXmaxLocal=iX-1;
/* move to left */
iX=iXmidLocal-1;
i=f(iX,iY);
while (_data[i]==iInterior) /* */
{ _data[i]=color;
iX-=1; /* move to right */
i=f(iX,iY);
}
iXminLocal=iX+1;
iY-=1; /* move down */
iXmidLocal=iXminLocal + (iXmaxLocal-iXminLocal)/2; /* new iX inside contour */
i=f(iXmidLocal,iY); /* index of _data array */;
if ( _data[i]==iJulia) break; /* it should not cross the border */
} while (0<iY);
/* mark seed point by big pixel */
const int iSide =iXmax/500; /* half of width or height of big pixel */
for(iY=iYseed-iSide;iY<=iYseed+iSide;++iY){
for(iX=iXseed-iSide;iX<=iXseed+iSide;++iX){
i= f(iX,iY); /* index of _data array */
_data[i]=10;}}
return 0;
}

View file

@ -1,93 +1,9 @@
#include "imglib.h"
/* #include <sys/queue.h> */
typedef struct {
color_component red, green, blue;
} rgb_color;
typedef rgb_color *rgb_color_p;
typedef struct _ffill_node {
int px, py;
TAILQ_ENTRY(_ffill_node) nodes;
} _ffill_node_t;
TAILQ_HEAD(_ffill_queue_s, _ffill_node);
typedef struct _ffill_queue_s _ffill_queue;
inline void _ffill_removehead(_ffill_queue *q)
{
_ffill_node_t *n = q->tqh_first;
if ( n != NULL ) {
TAILQ_REMOVE(q, n, nodes);
free(n);
}
}
inline void _ffill_enqueue(_ffill_queue *q, int px, int py)
{
_ffill_node_t *node;
node = malloc(sizeof(_ffill_node_t));
if ( node != NULL ) {
node->px = px; node->py = py;
TAILQ_INSERT_TAIL(q, node, nodes);
}
}
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));
}
inline void _ffill_rgbcolor(image img, rgb_color_p tc, int px, int py)
{
tc->red = GET_PIXEL(img, px, py)[0];
tc->green = GET_PIXEL(img, px, py)[1];
tc->blue = GET_PIXEL(img, px, py)[2];
}
#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,
void floodfill(image img, int px, int py,
rgb_color_p bankscolor,
rgb_color_p rcolor)
{
_ffill_queue head;
rgb_color thisnode;
unsigned int pixelcount = 0;
double tolerance = 0.05;
if ( (px < 0) || (py < 0) || (px >= img->width) || (py >= img->height) )
return;
TAILQ_INIT(&head);
_ffill_rgbcolor(img, &thisnode, px, py);
if ( color_distance(&thisnode, bankscolor) <= tolerance ) return;
_ffill_enqueue(&head, px, py);
while( head.tqh_first != NULL ) {
_ffill_node_t *n = head.tqh_first;
_ffill_rgbcolor(img, &thisnode, n->px, n->py);
if ( color_distance(&thisnode, bankscolor) > tolerance ) {
put_pixel_unsafe(img, n->px, n->py, rcolor->red, rcolor->green, rcolor->blue);
pixelcount++;
}
int tx = n->px, ty = n->py;
_ffill_removehead(&head);
NSOE(tx - 1, ty);
NSOE(tx + 1, ty);
NSOE(tx, ty - 1);
NSOE(tx, ty + 1);
}
return pixelcount;
}
rgb_color_p rcolor);

View file

@ -1,27 +1,93 @@
#include <stdio.h>
#include <stdlib.h>
#include "imglib.h"
int main(int argc, char **argv)
{
image animage;
rgb_color ic;
rgb_color rc;
typedef struct _ffill_node {
int px, py;
TAILQ_ENTRY(_ffill_node) nodes;
} _ffill_node_t;
TAILQ_HEAD(_ffill_queue_s, _ffill_node);
typedef struct _ffill_queue_s _ffill_queue;
if ( argc > 1 ) {
animage = read_image(argv[1]);
if ( animage != NULL ) {
ic.red = 255; /* = 0; */
ic.green = 255; /* = 0; */
ic.blue = 255; /* = 0; */
rc.red = 0;
rc.green = 255;
rc.blue = 0;
floodfill(animage, 100, 100, &ic, &rc);
/* 150, 150 */
print_jpg(animage, 90);
free(animage);
}
inline void _ffill_removehead(_ffill_queue *q)
{
_ffill_node_t *n = q->tqh_first;
if ( n != NULL ) {
TAILQ_REMOVE(q, n, nodes);
free(n);
}
return 0;
}
inline void _ffill_enqueue(_ffill_queue *q, int px, int py)
{
_ffill_node_t *node;
node = malloc(sizeof(_ffill_node_t));
if ( node != NULL ) {
node->px = px; node->py = py;
TAILQ_INSERT_TAIL(q, node, nodes);
}
}
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));
}
inline void _ffill_rgbcolor(image img, rgb_color_p tc, int px, int py)
{
tc->red = GET_PIXEL(img, px, py)[0];
tc->green = GET_PIXEL(img, px, py)[1];
tc->blue = GET_PIXEL(img, px, py)[2];
}
#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)
{
_ffill_queue head;
rgb_color thisnode;
unsigned int pixelcount = 0;
double tolerance = 0.05;
if ( (px < 0) || (py < 0) || (px >= img->width) || (py >= img->height) )
return;
TAILQ_INIT(&head);
_ffill_rgbcolor(img, &thisnode, px, py);
if ( color_distance(&thisnode, bankscolor) <= tolerance ) return;
_ffill_enqueue(&head, px, py);
while( head.tqh_first != NULL ) {
_ffill_node_t *n = head.tqh_first;
_ffill_rgbcolor(img, &thisnode, n->px, n->py);
if ( color_distance(&thisnode, bankscolor) > tolerance ) {
put_pixel_unsafe(img, n->px, n->py, rcolor->red, rcolor->green, rcolor->blue);
pixelcount++;
}
int tx = n->px, ty = n->py;
_ffill_removehead(&head);
NSOE(tx - 1, ty);
NSOE(tx + 1, ty);
NSOE(tx, ty - 1);
NSOE(tx, ty + 1);
}
return pixelcount;
}

View file

@ -0,0 +1,27 @@
#include <stdio.h>
#include <stdlib.h>
#include "imglib.h"
int main(int argc, char **argv)
{
image animage;
rgb_color ic;
rgb_color rc;
if ( argc > 1 ) {
animage = read_image(argv[1]);
if ( animage != NULL ) {
ic.red = 255; /* = 0; */
ic.green = 255; /* = 0; */
ic.blue = 255; /* = 0; */
rc.red = 0;
rc.green = 255;
rc.blue = 0;
floodfill(animage, 100, 100, &ic, &rc);
/* 150, 150 */
print_jpg(animage, 90);
free(animage);
}
}
return 0;
}

View file

@ -0,0 +1,60 @@
// version 1.1.4-3
import java.awt.Color
import java.awt.Point
import java.awt.image.BufferedImage
import java.util.LinkedList
import java.io.File
import javax.imageio.ImageIO
import javax.swing.JOptionPane
import javax.swing.JLabel
import javax.swing.ImageIcon
fun floodFill(image: BufferedImage, node: Point, targetColor: Color, replColor: Color) {
val target = targetColor.getRGB()
val replacement = replColor.getRGB()
if (target == replacement) return
val width = image.width
val height = image.height
val queue = LinkedList<Point>()
var nnode: Point? = node
do {
var x = nnode!!.x
val y = nnode.y
while (x > 0 && image.getRGB(x - 1, y) == target) x--
var spanUp = false
var spanDown = false
while (x < width && image.getRGB(x, y) == target) {
image.setRGB(x, y, replacement)
if (!spanUp && y > 0 && image.getRGB(x, y - 1) == target) {
queue.add(Point(x, y - 1))
spanUp = true
}
else if (spanUp && y > 0 && image.getRGB(x, y - 1) != target) {
spanUp = false
}
if (!spanDown && y < height - 1 && image.getRGB(x, y + 1) == target) {
queue.add(Point(x, y + 1))
spanDown = true
}
else if (spanDown && y < height - 1 && image.getRGB(x, y + 1) != target) {
spanDown = false
}
x++
}
nnode = queue.pollFirst()
}
while (nnode != null)
}
fun main(args: Array<String>) {
val image = ImageIO.read(File("Unfilledcirc.png"))
floodFill(image, Point(50, 50), Color.white, Color.yellow)
val title = "Floodfilledcirc.png"
ImageIO.write(image, "png", File(title))
JOptionPane.showMessageDialog(null, JLabel(ImageIcon(image)), title, JOptionPane.PLAIN_MESSAGE)
}

View file

@ -0,0 +1,23 @@
library(png)
img <- readPNG("Unfilledcirc.png")
M <- img[ , , 1]
M <- ifelse(M < 0.5, 0, 1)
image(M, col = c(1, 0))
# https://en.wikipedia.org/wiki/Flood_fill
floodfill <- function(row, col, tcol, rcol) {
if (tcol == rcol) return()
if (M[row, col] != tcol) return()
M[row, col] <<- rcol
floodfill(row - 1, col , tcol, rcol) # south
floodfill(row + 1, col , tcol, rcol) # north
floodfill(row , col - 1, tcol, rcol) # west
floodfill(row , col + 1, tcol, rcol) # east
return("filling completed")
}
options(expressions = 10000)
startrow <- 100; startcol <- 100
floodfill(startrow, startcol, 0, 2)
image(M, col = c(1, 0, 2))

View file

@ -0,0 +1,37 @@
library(png)
img <- readPNG("Unfilledcirc.png")
M <- img[ , , 1]
M <- ifelse(M < 0.5, 0, 1)
M <- rbind(M, 0)
M <- cbind(M, 0)
image(M, col = c(1, 0))
# https://en.wikipedia.org/wiki/Flood_fill
floodfill <- function(row, col, tcol, rcol) {
if (tcol == rcol) return()
if (M[row, col] != tcol) return()
Q <- matrix(c(row, col), 1, 2)
while (dim(Q)[1] > 0) {
n <- Q[1, , drop = FALSE]
west <- cbind(n[1] , n[2] - 1)
east <- cbind(n[1] , n[2] + 1)
north <- cbind(n[1] + 1, n[2] )
south <- cbind(n[1] - 1, n[2] )
Q <- Q[-1, , drop = FALSE]
if (M[n] == tcol) {
M[n] <<- rcol
if (M[west] == tcol) Q <- rbind(Q, west)
if (M[east] == tcol) Q <- rbind(Q, east)
if (M[north] == tcol) Q <- rbind(Q, north)
if (M[south] == tcol) Q <- rbind(Q, south)
}
}
return("filling completed")
}
startrow <- 100; startcol <- 100
floodfill(startrow, startcol, 0, 2)
startrow <- 50; startcol <- 50
floodfill(startrow, startcol, 1, 3)
image(M, col = c(1, 0, 2, 3))

View file

@ -4,14 +4,14 @@ red = '000000000000000011111111'b /* " " red " "
green= '000000001111111100000000'b /* " " green " " " */
white= '111111111111111111111111'b /* " " white " " " */
/*image is defined to the test image. */
hx=125; hy=125 /*define limits (x,Y) for the image. */
area=white; call fill 125, 25, red /*fill the white area in red. */
area=black; call fill 125, 125, green /*fill the center orb in green. */
hx=125; hy=125 /*define limits (X,Y) for the image. */
area=white; call fill 125, 25, red /*fill the white area in red. */
area=black; call fill 125, 125, green /*fill the center orb in green. */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
fill: procedure expose image. hx hy area; parse arg x,y,fill_color /*obtain the args.*/
if x<1 | x>hx | y<1 | y>hy then return /*X or Y are outside of the image area*/
pixel=@(x, y) /*obtain the color of the X,Y pixel. */
pixel=image.x.y /*obtain the color of the X,Y pixel. */
if pixel\==area then return /*the pixel has already been filled */
/*with the fill_color, or we are not */
/*within the area to be filled. */

View file

@ -0,0 +1,14 @@
fcn flood(pixmap, x,y, repl){ // slow!
targ,h,w:=pixmap[x,y], pixmap.h,pixmap.w;
stack:=List(T(x,y));
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) );
}
}
}
}

View file

@ -0,0 +1,8 @@
pixmap:=PPM(250,302,0xFF|FF|FF);
pixmap.circle(101,200,100,0); pixmap.circle(75,100,25,0);
flood(pixmap,200,100, 0xF0|00|00);
flood(pixmap, 75,110, 0x00|F0|00);
flood(pixmap, 75,100, 0x00|00|F0);
pixmap.writeJPGFile("flood.zkl.jpg");