I'm doing a sierpinski's carpet program and i managed to create a PGM image from a matrix.I first create a char **matrix which has # or ' ' .# = white color , ' ' = black color, and then i create a int **pixels with values 0 or 255 for black and white, pretty simple. The matrix size is equal to number of iterations of sierpinski's carpet : for 3 iterations of the algorithm i have a resulting matrix(so image) of 27 by 27 pixels. How can i multiply this matrix in order to enlarge the resulting picture but keep the same image.Something like for each pixel i want it to be 4 pixels in the output image. C program.
EDIT: Code for printing a PGM image from a matrix of pixel values
void print(char fout[30],int **pixels,int width,int height){
int i,j;
FILE *f = fopen(fout,"w");
fprintf(f,"%s\n","P2");
fprintf(f,"%d %d\n",width,height);
fprintf(f,"%d\n",255);
for(i=height-1;i>=0;i--){
for(j=0;j<width;j++){
fprintf(f,"%d ",pixels[i][j]);
}
fprintf(f,"\n");
}
fclose(f);
}
Code for creating the pixel value matrix
for(i=0;i<size;i++)
for(j=0;j<size;j++)
if(basegrid[i][j] == ' ')
pixels[i][j]=0;
else
pixels[i][j]=255;
First you can create a larger matrix (of size: size * 2 by size * 2) and then fill it according to the pixels you had at first.
Something like this should work:
int main()
{
int **pixels;
int size;
int **enlarged;
int idx;
enlarged = malloc(2 * size * sizeof(int *));
for(idx = 0; idx != size; ++idx)
{
enlarged[idx] = malloc(2 * size * sizeof(int));
}
int row;
int col;
for(row = 0; row != size; ++row)
{
for(col = 0; col != size; ++col)
{
enlarged[row * 2][col * 2] = pixels[row][col];
enlarged[row * 2 + 1][col * 2] = pixels[row][col];
enlarged[row * 2][col * 2 + 1] = pixels[row][col];
enlarged[row * 2 + 1][col * 2 + 1] = pixels[row][col];
}
}
}
Note that I left out the code where you read size and fill pixels.
Hope this helps.
Related
Working on an edge detection function. Looking back at my code I think that I have concept / logic down. But the results aren't coming out the way it should.
typedef struct {
int Red;
int Green;
int Blue;
} GTOTALS;
// Detect edges
void edges(int height, int width, RGBTRIPLE image[height][width])
{
const int MAX = 3;
// Copy Image
RGBTRIPLE Copy[height][width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
Copy[i][j] = image[i][j];
}
}
// Gx and Gy Grids 3 x 3
int Gx[MAX][MAX] = {
{-1, 0, 1},
{-2, 0, 2},
{-1, 0, 1}
};
int Gy[MAX][MAX] = {
{-1, -2, -1},
{0, 0, 0},
{1, 2, 1}
};
// Loop through each pixel
for (int Rows = 0; Rows < height; Rows++)
{
for (int Cols = 0; Cols < width; Cols++)
{
// Hold RGB Values + Refresh Current Pixel RGB
int CRed = 0, CGreen = 0, CBlue = 0;
// Store Gx and Gy RGB Values
GTOTALS X;
GTOTALS Y;
// Loop through surrouding pixels
for (int S_Rows = Rows - 1, R = 0; S_Rows <= Rows + 1; S_Rows++, R++)
{
for (int S_Cols = Cols - 1, C = 0; S_Cols <= Cols + 1; S_Cols++, C++)
{
// Check Pixel Validity
if ((S_Rows >= 0) && (S_Rows < height) && (S_Cols >= 0) && (S_Cols < width))
{
// RGB Gx Total Values
X.Red += Copy[S_Rows][S_Cols].rgbtRed * Gx[R][C]; // Current Pixel Red * Gx[N][N]
X.Green += Copy[S_Rows][S_Cols].rgbtGreen * Gx[R][C]; // Current Pixel Green * Gx[N][N]
X.Blue += Copy[S_Rows][S_Cols].rgbtBlue * Gx[R][C]; // Current Pixel Blue * Gx[N][N]
// RGB Gy Total Values
Y.Red += Copy[S_Rows][S_Cols].rgbtRed * Gy[R][C]; // Current Pixel Red * Gy[N][N]
Y.Green += Copy[S_Rows][S_Cols].rgbtGreen * Gy[R][C]; // Current Pixel Green * Gy[N][N]
Y.Blue += Copy[S_Rows][S_Cols].rgbtBlue * Gy[R][C]; // Current Pixel Blue * Gy[N][N]
}
}
}
// Value = Square Root(Gx^2 + Gx^2)
CRed = round( sqrt( pow(X.Red, 2.0) + pow(Y.Red, 2.0) ) );
CGreen = round( sqrt( pow(X.Green, 2.0) + pow(Y.Green, 2.0) ) );
CBlue = round( sqrt( pow(X.Blue, 2.0) + pow(Y.Blue, 2.0) ) );
// MAX 255
Cap(&CRed);
Cap(&CGreen);
Cap(&CBlue);
// Update Target Pixel
image[Rows][Cols].rgbtRed = CRed;
image[Rows][Cols].rgbtGreen = CGreen;
image[Rows][Cols].rgbtBlue = CBlue;
}
}
return;
}
void Cap(int *Value)
{
if (*Value > 255)
{
*Value = 255;
}
}
When I run the prograM most of the RGB values turn out to be 255. I've played around with using different data types and moving around when variables are created but that doesn't seem to help. I've also tried miniature versions of the code and all seems to work as intended but not sure why when I add it together it doesn't seem to give the correct results
Here is description of Sobel filter
// from Source to Destination
int ComputeBoundaries(unsigned char S[], unsigned char D[])
{
unsigned int iX,iY; /* indices of 2D virtual array (image) = integer coordinate /
unsigned int i; / index of 1D array /
/ sobel filter */
unsigned char G, Gh, Gv;
// boundaries are in D array ( global var )
// clear D array
memset(D, iColorOfBasin1, iSize*sizeof(*D)); // for heap-allocated arrays, where N is the number of elements = FillArrayWithColor(D , iColorOfBasin1);
// printf(" find boundaries in S array using Sobel filter\n");
#pragma omp parallel for schedule(dynamic) private(i,iY,iX,Gv,Gh,G) shared(iyMax,ixMax)
for(iY=1;iY<iyMax-1;++iY){
for(iX=1;iX<ixMax-1;++iX){
Gv= S[Give_i(iX-1,iY+1)] + 2S[Give_i(iX,iY+1)] + S[Give_i(iX-1,iY+1)] - S[Give_i(iX-1,iY-1)] - 2S[Give_i(iX-1,iY)] - S[Give_i(iX+1,iY-1)];
Gh= S[Give_i(iX+1,iY+1)] + 2S[Give_i(iX+1,iY)] + S[Give_i(iX-1,iY-1)] - S[Give_i(iX+1,iY-1)] - 2S[Give_i(iX-1,iY)] - S[Give_i(iX-1,iY-1)];
G = sqrt(GhGh + GvGv);
i= Give_i(iX,iY); /* compute index of 1D array from indices of 2D array /
if (G==0) {D[i]=255;} / background /
else {D[i]=0;} / boundary */
}
}
return 0;
}
// copy from Source to Destination
int CopyBoundaries(unsigned char S[], unsigned char D[])
{
unsigned int iX,iY; /* indices of 2D virtual array (image) = integer coordinate /
unsigned int i; / index of 1D array */
//printf("copy boundaries from S array to D array \n");
for(iY=1;iY<iyMax-1;++iY)
for(iX=1;iX<ixMax-1;++iX)
{i= Give_i(iX,iY); if (S[i]==0) D[i]=0;}
return 0;
}
Here is the image and a full program
result:
I have 3d array stored in .txt file that looks like this (720x1280 with image pixels locations stored in python, 1st number is x, second is y)(shorten):
[[[ 253 122]
[ 253 121]
[ 253 121]
...
[1027 119]
[1027 120]
[1028 120]]
[[ 252 122]
[ 253 122]
[ 253 122]
...
[1067 573]
[1067 573]
[1067 573]]]
First: So now I have to read this file and store this integers in 1d array.
Second: Use it on input image to remap it. Input image is represented with 1d array with 720x1280 elements.
This is example of rotating input image. I have to do remap with loaded pixels locations from file.
for(rowIdx = 0; rowIdx < height; rowIdx++)
{
for(colIdx = 0; colIdx < width; colIdx++)
{
temp = inputPtr[rowIdx * width + colIdx];
inputPtr[rowIdx * width + colIdx] = inputPtr[height * width - rowIdx * width - colIdx];
inputPtr[height * width - rowIdx * width - colIdx] = temp;
}
}
Solved, allocated array for 12843200 elements, took x,y and got exact location and saved it to array file:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main(void)
{
int *array;
array = (int*)malloc(1843200 * sizeof(int));
int i = 0;
FILE *file;
FILE *f = fopen("array.txt", "w+");
if (file = fopen("file1.txt", "r"))
{
while (fscanf(file, "%d", &array[i]) != EOF)
{
i++;
}
fclose(file);
array[i] = '\0';
//for (i = 0; i < 30;i++){
for (i = 0; array[i] != '\0'; i++){
if(i % 2 != 0){
printf("%d, ", array[i] * 1280 + array[i-1]);
fprintf(f,"%d, ",array[i] * 1280 + array[i-1]);
}
}
}
fclose(f);
free(array);
return 0;
}
and also removed brackets from input file so it only separated with spaces.
I'm trying to practice C by writing a memory-type card game. The game is compiled by gcc on ARMv8. The user enters a number "users_N" in the argument line and a board of cards is created size: 2N x 2N.
The program runs just fine when the number is 1 or 2. But if it's 3 or bigger, I get a segmentation fault when trying to initialize the board. I thought this meant it was a stack overflow, but I increased the stack size to unlimited on my SSH and the problem was not resolved. I don't think it's a problem with pointers or trying to access an array out-of-bounds either, as it runs just fine until after 10 cards are added to the array.
The print statements are just to determine exactly when the segfault occurs.See image of for loop segfault
EDIT: to add more context... I know it's a bit messy, sorry!
int main(int argc, char *argv[]) {
if (argc < 3){ //Checking user's command line input.
printf("Missing argument. Exiting... \n");
return 0;
}
users_N = atoi(argv[2]);
srand(time(NULL)); //Initialize random number generator.
int ***board = (int ***)malloc(2 * users_N * sizeof(int)); //Dynamic array to store the board values
for (int i = 0; i < 2 * users_N; i++){
board[i] = (int **)malloc(2 * users_N * sizeof(int)); /*Array of pointers (rows) filled with
an array (columns). */
for (int j = 0; j < 2 * users_N; j++){
board[i][j] = (int *)malloc(2 * sizeof(int)); //3rd dimension to show/hide cards.
}
}
initialize(board);
}
/*
* Function initialize sets up the board. It takes the 3D board array. A card deck is created the
* size of 2N^2, then shuffled and added to the board. The 3rd dimension is initialized
* completely to 1, so all cards are shown. There is no return.
*/
void initialize(int*** board){
int* cards = (int *)malloc(2 * users_N * users_N * sizeof(int)); //Create an array of cards.
printf("Cards created\n");
for (int c = 0; c < (2 * users_N * users_N); c++){
printf("card: %d\n",c);
cards[c]=c;
}
int half = 0;
while (half < 2){ //Divide up into 2 halves of the board, to repeat shuffle and card placement.
shuffle(cards);
int cardsNum = 0;
for (int j = 0; j < users_N; j++){ //For each row in the current half:
printf("\n row = %d ", j);
for (int k = 0; k < (users_N * 2); k++){ //For each column:
printf("col = %d ",k);
board[j + (half * users_N)][k][0] = cards[cardsNum]; /* Assign appropriate
card to each board
position. */
printf("set to: %d ", board[j + (half * users_N)][k][0]);
board[j + (half * users_N)][k][1] = 1;
cardsNum++;
printf("Card num: %d \n", cardsNum);
}
}
half++; //Moves to next half to repeat.
}
}
/*
* Function shuffle takes the array of cards as a parameter. It will then randomly mix array.
* Numbers are not repeated and will not exceed 2N*N-1. No return values.
*/
void shuffle(int *cards){
int j;
for (int k = 0; k < (2 * users_N * users_N) - 2; k++){
j = randomNum(k, (2 * users_N * users_N) - 1); //Assign a random number between k and 2N*N-1.
swap(cards, k, j);
printf("cards swapped: %d,%d\n",k,j);
}
}
/*
* Function swap takes the array of cards, two index integers. The index integers indicate the positions of
* the elements (cards) to switch. No return values.
*/
void swap(int *cards, int i, int j){
int temp = cards[i]; //Value of position i stored in temp.
cards[i] = cards[j]; //value of card j assigned to card i.
cards[j] = temp; //Value of temp assigned to card j.
}
Allocation of your board is wrong:
int ***board = (int ***)malloc(2 * users_N * sizeof(int));
^^^^^^^^^^^
wrong size
for (int i = 0; i < 2 * users_N; i++){
board[i] = (int **)malloc(2 * users_N * sizeof(int));
^^^^^^^^^^^
wrong size
...
}
When you have board as int *** you don't want size of int during first allocation. You want size of int **. Like
int ***board = malloc(2 * users_N * sizeof(int**));
A better approach is to use the variable name - like:
int ***board = malloc(2 * users_N * sizeof *board);
^^^^^^
Better approach
to get correct size
The same applies to the next malloc
The following code was given to me by my instructor. I just don't understand how this is scaling a bmp image. I know the basics about bmp images (the info on wikipedia). I know that this method is supposed to multiply the rows and cols of the new image by whatever scale is. I tried to run the code by hand but it confused me even more. Any help will be much appreciated. Thanks!
int enlarge(PIXEL* original, int rows, int cols, int scale,
PIXEL** new, int* newrows, int* newcols)
{
//scaling the new rows & cols
*newcols = cols * scale;
*newrows = rows * scale;
//memory allocated for enlaged bmp
*new = (PIXEL*)malloc(*newrows * *newcols * sizeof(PIXEL));
int row, col, sx, sy;
//transverse through every row
for (row = 0; row < rows; row++ )
//transvere through every col
for (col = 0; col < cols; col++ ){
//im unsure what this is for
PIXEL* o = original + (row * cols) + col;
for(sy = 0; sy < scale; sy++ )
for(sx = 0; sx < scale; sx++ )
{
//im unsure what this is for
PIXEL* n = *new + (scale * row) * *newcols + (scale * col) + (sy * *newcols) + sx;
*n = *o;
}
}
return 0;
}
Here is the struct for PIXEL.
typedef struct {
unsigned char r;
unsigned char g;
unsigned char b;
} PIXEL;
There is additional code but I do not think that is needed for this question.
PIXEL* o = original + (row * cols) + col;
Here he is retrieving a pointer to the source pixel in the original image; it's just trivial pointer arithmetic, based on the fact that the rows in the bitmap are consecutive in memory. In general, in a C-style matrix width-wide the address of the element (x, y) is beginning + (y * width) + x.
Then, he loops over a square scale x scale wide in the target image.
for(sy = 0; sy < scale; sy++ )
for(sx = 0; sx < scale; sx++ )
{
//im unsure what this is for
PIXEL* n = *new + (scale * row) * *newcols + (scale * col) + (sy * *newcols) + sx;
The n pointer points to the target pixel in the destination image; if you match the formula above from the source image and rearrange a bit the terms, you'll see he is accessing the new image, at position
(scale * col + sx, scale * row + sy)
(remember that the new image is *newcols wide).
*n = *o;
Here he's just copying the source pixel to the target pixel.
In practice, he's "expanding" each source pixel into a scale x scale square in the target image.
I have the following problem with rotating the PPM image to the right
The first two lines in the result image are black (or some color from the rainbow)
Here's the code that sets the buffer for the image (the variables g_Width and g_height are set by a function)
struct pixel *image = malloc(sizeof(struct pixel) * g_width * g_height);
here's the function with the pointer passed into it
void rotate90(struct pixel *img) {
int i, j, size, th;
size = sizeof(struct pixel) * g_width * g_height;
struct pixel *buffer = malloc(size);
if (buffer == NULL) {
fprintf(stderr, "Unable to allocate memory\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < g_height; i++) {
for (j=0; j < g_width; j++) {
buffer[(g_height*j)+(g_height-i)] = img[(g_width*i) + j];
}
}
//copy the buffer into the image pointer
memcpy(img, buffer, size);
//free the buffer and swap the width and height around
free(buffer);
th = g_height;
g_height = g_width;
g_width = th;
}
If I print the image buffer it comes out just fine, but if I rotate it it comes out like this (note the first 2 lines of pixels)
https://www.dropbox.com/s/vh8l6s26enbxj42/t3.png?dl=0
it's as if the last 2 lines aren't being swapped at all, please help
EDIT: I solved the second black line at least, but I still need help with the
last line
As said you mix the first line (and overflow)
void rotate90(struct pixel *img) {
int i, j, size, th;
size = sizeof(struct pixel) * g_width * g_height;
struct pixel *buffer = malloc(size);
if (buffer == NULL) {
fprintf(stderr, "Unable to allocate memory\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < g_height; i++) {
for (j=0; j < g_width; j++) {
buffer[(g_height*j)+(g_height-i -- 1)] = img[(g_width*i) + j];
}
}
//copy the buffer into the image pointer
memcpy(img, buffer, size);
//free the buffer and swap the width and height around
free(buffer);
th = g_height;
g_height = g_width;
g_width = th;
}
This would rotate it one way (removing unnecessary brackets)
for (i=0; i<g_height; i++) {
for (j=0; j<g_width; j++) {
buffer[g_height * j + i] = img[g_width * i + j];
}
}
But your code suggest you want it the other way, and the code lacks a -1, resulting in clipping a line at one edge and an undefined line at the other edge.
for (i=0; i<g_height; i++) {
for (j=0; j<g_width; j++) {
buffer[g_height * j + g_height - i - 1] = img[g_width * i + j];
}
}