average pooling C++ error - c++

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <math.h>
#include <fstream>
#include <iostream>
using namespace cv;
using namespace std;
#define ATD at<double>
Mat average_pooling2x2(Mat mat, int padding_mathed)
{
int width_remain = mat.cols % 2;
int high_remain = mat.rows % 2;
Mat mat_new;
if (width_remain == 0 && high_remain == 0)
mat.copyTo(mat_new);
else
{
if (padding_mathed == 1)//valid
{
Rect roi = Rect(0, 0, mat.cols - width_remain, mat.rows - high_remain);
mat(roi).copyTo(mat_new);
}
else //same
{
mat.copyTo(mat_new);
if (high_remain != 0)
{
Mat row_add = cv::Mat::zeros(high_remain, mat_new.cols,mat_new.type());
mat_new.push_back(row_add);
}
if (width_remain != 0)
{
Mat col_add = cv::Mat::zeros(width_remain, mat_new.rows, mat_new.type());
mat_new = mat_new.t();
mat_new.push_back(col_add);
mat_new = mat_new.t();
}
}
}
Mat res(mat_new.cols / 2, mat_new.rows / 2, mat_new.type(), Scalar::all(0));
if (mat_new.channels() ==3)
{
for (int i = 0; i < res.rows; i++)//this is where error happened
{
uchar *data_res = res.ptr<uchar>(i);
uchar * data = mat_new.ptr<uchar>(2*i);
uchar * data1 = mat_new.ptr<uchar>(2*i+1);
for (int j = 0; j < res.cols*res.channels(); j = j + 3)
{
data_res[j] = (data[j*2] + data[j*2+3] + data1[j*2] + data1[j*2+3]) / 4;
data_res[j + 1] = (data[j*2+1] + data[j*2+4] + data1[j*2+1] + data1[j*2+4]) / 4;
data_res[j + 2] = (data[j*2+2] + data[j*2+5] + data1[j*2+2] + data1[j*2+5]) / 4;
}
}
}
else
{
for (int i = 0; i<res.rows; i++)
{
for (int j = 0; j<res.cols; j++)
{
Mat temp;
Rect roi = Rect(j * 2, i * 2, 2, 2);
mat_new(roi).copyTo(temp);
double val;
val = sum(temp)[0] / (2 * 2);
res.ATD(i, j) = val;
}
}
}
return res;
}
int main(int argc, char** argv)
{
Mat image = imread("C://Users//Administrator//Desktop//11.jpg");
imshow("???", image);
Mat pooling_image;
average_pooling2x2(image, 2).copyTo(pooling_image);
imshow("???", pooling_image);
waitKey();
return 0;
}
OpenCV Error: Assertion failed (y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0])) in cv::Mat::ptr, file d:\opencv\build\include\opencv2\core\mat.inl.hpp, line 827
reccently I try to implement the average pooling using C++, this is the error when I run the code, it seems that maybe the ptr pointer is out of range. but I just can not figure out where is the problem. Really need some help

If you opened the file that the error message references to, you would see that the ptr() method is defined as follows:
template<typename _Tp> inline _Tp* Mat::ptr(int y)
{
CV_DbgAssert( y == 0 || (data && dims >= 1 && (unsigned)y < (unsigned)size.p[0]) );
return (_Tp*)(data + step.p[0]*y);
}
Everything inside CV_DbgAssert() must evaluate to true - otherwise the program is going to crash at runtime. From that condition, it is clear that you are referring to the row in your program that is outside of Mat boundaries (the variable y above).
In your case, I can see several line where the program is going to crash.
In these lines, the crash happens when i gets equal or greater than res.rows/2 (the first one will crash if res.rows is an odd number):
uchar * data = mat_new.ptr<uchar>(2*i);
uchar * data1 = mat_new.ptr<uchar>(2*i+1);
This loop will also crash, because data_res has only res.cols columns, and you allow j to reach res.cols*res.channels()-1:
for (int j = 0; j < res.cols*res.channels(); j = j + 3)
{
data_res[j] = (data[j*2] + data[j*2+3] + data1[j*2] + data1[j*2+3]) / 4;
data_res[j + 1] = (data[j*2+1] + data[j*2+4] + data1[j*2+1] + data1[j*2+4]) / 4;
data_res[j + 2] = (data[j*2+2] + data[j*2+5] + data1[j*2+2] + data1[j*2+5]) / 4;
}
Also, I believe that here:
Mat res(mat_new.cols / 2, mat_new.rows / 2, mat_new.type(), Scalar::all(0));
you may have accidentaly swapped arguments - res has mat_new.cols/2 rows, whereas I think you wanted it to be mat_new.rows/2.

Related

Codewars:Path Finder #3: the Alpinist in C++

I just tried to finish a problem:Path Finder #3: the Alpinist in Codewars. I had passed all basic test cases and there were any errors under my own test cases. But when i submited my solution, my code failed for random test cased. My solution of problem is graph searching based Dijkstra algorithm and priority_queue. I think there my some potential errors i didn't consider. Please help me check it. I have tried achieve it for three hours.
My solution is below.
#include <iostream>
#include <cmath>
#include <vector>
#include <queue>
using namespace std;
const int INF = 1e9;
const int WHITE = -1;
const int GRAY = 0;
const int BLACK = 1;
int path_finder(string maze)
{
int result = 0;
vector<pair<int, int>> element;
vector<vector<pair<int, int>>> altitude;
int width = (-1 + sqrt(5 + 4 * maze.size())) / 2;
auto tem = maze.find('\n');
while (tem != string::npos)
{
maze.erase(tem, 1);
tem = maze.find('\n');
}
for (int i = 0; i < width; ++i)
{
for (int j = 0; j < width; ++j)
{
altitude.push_back(element);
if (i >= 1)
altitude[i * width + j].push_back(make_pair(i * width + j - width, abs(maze[i * width + j] - maze[i * width + j - width])));
if (i < width - 1)
altitude[i * width + j].push_back(make_pair(i * width + j + width, abs(maze[i * width + j] - maze[i * width + j + width])));
if (j >= 1)
altitude[i * width + j].push_back(make_pair(i * width + j - 1, abs(maze[i * width + j] - maze[i * width + j - 1])));
if (j < width - 1)
altitude[i * width + j].push_back(make_pair(i * width + j + 1, abs(maze[i * width + j] - maze[i * width + j + 1])));
}
}
int* distance = new int[width * width];
int* state = new int[width * width];
for (int i = 0; i < width * width; ++i)
{
distance[i] = INF;
state[i] = WHITE;
}
priority_queue<pair<int, int>> unfinished;
unfinished.push(make_pair(0, 0));
state[0] = GRAY;
distance[0] = 0;
while (!unfinished.empty())
{
pair<int, int> tem = unfinished.top();
unfinished.pop();
state[tem.second] = BLACK;
if(distance[tem.second] < tem.first * (-1))
continue;
for (int i = 0; i < altitude[tem.second].size(); ++i)
{
if(state[altitude[tem.second][i].first] != BLACK)
{
unfinished.push(make_pair(-1 * altitude[tem.second][i].second, altitude[tem.second][i].first));
if (distance[tem.second] + altitude[tem.second][i].second < distance[altitude[tem.second][i].first])
{
distance[altitude[tem.second][i].first] = distance[tem.second] + altitude[tem.second][i].second;
state[altitude[tem.second][i].first] = GRAY;
}
}
}
}
result = distance[width * width - 1];
return result;
}
Here is a test case where your code has the wrong answer.
"53072\n"
"09003\n"
"29977\n"
"31707\n"
"59844"
The least cost is 13, with this path:
{1 1 0 0 0}
{0 1 0 0 0}
{0 1 1 1 1}
{0 0 0 0 1}
{0 0 0 0 1}
But your program outputs 15.

Why does my image get cropped in half when applied Sobel Edge Detector?

Let me start by saying I am very newbie at C++ and so I don't really know the best practices or handle very well with the syntax.
I'm trying to read a black and white image, and using the sobel algorithm to detect its edges and output the result, but halfway my execution I get an error:
munmap_chunk(): invalid pointer
Aborted (core dumped)
Though the image is outputted, it's only half of it and I can't seem to figure out whats causing this.
I wrote the following code:
#include <iostream>
#include <omp.h>
#include "CImg.h"
using namespace std;
using namespace cimg_library;
int main() {
const int x_mask [9] = {
-1, 0, 1,
-2, 0, 2,
-1, 0, 1
};
const int y_mask [9] = {
-1, -2, -1,
0, 0, 0,
1, 2, 1
};
const char* fileName = "test.png";
CImg<float> img = CImg<float>(fileName);
int cols = img.width();
int lines = img.height();
CImg<float> output = CImg<float>(cols, lines, 1, 1, 0.0);
printf("Loading %d x %d image...\n", cols, lines);
const int mask_size = 3;
int gradient_x;
int gradient_y;
// Loop through image ignoring borders
for(int i = 1; i<cols-1; i++) {
for(int j = 1; j<lines-1; j++){
output(j,i) = 0;
gradient_x = 0;
gradient_y = 0;
// Find the x_gradient and y_gradient
for(int m = 0; m < mask_size; m++) {
for(int n = 0; n < mask_size; n++) {
// Neighbourgh pixels
int np_x = j + (m - 1);
int np_y = i + (n - 1);
float v = img(np_x,np_y);
int mask_index = (m*3) + n;
gradient_x = gradient_x + (x_mask[mask_index] * v);
gradient_y = gradient_y + (y_mask[mask_index] * v);
}
}
float gradient_sum = sqrt((gradient_x * gradient_x) + (gradient_y * gradient_y));
if(gradient_sum >= 255) {
gradient_sum = 255;
} else if(gradient_sum <= 0) {
gradient_sum = 0;
}
output(j, i) = gradient_sum;
}
}
printf("Outputed image of size %d x %d\n", output.width(), output.height());
output.save("test_edges.png");
return 0;
}
Applied to this image:
I get this ouput:

Painterly Rendering, Clipping line, I'm have an error

I'm making a painterly rendering.
And now I'm doing that clipping line things.
But I got this error:
<<unsigned><pt.x*DataType<_Tp>::channels> <<unsigned<size.p[1]*channels<>>>
And
template<typename _Tp> inline const _Tp& Mat::at(int i0, int i1) const
{
CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] &&
(unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) &&
CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1());
return ((const _Tp*)(data + step.p[0]*i0))[i1];
}
Maybe this is the error that on 'Lineclipping()'
Please, tell me another good idea that clipped line.
this is my code. And I'm just a student so my codding skill is very beginner.
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <sstream>
#include <cmath>
#include <stdio.h>
#include <cstdlib>
#include <time.h>
#include <random>
using namespace cv;
using namespace std;
random_device rd;
mt19937_64 rng(rd());
double PI = 3.141592;
int perturbLength = (rand() % 6) + 1;
int perturbRadius = ((rand() % 5) + 0) / 10;
int perturbAngle = (rand() % 15) + (-15);
int Maxlength = 10 - perturbLength;
int radius = 2 - perturbRadius;
int angle = 45 - perturbAngle;
double theta = angle*(PI / 180);
void Lineclipping(int x, int y, double theta, int len, Point2d& pt1, Point2d& pt2, Mat& EdgeMap)
{
double length = ceil(len);
enter code here
float detectPT = len / length;
for (int i = detectPT; i <= len;)
{
Point2d Mpt1(x + length*cos(theta), y + length*sin(theta));
if (EdgeMap.at<uchar>(Mpt1.y, Mpt1.x) > 0)
{
pt1.x = Mpt1.x;
pt1.y = Mpt1.y;
}
else if (i == length)
{
pt1.x = Mpt1.x;
pt1.y = Mpt1.y;
}
i = i + detectPT;
}
for (int i = detectPT; i <= len;)
{
Point2d Mpt2(x - length*cos(theta), y - length*sin(theta));
if (EdgeMap.at<uchar>(Mpt2.y, Mpt2.x) > 0)
{
pt2.x = Mpt2.x;
pt2.y = Mpt2.y;
}
else if (i == length)
{
pt2.x = Mpt2.x;
pt2.y = Mpt2.y;
}
i = i + detectPT;
}
}
Mat EdgeDetect(Mat& referenceimg, Mat& Edge)
{
Mat image = referenceimg.clone();
//Make Edge Map
Mat IntensityImg(image.size(), CV_8U, 255);
Mat sobelx, sobely;
for (int i = 0; i < image.rows; i++)
{
for (int j = 0; j < image.cols; j++)
{
Vec3b intensity = image.at<Vec3b>(j, i);
uchar blue = intensity.val[0];
uchar green = intensity.val[1];
uchar red = intensity.val[2];
IntensityImg.at<uchar>(j, i) = (30 * red + 59 * green + 11 * blue) / 100;
}
}
GaussianBlur(IntensityImg, IntensityImg, Size(5, 5), 0.1, 0.1);
Sobel(IntensityImg, sobelx, CV_32F, 1, 0);
Sobel(IntensityImg, sobely, CV_32F, 0, 1);
Mat magnitudeXY = abs(sobelx), abs(sobely);
magnitudeXY.convertTo(Edge, CV_8U);
Mat mask(3, 3, CV_8UC1, 1);
morphologyEx(Edge, Edge, MORPH_ERODE, mask);
for (int i = 0; i < image.rows; i++)
{
for (int j = 0; j < image.cols; j++)
{
Edge.at<uchar>(j, i) = (Edge.at<uchar>(j, i) > 20 ? 255 : 0);
}
}
imshow("intensity", Edge);
return Edge;
}
void paint(Mat &image, int snum)
{
Mat Edge;
EdgeDetect(image, Edge);
for (int n = 0; n < snum; n++)
{
int x = rand() % image.cols;
int y = rand() % image.rows;
if (image.channels() == 1)
{
image.at<uchar>(x, y) = 255;
}
else if (image.channels() == 3)
{
int length = Maxlength / 2;
Point2d pt1(x + length*cos(theta), y + length*sin(theta));
Point2d pt2(x - length*cos(theta), y - length*sin(theta));
Lineclipping(x, y, theta, length, fpt1, fpt2, Edge);
//draw line
Scalar color(image.at<Vec3b>(y, x)[0], image.at<Vec3b>(y, x)[1], image.at<Vec3b>(y, x)[2]);
line(image, pt1, pt2, color, radius);
}
}
}
int main()
{
Mat Img = imread("fruit.jpg", IMREAD_COLOR);
CV_Assert(Img.data);
Mat resultImage = Img.clone();
Mat sobel = Img.clone();
int num = Img.rows*Img.cols;
paint(resultImage, num);
imshow("result", resultImage);
waitKey();
return 0;
}
And This is the error parts.
for (int i = detectPT; i <= len;)
{
Point2d Mpt1(x + length*cos(theta), y + length*sin(theta));
if (EdgeMap.at<uchar>(Mpt1.y, Mpt1.x) > 0)
{
pt1.x = Mpt1.x;
pt1.y = Mpt1.y;
}
else if (i == length)
{
pt1.x = Mpt1.x;
pt1.y = Mpt1.y;
}
i = i + detectPT;
}
for (int i = detectPT; i <= len;)
{
Point2d Mpt2(x - length*cos(theta), y - length*sin(theta));
if (EdgeMap.at<uchar>(Mpt2.y, Mpt2.x) > 0)
{
pt2.x = Mpt2.x;
pt2.y = Mpt2.y;
}
else if (i == length)
{
pt2.x = Mpt2.x;
pt2.y = Mpt2.y;
}
i = i + detectPT;
}
Thank you!
Since I can't compile this and run it, I am going to run through a possible execution and show you where you can hit this out of range error.
int perturbLength = (rand() % 6) + 1; // Range is 1 to 6, let's assume 4
int perturbAngle = (rand() % 15) + (-15); // Range is -15 to -1 let's assume -14
int Maxlength = 10 - perturbLength; // 6
int angle = 45 - perturbAngle; // 44
double theta = angle*(PI / 180); // .7679
Now we get into this code inside the paint method:
int x = rand() % image.cols; // Let's assume image.cols - 2
int y = rand() % image.rows; // Let's assume image.rows - 1
Inside of paint we will reach this code:
int length = Maxlength / 2; // Maxlength is 6 so this is 3
Lineclipping(x, y, theta, length, fpt1, fpt2, Edge);
Which leads to the Lineclipping method and here we get a problem:
Point2d Mpt1(x + length*cos(theta), y + length*sin(theta));
if (EdgeMap.at<uchar>(Mpt1.y, Mpt1.x) > 0)
This is the problem. Remember, x is image.cols - 2. Now we perform the operations x + length * cos(theta), which is (image.cols-2) + 3 * cos(.7679). 3 * cos(.7679) is 2.999 which whether you floor it or round it is going to cause a problem when you add it to image.cols - 2. If it is floored and you get 2 we have image.cols which causes out of range, if it is rounded then we have image.cols + 1, so in either case we go beyond the bounds of the array.

What is the difference between kmeans and cvKMeans2 algorithms in OpenCV?

I want to find dominant N colors on the picture. For this purpose I decided to use KMeans algorithm. My project written on C, that is way I used cvKMeans2 algorithm. But it gives me very strange results. Then I decided to try kmeans algorithm on OpenCV C++. It gives me more accurate results. So, where is my fault? Could someone explain it to me?
1. I used this image for test.
2. Implementation on C.
#include <cv.h>
#include <highgui.h>
#define CLUSTERS 3
int main(int argc, char **argv) {
const char *filename = "test_12.jpg";
IplImage *tmp = cvLoadImage(filename);
if (!tmp) {
return -1;
}
IplImage *src = cvCloneImage(tmp);
cvCvtColor(tmp, src, CV_BGR2RGB);
CvMat *samples = cvCreateMat(src->height * src->width, 3, CV_32F);
for (int i = 0; i < samples->height; i++) {
samples->data.fl[i * 3 + 0] = (uchar) src->imageData[i * 3 + 0];
samples->data.fl[i * 3 + 1] = (uchar) src->imageData[i * 3 + 1];
samples->data.fl[i * 3 + 2] = (uchar) src->imageData[i * 3 + 2];
}
CvMat *labels = cvCreateMat(samples->height, 1, CV_32SC1);
CvMat *centers = cvCreateMat(CLUSTERS, 3, CV_32FC1);
int flags = 0;
int attempts = 5;
cvKMeans2(samples, CLUSTERS, labels,
cvTermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 10000, 0.005),
attempts, 0, flags, centers);
int rows = 40;
int cols = 300;
IplImage *des = cvCreateImage(cvSize(cols, rows), 8, 3);
int part = 4000;
int r = 0;
int u = 0;
for (int y = 0; y < 300; ++y) {
for (int x = 0; x < 40; ++x) {
if (u >= part) {
r++;
part = (r + 1) * part;
}
des->imageData[(300 * x + y) * 3 + 0] = static_cast<char>(centers->data.fl[r * 3 + 0]);
des->imageData[(300 * x + y) * 3 + 1] = static_cast<char>(centers->data.fl[r * 3 + 1]);
des->imageData[(300 * x + y) * 3 + 2] = static_cast<char>(centers->data.fl[r * 3 + 2]);
u++;
}
}
IplImage *dominant_colors = cvCloneImage(des);
cvCvtColor(des, dominant_colors, CV_BGR2RGB);
cvNamedWindow("dominant_colors", CV_WINDOW_AUTOSIZE);
cvShowImage("dominant_colors", dominant_colors);
cvWaitKey(0);
cvDestroyWindow("dominant_colors");
cvReleaseImage(&src);
cvReleaseImage(&des);
cvReleaseMat(&labels);
cvReleaseMat(&samples);
return 0;
}
3. Implementation on C++.
#include <cv.h>
#include <opencv/cv.hpp>
#define CLUSTERS 3
int main(int argc, char **argv) {
const cv::Mat &tmp = cv::imread("test_12.jpg");
cv::Mat src;
cv::cvtColor(tmp, src, CV_BGR2RGB);
cv::Mat samples(src.rows * src.cols, 3, CV_32F);
for (int y = 0; y < src.rows; y++)
for (int x = 0; x < src.cols; x++)
for (int z = 0; z < 3; z++)
samples.at<float>(y + x * src.rows, z) = src.at<cv::Vec3b>(y, x)[z];
int attempts = 5;
cv::Mat labels;
cv::Mat centers;
kmeans(samples, CLUSTERS, labels, cv::TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 1000, 0.005),
attempts, cv::KMEANS_PP_CENTERS, centers);
cv::Mat colors(cv::Size(CLUSTERS * 100, 30), tmp.type());
int p = 100;
int cluster_id = 0;
for (int x = 0; x < CLUSTERS * 100; x++) {
for (int y = 0; y < 30; y++) {
if (x >= p) {
cluster_id++;
p = (cluster_id + 1) * 100;
}
colors.at<cv::Vec3b>(y, x)[0] = static_cast<uchar>(centers.at<float>(cluster_id, 0));
colors.at<cv::Vec3b>(y, x)[1] = static_cast<uchar>(centers.at<float>(cluster_id, 1));
colors.at<cv::Vec3b>(y, x)[2] = static_cast<uchar>(centers.at<float>(cluster_id, 2));
}
}
cv::Mat dominant_colors;
cv::cvtColor(colors, dominant_colors, CV_RGB2BGR);
cv::imshow("dominant_colors", dominant_colors);
cv::waitKey(0);
return 0;
}
4. Result of code on C.
5. Result of code on C++.
I found my mistake. It is related to IplImage's widthStep field. As I read here widthStep gets padded up to a multiple of 4 for performance reasons. If widthStep is equal to 30 it will padded up to 32.
int h = src->height;
int w = src->width;
int c = 3;
int delta = 0;
for (int i = 0, y = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
for (int k = 0; k < c; ++k, y++) {
samples->data.fl[i * w * c + c * j + k] = (uchar) src->imageData[delta + i * w * c + c * j + k];
}
}
delta += src->widthStep - src->width * src->nChannels;
}
With pointers
for (int x = 0, i = 0; x < src->height; ++x) {
auto *ptr = (uchar *) (src->imageData + x * src->widthStep);
for (int y = 0; y < src->width; ++y, i++) {
for (int j = 0; j < 3; ++j) {
samples->data.fl[i * 3 + j] = ptr[3 * y + j];
}
}
}

Performant Way to create checkerboard pattern

So I have an image that I want to overlay with a checkerboard pattern.
This is what I have come up with so far:
for ( uint_8 nRow = 0; nRow < image.width(); ++nRow)
for (uint_8 nCol = 0; nCol < image.height(); ++nCol)
if(((nRow/20 + nCol/20) % 2) == 0)
memset(&image.data[nCol + nRow], 0, 1);
Produces a white image unfortunately. I dont think this is very performant because memset is called for every single pixel in the image instead of multiple.
Why does this code not produce a chckerboard pattern? How would you improve it?
For better performance, don't treat the image as a 2-dimensional entity. Instead, look at it as a 1D array of continuous data, where all lines of the image are arranged one after the other.
With this approach, you can write the pattern in one go with a single loop, where in every iteration you memset() multiple adjacent pixels and increase the index by twice the amount of pixels you set:
int data_size = image.width() * image.height();
for (auto it = image.data; it < image.data + data_size; it += 20) {
memset(it, 0, 20);
if (((it - data) + 40) % (20 * 400) == 0) {
it += 40;
} else if (((it - data) + 20) % (20 * 400) != 0) {
it += 20;
}
}
(Replace auto with the type of image.data if you're not using C++11; I suspect it's unsigned char*.)
This is quite friendly for the CPU cache prefetch. It's also friendly for the compiler, which can potentially vectorize and/or perform loop unrolling.
If you have an image's dimensions which are multiple of the checker square size :
(I coded in C but it is fairly easy to transpose to C++)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define uint unsigned int
#define WIDTH 40
#define HEIGHT 40
#define BLOCK_SIZE 5
void create_checker_row(uint* row, uint size_block, uint nb_col, uint offset )
{
uint ic;
for (ic = size_block*offset ; ic < nb_col; ic+= 2*size_block )
{
memset( (row + ic) , 0, size_block*sizeof(uint) );
}
}
int main()
{
uint ir,ic;
// image creation
uint* pixels = (uint*) malloc(WIDTH*HEIGHT*sizeof(uint));
for (ir = 0; ir < WIDTH; ir++)
{
for ( ic = 0; ic < HEIGHT; ic++)
{
// arbitrary numbers
pixels[ir*WIDTH + ic] = (ir*WIDTH + ic) % 57 ;
printf("%d,", pixels[ir*WIDTH + ic] );
}
printf("\n");
}
for (ir = 0; ir < WIDTH; ir++)
{
create_checker_row( pixels + ir*WIDTH , // pointer at the beggining of n-th row
BLOCK_SIZE , // horizontal length for square
WIDTH , // image width
(ir/BLOCK_SIZE) % 2 // offset to create the checker pattern
);
}
// validation
printf("\n");
printf("Validation \n");
printf("\n");
for (ir = 0; ir < WIDTH; ir++)
{
for ( ic = 0; ic < HEIGHT; ic++)
{
printf("%d,", pixels[ir*WIDTH + ic] );
}
printf("\n");
}
return 0;
}
Seems pretty checkered for me : http://ideone.com/gp9so6
I use this and stb_image_write.h
#include <stdlib.h>
#include <stb_image_write.h>
int main(int argc, char *argv[])
{
const int w = 256, h = 256, ch = 4, segments = 8, box_sz = w / segments;
unsigned char rgba_fg[4] = {255, 255, 0, 255}; //yellow
unsigned char rgba_bg[4] = {255, 0, 0, 255}; //red
unsigned char* data = calloc(w * h * ch, sizeof(unsigned char));
int swap = 0;
int fill = 0; /* set to 1 to fill fg first*/
unsigned char* col = NULL;
for(int i = 0; i < w * h; i++)
{
if(i % (w * box_sz) == 0 && i != 0)
swap = !swap;
if(i % box_sz == 0 && i != 0)
fill = !fill;
if(fill)
{
if(swap)
col = rgba_bg;
else
col = rgba_fg;
}else
{
if(swap)
col = rgba_fg;
else
col = rgba_bg;
}
for(int j = 0; j < ch; j++)
{
data[i*ch + j] = col[j];
}
}
stbi_write_png("checker.png", w, h, ch, data, 0);
free(data);
return 0;
}
Its a bit slow with large images but gets the job done if you cache them