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];
}
}
Related
I've been breaking my head over this issue, VScode gives me this weird warning about malloc calculations
c6385 "Severity Code Description Project File Line Suppression State
Warning C6385 Reading invalid data from 'temp': the readable size is 'sizeof(int *)*width_flag' bytes, but '16' bytes may be read"
And again with
Warning C6386 Buffer overrun while writing to 'temp': the writable size is 'sizeof(int *)*width_flag' bytes, but '16' bytes might be written"
I think I am doing mallloc and free by the book and still this comes up
the code
poolList_t* pools_f(pixmat** mtrx, image_t image, poolList_t* pools, int width_flag) {
int i, j, size;
int** temp = NULL;
pix_t* root = NULL;
co_t center;
if (sizeof(int*) * width_flag > 0)
temp = malloc(sizeof(int*) * width_flag); //alocating memory for matrix which will contain 1/0 for each blue/non-blue pixel
if (temp) {
if (sizeof(int) * image.height > 0)
for (i = 0;i < width_flag; i++) {
temp[i] = malloc(sizeof(int) * image.height);
}// allocate memory to temp color signed matrix
}
if (temp != 0)
{
for (i = 0; i < image.height; i++) {
for (j = 0;j < width_flag;j++) {
if (mtrx[j][i].color.r == 155 && mtrx[j][i].color.g == 190 && mtrx[j][i].color.b == 245) { // Registering blue and non-blue pixel to 2d matrix named temp
temp[j][i] = 1;
}
else {
temp[j][i] = 0;
}
}
}
for (i = 0;i < image.height;i++) {
for (j = 0;j < width_flag;j++) {
if (temp[j][i] == 1) { //Going over all the pixels in the matrix and checking if it is blue or not
size = 1;
temp[j][i] = 0;
pix_insert(&root, mtrx[j][i].cordinate); //saving the blue pixel to the head of linked list
segment(root, mtrx, temp, image, i, j, &size); //entering to Image segmentation function to find adjacent blue pixels
if (size > 9) {
center = pool_middle(root, size);
pool_insert(&pools, size, center, root); //saving the pool to linked list ONLY if it has size of 10 or more
}
}
deallocpix(&root); //deallocting the memory of the pixel's linked list
}
}
for (i = 0;i < width_flag;i++) {
free(temp[i]); //deallocating temp matrix memory
}
free(temp);
return pools;
} else
return pools;
}
the structs I use
typedef struct pool { //pools' list extructed of bmp
int size; //the number of pixels that combine the pool
co_t pool_center;
pix_t* pix; //list of pool pixels
struct pool* next;
}poolList_t;
typedef struct pixel { //list of pixels
co_t p;
struct pixel* next;
}pix_t;
typedef struct { //pixel's coordinates
int x;
int y;
}co_t;
typedef struct { // struct to contain each pixel color & coordinates
color_t color;
co_t coordinate;
} pixmat;
Using arrays of pointers adds unnecesary indirection. Use array pointers
if(width_flag && image.height)
{
int (*temp)[image.height];
temp = malloc(sizeof(*temp) * width_flag); //alocating memory for matrix which will contain 1/0 for each blue/non-blue pixel
}
My function is getting an Image and I am trying to crop the BMP image
by size: 100 x 100, 200 x 200, 300 x 300, 400 x 400 by Pixels ,
i don't know what to do make it work. please help me
The size of the image is int height and int width and the function knows the values in pixels.
Here is my code:
void re_allocate_pixels(struct RGB_Image *image, int new_height, int new_width)
{
int org_height = image->height;
int org_width = image->width;
int org_size = image->size;
int i;
struct Pixel **pxls;
pxls = (struct Pixel **)malloc((org_height) * sizeof(struct Pixel *));
if (pxls == NULL)
{
printf("Memory allocation failed\n");
exit(1);
}
for (i = 0; i < org_height; i++)
{
pxls[i] = (struct Pixel *)malloc(org_width * sizeof(struct Pixel));
if (pxls[i] == NULL)
{
printf("Memory allocation failed\n");
exit(1);
}
}
//i have no idea what to do next to crop the image and pixecl
/*for (int j = 0; j < org_height; j++)
{
for (int k = 0; k < org_width; k++)
{
pxls[i][j] = pxls[k][j];
}
}*/
}
here are struct data:
struct Pixel
{
unsigned char red;
unsigned char green;
unsigned char blue;
};
struct RGB_Image
{
char file_name[MAX_FILE_NAME_SIZE];
long height;
long width;
long size;
struct Pixel **pixels;
};
here is how am calling this function
struct RGB_Image *rgb_img_ptr;
struct RGB_Image image;
rgb_img_ptr = ℑ
int image_load_ret_value = load_image(rgb_img_ptr);
re_allocate_pixels(rgb_img_ptr, 100,100); // here is calling
You have to delete the old allocation and also assign the new size value. size usually refers to "width in bytes" multiplied by height.
In this case the value for "width in bytes" should be "width * 3", and it should always be a multiple of 4.
Read the image one row at a time. Use mempcy to copy each row.
Note that bitmaps are usually upside down. You may have to change the loop to for (int y = dst.height - 1; y >=0; y--){memcpy...}
void re_allocate_pixels(struct RGB_Image *image, int new_height, int new_width)
{
if(new_width > image->width) return;
if(new_height > image->height) return;
struct RGB_Image *src = image;
struct RGB_Image dst;
dst.width = new_width;
dst.height = new_height;
//allocate memory
dst.pixels = malloc(dst.height * sizeof(struct Pixel*));
for(int y = 0; y < dst.height; y++)
dst.pixels[y] = malloc(dst.width * sizeof(struct Pixel));
//copy from source to destination
for(int y = 0; y < dst.height; y++)
memcpy(dst.pixels[y], src->pixels[y], dst.width * sizeof(struct Pixel));
//free the old allocation
for(int y = 0; y < src->height; y++)
free(image->pixels[y]);
free(image->pixels);
//assing new allocation
image->pixels = dst.pixels;
//set the new width, height, size
image->width = dst.width;
image->height = dst.height;
int bitcount = 24;
int bytecount = 3; //<- same as sizeof(struct Pixel)
//calculate width in bytes
int width_in_bytes = ((dst.width * bitcount + 31) / 32) * 4;
image->size = width_in_bytes * dst.height;
}
I am trying to extract the RGB components from a bmp file but I am getting a seg fault when it gets to Data[i][j].Blue. I try printing out the hex of the three colors and it prints them out good but then it prints out that all RGB components are 0xFF and then it seg faults when it gets to the blue. Any help I get is greatly appreciated.
int inputColors(char *filename, struct INFOHEADER *InfoHeader, struct PIXEL **Data){
int i = 0, j = 0;
FILE *inputFile;
printf("The height of the picture is %d\n", InfoHeader->Height);
printf("The width of the picture is %d\n", InfoHeader->Width);
if((inputFile = fopen(filename, "r")) == NULL){
printf("Unable to open .bmp file\n");
exit(1);
}
//Mallocing enough space for the 2D structures of pixels (colors)
Data = (struct PIXEL **)malloc(InfoHeader->Width * sizeof(struct PIXEL *));
for(i = 0; i < InfoHeader->Height; i++){
Data[i] = (struct PIXEL *)malloc(InfoHeader->Height * InfoHeader->Width * sizeof(struct PIXEL));
}
//This goes until after we are down with the header
fseek(inputFile, 54, SEEK_SET);
//Inputing the data into the malloced struct
i = 0;
for(i = 0; i < InfoHeader->Height; i++){
for(j = 0; j < InfoHeader->Width; j++){
Data[i][j].Red = getc(inputFile);
// printf("The Red componet is %X\n", Data[i][j].Red);
Data[i][j].Green = getc(inputFile);
// printf("The green componet is %X\n", Data[i][j].Green);
Data[i][j].Blue = getc(inputFile);
// printf("The blue componet is %X\n", Data[i][j].Blue);
}
}
fclose(inputFile);
return 0;
}
Well for starters, your first malloc uses
InfoHeader->Width * sizeof(struct PIXEL *)
But then you use InfoHeader->Height when iterating over the array. Because of this mismatch, If InfoHeader->Width is smaller than InfoHeader->Height, it will not allocate enough memory to perform the iteration, and it will SEGFAULT.
Data = (struct PIXEL **)malloc(InfoHeader->Width * sizeof(struct PIXEL *));
// ^^^^^
for(i = 0; i < InfoHeader->Height; i++){
// ^^^^^^
Data[i] = (struct PIXEL *)malloc(InfoHeader->Height * InfoHeader->Width * sizeof(struct PIXEL));
}
I'm trying to write a program to blur an image, but first of am trying to see if I can even reproduce the image, pixel by pixel, in another file. I've allocated a 2-dimensional char array to hold the value of each pixel in the image.
Note: The image is in grayscale, and it is of type .raw
However, whenever I attempt to read the pixels into my 2D array, my program crashes. I feel like it has something to do with me not looping through the dimensions of the image correctly, but I'm not sure.
Code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fin, *fout;
char path_in[64], path_out[64], **rev, px;
int width, height, read, i, j;
printf("Input file name: ");
scanf("%s", path_in);
printf("Output file name: ");
scanf("%s", path_out);
printf("Width of image (in pixels): ");
scanf("%d", &width);
printf("Height of image (in pixels): ");
scanf("%d", &height);
fin = fopen(path_in, "rb");
fout = fopen(path_out, "wb");
row = 0;
rev = (char **)malloc(height * sizeof(char));
for(i = 0; i < width; i++)
rev[i] = (char *)malloc(width * sizeof(char));
for(i = 0; i < height; i++)
{
for(j = 0; j < width; j++)
{
read = fread(&px, sizeof(char), 1, fin);
rev[i][j] = px;
}
}
fclose(fout);
fclose(fin);
return 0;
}
My program is pretty narrow, as it only accepts grayscale .raw image type.
Change these lines as this:
row = 0;
rev = malloc(height * sizeof *rev);
for(i = 0; i < width; i++)
rev[i] = malloc(width * sizeof **rev);
You were allocating memory for height chars, not for height pointers to chars, as you intended.
Also, don't cast the result of malloc if developing with C
This line: rev = (char **)malloc(height * sizeof(char));
should be rev = (char **)malloc(height * sizeof(char*));
I think is better to use contiguous memory to manage the image!
Using char ** in the way as in your code you don't have a block of memory that contains the whole image, but a lot of not contiguous vectors each one containing a line!
The following code reads the image in a contiguous block of memory using only one malloc:
char * rev;
/* HERE your code to insert width and height */
rev = malloc(height * width *sizeof(char));
if (rev==NULL) {
/* Ops! The buffer is not allocated!!! */
}
/* HERE you open the file and so on */
for(i = 0; i < height; i++)
{
for(j = 0; j < width; j++)
{
read = fread(&rev[i*width+j], sizeof(char), 1, fin);
if (read!=1) { /* 1 is the number of bytes fread reads if ok */
/* Ops, there's a problem! The fread didn't read! */
}
}
}
Using char * you might load all the image with one fread, thus avoiding the two for loops :)
fread(rev,witdh,height,fin);
In this way you may point each single pixel using:
rev[y*width+x];
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.