diff --git a/core/src/global.cpp b/core/src/global.cpp index c88e74441..feb91a4a2 100755 --- a/core/src/global.cpp +++ b/core/src/global.cpp @@ -1816,21 +1816,11 @@ void helios::writePNG(const std::string &filename, uint width, uint height, cons } -//! Error manager for JPEG library. -struct jpg_error_mgr { - jpeg_error_mgr pub; /* "public" fields */ - - jmp_buf setjmp_buffer; /* for return to caller */ -}; - -//! Pointer to JPEG error manager. -typedef jpg_error_mgr *jpg_error_ptr; - //! Error exit function for JPEG library. METHODDEF(void) jpg_error_exit(j_common_ptr cinfo) { - auto myerr = (jpg_error_ptr) cinfo->err; - (*cinfo->err->output_message)(cinfo); - longjmp(myerr->setjmp_buffer, 1); + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(cinfo, buffer); + throw std::runtime_error(buffer); } void helios::readJPEG(const std::string &filename, uint &width, uint &height, std::vector &pixel_data) { @@ -1841,64 +1831,58 @@ void helios::readJPEG(const std::string &filename, uint &width, uint &height, st jpeg_decompress_struct cinfo{}; - jpg_error_mgr jerr{}; - FILE *infile; /* source file */ - JSAMPARRAY buffer; /*output row buffer */ + jpeg_error_mgr jerr{}; + JSAMPARRAY buffer; int row_stride; - if ((infile = fopen(filename.c_str(), "rb")) == nullptr) { + std::unique_ptr infile(fopen(filename.c_str(), "rb"), fclose); + if (!infile) { helios_runtime_error("ERROR (Context::readJPEG): File " + filename + " could not be opened. Check that the file exists and that you have permission to read it."); } - cinfo.err = jpeg_std_error(&jerr.pub); - jerr.pub.error_exit = jpg_error_exit; - if (setjmp(jerr.setjmp_buffer)) { - jpeg_destroy_decompress(&cinfo); - fclose(infile); - return; - } - - jpeg_create_decompress(&cinfo); - - jpeg_stdio_src(&cinfo, infile); + cinfo.err = jpeg_std_error(&jerr); + jerr.error_exit = jpg_error_exit; - (void) jpeg_read_header(&cinfo, TRUE); + try { + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, infile.get()); + (void) jpeg_read_header(&cinfo, TRUE); + (void) jpeg_start_decompress(&cinfo); - (void) jpeg_start_decompress(&cinfo); + row_stride = cinfo.output_width * cinfo.output_components; + buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); - row_stride = cinfo.output_width * cinfo.output_components; - buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + width = cinfo.output_width; + height = cinfo.output_height; - width = cinfo.output_width; - height = cinfo.output_height; + if (cinfo.output_components != 3) { + helios_runtime_error("ERROR (Context::readJPEG): Image file does not have RGB components."); + } else if (width == 0 || height == 0) { + helios_runtime_error("ERROR (Context::readJPEG): Image file is empty."); + } - if (cinfo.output_components != 3) { - helios_runtime_error("ERROR (Context::readJPEG): Image file does not have RGB components."); - } else if (width == 0 || height == 0) { - helios_runtime_error("ERROR (Context::readJPEG): Image file is empty."); - } + pixel_data.resize(width * height); - pixel_data.resize(width * height); + JSAMPLE *ba; + int row = 0; + while (cinfo.output_scanline < cinfo.output_height) { + (void) jpeg_read_scanlines(&cinfo, buffer, 1); - JSAMPLE *ba; - int row = 0; - while (cinfo.output_scanline < cinfo.output_height) { - (void) jpeg_read_scanlines(&cinfo, buffer, 1); + ba = buffer[0]; - ba = buffer[0]; + for (int col = 0; col < row_stride; col += 3) { + pixel_data.at(row * width + col / 3.f) = make_RGBcolor(ba[row] / 255.f, ba[row + 1] / 255.f, ba[row + 2] / 255.f); + } - for (int col = 0; col < row_stride; col += 3) { - pixel_data.at(row * width + col / 3.f) = make_RGBcolor(ba[row] / 255.f, ba[row + 1] / 255.f, ba[row + 2] / 255.f); + row++; } - row++; + (void) jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + } catch (...) { + jpeg_destroy_decompress(&cinfo); + throw; } - - (void) jpeg_finish_decompress(&cinfo); - - jpeg_destroy_decompress(&cinfo); - - fclose(infile); } helios::int2 helios::getImageResolutionJPEG(const std::string &filename) { @@ -1909,39 +1893,30 @@ helios::int2 helios::getImageResolutionJPEG(const std::string &filename) { jpeg_decompress_struct cinfo{}; - jpg_error_mgr jerr{}; - FILE *infile; /* source file */ - - if ((infile = fopen(filename.c_str(), "rb")) == nullptr) { + jpeg_error_mgr jerr{}; + std::unique_ptr infile(fopen(filename.c_str(), "rb"), fclose); + if (!infile) { helios_runtime_error("ERROR (Context::getImageResolutionJPEG): File " + filename + " could not be opened. Check that the file exists and that you have permission to read it."); } - cinfo.err = jpeg_std_error(&jerr.pub); - jerr.pub.error_exit = jpg_error_exit; - if (setjmp(jerr.setjmp_buffer)) { + cinfo.err = jpeg_std_error(&jerr); + jerr.error_exit = jpg_error_exit; + + try { + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, infile.get()); + (void) jpeg_read_header(&cinfo, TRUE); + (void) jpeg_start_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); - fclose(infile); - return {0, 0}; + } catch (...) { + jpeg_destroy_decompress(&cinfo); + throw; } - jpeg_create_decompress(&cinfo); - - jpeg_stdio_src(&cinfo, infile); - - (void) jpeg_read_header(&cinfo, TRUE); - (void) jpeg_start_decompress(&cinfo); - - jpeg_destroy_decompress(&cinfo); - return make_int2(cinfo.output_width, cinfo.output_height); } void helios::writeJPEG(const std::string &a_filename, uint width, uint height, const std::vector &pixel_data) { - struct my_error_mgr { - jpeg_error_mgr pub; /* "public" fields */ - - jmp_buf setjmp_buffer; /* for return to caller */ - }; std::string filename = a_filename; auto file_extension = getFileExtension(filename); @@ -1967,21 +1942,19 @@ void helios::writeJPEG(const std::string &a_filename, uint width, uint height, c struct jpeg_compress_struct cinfo{}; struct jpeg_error_mgr jerr{}; - cinfo.err = jpeg_std_error(&jerr); + jerr.error_exit = jpg_error_exit; - /* More stuff */ - FILE *outfile; /* target file */ - JSAMPROW row_pointer; /* pointer to JSAMPLE row[s] */ + JSAMPROW row_pointer; int row_stride; - /* Now we can initialize the JPEG compression object. */ - jpeg_create_compress(&cinfo); - - if ((outfile = fopen(filename.c_str(), "wb")) == nullptr) { + std::unique_ptr outfile(fopen(filename.c_str(), "wb"), fclose); + if (!outfile) { helios_runtime_error("ERROR (Context::writeJPEG): File " + filename + " could not be opened. Check that the file path is correct you have permission to write to it."); } - jpeg_stdio_dest(&cinfo, outfile); + + jpeg_create_compress(&cinfo); + jpeg_stdio_dest(&cinfo, outfile.get()); cinfo.image_width = width; /* image width and height, in pixels */ cinfo.image_height = height; @@ -1994,18 +1967,20 @@ void helios::writeJPEG(const std::string &a_filename, uint width, uint height, c jpeg_start_compress(&cinfo, TRUE); - row_stride = width * 3; /* JSAMPLEs per row in image_buffer */ - - while (cinfo.next_scanline < cinfo.image_height) { - row_pointer = (JSAMPROW) &screen_shot_trans[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride]; - (void) jpeg_write_scanlines(&cinfo, &row_pointer, 1); - } + try { + row_stride = width * 3; /* JSAMPLEs per row in image_buffer */ - jpeg_finish_compress(&cinfo); - /* After finish_compress, we can close the output file. */ - fclose(outfile); + while (cinfo.next_scanline < cinfo.image_height) { + row_pointer = (JSAMPROW) &screen_shot_trans[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride]; + (void) jpeg_write_scanlines(&cinfo, &row_pointer, 1); + } - jpeg_destroy_compress(&cinfo); + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + } catch (...) { + jpeg_destroy_compress(&cinfo); + throw; + } } void helios::writeJPEG(const std::string &a_filename, uint width, uint height, const std::vector &pixel_data) { diff --git a/plugins/visualizer/src/Visualizer.cpp b/plugins/visualizer/src/Visualizer.cpp index c090a9082..33039e01b 100755 --- a/plugins/visualizer/src/Visualizer.cpp +++ b/plugins/visualizer/src/Visualizer.cpp @@ -42,21 +42,14 @@ using namespace helios; struct my_error_mgr { struct jpeg_error_mgr pub; /* "public" fields */ - - jmp_buf setjmp_buffer; /* for return to caller */ }; -typedef struct my_error_mgr *my_error_ptr; -METHODDEF(void) my_error_exit(j_common_ptr cinfo) { - /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ - auto myerr = (my_error_ptr) cinfo->err; - - /* Always display the message. */ - /* We could postpone this until after returning, if we chose. */ - (*cinfo->err->output_message)(cinfo); +using my_error_ptr = struct my_error_mgr *; - /* Return control to the setjmp point */ - longjmp(myerr->setjmp_buffer, 1); +METHODDEF(void) my_error_exit(j_common_ptr cinfo) { + char buffer[JMSG_LENGTH_MAX]; + (*cinfo->err->format_message)(cinfo, buffer); + throw std::runtime_error(buffer); } int read_JPEG_file(const char *filename, std::vector &texture, uint &height, uint &width) { @@ -65,62 +58,54 @@ int read_JPEG_file(const char *filename, std::vector &texture, ui helios_runtime_error("ERROR (read_JPEG_file): File " + fn + " is not JPEG format."); } - struct jpeg_decompress_struct cinfo; - - struct my_error_mgr jerr; - FILE *infile; /* source file */ - JSAMPARRAY buffer; /*output row buffer */ + struct jpeg_decompress_struct cinfo{}; + struct my_error_mgr jerr{}; + JSAMPARRAY buffer; uint row_stride; - if ((infile = fopen(filename, "rb")) == nullptr) { + std::unique_ptr infile(fopen(filename, "rb"), fclose); + if (!infile) { fprintf(stderr, "can't open %s\n", filename); return 0; } cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; - if (setjmp(jerr.setjmp_buffer)) { - jpeg_destroy_decompress(&cinfo); - fclose(infile); - helios_runtime_error("ERROR (read_JPEG_file): Error reading JPEG file " + std::string(filename)); - } - - jpeg_create_decompress(&cinfo); - jpeg_stdio_src(&cinfo, infile); + try { + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, infile.get()); + (void) jpeg_read_header(&cinfo, TRUE); + (void) jpeg_start_decompress(&cinfo); - (void) jpeg_read_header(&cinfo, TRUE); + row_stride = cinfo.output_width * cinfo.output_components; + buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); - (void) jpeg_start_decompress(&cinfo); + width = cinfo.output_width; + height = cinfo.output_height; - row_stride = cinfo.output_width * cinfo.output_components; - buffer = (*cinfo.mem->alloc_sarray) - ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + assert(cinfo.output_components==3); - width = cinfo.output_width; - height = cinfo.output_height; + JSAMPLE *ba; + while (cinfo.output_scanline < cinfo.output_height) { + (void) jpeg_read_scanlines(&cinfo, buffer, 1); - assert(cinfo.output_components==3); + ba = buffer[0]; - JSAMPLE *ba; - while (cinfo.output_scanline < cinfo.output_height) { - (void) jpeg_read_scanlines(&cinfo, buffer, 1); - - ba = buffer[0]; - - for (int i = 0; i < row_stride; i = i + 3) { - texture.push_back(ba[i]); - texture.push_back(ba[i + 1]); - texture.push_back(ba[i + 2]); - texture.push_back(255.f); //alpha channel -- opaque + for (int i = 0; i < row_stride; i += 3) { + texture.push_back(ba[i]); + texture.push_back(ba[i + 1]); + texture.push_back(ba[i + 2]); + texture.push_back(255.f); //alpha channel -- opaque + } } - } - (void) jpeg_finish_decompress(&cinfo); - - jpeg_destroy_decompress(&cinfo); - - fclose(infile); + (void) jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + } catch (...) { + jpeg_destroy_decompress(&cinfo); + throw; + } return 0; } @@ -143,47 +128,47 @@ int write_JPEG_file(const char *filename, uint width, uint height, void *window, glReadPixels(0, 0, GLsizei(width), GLsizei(height), GL_RGB, GL_UNSIGNED_BYTE, &screen_shot_trans[0]); glFinish(); - struct jpeg_compress_struct cinfo; - - struct jpeg_error_mgr jerr; - /* More stuff */ - FILE *outfile; /* target file */ - JSAMPROW row_pointer; /* pointer to JSAMPLE row[s] */ + struct jpeg_compress_struct cinfo{}; + struct jpeg_error_mgr jerr{}; + JSAMPROW row_pointer; int row_stride; cinfo.err = jpeg_std_error(&jerr); - /* Now we can initialize the JPEG compression object. */ - jpeg_create_compress(&cinfo); + jerr.error_exit = my_error_exit; - if ((outfile = fopen(filename, "wb")) == nullptr) { + std::unique_ptr outfile(fopen(filename, "wb"), fclose); + if (!outfile) { helios_runtime_error("ERROR (write_JPEG_file): Can't open file " + std::string(filename)); } - jpeg_stdio_dest(&cinfo, outfile); + + jpeg_create_compress(&cinfo); + jpeg_stdio_dest(&cinfo, outfile.get()); cinfo.image_width = width; /* image width and height, in pixels */ - cinfo.image_height = height; - cinfo.input_components = 3; /* # of color components per pixel */ - cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + try { + cinfo.image_height = height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ - jpeg_set_defaults(&cinfo); + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, 100, TRUE /* limit to baseline-JPEG values */); - jpeg_set_quality(&cinfo, 100, TRUE /* limit to baseline-JPEG values */); + jpeg_start_compress(&cinfo, TRUE); - jpeg_start_compress(&cinfo, TRUE); + row_stride = width * 3; /* JSAMPLEs per row in image_buffer */ - row_stride = width * 3; /* JSAMPLEs per row in image_buffer */ + while (cinfo.next_scanline < cinfo.image_height) { + row_pointer = (JSAMPROW) &screen_shot_trans[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride]; + (void) jpeg_write_scanlines(&cinfo, &row_pointer, 1); + } - while (cinfo.next_scanline < cinfo.image_height) { - row_pointer = (JSAMPROW) &screen_shot_trans[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride]; - (void) jpeg_write_scanlines(&cinfo, &row_pointer, 1); + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + } catch (...) { + jpeg_destroy_compress(&cinfo); + throw; } - jpeg_finish_compress(&cinfo); - /* After finish_compress, we can close the output file. */ - fclose(outfile); - - jpeg_destroy_compress(&cinfo); - return 1; } @@ -206,47 +191,48 @@ int write_JPEG_file(const char *filename, uint width, uint height, const std::ve ii += 3; } - struct jpeg_compress_struct cinfo; + struct jpeg_compress_struct cinfo{}; - struct jpeg_error_mgr jerr; - /* More stuff */ - FILE *outfile; /* target file */ - JSAMPROW row_pointer; /* pointer to JSAMPLE row[s] */ + struct jpeg_error_mgr jerr{}; + JSAMPROW row_pointer; int row_stride; cinfo.err = jpeg_std_error(&jerr); - /* Now we can initialize the JPEG compression object. */ - jpeg_create_compress(&cinfo); + jerr.error_exit = my_error_exit; - if ((outfile = fopen(filename, "wb")) == nullptr) { + std::unique_ptr outfile(fopen(filename, "wb"), fclose); + if (!outfile) { helios_runtime_error("ERROR (write_JPEG_file): Can't open file " + std::string(filename)); } - jpeg_stdio_dest(&cinfo, outfile); + + jpeg_create_compress(&cinfo); + jpeg_stdio_dest(&cinfo, outfile.get()); cinfo.image_width = width; /* image width and height, in pixels */ - cinfo.image_height = height; - cinfo.input_components = 3; /* # of color components per pixel */ - cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ + try { + cinfo.image_height = height; + cinfo.input_components = 3; /* # of color components per pixel */ + cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ - jpeg_set_defaults(&cinfo); + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, 100, TRUE /* limit to baseline-JPEG values */); - jpeg_set_quality(&cinfo, 100, TRUE /* limit to baseline-JPEG values */); + jpeg_start_compress(&cinfo, TRUE); - jpeg_start_compress(&cinfo, TRUE); + row_stride = width * 3; /* JSAMPLEs per row in image_buffer */ - row_stride = width * 3; /* JSAMPLEs per row in image_buffer */ + while (cinfo.next_scanline < cinfo.image_height) { + row_pointer = (JSAMPROW) &screen_shot_trans[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride]; + (void) jpeg_write_scanlines(&cinfo, &row_pointer, 1); + } - while (cinfo.next_scanline < cinfo.image_height) { - row_pointer = (JSAMPROW) &screen_shot_trans[(cinfo.image_height - cinfo.next_scanline - 1) * row_stride]; - (void) jpeg_write_scanlines(&cinfo, &row_pointer, 1); + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + } catch (...) { + jpeg_destroy_compress(&cinfo); + throw; } - jpeg_finish_compress(&cinfo); - /* After finish_compress, we can close the output file. */ - fclose(outfile); - - jpeg_destroy_compress(&cinfo); - return 1; }