September 2017 Update
This commit is contained in:
parent
bba7bfd280
commit
ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
27
Task/Bitmap-Flood-fill/C/bitmap-flood-fill-5.c
Normal file
27
Task/Bitmap-Flood-fill/C/bitmap-flood-fill-5.c
Normal 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;
|
||||
}
|
||||
60
Task/Bitmap-Flood-fill/Kotlin/bitmap-flood-fill.kotlin
Normal file
60
Task/Bitmap-Flood-fill/Kotlin/bitmap-flood-fill.kotlin
Normal 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)
|
||||
}
|
||||
23
Task/Bitmap-Flood-fill/R/bitmap-flood-fill-1.r
Normal file
23
Task/Bitmap-Flood-fill/R/bitmap-flood-fill-1.r
Normal 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))
|
||||
37
Task/Bitmap-Flood-fill/R/bitmap-flood-fill-2.r
Normal file
37
Task/Bitmap-Flood-fill/R/bitmap-flood-fill-2.r
Normal 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))
|
||||
|
|
@ -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. */
|
||||
|
|
|
|||
14
Task/Bitmap-Flood-fill/Zkl/bitmap-flood-fill-1.zkl
Normal file
14
Task/Bitmap-Flood-fill/Zkl/bitmap-flood-fill-1.zkl
Normal 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) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
Task/Bitmap-Flood-fill/Zkl/bitmap-flood-fill-2.zkl
Normal file
8
Task/Bitmap-Flood-fill/Zkl/bitmap-flood-fill-2.zkl
Normal 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");
|
||||
Loading…
Add table
Add a link
Reference in a new issue