cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 JPEG encode for grayscale inputs

DLane.1
Associate II

Hello

I am trying to encode an image of (160*120) in grayscale format - i.e a bmp file of 1bpp color depth.

Unfortunately, the encoder would not finish its conversion. and the `HAL_JPEG_EncodeCpltCallback` is not called.

My setup is based on the `JPEG_EncodingUsingFs_DMA` from ST, while this example is designed for 24bits pixel depth, I tried to modify it for my application - with changing the `ReadBmpRgbLines`to read only 1 color:

static void ReadBmpRgbLines(FIL *file, JPEG_ConfTypeDef Conf, uint8_t * pDataBuffer, uint32_t *BufferSize)
{
	uint32_t bytesReadfile    = 1;
	uint32_t CurrentBlockLine = 1;
	*BufferSize = 0;
 
	while((CurrentLine <= Conf.ImageHeight) && (CurrentBlockLine <= MAX_INPUT_LINES))
	{
		f_lseek (file,BMP_HEADER_SIZE + Conf.ImageWidth *(Conf.ImageHeight - CurrentLine)*1);
		f_read (file, pDataBuffer , Conf.ImageWidth*1 , (UINT*)(&bytesReadfile));
 
		pDataBuffer += bytesReadfile;
		*BufferSize += bytesReadfile;
		CurrentLine +=1 ;
		CurrentBlockLine += 1;
	}
}

My encoder values are as follow:

#define JPEG_RGB_FORMAT JPEG_RGB888
 
#define JPEG_CHROMA_SAMPLING   JPEG_444_SUBSAMPLING
#define JPEG_COLOR_SPACE     JPEG_YCBCR_COLORSPACE\
#define JPEG_IMAGE_QUALITY    100          
#define MAX_INPUT_WIDTH     800        
#define MAX_INPUT_LINES     8  

I have noticed the function that is called to generate a new MCU block is 'stuck` on the same bmp image line.

Can anyone send a hint about this problem? Do I have to set different parameters for the encoder?

Sincerely

Dan

1 ACCEPTED SOLUTION

Accepted Solutions
sirius506
Associate III

Oh sorry, you are correct. I didn't noticed that they don't support proper conversion function.

Then, it would be easier to pretend as if you have RGB88 - just repeat the gray scale value three times.

static void ReadBmpRgbLines(FIL *file, JPEG_ConfTypeDef Conf, uint8_t * pDataBuffer, uint32_t *BufferSize)
{
	uint32_t bytesReadfile    = 1;
	uint32_t CurrentBlockLine = 1;
	*BufferSize = 0;
        uint8_t workbuffer[200];
        int i;
 
	while((CurrentLine <= Conf.ImageHeight) && (CurrentBlockLine <= MAX_INPUT_LINES))
	{
		f_lseek (file,BMP_HEADER_SIZE + Conf.ImageWidth *(Conf.ImageHeight - CurrentLine)*1);
		f_read (file, workbuffer , Conf.ImageWidth*1 , (UINT*)(&bytesReadfile));
 
                for (i = 0; i < Conf.ImageWidth; i++)
                {
		   *pDataBuffer++= workbuffer[i];
		   *pDataBuffer++= workbuffer[i];
		   *pDataBuffer++= workbuffer[i];
                }
		*BufferSize += bytesReadfile * 3;
		CurrentLine +=1 ;
		CurrentBlockLine += 1;
	}
}

View solution in original post

6 REPLIES 6
sirius506
Associate III

I believe you should use JPEG_GRAYSCALE_COLORSPACE instead of JPEG_YCBCR_COLORSACE.

#define JPEG_COLOR_SPACE JPEG_GRAYSCALE_COLORSPACE

Regards,

Dear sirius

Thank you for your response.

I tried also the GRAYSCALE_COLORSPACE, which gave in the same result - a non-finished conversion.

BTW I belive the colorspace relates to the convertion output, am I right?

Any other ideas about the convertor parameters?

Dan

sirius506
Associate III

JPEG encoder hardware expects MCU format -- where Grayscale MCU and YCBCR MCU formats are different.

In ST's example code, JPEG_GetEncodeColorConvertFunc() handles the difference of color space and returns associated conversion function pointer.

I checked ST's `JPEG_EncodingUsingFs_DMA` example code, and found that you also need to fix BMP_GetInfo() in main.c.

This function expects JPEG_YCBCR_COLORSPACE and  'stucks` at there.

Thank you for your reply

Tthe ` BMP_GetInfo()` can get stuck if the dimentions does not meet the size of (%8 for any color format or %16 for YCMCR format).

My image size (160x120) meets the condition of %8==0 than does not hangs there.

Regarding `JPEG_GetEncodeColorConvertFunc`, the HAL has only functions of convertion of the types: JPEG_ARGB_MCU_Gray_ConvertBlocks. i.e ARGB -> Gray MCU. And I could not find a Gray -> Gray MCU.

I think my only option is to manipulate the input to this MCU generator.

I would really appreciate if you could explain me other method, or reference me to a other MCU building functions.

Thanks

Dan

sirius506
Associate III

Oh sorry, you are correct. I didn't noticed that they don't support proper conversion function.

Then, it would be easier to pretend as if you have RGB88 - just repeat the gray scale value three times.

static void ReadBmpRgbLines(FIL *file, JPEG_ConfTypeDef Conf, uint8_t * pDataBuffer, uint32_t *BufferSize)
{
	uint32_t bytesReadfile    = 1;
	uint32_t CurrentBlockLine = 1;
	*BufferSize = 0;
        uint8_t workbuffer[200];
        int i;
 
	while((CurrentLine <= Conf.ImageHeight) && (CurrentBlockLine <= MAX_INPUT_LINES))
	{
		f_lseek (file,BMP_HEADER_SIZE + Conf.ImageWidth *(Conf.ImageHeight - CurrentLine)*1);
		f_read (file, workbuffer , Conf.ImageWidth*1 , (UINT*)(&bytesReadfile));
 
                for (i = 0; i < Conf.ImageWidth; i++)
                {
		   *pDataBuffer++= workbuffer[i];
		   *pDataBuffer++= workbuffer[i];
		   *pDataBuffer++= workbuffer[i];
                }
		*BufferSize += bytesReadfile * 3;
		CurrentLine +=1 ;
		CurrentBlockLine += 1;
	}
}

That's seems to work

Thanks!