Negative heights when converting SRTM data - c++

I want to get the height for a certain latitude/longitude pair from the NASA SRTM dataset (http://dds.cr.usgs.gov/srtm/version2_1/SRTM3/Eurasia/).
As a starter I want to get all heights from a HGT file:
int totalPx = 1201; //3 degree
char buffer[2];
for (int i=0; i<totalPx; i++)
{
for (int j=0; j<totalPx; j++)
{
int pos = (i * totalPx + j) * 2;
m_openedFile.seek(pos); //m_openedFile is a Qt QFile
m_openedFile.read(buffer, 2);
short h = 0 | (buffer[0] << 8) | (buffer[1] << 0);
if (h < 0)
printf("%d", h);
}
}
This seems to work for some coordinates (e.g. the height values look plausible) but there are also many negative height values. How can I correctly read the SRTM/HGT file?
Regards,

Beware of sign extension when converting char to int
// char buffer[2];
unsigned char buffer[2];
short h = buffer[0] << 8 | buffer[1];

I figured it out: the problem was the signed char instead of the unsigned char which lead to the wrong bit shifts:
int totalPx = 1201; //3 degree
unsigned char buffer[2];
for (int i=0; i<totalPx; i++)
{
for (int j=0; j<totalPx; j++)
{
int pos = (i * totalPx + j) * 2;
m_openedFile.seek(pos); //m_openedFile is a Qt QFile
m_openedFile.read(buffer, 2);
short h = 0 | (buffer[0] << 8) | (buffer[1] << 0);
if (h < 0)
printf("%d", h);
}
}

Related

I'm reading the RGB values of pixels from a BMP file and not getting the correct values

I followed the code at this link read pixel value in bmp file to be able to read the RGB values of pixels and when I have the entire image as one color and read a random pixel's values they are correct. After this I tried to make it so the function would also try and find how many unique colors there were so I added a box with a different color to the image but the function still only finds one color. I'm wondering if maybe I'm somehow not looking at all the bytes contained in the BMP but I'm not sure how that would be as I'm new to trying this stuff.
To make sure the code wasn't finding different colored pixels but failing to add them to the list of unique pixels I tried printing output when a color is found that is different from the one that is always found but no output ever came from it.
struct Color {
int R = -1;
int G = -1;
int B = -1;
};
unsigned char* readBMP(char* filename) {
int i;
FILE* f = fopen(filename, "rb");
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f);
int width = *(int*)&info[18]; //the reason *(int*) is used here because there's an integer stored at 18 in the array that indicates how wide the BMP is
int height = *(int*)&info[22]; // same reasoning for *(int*)
int size = 3 * width * height;
unsigned char* data = new unsigned char[size];
fread(data, sizeof(unsigned char), size, f);
fclose(f);
// windows has BMP saved as BGR tuples and this switches it to RGB
for(i = 0; i < size; i += 3){
unsigned char tmp = data[i];
data[i] = data[i+2];
data[i+2] = tmp;
}
i = 0; // i is the x value of the pixel that is having its RGB values checked
int j = 0; // j is the y value of the pixel that is having its RGB values checked
unsigned char R = data[3 * (i * width + j)]; // value of R of the pixel at (i,j)
unsigned char G = data[3 * (i * width + j) + 1]; // value of G of the pixel at (i,j)
unsigned char B = data[3 * (i * width + j) + 2]; // value of B of the pixel at (i,j)
std::cout << "value of R is " << int(R);
std::cout << " value of G is " << int(G);
std::cout << " value of B is " << int(B);
Color num_colors[5];
int count;
int z;
int flag;
int iterator;
int sum;
for(count = 0; count < size; count += 1){
unsigned char R = data[3 * (i * width + j)];
unsigned char G = data[3 * (i * width + j) + 1];
unsigned char B = data[3 * (i * width + j) + 2];
sum = int(R) + int(G) + int(B);
if(sum != 301) {// 301 is the sum of the RGB values of the color that the program does manage to find
std::cout << sum;
}
flag = 0;
for(z = 0; z < 5; z += 1){
if(num_colors[z].R == R && num_colors[z].G == G && num_colors[z].B == B){
flag = 1;
}
}
if(flag == 1){
continue;
}
iterator = 0;
while(num_colors[iterator].R != -1){
iterator += 1;
}
num_colors[iterator].R = R;
num_colors[iterator].G = G;
num_colors[iterator].B = B;
}
int number = 0;
for(int r = 0; r < 5; r += 1){
std::cout << "\nValue of R here: " << num_colors[r].R;
if(num_colors[r].R != -1){
number += 1;
}
}
std::cout << "\nNumber of colors in image: " << number;
return data;
}
https://imgur.com/a/dXllIWL
This is the picture I'm using so there should be two colors found but the code only finds red pixels.
Your problem is that you are always checking the RGB values at (0,0)
i = 0; // i is the x value of the pixel that is having its RGB values checked
int j = 0; // j is the y value of the pixel that is having its RGB values checked
...
for(count = 0; count < size; count += 1){
unsigned char R = data[3 * (i * width + j)];
unsigned char G = data[3 * (i * width + j) + 1];
unsigned char B = data[3 * (i * width + j) + 2];
i and j defines the X and Y position of the pixel you are checking, but notice that you never change those in the loop. Your loop will keep doing the same thing over and over again. What you probably want is a double loop, going through all coordinates in your image:
for(int y=0; y<height; y++)
for(int x=0; x<width; x++){
unsigned char R = data[3 * (y * width + x) + 0];
unsigned char G = data[3 * (y * width + x) + 1];
unsigned char B = data[3 * (y * width + x) + 2];

decompressing special rle - imageproc

I am trying to decompress an rle file which was compressed in special way .
I am getting back an image which is differenet then the original and I can't understand why.
1st Ill explain the way it was compressed :
the original Image is gray image with only 2 kind of pixels in it : White Or Black .
in the compression they used a byte to represent each sequence of pixels .
the MSB bit in each byte represent White(=1) or Black(=0) . the other 7 Bit represent the sequence so it can be maximum value of 127 .
for example 127 pixels of white will be : 11111111B => 255 DEC.
also 127DEC will represent 127 pixels of black (MSB is 0).
the original Image is 120x240 BMP and I am using a known function (it was given to me) to save BMP files so there is no problem in the saving of array to bmp files if all the rules were followed .
Also in the compressed file the first 2 BYTE will represent the arraysize . arraysize = rle[0]*256 + rle[1].
I'll put here only the part the decompress and compress ( I built them both)
void RleDeCompress(unsigned char rleimage[2 + 240 * 120], unsigned char decompressedimage[][NUMBER_OF_COLUMNS])
{
// 1st MSB bit from the 8 bit of each cell in the array represent color - Black or White
//2nd~7th BIT represent the number of times the color repeats itself
// first 2 cells in the array are represent the size of the array
int arraysize = rleimage[0] * 256 + rleimage[1];
int row = 0;
int col = 0;
unsigned char colormask = 128; //binary 10000000=128dec
unsigned char multiplymask = 127; // binary 01111111 = 127dec
unsigned int total = 0;
for (int i = 2; i < arraysize+2; i++)
{
unsigned char blackorwhitebinary = (rleimage[i] & colormask) >> 7 ; // mask only the msb and then shift it to be the lsb
unsigned char color = 255 * blackorwhitebinary; // decide if this is black or white
unsigned char multiply = rleimage[i] & multiplymask; // number of times the color repeats itself
for (int j = 0; j < multiply; j++)
{
decompressedimage[row][col] = color;
col++;
if (col == NUMBER_OF_COLUMNS)
{
row++;
col = 0;
}
if (row > NUMBER_OF_ROWS) cout << "error too many rows " << endl;
}
total += multiply;
// check total of cells real in the binary file
}
cout << "total is:" << total << endl;
}
void RleCompress(unsigned char image[][NUMBER_OF_COLUMNS], unsigned char RleImage[2 + 240 * 120])
{
unsigned char n = 0;
unsigned int N = 2;
unsigned int arrsize=0;
unsigned char temparray[ 240 * 120];
for (int row = 0; row < NUMBER_OF_ROWS; row++)
{
for (int column = 0; column < NUMBER_OF_COLUMNS; column++)
{
temparray[arrsize] = image[row][column] / 255;
arrsize++;
}
}
for (int i = 0; i < arrsize; i++)
{
n++;
if (n == 127)
{
RleImage[N+2] = temparray[i] * 128 + n;
n = 0;
N++;
}
else
{
if (i == arrsize)
{
RleImage[N + 2] = temparray[i] * 128 + n;
}
else
{
if (temparray[i] != temparray[i + 1])
{
RleImage[N + 2] = temparray[i] * 128 + n;
n = 0;
N++;
}
}
}
}
RleImage[0] = N / 256;
RleImage[1] = N % 256;
}
void SaveRleFile(unsigned char RleImage[2 + 240 * 120])
{
ofstream myfile;
myfile.open("P01C.bin", ios::out | ios::binary);
if (myfile.is_open())
{
int index = 0;
while (index < 2 + 120 * 240)
{
myfile << RleImage[index];
index++;
}
cout << "index is :" << index << endl;
}
myfile.close();
}
void LoadRleBinFile(char binfilename[], unsigned char * image)
{
//for (int j = 0; j < 2 + 120 * 240; j++) image[j] = 255; //clears the array from garbage and sets all of it to white.
ifstream myfile;
char c;
int i = 0;
myfile.open(binfilename, ios::in | ios::binary); // open file in binary mode input only
if (myfile.is_open())
{
while (!myfile.eof())
{
myfile.get(c);
image[i] = (unsigned char) c;
i++;
}
}
else
cout << "error while opening file " << endl;
myfile.close();
}
void main()
{
unsigned char GrayImage[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS];
unsigned char Rlearray[2 + 240 * 120]; //rlearray size is unknown when first initialzing . worst case is 2 + 240*120
LoadGrayImageFromTrueColorBmpFile(GrayImage, "P01A.bmp");
StoreGrayImageAsGrayBmpFile(GrayImage, "P01B.bmp");
//--------------------------------------------------------------------------------------------------------------------------
ConvertGrayImageToBlackWhite(GrayImage);
StoreGrayImageAsGrayBmpFile(GrayImage, "P01B2.bmp");
RleCompress(GrayImage, Rlearray);
SaveRleFile(Rlearray);
LoadRleBinFile("P01C.rle", Rlearray);
RleDeCompress(Rlearray, GrayImage);
StoreGrayImageAsGrayBmpFile(GrayImage, "P01C.BMP");
//WaitForUserPressKey();
}
I found a way to check that there is a problem and it's in the code .
the number of pixels in the picture (120*240 =28800 )should be ,or atleast thats what seems most logic to me , equal to the sum of all the sequence because if not then we didn't compressed the whole image.
In my code the sum of all the sequences is about 17000 . != 28800 .
I don't understand if I didn't compressed right or didnt decompressed right but from looking on the binary file (with binary viewer program) it seems the binary rle file is ok .

Write small bmp on console via C++

I'm trying to read painted 16x16 bmp, but there is no 1 pixel = 3 bits (RGB). Even if first 4-5 lines is white and the rest is black the document is still full of 255 255 255 for each pixel.
In my case I need to show this image in console by analyzing RGB layers of each pixel but have a lot of trouble with it.
int main()
{
FILE* f = fopen("image.bmp", "rb");
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header
// extract image height and width from header
int width = *(int*)&info[18];
int height = *(int*)&info[22];
int size = 3 * width * height;
unsigned char * data = new unsigned char[size]; // allocate 3 bytes per pixel
fread(data, sizeof(unsigned char), size, f); // read the rest of the data at once
fclose(f);
for (int i = 0; i < size; i += 3)
{
unsigned char tmp = data[i];
data[i] = data[i + 2];
data[i + 2] = tmp;
}
unsigned int * byteData = new unsigned int[size];
for (int i = 0; i <= size; i++)
{
byteData[i] = (int) data[i];
}
for (int i = 0; i <= size / 3; i++)
{
cout << i << ".\t" << byteData[i] << "\t" << byteData[i + 1] << "\t" << byteData[i + 2] << endl;
}
cout << endl;
cout << "=======================" << endl;
for (int j = 0; j < width; j++)
{
cout << j + 1 << ".\t";
for (int i = 0; i < height; i++)
{
//if ((int)data[j * width + i] >= 100 && (int)data[j * width + i + 1] >= 100 && (int)data[j * width + i + 2] >= 100)
if (((int) data[j * width + i] + (int) data[j * width + i + 1] + (int) data[j * width + i + 2]) / 3 <= 170)
cout << " ";
else cout << "*";
}
cout << endl;
}
getchar();
return 0;
}
As I think problem with byte sequenses and reading memory frome garbage, but if you could explain where is leak?
The solution is next: bmp should be created with 24 bpp and top-down row order.
Correct code is for 16x16 bitmap:
#include <iostream>
using namespace std;
unsigned char* readBMP(char* filename);
int main()
{
unsigned char * data = readBMP("winLogo.bmp");
int size = 16*16*3;
unsigned int * byteData = new unsigned int[size];
for (int i = 0; i <= size; i++)
{
byteData[i] = (int)data[i];
}
int k = 0;
//uncomment to write a line of RGB values
//for (int i = 0; i < size; i += 3)
//{
// cout << k+1 << ".\t" << byteData[i] << "\t" << byteData[i + 1] << "\t" << byteData[i + 2] << endl;
// k++;
//}
for (int i = 0; i < size; i+= 3)
{
if (i % 16*3 == 0)
{
cout << endl << (i/(16*3))+1 << ".\t";
}
else {};
if (byteData[i] >= 200 && byteData[i + 1] >= 200 && byteData[i + 2] >= 200)
cout << " ";
else
cout << "#";
}
getchar();
return 0;
}
unsigned char* readBMP(char* filename)
{
int i;
FILE* f = fopen(filename, "rb");
unsigned char info[54];
fread(info, sizeof(unsigned char), 54, f); // read the 54-byte header
// extract image height and width from header
int width = *(int*)&info[18];
int height = *(int*)&info[22];
int size = -3 * width * height;
unsigned char* data = new unsigned char[size]; // allocate 3 bytes per pixel
fread(data, sizeof(unsigned char), size, f); // read the rest of the data at once
fclose(f);
//BGR -> RGB
for (i = 0; i < size; i += 3)
{
unsigned char tmp = data[i];
data[i] = data[i + 2];
data[i + 2] = tmp;
}
return data;
}

Applying a transparent gradient from left to right in C/C++

I'm trying to create an algorithm in C/C++, which applies a uniform transparent gradient from left to right to a pixel buffer. As seen on the next image:
Next is so far my implementation. But the resulting image is not even close to what I need to achieve. Anyone can spot what I'm doing wrong? Thanks
void alphaGradient(uint32_t* pixelsBuffer, const int width, const int height)
{
const short OPAQUE = 255;
int pixelOffsetY, pixelIndex;
short A, R, G, B;
for (int y = 0; y < height; y++)
{
A = OPAQUE;
pixelOffsetY = y * height;
for (int x = 0; x < width; x++)
{
pixelIndex = pixelOffsetY + x;
A = (int)(OPAQUE - ((OPAQUE * x) / width));
R = (pixelsBuffer[pixelIndex] & 0x00FF0000) >> 16;
G = (pixelsBuffer[pixelIndex] & 0x0000FF00) >> 8;
B = (pixelsBuffer[pixelIndex] & 0x000000FF);
pixelsBuffer[pixelIndex] = (A << 24) + (R << 16) + (G << 8) + B;
}
}
}
I haven't tried this code out but something like this should work :
void alphaGradient(uint32_t* pixelBuffer, const int width, const int height)
{
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
const DWORD src = pixelBuffer[i + j * width];
const DWORD dst = MYBACKGROUNDCOLOR;
const unsigned char src_A = (width - i) * 255 / width;
const unsigned char src_R = (src & 0x00FF0000) >> 16;
const unsigned char src_G = (src & 0x0000FF00) >> 8;
const unsigned char src_B = (src & 0x000000FF);
//const unsigned char dst_Alpha = (src & 0xFF000000) >> 24;
const unsigned char dst_R = (dst & 0x00FF0000) >> 16;
const unsigned char dst_G = (dst & 0x0000FF00) >> 8;
const unsigned char dst_B = (dst & 0x000000FF);
const unsigned char rlt_R = (src_R * src_A + dst_R * (255 - src_A)) / 255;
const unsigned char rlt_G = (src_G * src_A + dst_G * (255 - src_A)) / 255;
const unsigned char rlt_B = (src_B * src_A + dst_B * (255 - src_A)) / 255;
//pixelBuffer[i + j*width] = (DWORD)(((255) << 24) | (((rlt_R)& 0xff) << 16) | (((rlt_G)& 0xff) << 8) | ((rlt_B)& 0xff));
// or if you want to save the transparancy then
//pixelBuffer[i + j*width] = (DWORD)(((src_A) << 24) | (((src_R)& 0xff) << 16) | (((src_G)& 0xff) << 8) | ((src_B)& 0xff));
}
}
}
But personally, I would try to use DirectX or OpenGL for this and write a good PixelShader. It would make this ALOT faster.
As a suggestion, since you only want to modify the alpha channel, you do not need to do anything with the colors. So the following would work too:
char *b((char *) pixelBuffer);
for(int j = 0; j < height; ++j)
{
for(int i = 0; i < width; ++i, b += 4)
{
*b = (width - i) * 255 / width;
}
}
That's it. You could also eliminate the computation for each line by duplicating the data of the first line in the following lines:
// WARNING: code expects height > 0!
char *b((char *) pixelBuffer);
for(int i = 0; i < width; ++i, b += 4)
{
*b = (width - i) * 255 / width;
}
int offset = width * -4;
for(int j = 1; j < height; ++j)
{
for(int i = 0; i < width; ++i, b += 4)
{
*b = b[offset];
}
}
I will leave as an exercise to you to change this double for() loop in a single for() loop, which would make it a little faster yet (because you'd have a single counter (variable b) instead of three).
Note that I do not understand how Mikael's answer would work as he uses the * 255 in the wrong place in his computation of the alpha channel. With integer arithmetic, that's very important. So this should return 0 or 255:
(width - i) / width * 255
because if value < width then value / width == 0. And (width - i) is either width or a value smaller than width...

How can I pad my md5 message with c/c++

I'm working on a program in c++ to do md5 checksums. I'm doing this mainly because I think I'll learn a lot of different things about c++, checksums, OOP, and whatever else I run into.
I'm having trouble the check sums and I think the problem is in the function padbuff which does the message padding.
#include "HashMD5.h"
int leftrotate(int x, int y);
void padbuff(uchar * buffer);
//HashMD5 constructor
HashMD5::HashMD5()
{
Type = "md5";
Hash = "";
}
HashMD5::HashMD5(const char * hashfile)
{
Type = "md5";
std::ifstream filestr;
filestr.open(hashfile, std::fstream::in | std::fstream::binary);
if(filestr.fail())
{
std::cerr << "File " << hashfile << " was not opened.\n";
std::cerr << "Open failed with error ";
}
}
std::string HashMD5::GetType()
{
return this->Type;
}
std::string HashMD5::GetHash()
{
return this->Hash;
}
bool HashMD5::is_open()
{
return !((this->filestr).fail());
}
void HashMD5::CalcHash(unsigned int * hash)
{
unsigned int *r, *k;
int r2[4] = {0, 4, 9, 15};
int r3[4] = {0, 7, 12, 19};
int r4[4] = {0, 4, 9, 15};
uchar * buffer;
int bufLength = (2<<20)*8;
int f,g,a,b,c,d, temp;
int *head;
uint32_t maxint = 1<<31;
//Initialized states
unsigned int h[4]{ 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476};
r = new unsigned int[64];
k = new unsigned int[64];
buffer = new uchar[bufLength];
if(r==NULL || k==NULL || buffer==NULL)
{
std::cerr << "One of the dyn alloc failed\n";
}
// r specifies the per-round shift amounts
for(int i = 0; i<16; i++)
r[i] = 7 + (5 * ((i)%4) );
for(int i = 16; i < 32; i++)
r[i] = 5 + r2[i%4];
for(int i = 32; i< 48; i++)
r[i] = 4 + r3[i%4];
for(int i = 48; i < 63; i++)
r[i] = 6 + r4[i%4];
for(int i = 0; i < 63; i++)
{
k[i] = floor( fabs( sin(i + 1)) * maxint);
}
while(!(this->filestr).eof())
{
//Read in 512 bits
(this->filestr).read((char *)buffer, bufLength-512);
padbuff(buffer);
//The 512 bits are now 16 32-bit ints
head = (int *)buffer;
for(int i = 0; i < 64; i++)
{
if(i >=0 && i <=15)
{
f = (b & c) | (~b & d);
g = i;
}
else if(i >= 16 && i <=31)
{
f = (d & b) | (~d & b);
g = (5*i +1) % 16;
}
else if(i >=32 && i<=47)
{
f = b ^ c ^ d;
g = (3*i + 5 ) % 16;
}
else
{
f = c ^ (b | ~d);
g = (7*i) % 16;
}
temp = d;
d = c;
c = b;
b = b + leftrotate((a + f + k[i] + head[g]), r[i]);
a = temp;
}
h[0] +=a;
h[1] +=b;
h[2] +=c;
h[3] +=d;
}
delete[] r;
delete[] k;
hash = h;
}
int leftrotate(int x, int y)
{
return(x<<y) | (x >> (32 -y));
}
void padbuff(uchar* buffer)
{
int lack;
int length = strlen((char *)buffer);
uint64_t mes_size = length % UINT64_MAX;
if((lack = (112 - (length % 128) ))>0)
{
*(buffer + length) = ('\0'+1 ) << 3;
memset((buffer + length + 1),0x0,lack);
memcpy((void*)(buffer+112),(void *)&mes_size, 64);
}
}
In my test program I run this on the an empty message. Thus length in padbuff is 0. Then when I do *(buffer + length) = ('\0'+1 ) << 3;, I'm trying to pad the message with a 1. In the Netbeans debugger I cast buffer as a uint64_t and it says buffer=8. I was trying to put a 1 bit in the most significant spot of buffer so my cast should have been UINT64_MAX. Its not, so I'm confused about how my padding code works. Can someone tell me what I'm doing and what I'm supposed to do in padbuff? Thanks, and I apologize for the long freaking question.
Just to be clear about what the padding is supposed to be doing, here is the padding excerpt from Wikipedia:
The message is padded so that its length is divisible by 512. The padding works as follows: first a single bit, 1, is appended to the end of the message. This is followed by as many zeros as are required to bring the length of the message up to 64 bits fewer than a multiple of 512. The remaining bits are filled up with 64 bits representing the length of the original message, modulo 264.
I'm mainly looking for help for padbuff, but since I'm trying to learn all comments are appreciated.
The first question is what you did:
length % UINT64_MAX doesn't make sense at all because length is in bytes and MAX is the value you can store in UINT64.
You thought that putting 1 bit in the most significant bit would give the maximum value. In fact, you need to put 1 in all bits to get it.
You shift 1 by 3. It's only half the length of the byte.
The byte pointed by buffer is the least significant in little endian. (I assume you have little endian since the debugger showed 8).
The second question how it should work.
I don't know what exactly padbuff should do but if you want to pad and get UINT64_MAX, you need something like this:
int length = strlen((char *)buffer);
int len_of_padding = sizeof(uint64_t) - length % sizeof(uint64_t);
if(len_of_padding > 0)
{
memset((void*)(buffer + length), 0xFF, len_of_padding);
}
You worked with the length of two uint64 values. May be you wanted to zero the next one:
uint64_t *after = (uint64_t*)(buffer + length + len_of_padding);
*after = 0;