-2

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

  • Swapping 1st and last bytes would give you "RGBA->AGBR". For "RGBA -> ARGB" you want a 32-bit rotate, and in C it might look like `dest[i] = (src[i] << 8) | (src[i] >> 24);` (using `uint32_t *` for `src` and `dest` - there's no reason to use `uint8_t` for 32 bit data). – Brendan Dec 21 '22 at 16:20
  • Are you trying to convert the C source code to modified C source code, or just to convert the image data in memory? If you want a source-to-source translation, then it would be helpful to post specs and / or an example of the format. – John Bollinger Dec 21 '22 at 16:27
  • Brendan - I was using uint8_t just because that was what GIMP was giving me. uint8_t or uint32_t doesn't matter as much, but yes it would be more efficient on a 32-bit micro while uint8_t is faster on 8-bit micros. – tiger19tony72 Dec 27 '22 at 17:59
  • John Bollinger - what I wanted to accomplish was outside of the microcontroller. A program on my PC that would take the RGBA array and convert it to an ARGB array. I should have clarified that I don't want to waste MCU resources converting the array. I just want to do this on the PC and then compile the corrected array into the microcontroller's flash. – tiger19tony72 Dec 27 '22 at 18:02

1 Answers1

0

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

Dúthomhas
  • 8,200
  • 2
  • 17
  • 39
  • Duthomhas - thanks, that is what I was thinking. I see you added checks if the files don't open or get created, I completely forgot about checking that. Thanks again for the help. – tiger19tony72 Dec 27 '22 at 18:05