Custom Sprite to BMP saving function with Inline

Previous topic - Next topic

dreamerman

SAVESPRITE is great, but if you would need to do some transformations like mirroring, grayscale, disable one channel, add filtering or whatever, this code can be handy:

Code (glbasic) Select
//offscreen sprite to BMP saving function
//answers from this topic were useful: http://stackoverflow.com/questions/2654480/writing-bmp-image-in-pure-c-c-without-other-libraries
//by dreamerman[at]wp[dot]pl
FUNCTION save_offscreen_bmp%: sprite_id%, file_name$
    LOCAL swidth%, sheight%, pixel_data%[]
    LOCAL extrabytes%, paddedSize%, filesize%, i1%, i2%, pos%, cx%, cy%
       
       
    GETSPRITESIZE sprite_id%, swidth%, sheight%
    extrabytes% = 4 - MOD((swidth% * 3), 4)
    IF (extrabytes% = 4) THEN extrabytes% = 0
    paddedSize% = (swidth% * 3 + extrabytes%) * sheight%
    filesize% = paddedSize% + 54
    SPRITE2MEM(pixel_data%[], sprite_id%)

   
   
    INLINE
        unsigned char bmp_cache[filesize];
//bmp header info       
// = {66,77, 0,0,0,0, 0,0, 0,0, 54,0,0,0, 40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0, 0,0,0,0, 0,0,0,0, 0x13,0x0B,0,0, 0x13,0x0B,0,0, 0,0,0,0, 0,0,0,0};
        for(i1=0;i1<54;i1++) {
            bmp_cache[i1] = 0;
        }
        bmp_cache[0] = 66;
        bmp_cache[1] = 77;
        bmp_cache[2] = (unsigned char)(filesize);
        bmp_cache[3] = (unsigned char)(filesize >> 8);
        bmp_cache[4] = (unsigned char)(filesize >> 16);
        bmp_cache[5] = (unsigned char)(filesize >> 24);
        bmp_cache[10] = 54;
        bmp_cache[14] = 40;
        bmp_cache[18] = (unsigned char)(swidth);
        bmp_cache[19] = (unsigned char)(swidth >> 8);
        bmp_cache[20] = (unsigned char)(swidth >> 16);
        bmp_cache[21] = (unsigned char)(swidth >> 24);
        bmp_cache[22] = (unsigned char)(sheight);
        bmp_cache[23] = (unsigned char)(sheight >> 8);
        bmp_cache[24] = (unsigned char)(sheight >> 16);
        bmp_cache[25] = (unsigned char)(sheight >> 24);
        bmp_cache[26] = 1;
        bmp_cache[28] = 24;
        bmp_cache[34] = (unsigned char)(paddedSize);
        bmp_cache[35] = (unsigned char)(paddedSize >> 8);
        bmp_cache[36] = (unsigned char)(paddedSize >> 16);
        bmp_cache[37] = (unsigned char)(paddedSize >> 24);
        bmp_cache[38] = 19;
        bmp_cache[39] = 11;
        bmp_cache[42] = 19;
        bmp_cache[43] = 11;
       
        int col;
        char cr, cg, cb;
        pos = 54;
        for(cy=sheight-1;cy>=0;cy--) {
            for(cx=0;cx<swidth;cx++) {
                col = pixel_data(cy * swidth + cx);
                cb = (col & 0x00FF0000) >> 16;
                cg = (col & 0x0000FF00) >> 8;
                cr = (col & 0x000000FF);
                bmp_cache[pos] = cb;
                bmp_cache[pos+1] = cg;
                bmp_cache[pos+2] = cr;
                pos+=3;
            }
            if(extrabytes) {
                for(i1=0;i1<=extrabytes;i1++) {
                    bmp_cache[pos+i1] = 0;
                }
                pos+=extrabytes;
            }
        }
       
        FILE * myfile;
        myfile = fopen(file_name_Str, "wb");
        fwrite(bmp_cache, 1, filesize, myfile);
        fclose(myfile);
    ENDINLINE   
   
   
ENDFUNCTION


As this function uses INLINE, remember to attach also this:
Code (glbasic) Select
INLINE
        }
                extern "C" {
                        #include <cstdio>
                }
        namespace __GLBASIC__ {
ENDINLINE


Check my source code editor for GLBasic - link Update: 20.04.2020

Kitty Hello

I'd rather use sprite2mem and mem2sprite with savesprite. Bzt hey, good work.

dreamerman

Honestly I forgot about SaveSprite.. And I made this for testing purposes / as exercise, then I looked into help file, saw SaveSprite and just  :giveup: :D  But since it's already done, so why not to share, maybe someone will need something like this. :-)
Check my source code editor for GLBasic - link Update: 20.04.2020