Weird pixel data, can't understand.

Started by
8 comments, last by frob 4 years, 4 months ago

I'm trying to read in the pixel data from a bitmap. The following code is supposed to display:

FF00 FFFFFF 00 00FF 0FF0 00

instead it displays this:

FF 0 0 FF FF FF 0 0 0 FF 0 F0 F 0 0 0

I can't find the problem, tracing the code looks okay, so I'm thinking it is the location variable, but so far, no luck. The solution should have only FF and 0, not F0 and F.

https://github.com/josheirm/BitmapExpander2/tree/branch7

Thanks!

 
    do {
        
        memset(dest2, 0x00, 100);
        memset(dest, 0x00, 100);
        int answer = 0;
        //set of three values       
        if (counter == 0 || counter == 1 )
        {
            file = fopen("b.bmp", "r");
            fseek(file, location, SEEK_SET);
           
            answer = fgetc(file);
            if (feof(file)) {
                fclose(file);
                break;
            }
            sprintf(dest, "%X", answer);
            strcpy(dest2, dest);
            location++;
           
            answer = fgetc(file);
            if (feof(file)) {
                fclose(file);
                break;
            }
            
            sprintf(dest, "%X", answer);
            strcat(dest2, dest);
            location++;
            
            answer = fgetc(file);
            if (feof(file)) {
                fclose(file);
                break;
            }
            fclose(file);
          
            sprintf(dest, "%X", answer);
            strcat(dest2, dest);
            counter++;
            location++;

            decimal = hexadecimalToDecimal(dest2);
            file = fopen("C:/Users/joshe/file7", "a");
            //set of three data
            fwrite(&decimal, 3, 1, file);
            fclose(file);
        }
        //set of two values
        else if (counter == 2)
        {
            memset(dest2, 0x00, 100);
            memset(dest, 0x00, 100);

            file = fopen("b.bmp", "r");
            fseek(file, location, SEEK_SET);
            
            answer = fgetc(file);
            if (feof(file)) {
                fclose(file);
                break;
            }
            sprintf(dest, "%X", answer);
            strcpy(dest2, dest);
            location++;
            
            
            answer = fgetc(file);
            if (feof(file)) {
                fclose(file);
                break;
            }
            fclose(file);
            sprintf(dest, "%X", answer);
            strcat(dest2, dest);
            counter = 0;
            location++;
            
            decimal = hexadecimalToDecimal(dest2);
            file = fopen("C:/Users/joshe/file7", "a");
            //set of two data
            fwrite(&decimal, 2, 1, file);
            fclose(file);
           
        }
    } while(1);    
Advertisement

God, this message editor sucks so bad!

Hard to say since you omit a few details. The code to hexadecimalToDecimal is missing, also how you determine the wrong output. By looking at file7?

Have you used a debugger to step through? Should be easy to pin point the cause.

The culprit is probably hexadecimalToDecimal, assuming the content of b.bmp is FF0000FFFFFF00000000FF00FF000000.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

I have tried stepping through and I can't determine the problem. The hexadecimalltodecimal seems right and the content of b.bmp is : 0 0 FF, FF FF FF, 0 0, FF 0 0, 0 FF 0, 0 0 before each section is reversed. I was also getting a bunch of ambiguous fclose and strcat errors but the project still executed. When I reloaded visual studio it tended to disappear. Here are the two functions:

// Function to convert hexadecimal to decimal 
int hexadecimalToDecimal(char hexVal[])
{
    int len = strlen(hexVal);

    // Initializing base value to 1, i.e 16^0 
    int base = 1;

    int dec_val = 0;

    // Extracting characters as digits from last character 
    //for (int i = len - 1 ; i >= 0; i--)
    for (int i = len - 1; i >= 0; i--)
    
    {
        // if character lies in '0'-'9', converting  
        // it to integral 0-9 by subtracting 48 from 
        // ASCII value. 
        if (hexVal[i] >= '0' &amp;amp;amp;&amp;amp;amp; hexVal[i] <= '9')
        {
            dec_val += (hexVal[i] - 48) * base;

            // incrementing base by power 
            base = base * 16;
        }

        // if character lies in 'A'-'F' , converting  
        // it to integral 10 - 15 by subtracting 55  
        // from ASCII value 
        else if (hexVal[i] >= 'A' &amp;amp;amp;&amp;amp;amp; hexVal[i] <= 'F')
        {
            dec_val += (hexVal[i] - 55) * base;

            // incrementing base by power 
            base = base * 16;
        }
    }

    return dec_val;
}

int GetSizeImageData()
{
    FILE* file;
    int i;
    int counter = 0;
    //char buf[27];
    file = fopen("C:/Users/joshe/file7", "r");
    //for (i = 0; i < 1478; i++)
    fseek(file, 0, SEEK_SET);
    do {


        
        i = fgetc(file);
        if (feof(file)) {
            fclose(file);
            break;
        }
        counter++;
        //4 bytes * 54 = 
        printf("%X ", i);

    } while (1);

removed

dest2 is correct throughout the code.

else if (hexVal[i] >= 'A' &amp;amp;amp;&amp;amp;amp; hexVal[i] <= 'F')

is

else if (hexVal[i] >= 'A' && hexVal[i] <= 'F')

Josheir said:
sprintf(dest, "%X", answer);

%X alone will print a number in hexidecimal format, yes, but you want more than that. You seem want it to be two digits using zeros as a prefix.

The Printf family supports that. I recommend learning about all the different flags and specifiers allowed.

I believe what you're looking for is “%02X”, which means to left-pad with zeros if necessary, and to print at least two characters. This will print values like 00, 01, 02, … 09, 0A, 0B … 0F, 10, 11, 12, … but once the value exceeds two digits it won't be limited: … FE, FF, 100, 101, 102 …

You have many oddities in that code, I'm not sure why they are there:

You are printing to a buffer, then copying to another buffer, but you aren't checking the lengths. If this is C++, consider using a string class that ensure you're not stomping on memory. Otherwise, add some limits to ensure you don't exceed lengths.

You have a magic number of 100 bytes rather than a named constant that would make some sense, but no explanation of why.

Consider using a member of the printf family that directly prints to the stream. While your add it, add a space to the printing code, either to print a space before each value except for the first time through, or to print a space after each value except for the last time through.

Your hexadecimalToDecimal() function also appears to be duplicate the standard library. Look up strtol().

But even if you used standard library functions to do the work, I'm not sure why you're doing what you do with it in code. You're first converting a data value into a hexidecimal string, then you're converting the hexidecimal string back into a data value, then you're using fwrite to incorrectly write a portion of the data value. I would expect that you either write the hex strings directly to the stream, or that you accumulate the hex strings then write a string.

When you do eventually get around to writing to the file -- after doing a several questionable conversions -- you have a four byte data value but you use fwrite to output two bytes of the data value instead of the whole thing. My guess there is you simply don't know what you're doing. Calling it a bug is generous. If you were a beginning student I'd call it a bug, but out in the professional world, I'd say it's a gross failure to understand multiple basic concepts of the C language. Understanding basic data types and the size of basic data types is fundamental to the language.

Putting on my instructor glasses reading the code, it looks as though you need a comprehensive review basic data structures, especially the difference between strings (an array of data values containing characters), ints (a data value typically containing 32 bytes, but possibly a low as 16 bytes and possibly many more), and a review of how to manipulate file data streams. I would also recommend, since your link says this is a C++ file, that you learn about C++ stream manipulations, C++ string manipulations, and C++ file manipulations. Doing it with C operations can work, but it is jarring for anyone working in C++ code to shift into C standard library instead of the C++ standard library.

When I was teaching, these basic data types, data sizes, and the other parts were literally covered and drilled in the very first programming course “Introduction to C++, Part 1". You MUST understand that data structure stuff to program. It is not optional. It cannot be a weak understanding. It must be mastered, and come out correctly every time. I'm sorry if this comes across as too preachy or too strong, but I feel I cannot stress enough just how fundamental these data types and manipulations are, not just fundamental to this programming language, but fundamental to everything done in computer programming and in computer science. It forms the basis of EVERYTHING in computer science, the data types are literally the alphabet of Turing machines and of all finite automata. They are called the alphabet, written on an infinite tape. You cannot write correct programs for a modern computer, nor do any serious work in the field of Computer Science, without understanding it. Go back and study your fundamental data types.

Well, all of this was all very helpful. I noticed that I was using getc incorrectly and of course I shouldn't have been using writef() at all. But, what else is there to know about data structures besides their size, and what they are (a string of characters for example.)

Thanks,

Josheir

Okay, a few of them.

The code has structures that are the wrong size. Why do you have a 100 byte array to hold 3 bytes individually, which is much too large? Why are you building a large, potentially unbounded size string out of another 100 byte array which may be too small? The first is sloppy and shows a failure to consider what's being stored. The second is potentially a crash or an exploit.

The code is doing conversions that are unnecessary. Data values are converted into strings, then the strings are converted back into data values. Then a partial data value was written. It seems to show a lack of understanding of what the data actually is. Choose to work in one or the other, either work as a string --- which is slower and more error prone --- or choose to work as a data value with a single data conversion at the end.

The cpp file you linked to on github is filled with data size errors. You've got a bunch of fixed arrays, like your char bitmap[2478] where it appears you only use 1078 bytes, hecaDeciNum[100] that never reaches anywhere near that, inside your ReadAndWrite function you've got buffer2[50] and buffer3[50], which you initialize twice each (rather than first initializing with a string constant then memsetting the values to zero, instead use char buffer2[50]={0}; ) where you proceed to read a file of unknown size appending into that 50 byte array, although it looks like you only happen to use at most 36 bytes through happenstance.

There doesn't seem to be any reason for most of your data sizes, other than that you like to allocate either 50 or 100, and they're rarely the actual memory you need. If you know the size then use the correct size. If you don't know the size use a structure or object that is dynamically sized. Never guess at how big data needs to be.

This topic is closed to new replies.

Advertisement