diff --git a/internal/decodejpeg/decode.c b/internal/decodejpeg/decode.c index 869cc31..9c9d775 100644 --- a/internal/decodejpeg/decode.c +++ b/internal/decodejpeg/decode.c @@ -1,44 +1,70 @@ +#include +#include + #include "decode.h" +char jpeg_last_error_message[JMSG_LENGTH_MAX]; + +void jpeg_error_exit (j_common_ptr cinfo) +{ + /* cinfo->err actually points to a jpeg_error_manager struct */ + JpegErrorManager* myerr = (JpegErrorManager*) cinfo->err; + + /* output_message is a method to print an error message */ + ( *(cinfo->err->output_message) ) (cinfo); + + /* Create the message */ + ( *(cinfo->err->format_message) ) (cinfo, jpeg_last_error_message); + + /* Jump to the setjmp point */ + longjmp(myerr->setjmp_buffer, 1); +} + GLOBAL(struct Image) -read_JPEG_file(char *inbuffer, size_t size) +read_JPEG_file(char* inbuffer, size_t size, char* error) { - struct Image result; - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; + struct Image result; + struct jpeg_decompress_struct cinfo; + struct JpegErrorManager jerr; - const int BYTES_PER_SAMPLE = sizeof(JSAMPLE); - JSAMPARRAY buffer; /* Output row buffer */ + const int BYTES_PER_SAMPLE = sizeof(JSAMPLE); + JSAMPARRAY buffer; /* Output row buffer */ - int row_stride; /* physical row width in output buffer */ + int row_stride; /* physical row width in output buffer */ - cinfo.err = jpeg_std_error(&jerr); + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = jpeg_error_exit; + if (setjmp(jerr.setjmp_buffer)) { + /* If we get here, the JPEG code has signaled an error. */ + jpeg_destroy_decompress(&cinfo); + strcpy(error, jpeg_last_error_message); + return result; + } - jpeg_create_decompress(&cinfo); + jpeg_create_decompress(&cinfo); - jpeg_mem_src(&cinfo, inbuffer, size); + jpeg_mem_src(&cinfo, inbuffer, size); - (void)jpeg_read_header(&cinfo, TRUE); + (void)jpeg_read_header(&cinfo, TRUE); - (void)jpeg_start_decompress(&cinfo); - result.pix = (char *)malloc(cinfo.output_height * cinfo.output_width - * cinfo.output_components * BYTES_PER_SAMPLE); - result.width = cinfo.output_width; - result.height = cinfo.output_height; + (void)jpeg_start_decompress(&cinfo); + row_stride = cinfo.output_width * cinfo.output_components * BYTES_PER_SAMPLE; + result.pix = (char *)malloc(cinfo.output_height * row_stride); + result.width = cinfo.output_width; + result.height = cinfo.output_height; - row_stride = cinfo.output_width * cinfo.output_components * BYTES_PER_SAMPLE; - buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1); + buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo, JPOOL_IMAGE, row_stride, 1); - while (cinfo.output_scanline < cinfo.output_height) - { - (void)jpeg_read_scanlines(&cinfo, buffer, 1); - memcpy(&(result.pix)[(cinfo.output_scanline - 1) * row_stride], - buffer[0], - row_stride); - } - (void)jpeg_finish_decompress(&cinfo); + while (cinfo.output_scanline < cinfo.output_height) + { + (void)jpeg_read_scanlines(&cinfo, buffer, 1); + memcpy(&(result.pix)[(cinfo.output_scanline - 1) * row_stride], + buffer[0], + row_stride); + } + (void)jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); - return result; + return result; } diff --git a/internal/decodejpeg/decode.go b/internal/decodejpeg/decode.go index 10c97ec..353dc61 100644 --- a/internal/decodejpeg/decode.go +++ b/internal/decodejpeg/decode.go @@ -12,22 +12,35 @@ import "C" import ( "bytes" "encoding/binary" + "fmt" + "strings" "unsafe" ) -//JpegImageData converts a grayscale image encoded in 12-bit jpeg to raw data +// JpegImageData converts a grayscale image encoded in 12-bit jpeg to raw data func JpegImageData(jpegData []byte) (rawData []uint16, height int, width int, err error) { jpegChar := C.CString(string(jpegData)) defer C.free(unsafe.Pointer(jpegChar)) - imageData, err := C.read_JPEG_file(jpegChar, C.size_t(len(jpegData))) - if err != nil { - return rawData, height, width, err - } + jErrBuf := strings.Repeat(" ", C.JMSG_LENGTH_MAX) + + jpegErr := C.CString(string(jErrBuf)) + defer C.free(unsafe.Pointer(jpegErr)) + + imageData, err := C.read_JPEG_file(jpegChar, C.size_t(len(jpegData)), jpegErr) defer C.free(unsafe.Pointer(imageData.pix)) - pixelString := C.GoStringN(imageData.pix, C.int(imageData.width*imageData.height*C.sizeof_short)) + jErr := C.GoStringN(jpegErr, C.JMSG_LENGTH_MAX) + jErr = strings.Trim(jErr, " ") + if jErr != "" { + return rawData, height, width, fmt.Errorf("JPEG decode error: %v", jErr) + } + + pixelString := C.GoStringN( + imageData.pix, + C.int(imageData.width*imageData.height*C.sizeof_short), + ) height = int(imageData.height) width = int(imageData.width) buffer := bytes.NewBufferString(pixelString) diff --git a/internal/decodejpeg/decode.h b/internal/decodejpeg/decode.h index 2a24abb..b61b6ee 100644 --- a/internal/decodejpeg/decode.h +++ b/internal/decodejpeg/decode.h @@ -1,13 +1,21 @@ #include #include #include +#include #include "jpeglib.h" typedef struct Image { - char *pix; + char* pix; JDIMENSION width; JDIMENSION height; } Image; -struct Image read_JPEG_file(char *, size_t); +typedef struct JpegErrorManager { + /* "public" fields */ + struct jpeg_error_mgr pub; + /* for return to caller */ + jmp_buf setjmp_buffer; +} JpegErrorManager; + +struct Image read_JPEG_file(char*, size_t, char*); diff --git a/raclambda/app.py b/raclambda/app.py index bf741ae..4c65b01 100644 --- a/raclambda/app.py +++ b/raclambda/app.py @@ -10,7 +10,7 @@ from raclambda.raclambda_stack import RacLambdaStack -RAC_VERSION = "v0.2.6" +RAC_VERSION = "v0.2.8" RAC_OS = "Linux" RAC_URL = f"https://github.com/innosat-mats/rac-extract-payload/releases/download/{RAC_VERSION}/Rac_for_{RAC_OS}.tar.gz" # noqa: E501 RAC_DIR = "./raclambda/handler"