Search code examples
arrayscrgbrgbaargb

Converting RGBA C array into ARGB C array


I am trying to generate images in ARGB format. I can use GIMP to take a BMP/JPG/PNG and output an RGBA8888 C source file. This project is on a microcontroller/embedded system (32-bit, 1MB flash, 512kB SRAM). The internal LCD peripheral uses the ARGB format so I cannot change how it reads an array.

So what I want to do is take the output of GIMP (RGBA8888 format) and convert it to ARGB8888 format. Basically, take the last byte and swap it to the front. Ideally, I would do this conversion on my computer and not on the embedded system. I just can think of an easy way to do this.

I have tried several of the online converters but they all output RGBA format.

I am comfortable programming in C, C++, Java, and Python and just need help coming up with the algorithm for the conversion. Even if someone could express it in Pseudocode that would be helpful. Please don't just say:

  1. copy the first byte in the array into var A
  2. copy the fourth byte in the array into var B
  3. copy var B into the first byte of the array
  4. copy var A into the fourth byte of the array
  5. continue for every group of four bytes of the array (the array is 300kB)

1 through 4 are easy, but handling every 4-byte group is stumping me. Is there an easy way to do this without a convoluted solution that looks like spaghetti code? Can the conversion be done in a Windows .bat script or Linux bash script?

I loaded the image into GIMP and exported the C array. In the MCU the array is stored in flash. Then loaded into the frame buffer in SRAM where the LCD peripheral sends the data to the display. The image displays but the colors are wrong because of the byte order.

Both arrays are in the format: const uint8_t displayImage[307200]; // in flash uint8_t frameBuffer[307200]; // in SRAM


Solution

  • You list C as your programming language, so here is a little C11 program to convert a raw RGBA file to a raw ARGB file.

    #include <stdarg.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    
    FILE * infile = NULL;
    FILE * outfile = NULL;
    
    
    _Noreturn void quit( int exitcode, const char * message, ... )
    {
      va_list args;
      va_start( args, message );
      vfprintf( exitcode ? stderr : stdout, message, args );
      va_end( args );
      
      if (infile)  fclose( infile );
      if (outfile) fclose( outfile );
      
      exit( exitcode );
    }
    
    
    int main( int argc, char ** argv )
    {
      if (argc != 3) 
        quit( 1, "usage:\n  %s RGBAFILE ARGBFILE\n", argv[0] );
      
      if ((infile = fopen( argv[1], "rb" )) == NULL)
        quit( 1, "Failure to open \"%s\"\n", argv[1] );
      
      if ((outfile = fopen( argv[2], "wb" )) == NULL)
        quit( 1, "Failure to create \"%s\"\n", argv[2] );
      
      unsigned char bytes[5];                 // ARGBA
      while (fread( bytes+1, 4, 1, infile ))  // read .RGBA
      {
        bytes[0] = bytes[4];                  // .RGBA --> ARGBA
        if (!fwrite( bytes, 4, 1, outfile ))  // write ARGB.
          quit( 1, "%s\n", "Failure to write to output file!" );
      }
      if (ferror( infile ))
        quit( 1, "%s\n", "Failure to read from input file!" );
      
      quit( 0, "%s\n", "done" );
    }
    

    Tested on Windows cl.exe /EHsc /W4 /Ox /std:c11 /D_CRT_SECURE_NO_WARNINGS a.c
    Tested on Linux clang -Wall -Wextra -pedantic-errors -O3 -std=c11 a.c