All SolutionsAll Solutions
⭐
Counting Stars
Week 18, 2026
it's gets confusing | Draw6 | C++ Solutions
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"//https://github.com/nothings/stb/blob/master/stb_image.h
#include "allheaders.hpp"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
using namespace std;
//------------------------------------[HELPER FUNCTION TO EXTRACT RGB VALUES]-
struct RGBPixel
{
uint8_t red;
uint8_t green;
uint8_t blue;
};
vector<string> values;
vector<int> ivaluesR;
vector<int> ivaluesG;
vector<int> ivaluesB;
int iX, iY, iR, iG, iB;
//------------------------------------------
void loadPNG(const std::string& filename)
{
int width, height, channels;
uint8_t* imageData = stbi_load(filename.c_str(), &width, &height, &channels, 3);
if (imageData == nullptr)
{
std::cerr << "Error loading image: " << filename << std::endl;
return;
}
std::vector<RGBPixel> pixels(width * height);
iX = width;
iY = height;
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
int index = (y * width + x) * 3;
RGBPixel& pixel = pixels[y * width + x];
pixel.red = imageData[index];
pixel.green = imageData[index + 1];
pixel.blue = imageData[index + 2];
iR = pixel.red;
iG = pixel.green;
iB = pixel.blue;
}
}
for (int y = 0; y < height; ++y)
{
for (int x = 0; x < width; ++x)
{
RGBPixel& pixel = pixels[y * width + x];
string s = to_string((int)pixel.red) + "," + to_string((int)pixel.green) + "," + to_string((int)pixel.blue);
values.push_back(s);
iR = pixel.red;
iG = pixel.green;
iB = pixel.blue;
ivaluesR.push_back(iR);
ivaluesG.push_back(iG);
ivaluesB.push_back(iB);
}
}
stbi_image_free(imageData);
}
//-----------------------------------------------------------------------[BEGIN]
int main(int argc, char* argv[])
{
string imgname = argv[1];
double totalpixels = 0;
double coverage = 0;
double icoverage = 0;//coverage calc
double emptyspace, stars, touching, nottouching = 0;
int nUL, nUC, nUR, nL, nR, nLL, nLC, nLR = 0;//neighbors = upper-left, upper-center, upper-right, etc
int iRedPixels, iGreenPixels, iBluePixels = 0;
double starcount = 0;
double icover, coveragemarker = 0;
fstream outfile("outfile", ios::in | ios::out | ios::trunc);
if(imgname == "")
{
cout << "No image file specified\n";
return -1;
}
std::string filename = imgname;
loadPNG(filename); //converts image to both string and int vectors
//values is the string vector -> save to file for comparing
//values not used for solution math
for (const auto& str : values)
{
outfile << str << "\n";
}
int iPixelColor = ivaluesR.size();
int iInput;
cout << "Enter threshold\n";
cin >> iInput;
int threshold = iInput;
cout << "working\n";//--------------------------------------[ SET THRESHOLD ];
for(int i = 0; i < iPixelColor; i++)
{
if((ivaluesR[i] < threshold) && (ivaluesG[i] < threshold) && (ivaluesB[i] < threshold))
{//anything below threshold gets zero'd' (black)
ivaluesR[i] = 0;
ivaluesG[i] = 0;
ivaluesB[i] = 0;
}
else
{//anything above threshold gets set to brightest (red)
ivaluesR[i] = 255;
coveragemarker++;//suspect is a Star
stars++;
nUL = i - (iX - 1);
nUC = i - (iX);
nUR = i - (iX + 1);
nL = i - 1;
nR = i + 1;
nLL = i + (iX - 1);
nLC = i + (iX);
nLR = i + (iX + 1);
if(i > iX && i < iX * iY)
{
if((ivaluesR[nUL] == 255))
{
ivaluesR[nUL] = 0;
ivaluesG[nUL] = 255;
ivaluesB[nUL] = 255;
}
if((ivaluesR[nUC] == 255))
{
ivaluesR[nUC] = 0;
ivaluesG[nUC] = 125;
ivaluesB[nUC] = 175;
}
if((ivaluesR[nUR] == 255))
{
ivaluesR[nUR] = 0;
ivaluesG[nUR] = 125;
ivaluesB[nUR] = 175;
}
if((ivaluesR[nL] == 255))
{
ivaluesR[nL] = 0;
ivaluesG[nL] = 125;
ivaluesB[nL] = 175;
}
if((ivaluesR[nR] == 255))
{
ivaluesR[nR] = 0;
ivaluesG[nR] = 125;
ivaluesB[nR] = 175;
}
if((ivaluesR[nLL] == 255))
{
ivaluesR[nLL] = 0;
ivaluesG[nLL] = 125;
ivaluesB[nLL] = 175;
}
if((ivaluesR[nLC] == 255))
{
ivaluesR[nLC] = 0;
ivaluesG[nLC] = 125;
ivaluesB[nLC] = 175;
}
if((ivaluesR[nLR] == 255))
{
ivaluesR[nLR] = 0;
ivaluesG[nLR] = 125;
ivaluesB[nLR] = 175;
}
if(ivaluesR[i] == 255)
{
nottouching++;
}
}
}
}
for(int i = 0; i < iPixelColor; i++)
{
cout << ivaluesR[i] << "," << ivaluesG[i] << "," << ivaluesB[i] << "\n";
}
for(int i = 0; i < iPixelColor; i++)
{
if(ivaluesR[i] > threshold)
{
starcount++;
icover++;
iRedPixels++;
}
if(ivaluesG[i] > threshold)
{
icover++;
iGreenPixels++;
icoverage++;
}
if(ivaluesB[i] > threshold)
{
iBluePixels++;
}
}
// -----------------------------------------------------------------------[END]
int count = ivaluesR.size();// int vector holding the reds
double bettercount = stars - starcount;
cout << "----------------------------------\n";
cout << "File: " << filename << "\n";
cout << "Imgage size = " << iX << "x" << iY << "\n";
cout << "Brightness threshold: " << threshold << "\n";
cout << "Stars count: " << nottouching - bettercount << "\n";
cout << "star pixels: " << nottouching << " / "<< count << "\n";
coverage = (nottouching / count) * 100;
cout << "Star coverage: " << coverage << "%\n";
cout << "----------------------------------\n";
return 0;
}
Food fill to mark all pixels of a star | greenya | Odin Solutions
package main
import "core:fmt"
import "core:image"
import "core:image/bmp"
import "core:image/jpeg"
import "core:image/png"
_, _ :: jpeg, png
// IMAGE1_BYTES :: #load("stars-example1.png")
// IMAGE2_BYTES :: #load("stars-example2.png")
IMAGE1_BYTES :: #load("stars1.png")
IMAGE2_BYTES :: #load("stars2.jpg")
RGB_THRESHOLD :: 140 // 0..255*3
main :: proc () {
fmt.printfln("RGB threshold: %d (0-%d)", RGB_THRESHOLD, 255*3)
process_image_bytes(IMAGE1_BYTES, RGB_THRESHOLD, "result1.bmp")
process_image_bytes(IMAGE2_BYTES, RGB_THRESHOLD, "result2.bmp")
}
R_NEW :: 254
R_VISITED :: 255
process_image_bytes :: proc (bytes: [] u8, rgb_threshold: int, save_result_bmp := "") {
img, err := image.load_from_bytes(bytes)
fmt.assertf(err == nil, "Failed to load image: %v", err)
fmt.assertf(img.channels == 3, "Image must have exactly 3 channels (RGB, no alpha)")
defer image.destroy(img)
fmt.println("------------------------------")
defer fmt.println("------------------------------")
fmt.printfln("Image resolution: %d x %d", img.width, img.height)
assert(img.width * img.height == len(img.pixels.buf) / 3)
pixels := transmute ([][3] u8) img.pixels.buf[:len(img.pixels.buf)/3]
fmt.println("Applying threshold...")
star_pixel_count: int
for i in 0..<img.width*img.height {
r := int(pixels[i].r)
g := int(pixels[i].g)
b := int(pixels[i].b)
if r + g + b > RGB_THRESHOLD {
pixels[i] = {R_NEW,255,255}
star_pixel_count += 1
} else {
pixels[i] = {}
}
}
fmt.println("Counting stars...")
star_count := count_stars(pixels, img.width, img.height)
fmt.printfln("Stars : %d", star_count)
fmt.printfln("Coverage (%%) : %.1f", (f32(star_pixel_count)*100) / f32(len(pixels)))
if save_result_bmp != "" {
fmt.printfln("Writing %s...", save_result_bmp)
bmp.save(save_result_bmp, img)
}
}
count_stars :: proc (pixels: [][3] u8, width, height: int) -> (count: int) {
for y in 0..<height do for x in 0..<width {
if pixels[y*width+x].r == R_NEW {
fill_star(pixels, width, height, x, y)
count += 1
}
}
return
}
fill_star :: proc (pixels: [][3] u8, width, height, x, y: int) {
list := make([dynamic] int, len=0, cap=400)
append(&list, y*width+x)
defer delete(list)
for len(list) > 0 {
i := pop(&list)
pixels[i].r = R_VISITED
for d in ([?] [2] int {
{ -1, -1 },
{ 0, -1 },
{ +1, -1 },
{ -1, 0 },
{ +1, 0 },
{ -1, +1 },
{ 0, +1 },
{ +1, +1 },
}) {
j := i + d.y * width + d.x
if j < 0 || j >= width*height do continue
if pixels[j].r == R_NEW do append(&list, j)
}
}
}