Skip to main content
ADow.1
Associate II
November 21, 2021
Solved

How to add images at runtime (jpg)

  • November 21, 2021
  • 3 replies
  • 2094 views

I tried using the Jpeg Loader here: Loading Images at Runtime | TouchGFX Documentation

but when I use it it causes a hardfault in JPEGFileLoader::readJPEGFile -> jpeg_start_decompress -> master_selection -> jinit_d_main_controller -> (line 482) main = (my_main_ptr)(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,SIZEOF(my_main_controller));

I found that the hardfault here is caused by the master_selection calling jinit_d_coef_controller  before jinit_d_main_controller, and in this function (jinit_d_coef_controller ) the "cinfo" variable gets destroyed in an "ERREXIT" (D_MULTISCAN_FILES_SUPPORTED is not defined in any file, and even if I define it manually it still hardfaults).

I don't know what the functions are actually supposed to do, and I don't know how to fix this.

Is there a workaround? or a new Loader file? (I downloaded the zip file from the documentation)

I'm attaching the hardfaulted function - jinit_d_main_controller, the jinit_d_coef_controller  , and how I'm calling the JpegLoader.

calling the JpegLoader in screenView.cpp:

 uint8_t lineBuffer[320*3]; //global
 
void Screen_1View::loadJpegImages(touchgfx::Image* image, const char* name, int x, int y)
{
 uint16_t width, height;
 
FS_FILE* f = FS_FOpen(name, "rb");
if (!f)
	return;
 JPEGFileLoader::getJPEGDimensions(f, width, height);
 
 BitmapId bmpId;
 
 //create dynamic bitmap matching file dimensions and in format matching LCD
 if (HAL::lcd().bitDepth() == 16)
 {
 bmpId = Bitmap::dynamicBitmapCreate(width, height, Bitmap::RGB565);
 }
 else
 {
 bmpId = Bitmap::dynamicBitmapCreate(width, height, Bitmap::RGB888);
 }
 
 if (bmpId != BITMAP_INVALID)
 {
 //Succesfully created, load JPEG file to bitmap
				if (file_type == FILE_TYPE_NONE)
					JPEGFileLoader::readJPEGFile(Bitmap(bmpId), f, lineBuffer);
 
				//Image shall show the loaded bitmap
				image->setBitmap(Bitmap(bmpId));
 
				//Position image and add to View
				image->setXY(x, y);
				add(*image);
				//image->invalidate();
		}
}

jinit_d_main_controller: (hardfault in line 8)

GLOBAL(void)
jinit_d_main_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
{
 my_main_ptr main;
 int ci, rgroup, ngroups;
 jpeg_component_info *compptr;
 
 main = (my_main_ptr)
 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
				SIZEOF(my_main_controller));
 cinfo->main = (struct jpeg_d_main_controller *) main;
 main->pub.start_pass = start_pass_main;
 
 if (need_full_buffer)		/* shouldn't happen */
 ERREXIT(cinfo, JERR_BAD_BUFFER_MODE);
 
 /* Allocate the workspace.
 * ngroups is the number of row groups we need.
 */
 if (cinfo->upsample->need_context_rows) {
 if (cinfo->min_DCT_v_scaled_size < 2) /* unsupported, see comments above */
 ERREXIT(cinfo, JERR_NOTIMPL);
 alloc_funny_pointers(cinfo); /* Alloc space for xbuffer[] lists */
 ngroups = cinfo->min_DCT_v_scaled_size + 2;
 } else {
 ngroups = cinfo->min_DCT_v_scaled_size;
 }
 
 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
 ci++, compptr++) {
 rgroup = (compptr->v_samp_factor * compptr->DCT_v_scaled_size) /
 cinfo->min_DCT_v_scaled_size; /* height of a row group of component */
 main->buffer[ci] = (*cinfo->mem->alloc_sarray)
			((j_common_ptr) cinfo, JPOOL_IMAGE,
			 compptr->width_in_blocks * compptr->DCT_h_scaled_size,
			 (JDIMENSION) (rgroup * ngroups));
 }
}

jinit_d_coef_controller :

GLOBAL(void)
jinit_d_coef_controller (j_decompress_ptr cinfo, boolean need_full_buffer)
{
 my_coef_ptr coef;
 
 coef = (my_coef_ptr)
 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
				SIZEOF(my_coef_controller));
 cinfo->coef = (struct jpeg_d_coef_controller *) coef;
 coef->pub.start_input_pass = start_input_pass;
 coef->pub.start_output_pass = start_output_pass;
#ifdef BLOCK_SMOOTHING_SUPPORTED
 coef->coef_bits_latch = NULL;
#endif
 
 /* Create the coefficient buffer. */
 if (need_full_buffer) {
#ifdef D_MULTISCAN_FILES_SUPPORTED
 /* Allocate a full-image virtual array for each component, */
 /* padded to a multiple of samp_factor DCT blocks in each direction. */
 /* Note we ask for a pre-zeroed array. */
 int ci, access_rows;
 jpeg_component_info *compptr;
 
 for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
	 ci++, compptr++) {
 access_rows = compptr->v_samp_factor;
#ifdef BLOCK_SMOOTHING_SUPPORTED
 /* If block smoothing could be used, need a bigger window */
 if (cinfo->progressive_mode)
	access_rows *= 3;
#endif
 coef->whole_image[ci] = (*cinfo->mem->request_virt_barray)
	((j_common_ptr) cinfo, JPOOL_IMAGE, TRUE,
	 (JDIMENSION) jround_up((long) compptr->width_in_blocks,
				(long) compptr->h_samp_factor),
	 (JDIMENSION) jround_up((long) compptr->height_in_blocks,
				(long) compptr->v_samp_factor),
	 (JDIMENSION) access_rows);
 }
 coef->pub.consume_data = consume_data;
 coef->pub.decompress_data = decompress_data;
 coef->pub.coef_arrays = coef->whole_image; /* link to virtual arrays */
#else
 ERREXIT(cinfo, JERR_NOT_COMPILED);
#endif
 } else {
 /* We only need a single-MCU buffer. */
 JBLOCKROW buffer;
 int i;
 
 buffer = (JBLOCKROW)
 (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
				 D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK));
 for (i = 0; i < D_MAX_BLOCKS_IN_MCU; i++) {
 coef->MCU_buffer[i] = buffer + i;
 }
 if (cinfo->lim_Se == 0)	/* DC only case: want to bypass later */
 FMEMZERO((void FAR *) buffer,
	 (size_t) (D_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)));
 coef->pub.consume_data = dummy_consume_data;
 coef->pub.decompress_data = decompress_onepass;
 coef->pub.coef_arrays = NULL; /* flag for no virtual arrays */
 }
}

Any help is appreciated!

This topic has been closed for replies.
Best answer by ADow.1

Hi MM

Thanks for the help, When I was watching the heap and stack sizes I noticed that the exit error I was getting was "Not a JPG format", apparently the image I had in my file system was only named *.jpg but in fact was a different type.

After switching it to a proper .jpg image I reach the third fail you mentioned before.

for future reference, the add should not be here, and the invalidate should be uncommented out.

3 replies

MM..1
Chief III
November 21, 2021

As first in normal you can call this load only from screensetup.

Second is linebufer ok size? Maybe jpeg need more as 320x3

Third fail is

add(*image);

ADow.1
ADow.1Author
Associate II
November 22, 2021

Hi MM

The linebuffer is ok, I ran it in debug and it isn't even used before the hardfault.

The code doesn't even run until the third fail.

/Abeer

MM..1
Chief III
November 22, 2021

Check your heap and stack size for ...

ADow.1
ADow.1AuthorBest answer
Associate II
November 23, 2021

Hi MM

Thanks for the help, When I was watching the heap and stack sizes I noticed that the exit error I was getting was "Not a JPG format", apparently the image I had in my file system was only named *.jpg but in fact was a different type.

After switching it to a proper .jpg image I reach the third fail you mentioned before.

for future reference, the add should not be here, and the invalidate should be uncommented out.

MM..1
Chief III
November 23, 2021

Helpfull is add to first message MCU used info and mark an reply as best for show thread as solved...