Image compression using Huffman Coding - c

I have some difficulties in my project. I got the RGB values from a 256x256 BMP image. However, I don't know how to continue by using the huffman coding to compress those RGB value.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*-------PROTOTYPES-------*/
long getImageInfo(FILE*, long, int);
void copyImageInfo(FILE* inputFile, FILE* outputFile);
void copyColorTable(FILE* inputFile, FILE* outputFile, int nColors);
//void bmpsave (FILE*, unsigned char , int , int );
/*------STRUCTURES--------*/
typedef struct {int rows; int cols; unsigned char* data;} sImage;
int main(int argc, char* argv[])
{
FILE *bmpInput, *rasterOutput, *bmpOutput,*RedText,*GreenText,*BlueText,*ErrorRedText,*ErrorBlueText,*ErrorGreenText;
FILE *entroGreen,*entroBlue,*entroRed;
sImage originalImage;
unsigned char someChar;
unsigned char *pChar;
long fileSize;
int vectorSize, nColors;
int totalGCount=0, totalBCount=0,totalRCount=0;
int r, c, i,j,k=0;
int redValue, greenValue, blueValue;
int dummyRed=0 ,dummyGreen=0, dummyBlue=0;
int count[256] = {0},countRed[256]= {0},countBlue[256]= {0},countGreen[256]= {0};
double EntropyGreen, EntropyBlue, EntropyRed;
//int error[414720];
//int Red[400][720];
//int Green[400][720];
//int Blue[400][720];
unsigned int uint1;
short word1;
unsigned char byte1, byte2;
FILE *imdata;
int **errorGreen;
int **errorRed;
int **errorBlue;
int **Red;
int **Blue;
int **Green;
int **b;
b = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
b[i] = malloc ( 256 * sizeof (int) );
errorGreen = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
errorGreen[i] = malloc ( 256 * sizeof (int) );
errorRed = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
errorRed[i] = malloc ( 256 * sizeof (int) );
errorBlue = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
errorBlue[i] = malloc ( 256 * sizeof (int) );
//error = (int *) malloc ( 414720 * sizeof (int) ); //Dynamic Memmory Allocation of 1D Array
Red = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
Red[i] = malloc ( 256 * sizeof (int) );
Green = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
Green[i] = malloc ( 256 * sizeof (int) );
Blue = malloc ( 256 * sizeof (int) );
for ( i = 0; i < 256; ++i )
Blue[i] = malloc ( 256 * sizeof (int) );
/*--------INITIALIZE POINTER----------*/
someChar = '0';
pChar = &someChar;
if(argc < 2)
{
printf("Usage: %s bmpInput.bmp\n", argv[0]);
exit(0);
}
printf("Reading file %s\n", "Kirschen_256.bmp");
/*----DECLARE INPUT AND OUTPUT FILES----*/
bmpInput = fopen("Kirschen_256.bmp", "rb");
/*RedText = fopen("Red.txt", "w");
BlueText = fopen("Blue.txt", "w");
GreenText = fopen("Green.txt", "w");*/
entroGreen = fopen("entroGreen.txt", "w");
entroRed = fopen("entroRed.txt", "w");
entroBlue = fopen("entroBlue.txt", "w");
ErrorRedText = fopen("ErrorRed.txt", "w");
ErrorBlueText = fopen("ErrorBlue.txt", "w");
ErrorGreenText = fopen("ErrorGreen.txt", "w");
rasterOutput = fopen("Kirschen_256.txt", "w");
bmpOutput = fopen("Kirschen_256().bmp", "wb");
fseek(bmpInput , 0L , SEEK_END);
//fseek is a C function belonging to the ANSI C standard library,
//and included in the file stdio.h. Its purpose is to change the file position indicator for the specified stream.
/*-----GET BMP DATA-----*/
originalImage.cols = (int)getImageInfo(bmpInput, 18, 4);
originalImage.rows = (int)getImageInfo(bmpInput, 22, 4);
fileSize = getImageInfo(bmpInput, 2, 4);
nColors = getImageInfo(bmpInput, 46, 4);
//vectorSize = fileSize - (14 + 40 + 4*nColors);
/*----PRINT DATA TO SCREEN-----*/
printf("Width: %d\n", originalImage.cols);
printf("Height: %d\n", originalImage.rows);
printf("File size: %ld\n", fileSize);
printf("Bits/pixel: %d\n", getImageInfo(bmpInput, 28, 4));
printf("No. colors: %d\n", nColors);
//printf("Vector size: %d\n", vectorSize);
copyImageInfo(bmpInput, bmpOutput);
//copyColorTable(bmpInput, bmpOutput, nColors);
/*----FOR 24-BIT BMP, THERE IS NO COLOR TABLE-----*/
fseek(bmpInput , 54 , SEEK_SET);
fseek(bmpOutput , 54 , SEEK_SET);
/*-----------READ RASTER DATA-----------*/
for(r=0; r<=originalImage.rows-1; r++)
{
for(c=0; c<=originalImage.cols-1; c++)
{
/*----READ FIRST BYTE TO GET BLUE VALUE-----*/
fread(pChar, sizeof(char), 1, bmpInput);
blueValue = *pChar;
Blue[r][c]=*pChar;
if (r==0||c==0){
errorBlue[r][c]=abs(dummyBlue-blueValue);
countBlue[abs(dummyBlue-blueValue)]++;
count[abs(dummyBlue-blueValue)]++;
totalBCount++;
}
else{
errorBlue[r][c]=abs(((dummyBlue+Blue[r-1][c]+Blue[r-1][c-1])/3)-blueValue);
countBlue[abs(((dummyBlue+Blue[r-1][c]+Blue[r-1][c-1])/3)-blueValue)]++;
count[abs(((dummyBlue+Blue[r-1][c]+Blue[r-1][c-1])/3)-blueValue)]++;
totalBCount++;
}
//error[k]=abs(dummyBlue-blueValue);
//k++;
*pChar=dummyBlue;
fwrite(pChar, sizeof(char), 1, bmpOutput);
dummyBlue=blueValue;
/*-----READ NEXT BYTE TO GET GREEN VALUE-----*/
fread(pChar, sizeof(char), 1, bmpInput);
greenValue = *pChar;
Green[r][c]=*pChar;
if (r==0||c==0){
errorGreen[r][c]=abs(dummyGreen-greenValue);
countGreen[abs(dummyGreen-greenValue)]++;
count[abs(dummyGreen-greenValue)]++;
totalGCount++;
}
else{
errorGreen[r][c]=abs(((dummyGreen+Green[r-1][c]+Green[r-1][c-1])/3)-greenValue);
countGreen[abs(((dummyGreen+Green[r-1][c]+Green[r-1][c-1])/3)-greenValue)]++;
count[abs(((dummyGreen+Green[r-1][c]+Green[r-1][c-1])/3)-greenValue)]++;
totalGCount++;
}
*pChar=dummyGreen;
fwrite(pChar, sizeof(char), 1, bmpOutput);
dummyGreen=greenValue;
/*-----READ NEXT BYTE TO GET RED VALUE-----*/
fread(pChar, sizeof(char), 1, bmpInput);
redValue = *pChar;
Red[r][c]=*pChar;
if (r==0||c==0){
errorRed[r][c]=abs(dummyRed-redValue);
countRed[abs(dummyRed-redValue)]++;
count[abs(dummyRed-redValue)]++;
totalRCount++;
}
else{
errorRed[r][c]=abs(((dummyRed+Red[r-1][c]+Red[r-1][c-1])/3)-redValue);
countRed[abs(((dummyRed+Red[r-1][c]+Red[r-1][c-1])/3)-redValue)]++;
count[abs(((dummyRed+Red[r-1][c]+Red[r-1][c-1])/3)-redValue)]++;
totalRCount++;
}
*pChar=dummyRed;
fwrite(pChar, sizeof(char), 1, bmpOutput);
dummyRed=redValue;
/*---------PRINT TO TEXT FILE---------*/
fprintf(rasterOutput, "(%d %d) = \tRed \t%d", r, c, redValue);
fprintf(rasterOutput, "\tGreen \t%d \tBlue \t%d\n", greenValue, blueValue);
/*-----read data, reflect and write to output file----*/
//fseek(bmpOutput, 54 , SEEK_SET);
//fwrite(pChar, sizeof(char), 1, bmpOutput);
}
}
for (j=0; j<256; j++) {
for (i=255; i>=0; i--) {
if(i>=256-(count[j]/16))
b[i][j] = 0x00;
else
b[i][j] = 0xFF;
}
}
imdata = fopen("Kirschen_256after4", "wb");
/* if (imdata == NULL) {
printf("%s open error.\n", imname); exit(0);
}
*/
byte1 = 'B'; byte2 = 'M';
fwrite(&byte1, 1, 1, imdata); fwrite(&byte2, 1, 1, imdata);
uint1 = 54 + 4*256 + originalImage.cols*originalImage.rows; fwrite(&uint1, 4, 1, imdata);
word1 = 0; fwrite(&word1, 2, 1, imdata); fwrite(&word1, 2, 1, imdata);
uint1 = 54 + 4*256; fwrite(&uint1, 4, 1, imdata);
uint1 = 40; fwrite(&uint1, 4, 1, imdata);
fwrite(&originalImage.cols, 4, 1, imdata); fwrite(&originalImage.rows, 4, 1, imdata);
word1 = 1; fwrite(&word1, 2, 1, imdata);
word1 = 8; fwrite(&word1, 2, 1, imdata);
uint1 = 0; fwrite(&uint1, 4, 1, imdata);
uint1 = originalImage.cols*originalImage.rows; fwrite(&uint1, 4, 1, imdata);
j = 11811; fwrite(&j, 4, 1, imdata); fwrite(&j, 4, 1, imdata);
uint1 = 256; fwrite(&uint1, 4, 1, imdata);
uint1 = 0; fwrite(&uint1, 4, 1, imdata);
for (i=0; i<256; i++) {
byte1 = i;
fwrite(&byte1, 1, 1, imdata); fwrite(&byte1, 1, 1, imdata);
fwrite(&byte1, 1, 1, imdata); fwrite(&byte1, 1, 1, imdata);
}
for (i=originalImage.rows-1; i>=0; i--) {
for (j=0; j<originalImage.cols; j++) {
fwrite(&b[i][j], 1, 1, imdata);
}
}
fclose(imdata);
for (i=0; i<256; i++) {
if (countGreen[i]==0)
EntropyGreen += 0;
else
EntropyGreen += ((double)countGreen[i]/(double)totalGCount) * (log2 ((double)1/((double)countGreen[i]/(double)totalGCount)));
if (countRed[i]==0)
EntropyRed += 0;
else
EntropyRed += ((double)countRed[i]/(double)totalRCount) * (log2 ((double)1/((double)countRed[i]/(double)totalRCount)));
if (countBlue[i]==0)
EntropyBlue +=0;
else
EntropyBlue += ((double)countBlue[i]/(double)totalBCount) * (log2 ((double)1/((double)countBlue[i]/(double)totalBCount)));
}
fprintf(entroGreen, "Entropy= %f", EntropyGreen);
fprintf(entroRed, "Entropy= %f", EntropyRed);
fprintf(entroBlue, "Entropy= %f", EntropyBlue);
for (i = 0; i < 256; i++) {
for (j = 0; j < 256; j++) {
fprintf(ErrorRedText, "[%d][%d] = %2d\n", i, j, errorRed[i][j]);
fprintf(ErrorGreenText, "[%d][%d] = %2d\n", i, j, errorGreen[i][j]);
fprintf(ErrorBlueText, "[%d][%d] = %2d\n", i, j, errorBlue[i][j]);
fprintf (ErrorRedText,"\n");
fprintf (ErrorBlueText,"\n");
fprintf (ErrorGreenText,"\n");
}
}
/*for (i = 0; i < 768; i++) {
for (j = 0; j < 1024; j++) {
fprintf(RedText, "a[%d][%d] = %2d\n", i, j, Red[i][j]);
fprintf(GreenText, "a[%d][%d] = %2d\n", i, j, Green[i][j]);
fprintf(BlueText, "a[%d][%d] = %2d\n", i, j, Blue[i][j]);
}
fprintf (RedText,"\n");
fprintf (BlueText,"\n");
fprintf (GreenText,"\n");
}*/
/*for (i = 0; i < 414720; i++){
fprintf(ErrorText, "error[%d] = %d\n",i,error[i]);
fprintf (ErrorText,"\n");
}*/
// PrintHistogram(freq_array, NUM_RANGE);
fclose(bmpInput);
/*fclose(RedText);
fclose(GreenText);
fclose(BlueText);*/
fclose(ErrorRedText);
fclose(ErrorGreenText);
fclose(ErrorBlueText);
fclose(rasterOutput);
fclose(bmpOutput);
fclose(entroGreen);
fclose(entroRed);
fclose(entroBlue);
return 0;
}
/*----GET IMAGE INFO SUBPROGRAM------*/
long getImageInfo(FILE* inputFile, long offset, int numberOfChars)
{
unsigned char *ptrC;
long value=0L;
int i;
unsigned char dummy;
dummy = '0';
ptrC = &dummy;
fseek(inputFile, offset, SEEK_SET);
for(i=1; i<=numberOfChars; i++)
{
fread(ptrC, sizeof(char), 1, inputFile);
/* calculate value based on adding bytes */
value = (long)(value + (*ptrC)*(pow(256, (i-1))));
}
return(value);
}
/*-------------COPIES HEADER AND INFO HEADER----------------*/
void copyImageInfo(FILE* inputFile, FILE* outputFile)
{
unsigned char *ptrC;
unsigned char dummy;
int i;
dummy = '0';
ptrC = &dummy;
fseek(inputFile, 0L, SEEK_SET);
fseek(outputFile, 0L, SEEK_SET);
for(i=0; i<=50; i++)
{
fread(ptrC, sizeof(char), 1, inputFile);
fwrite(ptrC, sizeof(char), 1, outputFile);
}
}
/*----------------COPIES COLOR TABLE-----------------------------*/
void copyColorTable(FILE* inputFile, FILE* outputFile, int nColors)
{
unsigned char *ptrC;
unsigned char dummy;
int i;
dummy = '0';
ptrC = &dummy;
fseek(inputFile, 54L, SEEK_SET);
fseek(outputFile, 54L, SEEK_SET);
for(i=0; i<=(4*nColors); i++) /* there are (4*nColors) bytesin color table */
{
fread(ptrC, sizeof(char), 1, inputFile);
fwrite(ptrC, sizeof(char), 1, outputFile);
}
}

I highly recommend using a search engine such as Google before asking on StackOverflow. This is a prime example. My Google Search yield examples in both C and C++.
When you have difficulties with your program, show the relevant code here.

Related

Hough transform implementation using C using 2D raw image

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);
}

How to share a string array using open mpi

I'm new in openmpi and I don't know how to use scatter and gather to send an array of strings to all processors. I would like to divide an array and send it to each processor, but all I can divide are the characters of a single array element. Can anyone help me please?
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
#define MASTER 0
#define BUF_SIZE 2048
#define CHAR_SIZE 900
#define CHARS 13
#define MAX_SIZE 3500
#define NUMBER_OF_FILES 2
int main(int argc, char** argv) {
int number_of_words = 0;
int total_rows = 0;
int i, j = 0;
char **words = (char**) calloc(MAX_SIZE, sizeof (char*));
for (i = 0; i < MAX_SIZE; i++) {
words[i] = (char*) calloc(CHARS, sizeof (char));
}
char **local_words = (char**) calloc(MAX_SIZE, sizeof (char*));
for (i = 0; i < MAX_SIZE; i++) {
local_words[i] = (char*) calloc(CHARS, sizeof (char));
}
char **rec_words = (char**) calloc(MAX_SIZE, sizeof (char*));
for (i = 0; i < MAX_SIZE; i++) {
rec_words[i] = (char*) calloc(CHARS, sizeof (char));
}
char str_righe[BUF_SIZE][CHAR_SIZE];
FILE *f = NULL;
char f_title[10];
char str_nfiles[10];
char delim[10] = {10, 32, 33, 39, 44, 46, 58, 59, 63};
char *ptr;
int rank;
int size;
int message_length;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
for (i = 1; i <= NUMBER_OF_FILES; i++) {
strcpy(f_title, "f");
sprintf(str_nfiles, "%d", i);
strcat(f_title, str_nfiles);
strcat(f_title, ".txt");
f = fopen(f_title, "r");
while (fgets(str_righe[j], BUF_SIZE, f)) {
str_righe[j][strlen(str_righe[j])] = '\0';
j++;
}
fclose(f);
}
total_rows = j;
for (i = 0; i < total_rows; ++i) {
ptr = strtok(str_righe[i], delim);
while (ptr != NULL) {
strcpy(words[number_of_words], ptr);
ptr = strtok(NULL, delim);
number_of_words++;
}
}
message_length = number_of_words / size;
if (rank == MASTER) {
for (i = 0; i < number_of_words; i++)
printf("%s\n", words[i]);
}
MPI_Scatter(*words, message_length, MPI_CHAR, *local_words, message_length, MPI_CHAR, MASTER, MPI_COMM_WORLD);
printf("rank %d, fragment: \t%s\n", rank, *local_words);
MPI_Gather(*local_words, message_length, MPI_CHAR, *rec_words, message_length, MPI_CHAR, MASTER, MPI_COMM_WORLD);
if (rank == MASTER) {
printf("rank %d, gathered: \t%s\n", rank, *rec_words);
}
MPI_Finalize();
return EXIT_SUCCESS;
}
I expect the output:
iMac-di-iMac01:mpi macbook$ mpirun -n 2 main
Good
time
by
antonio
rank 0, fragment: Good time
rank 1, fragment: by antonio
rank 0, gathered: Good time by antonio
But the actual output is:
iMac-di-iMac01:mpi macbook$ mpirun -n 2 main
Good
time
by
antonio
rank 0, fragment: Go
rank 1, fragment: od
rank 0, gathered: Good
I realized that I never shared the solution to the problem. I do it now:
I created the matrix variable and I sent the one with the scatter. In this way the slaves received the words and not the characters
int *matrix = 0;
matrix = malloc(sizeof (int) * n_words);
j = 1;
for (i = 0; i <= n_words; i++) {
matrix[i] = j;
j++;
}
n_words_cpu = n_words / (size);
procRow = malloc(sizeof (int) * n_words); // received row will contain p integers
MPI_Scatter(
/* send_data = */ matrix,
/* send_count = */ n_words_cpu,
/* send_datatype = */ MPI_INT,
/* recv_data = */ procRow,
/* recv_count = */ n_words_cpu,
/* recv_datatype = */ MPI_INT,
/* root = */ MASTER,
/* MPI_commuicator = */ MPI_COMM_WORLD);

MPI basic image processing - convolution using MPI

I am trying to learn MPI, so i created this simple program which is doing the convolution on grayscale uint8 image. I modified the openMP code which was working quite ok, with sliceing the vectorized image to parts for each processor - to scatterDataSize, but i am getting weird error from MPI:
"Primary job terminated normally, but 1 process returned
a non-zero exit code. Per user-direction, the job has been aborted.
mpirun noticed that process rank 1 with PID 5360 on node wn25 exited on signal 11 (Segmentation fault)."
I've tried to make it using MPI_Scatter to brodcast the image to all processes, and after convolution collect the data with MPI_Gather or MPI_Allgather, but result from both is the same...
argv are image dimensions - the images are i.e. input1000_800.bin so the program is being executed as:
mpirun -np 4 ./main 1000 800 and the source code of my program is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
#include <mpi.h>
const int ROOT = 0;
const double filter[][5] = { {0,0,1,0,0},
{0,1,2,1,0},
{1,2,-16,2,1},
{0,1,2,1,0},
{0,0,1,0,0} };
unsigned char normalize(double value);
double convolution(int i, int j, unsigned char *image, int height, int width, int filterDimension);
void saveImage(char* filename[], unsigned char* image, long fileLength);
long getFileSize(char* filename[]);
unsigned char * readImage(char* filename[]);
int main(int argc, char * argv[])
{
int width = atoi(argv[1]);
int height = atoi(argv[2]);
const char * prefixInFile = "../../labMPI/infile";
const char * prefixOutFile = "result";
const char * fileExtension = ".bin";
char outFileName[64], fileName[64];
unsigned char * image, *buffer, *data;
long fileSize;
int processorsAmount, processId, scatterDataSize;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &processorsAmount);
MPI_Comm_rank(MPI_COMM_WORLD, &processId);
strcpy(fileName, prefixInFile);
strcat(fileName, argv[1]);
strcat(fileName, "_");
strcat(fileName, argv[2]);
strcat(fileName, fileExtension);
strcpy(outFileName, prefixOutFile);
strcat(outFileName, argv[1]);
strcat(outFileName, "_");
strcat(outFileName, argv[2]);
strcat(outFileName, fileExtension);
fileSize = getFileSize(fileName);
data = (unsigned char *)malloc(fileSize * sizeof(unsigned char));
scatterDataSize = fileSize / processorsAmount;
int startPoint = scatterDataSize * processId;
int endPoint = scatterDataSize * (processId + 1);
printf("filesize: %d\nprocessorsAmount: %d\niam: %d\nscatterDataSize: %d\nstartPoint: %d\nendPoint: %d\n",
fileSize, processorsAmount, processId, scatterDataSize, startPoint, endPoint);
if (processId == ROOT)
{
printf("Reading file %s on ROOT \n output file will be: %s \n", fileName, outFileName);
image = readImage(fileName);
}
MPI_Bcast(image,fileSize, MPI_UNSIGNED_CHAR, ROOT, MPI_COMM_WORLD);
#pragma omp parallel for
for (int i = startPoint; i < endPoint; i++)
{
register int col = i % width;
register int row = i / width;
register long idx = col + width * row;
data[idx] = normalize(convolution(col, row, image, height, width, 5));
}
/* i am not sure how to collect processed data on workers back to root and perform save */
MPI_Bcast(data,fileSize, MPI_UNSIGNED_CHAR, ROOT, MPI_COMM_WORLD);
if (processId == ROOT)
{
saveImage(outFileName, data, fileSize);
printf("Image processing is finished");
free(image);
}
free(data);
MPI_Finalize();
return 0;
}
double convolution(int i, int j, unsigned char *image, int height, int width, int filterDimension)
{
register int filterHeight, filterWidth, kernelCenter, ii, jj;
filterHeight = filterWidth = filterDimension;
kernelCenter = filterHeight / 2;
register double tmp = 0;
for (long m = 0; m < filterHeight; ++m) {
for (long n = 0; n < filterWidth; ++n) {
ii = i + (kernelCenter - m);
jj = j + (kernelCenter - n);
if (ii >= 0 && ii < width && jj >= 0 && jj < height)
tmp += image[jj * width + ii] * filter[m][n];
}
}
return tmp;
}
unsigned char * readImage(char* filename[])
{
FILE *inFile = fopen(filename, "rb");
fseek(inFile, 0, SEEK_END);
long long fileLength = ftell(inFile);
fseek(inFile, 0, SEEK_SET);
unsigned char * image = (unsigned char *)malloc(fileLength * sizeof(unsigned char));
fread(image, sizeof(unsigned char), fileLength, inFile);
fclose(inFile);
return image;
}
long getFileSize(char* filename[])
{
FILE *inFile = fopen(filename, "rb");
fseek(inFile, 0, SEEK_END);
long fileLength = ftell(inFile);
fclose(inFile);
return fileLength;
}
void saveImage(char* filename[], unsigned char* image, long fileLength)
{
FILE *write = fopen(filename, "wb");
fwrite(image, sizeof(unsigned char), fileLength * sizeof(unsigned char), write);
fclose(write);
}
unsigned char normalize(double value)
{
if (value > 255)
{
value = 255;
}
else if (value < 0) {
value = 0;
}
return (unsigned char)value;
}

Reading binary signed short issue in C

I am learning C as a hobbyist. As a fun project I decided to code a .hgt file reader. hgt file are earth elevation files.
I found few information on this file format : https://dds.cr.usgs.gov/srtm/version2_1/Documentation/Quickstart.pdf
You can find files for the whole planet here :
http://viewfinderpanoramas.org/Coverage%20map%20viewfinderpanoramas_org3.htm
but it seems to be pretty straight forward : a list of signed two bytes integers they say.
I found that two bytes integers are well represented by "signed short" type, is that right ? In my code , you will see I used int_16t ( I tried that when having issues with signed shorts) I believe they have the same range )
Anyway, I open the file , dump the data in an array, and write it to a bmp file.
At first I thought it worked great, but that was because I was viewing the result of a very low elevation part of the earth. When I tried to render some files corresponding to areas with mountains, the image below shows the issue.
Below is my code so far.
I was pretty sure the issue is at the beginning, when reading the data, but I don't know anymore.
I would love some help.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stdint.h>
#include <math.h>
int main(int argc, char *argv[]) {
if(argc < 2) {
printf("I need a hgt file path as a paramater\n");
return 0;
} else {
const int DIM = 1201;
FILE *fp;
int16_t *elevation_buffer;
elevation_buffer = malloc(sizeof(int16_t) * DIM * DIM); // 2 bytes integers
fp = fopen(argv[1], "rb");
/* Seek to the beginning of the file */
fseek(fp, 0, SEEK_SET);
/* read elevation data from HGT file */
fread(elevation_buffer, sizeof(int16_t), DIM*DIM, fp);
fclose(fp);
printf("sizeof signed short int : %d\n", sizeof(signed short int));
printf("sizeof int16_t : %d\n", sizeof(int16_t));
/* creating a bmp file to visualize elevation tile*/
int w = DIM;
int h = DIM;
int x,y,r,g,b;
FILE *f;
unsigned char *img = NULL;
int filesize = 54 + 3 * w * h; //w is your image width, h is image height, both int
img = (unsigned char *)malloc(3 * w * h);
memset(img, 0, 3 * w * h);
for (int i = 0; i < w; i++)
{
for (int j = 0; j < h; j++)
{
x = i;
y = (h - 1) - j;
float elevation = (elevation_buffer[x + y * w] - INT16_MIN) / (float)(INT16_MAX - INT16_MIN);
r = (int)(elevation * 255);
float freq = 100.0f;
if (r > 255) {
r = 255;
} else if(r < 0) {
r = 0;
}
g = r;
b = r;
img[(x + y * w) * 3 + 2] = (unsigned char)(r);
img[(x + y * w) * 3 + 1] = (unsigned char)(g);
img[(x + y * w) * 3 + 0] = (unsigned char)(b);
}
}
unsigned char bmpfileheader[14] = {'B', 'M', 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0};
unsigned char bmpinfoheader[40] = {40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 24, 0};
unsigned char bmppad[3] = {0, 0, 0};
bmpfileheader[2] = (unsigned char)(filesize);
bmpfileheader[3] = (unsigned char)(filesize >> 8);
bmpfileheader[4] = (unsigned char)(filesize >> 16);
bmpfileheader[5] = (unsigned char)(filesize >> 24);
bmpinfoheader[4] = (unsigned char)(w);
bmpinfoheader[5] = (unsigned char)(w >> 8);
bmpinfoheader[6] = (unsigned char)(w >> 16);
bmpinfoheader[7] = (unsigned char)(w >> 24);
bmpinfoheader[8] = (unsigned char)(h);
bmpinfoheader[9] = (unsigned char)(h >> 8);
bmpinfoheader[10] = (unsigned char)(h >> 16);
bmpinfoheader[11] = (unsigned char)(h >> 24);
f = fopen("img.bmp", "wb");
fwrite(bmpfileheader, 1, 14, f);
fwrite(bmpinfoheader, 1, 40, f);
for (int i = 0; i < h; i++)
{
fwrite(img + (w * (h - i - 1) * 3), 3, w, f);
fwrite(bmppad, 1, (4 - (w * 3) % 4) % 4, f);
}
free(img);
free(elevation_buffer);
fclose(f);
return 0;
}
}
You should account for the byte order... your input file format is specified to contain bytes in big endian byte order.
As a simple fix, you could just check your byteorder and reverse the read in data as necessary. The answer https://stackoverflow.com/a/8571139/5265292 explains a way how to detect byte order on your system.
// ...
fread(elevation_buffer, sizeof(int16_t), DIM*DIM, fp);
fclose(fp);
int byteOrderCheck = 1;
if (*(char *)&byteOrderCheck == 1)
{
// need to revert byte order for little endian
for (int i = 0; i < DIM*DIM; ++i)
{
elevation_buffer[i] = (int16_t)reverse_byte_order((uint16_t)elevation_buffer[i]);
}
}
// ...
with function reverse_byte_order as
uint16_t reverse_byte_order(uint16_t num)
{
return ((num & 0xff) << 8) | (num >> 8);
}
Note this is untested, you may need to change some details.

Copy value of short array to long array

The following is an example showing what I want:
int buf[3] = {10, 20, 30};
int * send_buf = (int *)malloc(5 * sizeof(int));
*send_buf = 1;
*(send_buf + 4) = 1;
After copy buf to send_buf, the values in send_buf should be :
1 10 20 30 1
Could anyone let me know what's the most efficient way to do this without using memcpy() or memmove()?
Try the following changes-
int buf[3] = {10, 20, 30};
int * send_buf = (int *)malloc(5 * sizeof(int));
*send_buf = 1;
for(i=1;i<=3;i++) // this will work for you.
*(send_buf+i)=buf[i-1];
*(send_buf + 4) = 1;
A simple implementation of memcpy() is:
memcpy(uint8_t *dest, uint8_t *src, size_t num_bytes) {
for (size_t i=0; i<num_bytes; ++i)
dest[i] = src[i];
}
So, since we can't use memcpy() for no good reason, let's just inline the body:
int buf[3] = {10, 20, 30};
int *send_buf = malloc(5 * sizeof(int));
send_buf[0] = 1;
send_buf[4] = 1;
for (int i=0; i<3; ++i)
send_buf[i + 1] = buf[i];
Well, one can always do it with sprintf and sscanf
char buffer[1024];
sprintf(buffer, "%d %d %d", buf[0], buf[1], buf[2]);
sscanf(buffer, "%d%d%d", send_buf[1], send_buf[2], send_buf[3]);

Resources