Search code examples
c++graphicssdlsdl-2

streaming a bitmap while it is modified in C++


What I am trying to do is use some process to alter the contents of a bitmap image ( dimensions and everything else is kept constant). While I run a process to perform transformations on it, I want to concurrently stream the image to my screen as it happens. So it's basically video without a series of images, but rather the same image in different stages of a transformation. I am trying to do this because the bitmap I want to do this with is large, so actually saving each state as its own image and then combining will not be possible due to memory constraints.

My question is regarding the "live image display" while another process modifies the image, is there any way something like this can be done with a bitmap image?


Solution

  • You could stream the images in a video encoder directly.

    For example you can feed ffmpeg with raw PGM/PPM images as input and you will get the compressed video as output without the need to ever create the actual images on disk.

    Writing a PGM or PPM image means just generating a few header bytes followed by actual pixel values and thus is trivial to do with any language without the need of any image library. For example:

    #include <stdio.h>
    #include <math.h>
    #include <algorithm>
    
    int main(int argc, const char *argv[]) {
        int w = 1920, h = 1080;
        for (int frame=0; frame<100; frame++) {
            // output frame header
            printf("P5\n%i %i 255\n", w, h);
            for (int y=0; y<h; y++) {
                for (int x=0; x<w; x++) {
                    double dx = (x - w/2),
                           dy = (y - h/2),
                           d = sqrt(dx*dx + dy*dy),
                           a = atan2(dy, dx) - frame*2*3.14159265359/100,
                           value = 127 + 127*sin(a+d/10);
                    // output pixel
                    putchar(std::max(0, std::min(255, int(value))));
                }
            }
        }
        return 0;
    }
    

    generates on standard output a sequence of images that can be combined in a video directly. Running the program with

    ./video | ffmpeg -i - -r 60 -format pgm -y out.mp4
    

    will generate a video named out.mp4. The video will be at 60fps (what -r is for) created from source images in PGM format (-format pgm) from standard input (option -i -) overwriting the output file if it's already present (-y).

    This code was tested on linux; for this approach to work on windows you need also to set stdout to binary more with _setmode(fileno(stdout), _O_BINARY); or something similar (I didn't test on windows).

    A more sophisticated way to do basically the same would be to start a child process instead of using piping thus leaving standard output usable by the program.