1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
// Copyright 2009-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#ifdef EMBREE_TUTORIALS_LIBJPEG
#include "image.h"
#include "jpeglib.h"
namespace embree
{
void compress(struct jpeg_compress_struct *cinfo, unsigned char *image)
{
/*! Start compression. */
jpeg_start_compress(cinfo, TRUE);
/*! Pointer to and size of a scanline in the image. */
JSAMPROW scanline[1]; size_t bytes = cinfo->image_width * cinfo->input_components;
/*! Here we use the library state variable 'next_scanline' as the loop index. */
while (cinfo->next_scanline < cinfo->image_height) {
scanline[0] = &image[cinfo->next_scanline * bytes];
jpeg_write_scanlines(cinfo, scanline, 1);
}
/*! Finish compression. */
jpeg_finish_compress(cinfo);
}
unsigned char *decompress(struct jpeg_decompress_struct *cinfo)
{
/*! Start decompression. */
jpeg_start_decompress(cinfo);
/*! Bytes per row in the scanline buffer. */
size_t bytes = cinfo->output_width * cinfo->output_components;
/*! Allocate scratch space for a single scanline. */
JSAMPARRAY scanline = (*cinfo->mem->alloc_sarray)((j_common_ptr) cinfo, JPOOL_IMAGE, bytes, 1);
/*! Allocate storage for the decompressed image. */
unsigned char* image = new unsigned char[cinfo->output_height * bytes];
/*! Here we use the library state variable 'output_scanline' as the loop index. */
while (cinfo->output_scanline < cinfo->output_height) {
jpeg_read_scanlines(cinfo, scanline, 1);
for (size_t i=0; i<bytes; i++)
image[(cinfo->output_scanline - 1) * bytes + i] = scanline[0][i];
}
/*! Finish decompression. */
jpeg_finish_decompress(cinfo);
return(image);
}
void encodeRGB8_to_JPEG(unsigned char *image, size_t width, size_t height, unsigned char **encoded, unsigned long *capacity)
{
#if JPEG_LIB_VERSION >= 80
/*! Compression parameters and scratch space pointers (allocated by the library). */
struct jpeg_compress_struct cinfo;
/*! The library error handler. */
struct jpeg_error_mgr jerror; cinfo.err = jpeg_std_error(&jerror);
/*! Initialize the JPEG compression object. */
jpeg_create_compress(&cinfo);
/*! Specify the incoming image resolution, color space, and color space components. */
cinfo.image_width = width; cinfo.image_height = height; cinfo.in_color_space = JCS_RGB; cinfo.input_components = 3;
/*! Fill in a sensible set of defaults. */
jpeg_set_defaults(&cinfo);
/*! Set the image quality. */
jpeg_set_quality(&cinfo, 90, TRUE);
/*! Specify the data source. */
jpeg_mem_dest(&cinfo, encoded, capacity);
/*! Compress and write the image into the target buffer. */
compress(&cinfo, image);
/*! At this point 'jerror.num_warnings' could be checked for corrupt-data warnings. */
jpeg_destroy_compress(&cinfo);
#else // JPEG_LIB_VERSION
THROW_RUNTIME_ERROR("JPEG encoding into a memory buffer requires LibJPEG 8a or higher");
#endif // JPEG_LIB_VERSION
}
Ref<Image> loadJPEG(const FileName &filename)
{
/*! Open the source JPEG file. */
FILE *file = fopen(filename.c_str(), "rb"); if (!file) THROW_RUNTIME_ERROR("Unable to open \"" + filename.str() + "\".");
/*! Decompression parameters and scratch space pointers allocated by the library. */
struct jpeg_decompress_struct cinfo;
/*! The library error handler. */
struct jpeg_error_mgr jerror; cinfo.err = jpeg_std_error(&jerror);
/*! Initialize the JPEG decompression object. */
jpeg_create_decompress(&cinfo);
/*! Specify the data source. */
jpeg_stdio_src(&cinfo, file);
/*! Read file parameters with jpeg_read_header(). */
jpeg_read_header(&cinfo, TRUE);
/*! Specify the color space and color space components of the decompressed image. */
cinfo.out_color_space = JCS_RGB; cinfo.output_components = 3;
/*! Decompress the image into an output buffer and get the image dimensions. */
unsigned char *rgb = decompress(&cinfo); size_t width = cinfo.output_width; size_t height = cinfo.output_height;
/*! Allocate the Embree image. */
Ref<Image> image = new Image4uc(width, height, filename);
/*! Convert the image from unsigned char RGB to unsigned char RGBA. */
for (size_t y=0, i=0 ; y < height ; y++) {
for (size_t x=0 ; x < width ; x++) {
const float r = (float) rgb[i++] / 255.0f;
const float g = (float) rgb[i++] / 255.0f;
const float b = (float) rgb[i++] / 255.0f;
image->set(x, y, Color4(r,g,b,1.0f));
}
}
/*! Clean up. */
jpeg_destroy_decompress(&cinfo);
delete[] rgb;
fclose(file);
return(image);
}
void storeJPEG(const Ref<Image> &image, const FileName &filename)
{
/*! Open the target JPEG file. */
FILE *file = fopen(filename.c_str(), "wb"); if (!file) THROW_RUNTIME_ERROR("Unable to open \"" + filename.str() + "\".");
/*! Compression parameters and scratch space pointers (allocated by the library). */
struct jpeg_compress_struct cinfo;
/*! The library error handler. */
struct jpeg_error_mgr jerror; cinfo.err = jpeg_std_error(&jerror);
/*! Initialize the JPEG compression object. */
jpeg_create_compress(&cinfo);
/*! Specify the incoming image resolution, color space, and color space components. */
cinfo.image_width = image->width; cinfo.image_height = image->height; cinfo.in_color_space = JCS_RGB; cinfo.input_components = 3;
/*! Fill in a sensible set of defaults. */
jpeg_set_defaults(&cinfo);
/*! Specify the data source. */
jpeg_stdio_dest(&cinfo, file);
/*! Allocate storage for the uncompressed packed image. */
unsigned char* rgb = new unsigned char [3 * image->height * image->width];
/*! Convert the image to unsigned char RGB. */
for (size_t y=0, i=0 ; y < image->height ; y++) {
for (size_t x=0 ; x < image->width ; x++) {
const Color4 pixel = image->get(x, y);
rgb[i++] = (unsigned char)(clamp(pixel.r) * 255.0f);
rgb[i++] = (unsigned char)(clamp(pixel.g) * 255.0f);
rgb[i++] = (unsigned char)(clamp(pixel.b) * 255.0f);
}
}
/*! Compress and write the image into the target file. */
compress(&cinfo, rgb);
/*! At this point 'jerror.num_warnings' could be checked for corrupt-data warnings. */
jpeg_destroy_compress(&cinfo);
delete [] rgb;
fclose(file);
}
}
#endif // EMBREE_TUTORIALS_LIBJPEG
|