problems with data type conversion (maybe)

C

CAFxX

i'm writing a program that executes some calculations on a bitmap loaded in
memory.
these calculation ends up with pixel wth values far over 255, but i need
them to be between 0 and 255 since i got to write them in a bmp file (in
which RGB values are limited to 8 bits per channel). so i need to have them
scaled down.

first of all i find the highest and lowest of those values:(keep in mind
that max, min, bmp[], ptr are ulong and w, h are uint):

// FIND HIGHEST/LOWEST VALUES TO BE USED IN 0-255 NORMALIZATION
max = 0; min = 0-1;
for (int ptr=0; ptr<w*h*3; ptr++) {
if (max < bmp[ptr]) {
max = bmp[ptr];
} else if (min > bmp[ptr]) {
min = bmp[ptr];
}
}

then i normalize everything to 255:

// NORMALIZE VALUES
for (int ptr=0; ptr<w*h*3; ptr++) {
bmp[ptr] = (unsigned long)((float)(bmp[ptr] - min) / (float)max *
(float)255);
}

at this point, everything is alright. if i write in a bmp file the contents
of the array i get what i expected.
but as soon as i denormalize and apply the inverse of the calculations i did
before (i tested them separately: without normalization/denormalization they
work fine)

//DENORMALIZE VALUES
for (int ptr=0; ptr<w*h*3; ptr++) {
bmp[ptr] = (unsigned long)((float)bmp[ptr] / (float)255 * (float)max) + min;
}

then i write down the content of the array:

// OUTPUTTING LOOPs
// COPY SOURCE IMAGE BMP HEADER - WORKING
fseek(fp1, 0, SEEK_SET);
for (int i=0; i<54; i++) {
fputc(fgetc(fp1),fp2);
}
// WRITE DATA CONTAINED IN THE BMP ARRAY IN THE SAME ORDER THEY WERE READ -
WORKING
for (int ptr=0; ptr<w*h*3; ptr++) {
fputc ((unsigned int)bmp[ptr], fp2);
}

but the bitmap i end up with it's a mess of random pixels.
i think i'm doing something wrong in the data type conversion of the
denormalization loop. anyone knows why? i do thank you in advance.

p.s. if you want the full source of the program go to
sourceforge.net/projects/simplify. the function you got to point at is void
test ()
 
R

Ron Natalie

CAFxX said:
// FIND HIGHEST/LOWEST VALUES TO BE USED IN 0-255 NORMALIZATION
max = 0; min = 0-1;
0-1? How about just -1? And unless min is unsigned, you don't
even want to do that. Th easiest way is just to seed min and max
with the first pixel value.

min = bmp[0];
max = bmp[0]
for(int ptr = 1; ...

// NORMALIZE VALUES
for (int ptr=0; ptr<w*h*3; ptr++) {
bmp[ptr] = (unsigned long)((float)(bmp[ptr] - min) / (float)max *
(float)255);

This calculation is wrong. You'll get bizarre results if min isn't zero.\
You don't even need to do float provided that the following won't overflow.
bmp[ptr] = (bmp[ptr] - min)*255 / (max - min)
You don't tell me what the types of min, max, and bmp are so I can't make a decision.
bmp[ptr] = (unsigned long)((float)bmp[ptr] / (float)255 * (float)max) + min;

Likewise
bmp[ptr] = bmp[ptr] *(max - min) / 255 + min;
Provided min and max are still the same value they were before.

// WRITE DATA CONTAINED IN THE BMP ARRAY IN THE SAME ORDER THEY WERE READ -
WORKING
for (int ptr=0; ptr<w*h*3; ptr++) {
fputc ((unsigned int)bmp[ptr], fp2);

Hopefully, you are doing this with the normalized bmp values as fputc. The cast is spurious.
 
C

CAFxX

this is the complete source of my program.
in my first post i forgot to paste the line
max -= min;
but it was already there.
are your instructions still valid? thanks for your help.

#include <stdio.h>
#include <stdlib.h>
#include "Simplify_private.h" // DEV-CPP version informations
using namespace std;

// GLOBALs
unsigned short c; //Components counter
unsigned int x; //X-axis pixel coordinate counter
unsigned int y; //Y-axis pixel coordinate counter
int rx; //X-axis spreading distance counter
int ry; //Y-axis spreading distance counter
unsigned int w; //Source image width
unsigned int h; //Source image height
unsigned short s; //Spreading factor
unsigned long max; //Normalizing MAX value
unsigned long min = 0-1; //Normalizing MIN value
unsigned long dummybytes; //Number of dummy bytes per line
unsigned long ptr; //*bmp array pseudo-pointer
FILE *fp1; //Input file pointer
FILE *fp2; //Output file pointer
unsigned long *bmp; //Memory pointer

void test() {
fseek (fp1, 54, SEEK_SET);
// BLURRING LOOP - WORKING
for (y=0; y<h; y++) {
printf("%3d\b\b\b",y);
for (x=0; x<w; x++) {
for (c=0; c<3; c++) {
unsigned short byte = fgetc(fp1);
bmp[(x+y*w)*3+c] += byte; // #1 (see TODO)
// bmp[(x+y*w)*3+c] += (unsigned long)byte * (unsigned
long)s; // this has to be tested
for (rx=-s; rx<=s; rx++) {
for (ry=1; ry<=s; ry++) {
if (!((x+rx < 0) or (x+rx >= w) or (y+ry >= h)))
{ // to avoid page fault
bmp[(x+rx+(y+ry)*w)*3+c] += byte;
}
}
}
}
}
fseek(fp1, dummybytes, SEEK_CUR);
}
fseek(fp1, 54, SEEK_SET);
for (ptr=0; ptr<w*3; ptr++) {
bmp[ptr] = fgetc(fp1);
}
// NORMALIZING LOOPs
// FIND HIGHEST/LOWEST VALUES TO BE USED IN 0-255 NORMALIZATION -
PROBABLY WORKING
max = min = bmp[0];
for (ptr=w*3; ptr<w*h*3; ptr++) {
if (max < bmp[ptr]) {
max = bmp[ptr];
} else if (min > bmp[ptr]) {
min = bmp[ptr];
}
}
printf ("%d %d\n", max, min);
max -= min;
// NORMALIZE VALUES
for (ptr=w*3; ptr<w*h*3; ptr++) {
bmp[ptr] = (unsigned int)((float)(bmp[ptr] - min) / (float)max *
(float)255);
}
//DENORMALIZE VALUES
for (ptr=w*3; ptr<w*h*3; ptr++) {
bmp[ptr] = (unsigned long)((float)bmp[ptr] / (float)255 *
(float)max) + min;
}
max=0; min=0-1;
for (ptr=w*3; ptr<w*h*3; ptr++) {
if (max < bmp[ptr]) {
max = bmp[ptr];
} else if (min > bmp[ptr]) {
min = bmp[ptr];
}
}
printf ("%d %d\n", max, min);
// DEBLURRING LOOP - WORKING
for (y=0; y<h; y++) {
printf("%3d\b\b\b",y);
for (x=0; x<w; x++) {
for (c=0; c<3; c++) {
for (rx=-s; rx<=s; rx++) {
for (ry=1; ry<=s; ry++) {
if (!((x+rx < 0) or (x+rx >= w) or (y+ry >= h)))
{ // to avoid page fault
bmp[(x+rx+(y+ry)*w)*3+c] -= bmp[(x+y*w)*3+c];
}
}
}
}
}
}
// OUTPUTTING LOOPs
// COPY SOURCE IMAGE BMP HEADER - WORKING
fseek(fp1, 0, SEEK_SET);
for (ptr=0; ptr<54; ptr++) {
fputc(fgetc(fp1),fp2);
}
// WRITE DATA CONTAINED IN THE BMP ARRAY IN THE SAME ORDER THEY WERE
READ - WORKING
for (ptr=0; ptr<w*h*3; ptr++) {
fputc (bmp[ptr], fp2);
}
fclose(fp1);
fclose(fp2);
}

Ron Natalie said:
// FIND HIGHEST/LOWEST VALUES TO BE USED IN 0-255 NORMALIZATION
max = 0; min = 0-1;
0-1? How about just -1? And unless min is unsigned, you don't
even want to do that. Th easiest way is just to seed min and max
with the first pixel value.

min = bmp[0];
max = bmp[0]
for(int ptr = 1; ...

// NORMALIZE VALUES
for (int ptr=0; ptr<w*h*3; ptr++) {
bmp[ptr] = (unsigned long)((float)(bmp[ptr] - min) / (float)max *
(float)255);

This calculation is wrong. You'll get bizarre results if min isn't zero.\
You don't even need to do float provided that the following won't overflow.
bmp[ptr] = (bmp[ptr] - min)*255 / (max - min)
You don't tell me what the types of min, max, and bmp are so I can't make a decision.
bmp[ptr] = (unsigned long)((float)bmp[ptr] / (float)255 * (float)max) +
min;

Likewise
bmp[ptr] = bmp[ptr] *(max - min) / 255 + min;
Provided min and max are still the same value they were before.

// WRITE DATA CONTAINED IN THE BMP ARRAY IN THE SAME ORDER THEY WERE READ -
WORKING
for (int ptr=0; ptr<w*h*3; ptr++) {
fputc ((unsigned int)bmp[ptr], fp2);

Hopefully, you are doing this with the normalized bmp values as fputc. The cast is spurious.
 
C

CAFxX

i really can't understand what's wrong in here.
i placed this code
for (ptr=0; ptr<w*h*3; ptr++) {
if (bmp[ptr]<0 or bmp[ptr]>255) { printf ("%7d: %12d\n", ptr,
(unsigned int)bmp[ptr]); }
}
after every loop to track the memory contents and i discovered that
normalizing and denormalizing are working. but what i can't understand is
that if i place it after the deblurring loop i get huge and even negatives
(even if bmp[] is unsigned long) values!
what's funny is that if i turn off the normalization/denormalization
process, the blurring/deblurring filters work correctly.
in case, this is the source (try to feed it a 24 bit uncompressed bmp file
with just a coloured text on a flat white bg):

// Simplify 0.0.7
// (C) 2003 CAFxX

#include <stdio.h>
#include <stdlib.h>
#include "Simplify_private.h" // DEV-CPP version informations
using namespace std;

// GLOBALs

unsigned short c; //Components counter
unsigned int x; //X-axis pixel coordinate counter
unsigned int y; //Y-axis pixel coordinate counter
int rx; //X-axis spreading distance counter
int ry; //Y-axis spreading distance counter
unsigned int w; //Source image width
unsigned int h; //Source image height
unsigned short s; //Spreading factor
unsigned long max; //Normalizing MAX value
unsigned long min; //Normalizing MIN value
unsigned long dummybytes; //Number of dummy bytes per line
unsigned long ptr; //*bmp array pseudo-pointer
FILE *fp1; //Input file pointer
FILE *fp2; //Output file pointer
unsigned long *bmp; //Memory pointer

void test() {
if ((fp1 = fopen("test.bmp", "rb")) == NULL) { exit(2); }
if ((fp2 = fopen("out.bmp", "wb")) == NULL) { exit(1); }
fseek (fp1, 54, SEEK_SET);
// BLURRING LOOP - WORKING
for (y=0; y<h; y++) {
printf("%3d\b\b\b",y);
for (x=0; x<w; x++) {
for (c=0; c<3; c++) {
unsigned short byte = fgetc(fp1);
bmp[(x+y*w)*3+c] += byte; // #1 (see TODO)
// bmp[(x+y*w)*3+c] += (unsigned long)byte * (unsigned
long)s; // this has to be tested
for (rx=-s; rx<=s; rx++) {
for (ry=1; ry<=s; ry++) {
if (!((x+rx < 0) or (x+rx >= w) or (y+ry >= h)))
{ // to avoid page fault
bmp[(x+rx+(y+ry)*w)*3+c] += byte;
}
}
}
}
}
fseek(fp1, dummybytes, SEEK_CUR);
}
fseek(fp1, 54, SEEK_SET);
for (ptr=0; ptr<w*3; ptr++) {
bmp[ptr] = fgetc(fp1);
}
// NORMALIZING LOOPs
// FIND HIGHEST/LOWEST VALUES TO BE USED IN 0-255 NORMALIZATION -
PROBABLY WORKING
max = min = bmp[0];
for (ptr=w*3; ptr<w*h*3; ptr++) {
if (max < bmp[ptr]) {
max = bmp[ptr];
} else if (min > bmp[ptr]) {
min = bmp[ptr];
}
}
printf ("%10d %10d\n", max, min);
max -= min;
// NORMALIZE VALUES - WORKKING
for (ptr=w*3; ptr<w*h*3; ptr++) {
//bmp[ptr] = (unsigned long)((float)(bmp[ptr] - min) /
(float)max * (float)255);
bmp[ptr] -= min;
bmp[ptr] <<= 8;
bmp[ptr] /= max;
}
//DENORMALIZE VALUES - WORKING
for (ptr=w*3; ptr<w*h*3; ptr++) {
bmp[ptr] *= max;
bmp[ptr] >>= 8; // it should be /255, but i think it will work
bmp[ptr] += min;
}
// DEBLURRING LOOP - WORKING
for (y=0; y<h; y++) {
printf("%3d\b\b\b",y);
for (x=0; x<w; x++) {
for (c=0; c<3; c++) {
for (rx=-s; rx<=s; rx++) {
for (ry=1; ry<=s; ry++) {
if (!((x+rx < 0) or (x+rx >= w) or (y+ry >= h)))
{ // to avoid page fault
bmp[(x+rx+(y+ry)*w)*3+c] -= bmp[(x+y*w)*3+c];
}
}
}
}
}
}
// OUTPUTTING LOOPs
// COPY SOURCE IMAGE BMP HEADER - WORKING
fseek(fp1, 0, SEEK_SET);
for (ptr=0; ptr<54; ptr++) {
fputc(fgetc(fp1),fp2);
}
// WRITE DATA CONTAINED IN THE BMP ARRAY IN THE SAME ORDER THEY WERE
READ - WORKING
for (ptr=0; ptr<w*h*3; ptr++) {
fputc (bmp[ptr], fp2);
}
fclose(fp1);
fclose(fp2);
}

long flen (FILE *fp)
{
long ptr = ftell(fp);
fseek(fp, 0, SEEK_END);
long lenght = ftell(fp);
fseek(fp, ptr, SEEK_SET);
return lenght;
}

int main(int argc, char *argv[]) {
printf("Simplify ");
printf(VER_STRING);
printf("\n(C) 2003 CAFxX\n\n");

// COMMAND LINE PARSING IS JUST EXPERIMENTAL AND HAS NEVER BEEN TESTED
// SYNTAX WOULD BE
// SIMPLIFY INPUT_FILE OUTPUT_FILE SPREADING_FACTOR [D | E]
// ALL PARAMETERS ARE MANDATORY. LAST PARAMETER IS D(ECODING) | E(NCODING).
// E.G: simplify input.bmp output.bmp 10 e
if (argc == 5) {
if ((fp1 = fopen(argv[2], "rb")) == NULL) { exit(2); }
if ((fp2 = fopen(argv[3], "wb")) == NULL) { exit(1); }
s = atoi(argv[4]);
if (argv[5] == "D" or argv[4] == "d") { /*decode();*/ }
else if (argv[5] == "E" or argv[4] == "e") { /*encode();*/ }
exit(0);
} else if (argc == 1) {

// COLLECTING IMAGE SIZE
printf("Input file must be a 24-bit uncompressed Windows BMP
file!\nSource image width > ");
scanf("%d",&w);
if (w <= 0) { exit(0); } // EXIT IF IMAGE DIMENSIONS ARE NOT VALID
printf("Source image height > ");
scanf("%d",&h);
if (h <= 0) { exit(0); }
// COLLECTING ENCODING SETTINGS
printf("Spreading factor > ");
scanf("%d",&s);

// DUMMY BYTES PER LINE
if ((fp1 = fopen("test.bmp", "rb")) == NULL) { exit(2); }
dummybytes = (flen(fp1) - h * w * 3 + 54) / h;
fclose(fp1);

// ALLOCATE MEMORY AND START PROCESSING
bmp = (unsigned long*)malloc(sizeof(unsigned long)*w*h*3);
if (bmp == NULL) { exit(3); }
test();
free(bmp);
system ("pause");
return 0;

} else {

printf ("Wrong parameter number");
exit(4);

}
}

thanks in advance to anyone that will help.

CAFxX said:
i'm writing a program that executes some calculations on a bitmap loaded in
memory.
these calculation ends up with pixel wth values far over 255, but i need
them to be between 0 and 255 since i got to write them in a bmp file (in
which RGB values are limited to 8 bits per channel). so i need to have them
scaled down.

first of all i find the highest and lowest of those values:(keep in mind
that max, min, bmp[], ptr are ulong and w, h are uint):

// FIND HIGHEST/LOWEST VALUES TO BE USED IN 0-255 NORMALIZATION
max = 0; min = 0-1;
for (int ptr=0; ptr<w*h*3; ptr++) {
if (max < bmp[ptr]) {
max = bmp[ptr];
} else if (min > bmp[ptr]) {
min = bmp[ptr];
}
}

then i normalize everything to 255:

// NORMALIZE VALUES
for (int ptr=0; ptr<w*h*3; ptr++) {
bmp[ptr] = (unsigned long)((float)(bmp[ptr] - min) / (float)max *
(float)255);
}

at this point, everything is alright. if i write in a bmp file the contents
of the array i get what i expected.
but as soon as i denormalize and apply the inverse of the calculations i did
before (i tested them separately: without normalization/denormalization they
work fine)

//DENORMALIZE VALUES
for (int ptr=0; ptr<w*h*3; ptr++) {
bmp[ptr] = (unsigned long)((float)bmp[ptr] / (float)255 * (float)max) + min;
}

then i write down the content of the array:

// OUTPUTTING LOOPs
// COPY SOURCE IMAGE BMP HEADER - WORKING
fseek(fp1, 0, SEEK_SET);
for (int i=0; i<54; i++) {
fputc(fgetc(fp1),fp2);
}
// WRITE DATA CONTAINED IN THE BMP ARRAY IN THE SAME ORDER THEY WERE READ -
WORKING
for (int ptr=0; ptr<w*h*3; ptr++) {
fputc ((unsigned int)bmp[ptr], fp2);
}

but the bitmap i end up with it's a mess of random pixels.
i think i'm doing something wrong in the data type conversion of the
denormalization loop. anyone knows why? i do thank you in advance.

p.s. if you want the full source of the program go to
sourceforge.net/projects/simplify. the function you got to point at is void
test ()
 
C

CAFxX

hmmm, posted the wrong loop
i really can't understand what's wrong in here.
i placed this code
this is the right one:
for (ptr=0; ptr<w*h*3; ptr++) {
if (bmp[ptr]<0 or bmp[ptr]>255) { printf ("%7d: %12d\n", ptr,
(unsigned int)bmp[ptr]); }
}

CAFxX said:
i really can't understand what's wrong in here.
i placed this code
for (ptr=0; ptr<w*h*3; ptr++) {
if (bmp[ptr]<0 or bmp[ptr]>255) { printf ("%7d: %12d\n", ptr,
(unsigned int)bmp[ptr]); }
}
after every loop to track the memory contents and i discovered that
normalizing and denormalizing are working. but what i can't understand is
that if i place it after the deblurring loop i get huge and even negatives
(even if bmp[] is unsigned long) values!
what's funny is that if i turn off the normalization/denormalization
process, the blurring/deblurring filters work correctly.
in case, this is the source (try to feed it a 24 bit uncompressed bmp file
with just a coloured text on a flat white bg):

// Simplify 0.0.7
// (C) 2003 CAFxX

#include <stdio.h>
#include <stdlib.h>
#include "Simplify_private.h" // DEV-CPP version informations
using namespace std;

// GLOBALs

unsigned short c; //Components counter
unsigned int x; //X-axis pixel coordinate counter
unsigned int y; //Y-axis pixel coordinate counter
int rx; //X-axis spreading distance counter
int ry; //Y-axis spreading distance counter
unsigned int w; //Source image width
unsigned int h; //Source image height
unsigned short s; //Spreading factor
unsigned long max; //Normalizing MAX value
unsigned long min; //Normalizing MIN value
unsigned long dummybytes; //Number of dummy bytes per line
unsigned long ptr; //*bmp array pseudo-pointer
FILE *fp1; //Input file pointer
FILE *fp2; //Output file pointer
unsigned long *bmp; //Memory pointer

void test() {
if ((fp1 = fopen("test.bmp", "rb")) == NULL) { exit(2); }
if ((fp2 = fopen("out.bmp", "wb")) == NULL) { exit(1); }
fseek (fp1, 54, SEEK_SET);
// BLURRING LOOP - WORKING
for (y=0; y<h; y++) {
printf("%3d\b\b\b",y);
for (x=0; x<w; x++) {
for (c=0; c<3; c++) {
unsigned short byte = fgetc(fp1);
bmp[(x+y*w)*3+c] += byte; // #1 (see TODO)
// bmp[(x+y*w)*3+c] += (unsigned long)byte * (unsigned
long)s; // this has to be tested
for (rx=-s; rx<=s; rx++) {
for (ry=1; ry<=s; ry++) {
if (!((x+rx < 0) or (x+rx >= w) or (y+ry >= h)))
{ // to avoid page fault
bmp[(x+rx+(y+ry)*w)*3+c] += byte;
}
}
}
}
}
fseek(fp1, dummybytes, SEEK_CUR);
}
fseek(fp1, 54, SEEK_SET);
for (ptr=0; ptr<w*3; ptr++) {
bmp[ptr] = fgetc(fp1);
}
// NORMALIZING LOOPs
// FIND HIGHEST/LOWEST VALUES TO BE USED IN 0-255 NORMALIZATION -
PROBABLY WORKING
max = min = bmp[0];
for (ptr=w*3; ptr<w*h*3; ptr++) {
if (max < bmp[ptr]) {
max = bmp[ptr];
} else if (min > bmp[ptr]) {
min = bmp[ptr];
}
}
printf ("%10d %10d\n", max, min);
max -= min;
// NORMALIZE VALUES - WORKKING
for (ptr=w*3; ptr<w*h*3; ptr++) {
//bmp[ptr] = (unsigned long)((float)(bmp[ptr] - min) /
(float)max * (float)255);
bmp[ptr] -= min;
bmp[ptr] <<= 8;
bmp[ptr] /= max;
}
//DENORMALIZE VALUES - WORKING
for (ptr=w*3; ptr<w*h*3; ptr++) {
bmp[ptr] *= max;
bmp[ptr] >>= 8; // it should be /255, but i think it will work
bmp[ptr] += min;
}
// DEBLURRING LOOP - WORKING
for (y=0; y<h; y++) {
printf("%3d\b\b\b",y);
for (x=0; x<w; x++) {
for (c=0; c<3; c++) {
for (rx=-s; rx<=s; rx++) {
for (ry=1; ry<=s; ry++) {
if (!((x+rx < 0) or (x+rx >= w) or (y+ry >= h)))
{ // to avoid page fault
bmp[(x+rx+(y+ry)*w)*3+c] -= bmp[(x+y*w)*3+c];
}
}
}
}
}
}
// OUTPUTTING LOOPs
// COPY SOURCE IMAGE BMP HEADER - WORKING
fseek(fp1, 0, SEEK_SET);
for (ptr=0; ptr<54; ptr++) {
fputc(fgetc(fp1),fp2);
}
// WRITE DATA CONTAINED IN THE BMP ARRAY IN THE SAME ORDER THEY WERE
READ - WORKING
for (ptr=0; ptr<w*h*3; ptr++) {
fputc (bmp[ptr], fp2);
}
fclose(fp1);
fclose(fp2);
}

long flen (FILE *fp)
{
long ptr = ftell(fp);
fseek(fp, 0, SEEK_END);
long lenght = ftell(fp);
fseek(fp, ptr, SEEK_SET);
return lenght;
}

int main(int argc, char *argv[]) {
printf("Simplify ");
printf(VER_STRING);
printf("\n(C) 2003 CAFxX\n\n");

// COMMAND LINE PARSING IS JUST EXPERIMENTAL AND HAS NEVER BEEN TESTED
// SYNTAX WOULD BE
// SIMPLIFY INPUT_FILE OUTPUT_FILE SPREADING_FACTOR [D | E]
// ALL PARAMETERS ARE MANDATORY. LAST PARAMETER IS D(ECODING) | E(NCODING).
// E.G: simplify input.bmp output.bmp 10 e
if (argc == 5) {
if ((fp1 = fopen(argv[2], "rb")) == NULL) { exit(2); }
if ((fp2 = fopen(argv[3], "wb")) == NULL) { exit(1); }
s = atoi(argv[4]);
if (argv[5] == "D" or argv[4] == "d") { /*decode();*/ }
else if (argv[5] == "E" or argv[4] == "e") { /*encode();*/ }
exit(0);
} else if (argc == 1) {

// COLLECTING IMAGE SIZE
printf("Input file must be a 24-bit uncompressed Windows BMP
file!\nSource image width > ");
scanf("%d",&w);
if (w <= 0) { exit(0); } // EXIT IF IMAGE DIMENSIONS ARE NOT VALID
printf("Source image height > ");
scanf("%d",&h);
if (h <= 0) { exit(0); }
// COLLECTING ENCODING SETTINGS
printf("Spreading factor > ");
scanf("%d",&s);

// DUMMY BYTES PER LINE
if ((fp1 = fopen("test.bmp", "rb")) == NULL) { exit(2); }
dummybytes = (flen(fp1) - h * w * 3 + 54) / h;
fclose(fp1);

// ALLOCATE MEMORY AND START PROCESSING
bmp = (unsigned long*)malloc(sizeof(unsigned long)*w*h*3);
if (bmp == NULL) { exit(3); }
test();
free(bmp);
system ("pause");
return 0;

} else {

printf ("Wrong parameter number");
exit(4);

}
}

thanks in advance to anyone that will help.

CAFxX said:
i'm writing a program that executes some calculations on a bitmap loaded in
memory.
these calculation ends up with pixel wth values far over 255, but i need
them to be between 0 and 255 since i got to write them in a bmp file (in
which RGB values are limited to 8 bits per channel). so i need to have them
scaled down.

first of all i find the highest and lowest of those values:(keep in mind
that max, min, bmp[], ptr are ulong and w, h are uint):

// FIND HIGHEST/LOWEST VALUES TO BE USED IN 0-255 NORMALIZATION
max = 0; min = 0-1;
for (int ptr=0; ptr<w*h*3; ptr++) {
if (max < bmp[ptr]) {
max = bmp[ptr];
} else if (min > bmp[ptr]) {
min = bmp[ptr];
}
}

then i normalize everything to 255:

// NORMALIZE VALUES
for (int ptr=0; ptr<w*h*3; ptr++) {
bmp[ptr] = (unsigned long)((float)(bmp[ptr] - min) / (float)max *
(float)255);
}

at this point, everything is alright. if i write in a bmp file the contents
of the array i get what i expected.
but as soon as i denormalize and apply the inverse of the calculations i did
before (i tested them separately: without normalization/denormalization they
work fine)

//DENORMALIZE VALUES
for (int ptr=0; ptr<w*h*3; ptr++) {
bmp[ptr] = (unsigned long)((float)bmp[ptr] / (float)255 * (float)max) + min;
}

then i write down the content of the array:

// OUTPUTTING LOOPs
// COPY SOURCE IMAGE BMP HEADER - WORKING
fseek(fp1, 0, SEEK_SET);
for (int i=0; i<54; i++) {
fputc(fgetc(fp1),fp2);
}
// WRITE DATA CONTAINED IN THE BMP ARRAY IN THE SAME ORDER THEY WERE READ -
WORKING
for (int ptr=0; ptr<w*h*3; ptr++) {
fputc ((unsigned int)bmp[ptr], fp2);
}

but the bitmap i end up with it's a mess of random pixels.
i think i'm doing something wrong in the data type conversion of the
denormalization loop. anyone knows why? i do thank you in advance.

p.s. if you want the full source of the program go to
sourceforge.net/projects/simplify. the function you got to point at is void
test ()
 
R

Ron Natalie

CAFxX said:
if (bmp[ptr]<0 or bmp[ptr]>255) { printf ("%7d: %12d\n", ptr,
(unsigned int)bmp[ptr]); }

The unsigned int cast doesn't do anything useful. %d always expects an int.
 
R

Ron Natalie

CAFxX said:
for (ptr=w*3; ptr<w*h*3; ptr++) {
//bmp[ptr] = (unsigned long)((float)(bmp[ptr] - min) /
(float)max * (float)255);
bmp[ptr] -= min;
bmp[ptr] <<= 8;
bmp[ptr] /= max;
}

You still want (max-min) as a divisor as I pointed out before.
//DENORMALIZE VALUES - WORKING
for (ptr=w*3; ptr<w*h*3; ptr++) {
bmp[ptr] *= max;

Same here.
for (y=0; y<h; y++) {
printf("%3d\b\b\b",y);
for (x=0; x<w; x++) {
for (c=0; c<3; c++) {
for (rx=-s; rx<=s; rx++) {
for (ry=1; ry<=s; ry++) {
if (!((x+rx < 0) or (x+rx >= w) or (y+ry >= h)))
{ // to avoid page fault
bmp[(x+rx+(y+ry)*w)*3+c] -= bmp[(x+y*w)*3+c];
}
}
}
}
}

The above looks bogus. Are you trying to implement an unsharp mask? You most likely
need two buffers, the resultant output pixel is hosed by the modification you make.
 
C

CAFxX

i already placed the max-min:
// NORMALIZING LOOPs
.....
max -= min;
The above looks bogus. Are you trying to implement an unsharp mask? You most likely
need two buffers, the resultant output pixel is hosed by the modification
you make.

no it's not an unsharp mask (at least that wasn't my intention, i don't know
how the unsharp mask filter works) the deblurring loop is supposed to be the
reverse filter of the blurring loop above.
it works this way:
a pixel is read from the source file.
its value is ADDED to its position in memory (§)
its value is ADDED to all the pixel ranging (provided x, y are the pixel's
coordinates): from (x-s, y+1) to (x+s, y+s) where s is the spreading factor
because of these sums the final values are likely above 255 so they have to
be normalized to 255.
this is encoding. now, for decoding:
all the pixels are read and placed in memory
the pixels' values are denormalized.
for every pixel, starting from the first that was encoded,
its value is SUBTRACTED to all the pixel ranging (provided x, y are the
pixel's coordinates): from (x-s, y+1) to (x+s, y+s) where s is the spreading
factor.
so we end up with the original image (because of §).




Ron Natalie said:
for (ptr=w*3; ptr<w*h*3; ptr++) {
//bmp[ptr] = (unsigned long)((float)(bmp[ptr] - min) /
(float)max * (float)255);
bmp[ptr] -= min;
bmp[ptr] <<= 8;
bmp[ptr] /= max;
}

You still want (max-min) as a divisor as I pointed out before.
//DENORMALIZE VALUES - WORKING
for (ptr=w*3; ptr<w*h*3; ptr++) {
bmp[ptr] *= max;

Same here.
for (y=0; y<h; y++) {
printf("%3d\b\b\b",y);
for (x=0; x<w; x++) {
for (c=0; c<3; c++) {
for (rx=-s; rx<=s; rx++) {
for (ry=1; ry<=s; ry++) {
if (!((x+rx < 0) or (x+rx >= w) or (y+ry >= h)))
{ // to avoid page fault
bmp[(x+rx+(y+ry)*w)*3+c] -= bmp[(x+y*w)*3+c];
}
}
}
}
}

The above looks bogus. Are you trying to implement an unsharp mask? You most likely
need two buffers, the resultant output pixel is hosed by the modification you make.
 
C

CAFxX

@ ron natalie
have you tryed to feed it a simple bmp image? for testing i use a 400x300
bitmap with a flat white bg and the text "TEST" on it, with letters coloured
respectively black, red, green, blue.

CAFxX said:
i already placed the max-min:
// NORMALIZING LOOPs
....
max -= min;
The above looks bogus. Are you trying to implement an unsharp mask? You most likely
need two buffers, the resultant output pixel is hosed by the
modification
you make.

no it's not an unsharp mask (at least that wasn't my intention, i don't know
how the unsharp mask filter works) the deblurring loop is supposed to be the
reverse filter of the blurring loop above.
it works this way:
a pixel is read from the source file.
its value is ADDED to its position in memory (§)
its value is ADDED to all the pixel ranging (provided x, y are the pixel's
coordinates): from (x-s, y+1) to (x+s, y+s) where s is the spreading factor
because of these sums the final values are likely above 255 so they have to
be normalized to 255.
this is encoding. now, for decoding:
all the pixels are read and placed in memory
the pixels' values are denormalized.
for every pixel, starting from the first that was encoded,
its value is SUBTRACTED to all the pixel ranging (provided x, y are the
pixel's coordinates): from (x-s, y+1) to (x+s, y+s) where s is the spreading
factor.
so we end up with the original image (because of §).




Ron Natalie said:
for (ptr=w*3; ptr<w*h*3; ptr++) {
//bmp[ptr] = (unsigned long)((float)(bmp[ptr] - min) /
(float)max * (float)255);
bmp[ptr] -= min;
bmp[ptr] <<= 8;
bmp[ptr] /= max;
}

You still want (max-min) as a divisor as I pointed out before.
//DENORMALIZE VALUES - WORKING
for (ptr=w*3; ptr<w*h*3; ptr++) {
bmp[ptr] *= max;

Same here.
for (y=0; y<h; y++) {
printf("%3d\b\b\b",y);
for (x=0; x<w; x++) {
for (c=0; c<3; c++) {
for (rx=-s; rx<=s; rx++) {
for (ry=1; ry<=s; ry++) {
if (!((x+rx < 0) or (x+rx >= w) or (y+ry >= h)))
{ // to avoid page fault
bmp[(x+rx+(y+ry)*w)*3+c] -= bmp[(x+y*w)*3+c];
}
}
}
}
}

The above looks bogus. Are you trying to implement an unsharp mask? You most likely
need two buffers, the resultant output pixel is hosed by the
modification
you make.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top