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;
}
Related
I'm trying to implement Hough algorithm using C programming language and 2D raw image.
I have written the code in order to get separate output image for edge detection and Hough transform. When I do edge detection only I'm getting the proper edge detected output image. But here I'm getting the output raw image of size 0KB.I'm not getting where I made mistake.
Can anybody please help me to rectify this problem and give idea for further development such as draw line based on Hough space for the below code.
Thank you in advance.
#include <stdio.h>
#include <math.h>
#define PI 3.14159265
void
hough_transform(unsigned char out[256][256], unsigned char h_out[][256],
int w, int h)
{
int i, j;
int thetaDeg;
float thetaRad;
int rho;
int distMax;
int thetamax;
distMax = sqrt((h * h) + (w * w));
thetamax = 360;
int Acc[180][180];
for (i = 0; i < w; i++) {
for (j = 0; j < h; j++) {
if (out[i][j] > 0) {
for (thetaDeg = 0; thetaDeg < thetamax; ++thetaDeg) {
thetaRad = thetaDeg * (PI / 180);
rho = i * cos(thetaRad) + j * sin(thetaRad);
// find rho value that is closest to this
if (distMax < rho) {
int min = abs(rho - distMax);
}
if (distMax <= 1) {
// Increment a value in an accumulator array
Acc[rho][thetaDeg] += 1;
}
}
}
}
}
for (rho = 0; rho < distMax; rho++) {
for (thetaDeg = 0; thetaDeg < thetamax; thetaDeg++) {
h_out[rho][thetaDeg] = Acc[rho][thetaDeg];
}
}
}
void
edge_detect(unsigned char input[256][256], unsigned char out[][256],
int width, int height)
{
int in[3][3] = { {1, 2, 1}, {0, 0, 0}, {-1, -2, -1} };
int pixel;
int i;
int j;
int x;
int y;
for (y = 1; y < height - 1; y++) {
for (x = 1; x < width - 1; x++) {
pixel = 0;
for (j = -1; j <= 1; j++) {
for (i = -1; i <= 1; i++) {
pixel += in[j + 1][i + 1] * input[y + j][x + i];
}
}
out[y][x] = (unsigned char) abs(pixel);
}
}
}
int
main()
{
FILE *fp;
FILE *fp1;
FILE *fp2;
unsigned char input[256][256];
unsigned char out[256][256];
unsigned char h_out[256][256];
int width = 256;
int height = 256;
fp = fopen("Image.raw", "rb");
fp1 = fopen("output.raw", "wb");
fp2 = fopen("h_output.raw", "wb");
fread(input, 256 * 256, 1, fp);
edge_detect(input, out, width, height);
hough_transform(out, h_out, width, height);
fwrite(out, 256 * 256, 1, fp1);
fwrite(h_out, 256 * 256, 1, fp2);
fclose(fp);
fclose(fp1);
fclose(fp2);
return (0);
}
I'm trying to write a program that reads a text file into a 2D array of structs, but trying to put a struct into that array causes the program to crash.
Here's the program
ppm.c
#include "ppm.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
image parse_ascii_image(FILE *fp) {
char magic[3];
char comm[1024];
char size[10];
image img;
int height;
int width;
... // some code
pixel **pixelarr;
printf("Commencing internal malloc...\n");
if (height <= 1024 && width <= 1024 && height > 0 && width > 0){
pixelarr = (pixel **) malloc(height * sizeof(pixel*));
}else{
fprintf(stderr, "Error: Invalid image size: %d * %d", width, height);
return img;
}
for (int i = 0; i < height; i++){
pixelarr[i] = malloc(width * sizeof(pixel));
}
int d = 0;
int e;
printf("Filling in array:\n");
for (int row = 0; row < height; row++){
for (int col = 0; col < width; col++){
for (int i = 0; i < 3; i++){
while ((e = fgetc(fp)) != '\n'){
d = d * 10;
e = e - 60;
d += e;
}
if (i == 0){
pixelarr[row][col].red = d;
}
if (i == 1){
pixelarr[row][col].green = d;
}
if (i == 2){
pixelarr[row][col].blue = d;
}
d = 0;
}
}
}
printf("Finished! Copying pixels over: \n");
for (int row = 0; row < height; row++){
for (int col = 0; col < width; col++){
img.pixels[row][col] = pixelarr[row][col];
// ^^^This is where the program crashes
}
}
printf("Finished! Freeing internal malloc:\n");
... // some more code
}
relevant info from ppm.h:
#ifndef PPM_H
#define PPM_H 1
#include <stdio.h>
...
typedef struct pixel pixel;
struct pixel {
int red;
int green;
int blue;
};
typedef struct image image;
struct image {
enum ppm_magic magic; // PPM format
char comments[1024]; // All comments truncated to 1023 characters
int width; // image width
int height; // image height
int max_color; // maximum color value
pixel **pixels; // 2D array of pixel structs.
};
...
// Parses an ASCII PPM file.
image parse_ascii_image(FILE *fp);
...
#endif
If anyone can help me figure out what's causing my program to crash there, I would appreciate it.
Thank you!
A few problems:
1: img.pixels is never initialized. Anytime you create a pointer to something without assigning it a value first, try to set it to NULL so it's easier to debug. Note that this will not fix the issue. To fix it, simply initialize them with a struct instance.
2: You should free pixelarr. Most modern OS's do this, but it's still really, really good practice.
3: Wouldn't it be easier to not use the nested loops, and instead do img.pixels = pixelarr? It achieves the same (unless this is for a class, and this part is required).
I am trying to load a font (arial) from a .ttf file and using the STB TrueType library: https://github.com/nothings/stb/blob/master/stb_truetype.h and display it on the screen.
It is working when displaying the 1st letter in the characters array 'a', but every character after that it looks all distorted and weird, see example below
Comes out as 'a' (correct):
Should be 'b':
I think maybe I am misunderstanding/misapplying how the memory ends up being laid out, or how the file is being read?
Here is the relevant code:
(In win32 platform layer file)
struct character_bitmap
{
unsigned char* memory;
int width;
int height;
};
struct font_buffer
{
character_bitmap* memory;
float size;
};
static font_buffer font_bitmaps;
void test_load_arial(float size)
{
if (font_bitmaps.memory)
{
// VirtualFree(font_bitmaps.memory, 0, MEM_RELEASE);
free(font_bitmaps.memory);
}
unsigned char* ttf_buffer = (unsigned char*)malloc(1 << 25);
stbtt_fontinfo font;
fread(ttf_buffer, 1, 1 << 25, fopen("c:/windows/fonts/arialbd.ttf", "rb"));
stbtt_InitFont(&font, (unsigned char*)ttf_buffer, stbtt_GetFontOffsetForIndex((unsigned char*)ttf_buffer, 0));
// int char_bitmap_width = (int)size;
// int char_bitmap_height = (int)size;
// unsigned int character_memory_size = ((int)size * (int)size) * 4 /*+ 8*/;
// int font_memory_size = character_memory_size * 52;
unsigned int font_memory_size = sizeof(character_bitmap) * 52;
// font_bitmaps.memory = (character_bitmap*)VirtualAlloc(0, font_memory_size, MEM_COMMIT, PAGE_READWRITE);
font_bitmaps.memory = (character_bitmap*)malloc(font_memory_size);
char alphabet[53] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
character_bitmap* current_character = font_bitmaps.memory;
for (int i = 0; i < 52; i++)
{
// current_character->width = char_bitmap_width;
// current_character->height = char_bitmap_height;
current_character->memory = stbtt_GetCodepointBitmap(&font, 0, stbtt_ScaleForPixelHeight(&font, size), alphabet[i],
¤t_character->width, ¤t_character->height, 0, 0);
current_character++;
}
}
(In different file, inside main update and render function which gets called every frame I call this function)
void test_render_text(offscreen_buffer* buffer, font_buffer* font_bitmaps)
{
int width = font_bitmaps->memory[0].width;
int height = font_bitmaps->memory[0].height;
unsigned char* dest_row = (unsigned char*)buffer->memory
unsigned char* source = font_bitmaps->memory[42].memory;
for (int y = 0; y < height; y++)
{
unsigned int* dest_pixel = (unsigned int*)dest_row;
for (int x = 0; x < width; x++)
{
unsigned char alpha = *source;
*dest_pixel = ((alpha << 24)
| (alpha << 16)
| (alpha << 8)
| (alpha << 0));
dest_pixel++;
source++;
}
dest_row += buffer->pitch;
}
}
Also posted on github if you want the full source to review/compile:
https://github.com/jackson-lenhart/loji
I am trying to create an image from a float * array. However, MagickConstituteImage constantly segfaults. Here is a summary of the relevant code (the problem occurs in the function writeRawImage()):
#include <stdio.h>
#include <stdlib.h>
#include <wand/MagickWand.h>
#define COLOR_MAX 65535.0
typedef struct {
float **px;
unsigned long width;
unsigned long height;
} RawPixels;
RawPixels getRawImage (char *path)
{
MagickWand *mw;
MagickBooleanType status;
PixelIterator *iter;
MagickPixelPacket pixel;
PixelWand **pixels;
RawPixels rp;
long x;
long y;
unsigned long width;
unsigned long count;
MagickWandGenesis();
mw = NewMagickWand();
status = MagickReadImage(mw, path);
rp.px = NULL;
if (status == MagickFalse) {
return rp;
}
iter = NewPixelIterator(mw);
if (iter == (PixelIterator *) NULL) {
return rp;
}
rp.width = 0;
rp.height = (unsigned long) MagickGetImageHeight(mw);
count = 0;
for (y = 0; y < rp.height; y++) {
pixels = PixelGetNextIteratorRow(iter, &width);
rp.width = (unsigned long) width;
if (rp.px == NULL) {
rp.px = malloc(sizeof(float *) * (width * rp.height + 1));
}
if (pixels == (PixelWand **) NULL) {
break;
}
for (x = 0; x < (long) width; x++) {
count++;
rp.px[count - 1] = malloc(sizeof(float) * 3);
PixelGetMagickColor(pixels[x], &pixel);
rp.px[count - 1][0] = pixel.red / COLOR_MAX;
rp.px[count - 1][1] = pixel.green / COLOR_MAX;
rp.px[count - 1][2] = pixel.blue / COLOR_MAX;
}
}
rp.px[count] = NULL;
return rp;
}
void freeRawImage (RawPixels rp)
{
for (int i = 0; rp.px[i] != NULL; i++) {
free(rp.px[i]);
}
free(rp.px);
}
void writeRawImage (RawPixels rp, char *path)
{
// This function is the one that gives me a headache.
// Basically, I take float **rp.px, which has the following structure
// at this point:
//
// {
// {float red, float green, float blue},
// {float red, float green, float blue},
// ...
// }
//
// Now, the documentation at https://www.imagemagick.org/api/magick-image.php#MagickConstituteImage
// says the following:
//
// "The pixel data must be in scanline order top-to-bottom"
//
// So up until the call to MagickConstituteImage() I am trying
// to restructure the data and write it into float *scanline
// to satisfy that requirement. However, once I call
// MagickConstituteImage(), my program segfaults.
MagickWand *mw;
float *scanline;
unsigned long pxcount;
for (pxcount = 0; rp.px[pxcount] != NULL; pxcount++);
pxcount *= 3;
scanline = malloc(sizeof(float) * pxcount);
pxcount = 0;
for (int i = 0; rp.px[i] != NULL; i++) {
for (int j = 0; j < 3; j++) {
scanline[pxcount++] = rp.px[i][j];
printf("%f\n", scanline[pxcount - 1]);
}
}
// This function causes a segfault
MagickConstituteImage(mw, rp.width, rp.height, "RGB", FloatPixel, scanline);
free(scanline);
}
int main ()
{
RawPixels rp;
if ((rp = getRawImage("samples/tiny-white.png")).px == NULL) {
fprintf(stderr, "ERROR: Failed to process image\n");
return 1;
}
// Some image processing using raw pixels here
writeRawImage(rp, "previews/preview.jpg");
freeRawImage(rp);
return 0;
}
You're not initializing
MagickWand *mw;
in the function writeRawImage(...) before using it in MagickConstituteImage(...)
I am trying to apply DCT(discrete cosine transformation) compression on a bmp(bitmap) file. I have a c file which i am running in Turbo C++. This is not actually compressing but i was trying to implement the DCT and IDCT. The code is as follows:
/*
the image to be compressed is a bmp with 24 bpp and
with name "college4.bmp" of dimensions 200*160 ie 25*20- 8*8 blocks
o/p is college2.dat
format: 8 bit signed integers starting rowwise from 0,0 to 8,8
the coefficients order is blue,green,red
for the block no 1 then 2 and soon
*/
#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#define WIDTH 25
#define HEIGHT 20
typedef struct {
unsigned int type;
unsigned long int filesize;
unsigned int reserved1,reserved2;
unsigned long int offset;
} BMPHEAD;
typedef struct {
unsigned long int infosize;
unsigned long int width,height;
unsigned int planes,bitsperpixel;
unsigned long int compression;
unsigned long int sizeimage;
long int xpelspermeter,ypelspermeter;
unsigned long int colorused,colorimportant;
} INFOHEAD;
typedef struct {
char rgbquad[4];
} colortable;
BMPHEAD bmphead;
INFOHEAD infohead;
FILE *bmp_fp1,*bmp_fp2;
int buf[WIDTH][8][8][3],buf1[WIDTH][8][8][3];
float pi=3.14159265,DCTcoeff[8][8][8][8];
void generatedctcoeff() {
int y, i, j, x;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
for (x = 0; x < 8; x++) {
for (y = 0; y < 8; y++) {
DCTcoeff[i][j][x][y] = cos(((2 * y + 1) * pi * j) / 16)
* cos(((2 * x + 1) * i * pi) / 16);
}
}
}
}
}
void outputtofile1() { // Write into college2.dat
int i, j, x, y, blockno; // One block at a time, buf contains pixel
int redcoef, greencoef, bluecoef; // data of one row of blocks
float gijred, gijgreen, gijblue, c, ci, cj;
c = 1 / (sqrt(2));
for (blockno = 0; blockno < WIDTH; blockno++) {
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
gijred = 0;
gijgreen = 0;
gijblue = 0;
for (x = 0; x < 8; x++) {
for (y = 0; y < 8; y++) {
gijblue = gijblue + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][0];
gijgreen = gijgreen + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][1];
gijred = gijred + DCTcoeff[i][j][x][y]
* buf[blockno][x][y][2];
}
}
ci = cj = 1.0;
if (i == 0)
ci = c;
if (j == 0)
cj = c;
gijblue = ci * cj * gijblue / 4;
gijgreen = ci * cj * gijgreen / 4;
gijred = ci * cj * gijred / 4;
bluecoef = (int) gijblue;
greencoef = (int) gijgreen;
redcoef = (int) gijred;
fprintf(bmp_fp2, "%d %d %d ", bluecoef, greencoef, redcoef);
}
}
} /* end of one block processing */
}
void compressimage() {
int rowcount,x,y;
bmp_fp1=fopen("college4.bmp","r");
bmp_fp2=fopen("college2.dat","w");
printf("generating coefficients...\n");
generatedctcoeff();
if(bmp_fp1==NULL) {
printf("can't open");
return;
}
printf("compressing....\n");
fread(&bmphead,1,sizeof(bmphead),bmp_fp1);
fread(&infohead,1,sizeof(infohead),bmp_fp1);
fseek(bmp_fp1,bmphead.offset,SEEK_SET);
for(rowcount=0;rowcount<HEIGHT;rowcount++) {
for(y=0;y<8;y++) {
for(x=0;x<infohead.width;x++) {
buf[x/8][x%8][y][0]=(int)fgetc(bmp_fp1);
buf[x/8][x%8][y][1]=(int)fgetc(bmp_fp1);
buf[x/8][x%8][y][2]=(int)fgetc(bmp_fp1);
}
}
outputtofile1(); //output contents of buf after dct to file
}
fclose(bmp_fp1);
fclose(bmp_fp2);
}
void outputtofile2() { //output buf to college3.bmp
int i, j, x, y, blockno; // buf now contains coefficients
float pxyred, pxygreen, pxyblue, c, ci, cj; // a temp buffer buf1 used to
c = 1 / (sqrt(2)); // store one row of block of
for (blockno = 0; blockno < WIDTH; blockno++) { // decoded pixel values
for (x = 0; x < 8; x++)
for (y = 0; y < 8; y++) {
pxyred = 0;
pxygreen = 0;
pxyblue = 0;
for (j = 0; j < 8; j++) {
cj = 1.0;
if (j == 0)
cj = c;
for (i = 0; i < 8; i++) {
ci = 1.0;
if (i == 0)
ci = c;
pxyblue = pxyblue + ci * cj * DCTcoeff[i][j][y][x] * buf[blockno][i][j][0];
pxygreen = pxygreen + ci * cj
* DCTcoeff[i][j][y][x] * buf[blockno][i][j][1];
pxyred = pxyred + ci * cj * DCTcoeff[i][j][y][x] * buf[blockno][i][j][2];
}
}
pxyblue /= 4;
pxygreen /= 4;
pxyred /= 4;
buf1[blockno][y][x][0] = pxyblue;
buf1[blockno][y][x][1] = pxygreen;
buf1[blockno][y][x][2] = pxyred;
}
}
for (y = 0; y < 8; y++) {
for (blockno = 0; blockno < WIDTH; blockno++)
for (x = 0; x < 8; x++) {
fprintf(bmp_fp2, "%c%c%c", (char) buf1[blockno][x][y][0],
(char) buf1[blockno][x][y][1],
(char) buf1[blockno][x][y][2]);
}
}
}
void uncompressimage() {
int blue,green,red,rowcount,colcount,i,j;
bmp_fp1=fopen("college2.dat","r");
bmp_fp2=fopen("college3.bmp","w");
printf("generating coefficients...\n");
generatedctcoeff();
if (bmp_fp1==NULL) {
printf("open failed");
return;
}
printf("uncompressing....\n");
bmphead.type=0x4d42;
bmphead.filesize=30518;
bmphead.reserved1=0;
bmphead.reserved2=0;
bmphead.offset=sizeof(bmphead)+sizeof(infohead);
infohead.infosize=sizeof(infohead);
infohead.width=200;
infohead.height=160;
infohead.planes=1;
infohead.bitsperpixel=24;
infohead.compression=0;
infohead.sizeimage=0;
infohead.xpelspermeter=3780;
infohead.ypelspermeter=3780;
infohead.colorused=0;
infohead.colorimportant=0;
fwrite(&bmphead,sizeof(BMPHEAD),1,bmp_fp2);
fwrite(&infohead,sizeof(INFOHEAD),1,bmp_fp2);
for(rowcount=0;rowcount<HEIGHT;rowcount++) {
for(colcount=0;colcount<WIDTH;colcount++) {
for(i=0;i<8;i++) {
for(j=0;j<8;j++) {
fscanf(bmp_fp1,"%d",&blue);
fscanf(bmp_fp1,"%d",&green);
fscanf(bmp_fp1,"%d",&red);
buf[colcount][i][j][0]=blue;
buf[colcount][i][j][1]=green;
buf[colcount][i][j][2]=red;
}
}
}
outputtofile2();
}
fclose(bmp_fp1);
fclose(bmp_fp2);
}
int main() {
printf("opening files...\n");
compressimage();
printf("opening files...again\n");
uncompressimage();
printf("successful decompression\nenter any key\n");
return 0;
}
Here is the image i am using as input
(im srry the site converted the bmp into png. You may convert it back to bmp to use it)
Here is the image that is generated:
The file college3.bmp that gets created is of size 200x160 and of 93.8 kB but till quarter of the image it has decoded the coefficients correctly but later the file is filled with black pixels. I have taken a screenshot of the o/p as it was saying not a valid bmp while uploading. I am sitting on this problem since feb,2004. If anyone can say me where there is a bug i would be very thankful. I have analysed the output file and found an EOF right at the place where the pixels are starting to be black. I read some other questions on the topic and found that the conversion factors ci,cj have been used improperly. While coding i had also got confused with the indices x,y,i and j. So i hope this problem i will solve in a few days.
Apparently, the problem in the above code is in how you open your files.
This is what should be in your code (note the explicitly specified open modes, binary and text):
void compressimage() {
...
bmp_fp1=fopen("college4.bmp","rb");
bmp_fp2=fopen("college2.dat","wt");
...
}
void uncompressimage() {
...
bmp_fp1=fopen("college2.dat","rt");
bmp_fp2=fopen("college3.bmp","wb");
...
}
With that and slightly altered structure definitions:
#pragma pack(push,1)
typedef struct {
unsigned short int type;
unsigned long int filesize;
unsigned short int reserved1,reserved2;
unsigned long int offset;
} BMPHEAD;
typedef struct {
unsigned long int infosize;
unsigned long int width,height;
unsigned short int planes,bitsperpixel;
unsigned long int compression;
unsigned long int sizeimage;
long int xpelspermeter,ypelspermeter;
unsigned long int colorused,colorimportant;
} INFOHEAD;
typedef struct {
char rgbquad[4];
} colortable;
#pragma pack(pop)
I'm able to compile your program successfully using 3 different compilers (Turbo C++, Open Watcom, gcc) and get the desired output picture.