2019-10-22 08:16 PM
Hi all,
I build a project with STM32CubeMX and using LibJPEG to decode the JPEG file from SDCard.
And now I face a problem ,when it goes to the step 5 - start to decompress, it will stock in that function with no reason and the hardfault descripe like down below.
Step 5 : Start decompressor
Is there anyone have that experience about LibJPEG?
Hope someone can help!
Thank you!
2019-10-22 08:44 PM
So you're going to need a more effective Hard Fault handler that can identify the faulting instructions/registers.
Likely you are overflowing an input or output buffer, or a malloc() is failing. If the code needs to allocate memory dynamically, make sure you actual have some heap space for it to use.
2019-10-22 08:56 PM
Hi @Community member ,
Thanks for your reply.
Do you mean the Hard Fault is not clear to know where it wrong,so I should to build a Hard Fault function to recognized it?
The Heap size has been increase,but the same problem.
2019-10-23 08:30 AM
I mean have the routine provide some actionable data rather than spin in a while(1) loop with nothing identifying the fault. The debug view you have screen shot really doesn't clearly identify the failure point and the registers.
This needs some output via a USART or SWV, but illustrates what the hard fault routines should be doing for any real field analysis or debugging to occur.
Determine where the code actually faults, and look at the disassembly of the code there, and immediately preceding. Likely acting on a memory pointer, or call-back, which are invalid.
2024-01-04 02:55 AM - edited 2024-01-08 12:00 AM
Hi,
i guess i had the same problem. Reason was that the picture I wanted to compress was too big for the buffers of libjpeg.
So I do not use a while loop and changed it to a switch. That means I repead the same case as long as I get new data in the buffer. Then I extract the data and clear the buffer.
Header:
/*
* LIBJPEG_RGBtoJPG.h
*
* Created on: 05.01.2024
* Author: MK
*/
#ifndef __LIBJPEG_RGBtoJPG_H
#define __LIBJPEG_RGBtoJPG_H
#ifdef __cplusplus
extern "C" {
#endif
//-----------------------------------------------------------------------------------------------------------------------------
#include "main.h"
//#define RGB_HEIGHT 480
//#define RGB_WIDTH 640
#define RGB_HEIGHT 800
#define RGB_WIDTH 1280
//-----------------------------------------------------------------------------------------------------------------------------
typedef enum
{
ERR_JPEG_OK = 0,
ERR_JPEG_BUSY = -1,
ERR_JPEG_FINISH_COMPRESSLINE = -2,
ERR_JPEG_NOT_ALLOWED_VALUE = -3,
}eRetValJPEG;
typedef struct
{
uint32_t JpegNewData;
uint8_t *ptrStartJpeg;
uint8_t *ptrEndJpeg;
uint8_t JpegCompressVal;
uint8_t *pJpegSrc;
uint8_t *pJpegDst;
uint8_t *pJpegImageData;
uint32_t JpegImageData_size;
}_sJPEG;
extern _sJPEG sJPEG;
//-----------------------------------------------------------------------------------------------------------------------------
extern eRetValJPEG JPEG_CompressStart(JDIMENSION image_width, JDIMENSION image_height, uint8_t input_components, J_COLOR_SPACE in_color_space, uint8_t quality, uint8_t **dest_buffer, uint32_t *newdatacnt);
extern void JPEG_CompressClearBuffer(void);
extern eRetValJPEG JPEG_CompressLine(uint8_t *src_linebuffer, uint8_t **dest_buffer, uint32_t *newdatacnt);
extern void JPEG_CompressFinish(uint8_t **dest_buffer, uint32_t *newdatacnt);
extern void JPEG_CompressDestroy(void);
//-----------------------------------------------------------------------------------------------------------------------------
#ifdef __cplusplus
}
#endif
#endif
C-Code:
/*
* LIBJPEG_RGBtoJPG.c
*
* Created on: 05.01.2024
* Author: MK
*/
#include "jpeglib.h"
#include "LIBJPEG_RGBtoJPG.h"
//-----------------------------------------------------------------------------------------------------------------------------
#ifdef JPEGTEST
//-----------------------------------------------------------------------------------------------------------------------------
uint8_t const oneline[1280];
//-----------------------------------------------------------------------------------------------------------------------------
_sJPEG sJPEG;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
struct jpeg_compress_struct const prs_cinfo;
uint8_t StartImageTransfer, Flag_StartImageTransfer;
//-----------------------------------------------------------------------------------------------------------------------------
/**
* @brief prepare everything to start a compression. creates the first jepeg data
*
* @retval ERR_JPEG_OK when no ongoing comression is active
*/
eRetValJPEG JPEG_CompressStart(JDIMENSION image_width, JDIMENSION image_height, uint8_t input_components, J_COLOR_SPACE in_color_space, uint8_t quality, uint8_t **dest_buffer, uint32_t *newdatacnt)
{
if ( (cinfo.image_height) || (cinfo.image_width) )
return ERR_JPEG_BUSY;
if (!image_width)
return ERR_JPEG_NOT_ALLOWED_VALUE;
if (!image_height)
return ERR_JPEG_NOT_ALLOWED_VALUE;
if (input_components != 3)
return ERR_JPEG_NOT_ALLOWED_VALUE;
if (in_color_space != JCS_RGB)
return ERR_JPEG_NOT_ALLOWED_VALUE;
if (!quality || quality > 100)
return ERR_JPEG_NOT_ALLOWED_VALUE;
if (!dest_buffer)
return ERR_JPEG_NOT_ALLOWED_VALUE;
if (!newdatacnt)
return ERR_JPEG_NOT_ALLOWED_VALUE;
//init all global
cinfo = prs_cinfo;
sJPEG.JpegImageData_size = 0;
sJPEG.pJpegImageData = NULL;
//prepare all
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_mem_dest(&cinfo, &sJPEG.pJpegImageData, &sJPEG.JpegImageData_size);
cinfo.image_width = image_width;
cinfo.image_height = image_height;
cinfo.input_components = input_components;
cinfo.in_color_space = in_color_space;
jpeg_set_defaults( &cinfo );
jpeg_set_quality(&cinfo, quality, 1 );
//memset(cinfo.dest->next_output_byte,0,cinfo.dest->free_in_buffer);//not neccessary
*dest_buffer = cinfo.dest->next_output_byte;
//start compress
*newdatacnt = cinfo.dest->free_in_buffer;
jpeg_start_compress(&cinfo, 1);
*newdatacnt -= cinfo.dest->free_in_buffer;
return ERR_JPEG_OK;
}
//-----------------------------------------------------------------------------------------------------------------------------
/**
* @brief need to be done after compressed data is created and handled. Avoid buffer overrun when compressing large images
*
* @retval none
*/
void JPEG_CompressClearBuffer(void)
{
jpeg_mem_dest(&cinfo, &sJPEG.pJpegImageData, &sJPEG.JpegImageData_size);
}
//-----------------------------------------------------------------------------------------------------------------------------
/**
* @brief compress one line of the image
*
* @retval
* ERR_JPEG_FINISH_COMPRESSLINE: when last line was compressed
* ERR_JPEG_OK': when line was compressed
*/
eRetValJPEG JPEG_CompressLine(uint8_t *src_linebuffer, uint8_t **dest_buffer, uint32_t *newdatacnt)
{
unsigned char* row_pointer[1];
*dest_buffer = cinfo.dest->next_output_byte;
*newdatacnt = cinfo.dest->free_in_buffer;
if (cinfo.next_scanline < cinfo.image_height) {
row_pointer[0] = src_linebuffer;
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
else
{
newdatacnt = 0;
return ERR_JPEG_FINISH_COMPRESSLINE;
}
*newdatacnt -= cinfo.dest->free_in_buffer;
return ERR_JPEG_OK;
}
//-----------------------------------------------------------------------------------------------------------------------------
/**
* @brief function will finish the compression and prepare the last bytes of the jpeg data
*
* @retval none
*/
void JPEG_CompressFinish(uint8_t **dest_buffer, uint32_t *newdatacnt)
{
*dest_buffer = cinfo.dest->next_output_byte;
*newdatacnt = cinfo.dest->free_in_buffer;
jpeg_finish_compress( &cinfo );
*newdatacnt -= cinfo.dest->free_in_buffer;
}
//-----------------------------------------------------------------------------------------------------------------------------
/**
* @brief has to be called after last data of JPEG_CompressFinish was handled
*
* @retval none
*/
void JPEG_CompressDestroy(void)
{
jpeg_destroy_compress( &cinfo );
//init all global for next compression
cinfo = prs_cinfo;
sJPEG.JpegImageData_size = 0;
sJPEG.pJpegImageData = NULL;
}
//-----------------------------------------------------------------------------------------------------------------------------
/**
* @brief function for sending the image. function call in main loop.
*
* @retval none
*/
void JPEG_StartImageTransfer(void)
{
switch (StartImageTransfer)
{
case 2:
sJPEG.pJpegsrc=(uint8_t *)&oneline[0];//one image line 1280px width
if (Init_ImageTransfer())//function to send image / ethernet
{
StartImageTransfer = 0;
}
else
StartImageTransfer++;
break;
case 3:
JPEG_CompressStart(RGB_WIDTH, RGB_HEIGHT, 3, JCS_RGB, sJPEG.JpegCompressVal, &sJPEG.pJpegDst, &sJPEG.JpegNewData);
Flag_StartImageTransfer = ++StartImageTransfer;
StartImageTransfer = 10;//send data
break;
case 4:
if (JPEG_CompressLine(&sJPEG.pJpegSrc[0],&sJPEG.pJpegDst,&sJPEG.JpegNewData) == ERR_JPEG_FINISH_COMPRESSLINE)
StartImageTransfer++;
else if (sJPEG.JpegNewData)
{
Flag_StartImageTransfer = StartImageTransfer;
StartImageTransfer = 10;//send data
}
break;
case 5:
JPEG_CompressFinish(&sJPEG.pJpegDst,&sJPEG.JpegNewData);
Flag_StartImageTransfer = ++StartImageTransfer;
StartImageTransfer = 10;//send data
break;
case 6:
JPEG_CompressDestroy();
StartImageTransfer = 20;//all done
break;
case 10://send data
if (Cont_ImageTransfer())//function to send image / ethernet
break;
JPEG_CompressClearBuffer();
StartImageTransfer = Flag_StartImageTransfer;
break;
case 20://all done
SendImageStatus = 0;
StartImageTransfer = 0;
break;
}//sw
}
#endif//JPEGTEST
Function call in main loop:
JPEG_StartImageTransfer();