Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I have an issue where I'm writing out a simple 8-bit grayscale bitmap as I read it from a stream.

The issue is this:

I'm going top to bottom left to right, and attempting to read the pixels out of the bitmap sequentially. I feel like this should work, but it doesn't. My data isn't in order.

However, when I explicitly force the stream to the correct position by seeking to this:
C++
bitmap_offset + (x + y * glyph.size.width)


It works.

Here's the thing I don't get - that should yield the same results as the sequential read because I am going top to bottom left to right (see the code in the other section). What am I missing? I don't want that extra seek in my code.

What I have tried:

C++
gfx_result vlw_font::draw(draw_callback draw_cb, const glyph& glyph, uint32_t bitmap_offset, void*state) const {
    if(draw_cb==nullptr || bitmap_offset<24+(glyph_count*28)) {
        return gfx_result::invalid_argument;
    }
    if(m_stream==nullptr || !m_stream->caps().read || !m_stream->caps().seek) {
        return gfx_result::invalid_state;
    }
    int y_adj = max_ascent-glyph.y_delta;
    seek_data(m_stream,bitmap_offset);
    for(int y = 0;y<glyph.size.height;++y) {
        for(int x = 0;x<glyph.size.width;++x) {
            uint8_t tmp;
            size_t s=1;
            // without the following two lines
            // the data is out of order
            uint32_t ofs = bitmap_offset + (x+y*glyph.size.width);
            seek_data(m_stream,ofs);

            read_data(m_stream,&tmp,&s);
            if(s!=1) return gfx_result::io_error;
            draw_cb(x+glyph.x_delta,y+y_adj,tmp,state);
        }
    }
    return gfx_result::success;
}
Posted
Comments
k5054 20-Aug-23 19:07pm    
What is read_data() doing? Is it somehow causing the file offset pointer to be somewhere other than current + s when it returns?
honey the codewitch 21-Aug-23 1:07am    
read_data simply reads from the stream at the last place it was seeked to, and advances the cursor by however many bytes were actually read.
Peter_in_2780 20-Aug-23 23:22pm    
Don't know about your case, but in the past I (and a zillion others) have been bitten by end-of-line padding.
Particularly when the pixel size is not a divisor of the (padded) line length, things go down the gurgler very quickly.
honey the codewitch 21-Aug-23 1:08am    
My bitmap code is such that there is no end of line padding, but yeah I know what you mean. I have to do some acrobatics on an e-paper panel driver i wrote due to that.
CPallini 21-Aug-23 2:53am    
It looks read_data is not doing what you expect it should. Maybe it is doing more than you expect :-)

1 solution

From what I could read (might be missing the ball completely) -

There shouldn't be a need for the extra seek operation, as you're already calculating the offset based on the pixel's position. It is possible that the issue might be related to the way your stream's internal state or buffer management is interacting with your sequential reads.

When you perform a read operation 'read_data' from the stream, it might consume a certain amount of data from your stream's internal buffer. This might cause the stream's internal position to become misaligned with your calculated offset 'ofs', leading to the out-of-order data.

By adding the extra seek operation, you are effectively resetting your stream's position to the expected offset, ensuring that the subsequent read operation starts from the correct position. While the extra seek might seem redundant, it could serve as a workaround for you to ensure proper alignment between your calculated offset and the stream's actual position. You can add a check if the calculated offset 'ofs' is different from your stream's current position. If the offset is the same as the current position, skip the seek operation and directly perform the read operation using 'read_data'. Not exactly what you wanted though but I hope it shed some light on your issue -
C++
gfx_result vlw_font::draw(draw_callback draw_cb, const glyph& glyph, uint32_t bitmap_offset, void* state) const {
    if (draw_cb == nullptr || bitmap_offset < 24 + (glyph_count * 28)) {
        return gfx_result::invalid_argument;
    }
    if (m_stream == nullptr || !m_stream->caps().read || !m_stream->caps().seek) {
        return gfx_result::invalid_state;
    }
    int y_adj = max_ascent - glyph.y_delta;

    for (int y = 0; y < glyph.size.height; ++y) {
        for (int x = 0; x < glyph.size.width; ++x) {
            uint8_t tmp;
            size_t s = 1;
            
            uint32_t ofs = bitmap_offset + (x + y * glyph.size.width);

            //Use seek_data only if the offset has changed to reset the misaligned position...
            if (ofs != m_stream->current_position()) {
                seek_data(m_stream, ofs);
            }

            read_data(m_stream, &tmp, &s);
            if (s != 1) return gfx_result::io_error;

            draw_cb(x + glyph.x_delta, y + y_adj, tmp, state);
        }
    }
    return gfx_result::success;
}
 
Share this answer
 
Comments
CPallini 21-Aug-23 5:23am    
I do believe your analysis is correct (my 5). Anyway, I would investigate the misbehavior of read_data instead to fix it the way you suggested.
Andre Oosthuizen 21-Aug-23 5:27am    
Thank you very much!I agree, my suggestions is more like taking a tablet rather than finding the cause.
honey the codewitch 21-Aug-23 7:16am    
Thanks. Exactly what I needed before I went further. Everything you say jibes with what I understand, but the stream code itself is used in professional projects. Yikes. It's never broken before that I know of, and I use it for complicated stuff like streaming TrueType off of a file
Andre Oosthuizen 21-Aug-23 7:34am    
You're welcome, trust it will work out for you!
honey the codewitch 21-Aug-23 8:22am    
Oh, I'm probably not going to use your workaround, no offense! :). I'm going to find the problem. I can't have this code underneath read_stream() not working properly, as it's mission critical in a lot of projects.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900