From 7b3fd74183d065995a9450d11a5bdea84e928a6f Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 29 Feb 2024 20:39:57 +0100 Subject: [PATCH] Start implementation of input from JPEG file This is work in progress and still not functional. It should at least support `opj_compress -i image.jpg -o image.jp2`. Signed-off-by: Stefan Weil --- src/bin/common/format_defs.h | 1 + src/bin/common/opj_apps_config.h.cmake.in | 2 + src/bin/jp2/CMakeLists.txt | 6 +- src/bin/jp2/convert.h | 4 + src/bin/jp2/convertjpeg.c | 600 ++++++++++++++++++++++ src/bin/jp2/opj_compress.c | 19 +- thirdparty/CMakeLists.txt | 18 + 7 files changed, 646 insertions(+), 4 deletions(-) create mode 100644 src/bin/jp2/convertjpeg.c diff --git a/src/bin/common/format_defs.h b/src/bin/common/format_defs.h index 1985b54f7..7d3521152 100644 --- a/src/bin/common/format_defs.h +++ b/src/bin/common/format_defs.h @@ -42,6 +42,7 @@ #define JP2_CFMT 1 #define JPT_CFMT 2 +#define JPEG_DFMT 9 #define PXM_DFMT 10 #define PGX_DFMT 11 #define BMP_DFMT 12 diff --git a/src/bin/common/opj_apps_config.h.cmake.in b/src/bin/common/opj_apps_config.h.cmake.in index a880205f7..716d479cc 100644 --- a/src/bin/common/opj_apps_config.h.cmake.in +++ b/src/bin/common/opj_apps_config.h.cmake.in @@ -2,6 +2,8 @@ /* create opj_apps_config.h for CMake */ +#cmakedefine OPJ_HAVE_LIBJPEG @HAVE_LIBJPEG@ +#cmakedefine OPJ_HAVE_JPEG_H @HAVE_JPEG_H@ #cmakedefine OPJ_HAVE_LIBPNG @HAVE_LIBPNG@ #cmakedefine OPJ_HAVE_PNG_H @HAVE_PNG_H@ #cmakedefine OPJ_HAVE_LIBTIFF @HAVE_LIBTIFF@ diff --git a/src/bin/jp2/CMakeLists.txt b/src/bin/jp2/CMakeLists.txt index 26156bcbf..87a5c9c73 100644 --- a/src/bin/jp2/CMakeLists.txt +++ b/src/bin/jp2/CMakeLists.txt @@ -14,6 +14,9 @@ set(common_SRCS ${OPENJPEG_SOURCE_DIR}/src/bin/common/opj_string.h ) +if(OPJ_HAVE_LIBJPEG) + list(APPEND common_SRCS convertjpeg.c) +endif() if(OPJ_HAVE_LIBTIFF) list(APPEND common_SRCS converttif.c) endif() @@ -29,6 +32,7 @@ include_directories( ${OPENJPEG_SOURCE_DIR}/src/bin/common ${LCMS_INCLUDE_DIRNAME} ${Z_INCLUDE_DIRNAME} + ${JPEG_INCLUDE_DIRNAME} ${PNG_INCLUDE_DIRNAME} ${TIFF_INCLUDE_DIRNAME} ) @@ -46,7 +50,7 @@ foreach(exe opj_decompress opj_compress opj_dump) add_executable(${exe} ${exe}.c ${common_SRCS}) target_compile_options(${exe} PRIVATE ${OPENJP2_COMPILE_OPTIONS}) target_link_libraries(${exe} ${OPENJPEG_LIBRARY_NAME} - ${PNG_LIBNAME} ${TIFF_LIBNAME} ${LCMS_LIBNAME} + ${JPEG_LIBNAME} ${PNG_LIBNAME} ${TIFF_LIBNAME} ${LCMS_LIBNAME} ) # To support universal exe: if(ZLIB_FOUND AND APPLE) diff --git a/src/bin/jp2/convert.h b/src/bin/jp2/convert.h index b9b009ce1..0375bfbc9 100644 --- a/src/bin/jp2/convert.h +++ b/src/bin/jp2/convert.h @@ -94,6 +94,10 @@ int imagetotga(opj_image_t * image, const char *outfile); opj_image_t* bmptoimage(const char *filename, opj_cparameters_t *parameters); int imagetobmp(opj_image_t *image, const char *outfile); +/* JPEG conversion*/ +opj_image_t* jpegtoimage(const char *filename, opj_cparameters_t *parameters); +int imagetojpeg(opj_image_t *image, const char *outfile); + /* TIFF conversion*/ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters, const unsigned int target_bitdepth); diff --git a/src/bin/jp2/convertjpeg.c b/src/bin/jp2/convertjpeg.c new file mode 100644 index 000000000..9b1f7b9b2 --- /dev/null +++ b/src/bin/jp2/convertjpeg.c @@ -0,0 +1,600 @@ +/* + * The copyright in this software is being made available under the 2-clauses + * BSD License, included below. This software may be subject to other third + * party and contributor rights, including patent rights, and no such rights + * are granted under this license. + * + * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium + * Copyright (c) 2024, Stefan Weil + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "opj_apps_config.h" + +#include +#include +#include +#include + +#include +#include + +#include "openjpeg.h" +#include "convert.h" + +#if 0 +static void convert_16u32s_C1R(const OPJ_BYTE* pSrc, OPJ_INT32* pDst, + OPJ_SIZE_T length) +{ + OPJ_SIZE_T i; + for (i = 0; i < length; i++) { + OPJ_INT32 val0 = *pSrc++; + OPJ_INT32 val1 = *pSrc++; + pDst[i] = val0 << 8 | val1; + } +} + +static opj_image_t * jpegtoimage_internal(opj_cparameters_t * params, + FILE *reader, + jpeg_structp jpeg, + jpeg_infop info, + jpeg_uint_32* pheight, + OPJ_BYTE*** prows, + OPJ_INT32** prow32s) +{ + *pheight = 0; + *prows = NULL; + *prow32s = NULL; + + if (setjmp(jpeg_jmpbuf(jpeg))) { + return NULL; + } + + { + opj_image_t *image = NULL; + opj_image_cmptparm_t cmptparm[4]; + OPJ_UINT32 nr_comp; + convert_XXx32s_C1R cvtXXTo32s = NULL; + convert_32s_CXPX cvtCxToPx = NULL; + OPJ_INT32* planes[4]; + double gamma; + int bit_depth, interlace_type, compression_type, filter_type; + OPJ_UINT32 i; + jpeg_uint_32 width, height = 0U; + int color_type; + OPJ_BYTE** rows = NULL; + OPJ_INT32* row32s = NULL; + + jpeg_init_io(jpeg, reader); + jpeg_set_sig_bytes(jpeg, MAGIC_SIZE); + + jpeg_read_info(jpeg, info); + + if (jpeg_get_IHDR(jpeg, info, &width, &height, + &bit_depth, &color_type, &interlace_type, + &compression_type, &filter_type) == 0) { + return image; + } + *pheight = height; + + /* jpeg_set_expand(): + * expand paletted images to RGB, expand grayscale images of + * less than 8-bit depth to 8-bit depth, and expand tRNS chunks + * to alpha channels. + */ + if (color_type == JPEG_COLOR_TYPE_PALETTE) { + jpeg_set_expand(jpeg); + } + + if (jpeg_get_valid(jpeg, info, JPEG_INFO_tRNS)) { + jpeg_set_expand(jpeg); + } + /* We might want to expand background */ + /* + if(jpeg_get_valid(jpeg, info, JPEG_INFO_bKGD)) { + jpeg_color_16p bgnd; + jpeg_get_bKGD(jpeg, info, &bgnd); + jpeg_set_background(jpeg, bgnd, JPEG_BACKGROUND_GAMMA_FILE, 1, 1.0); + } + */ + + if (!jpeg_get_gAMA(jpeg, info, &gamma)) { + gamma = 1.0; + } + + /* we're not displaying but converting, screen gamma == 1.0 */ + jpeg_set_gamma(jpeg, 1.0, gamma); + + jpeg_read_update_info(jpeg, info); + + color_type = jpeg_get_color_type(jpeg, info); + + switch (color_type) { + case JPEG_COLOR_TYPE_GRAY: + nr_comp = 1; + break; + case JPEG_COLOR_TYPE_GRAY_ALPHA: + nr_comp = 2; + break; + case JPEG_COLOR_TYPE_RGB: + nr_comp = 3; + break; + case JPEG_COLOR_TYPE_RGB_ALPHA: + nr_comp = 4; + break; + default: + fprintf(stderr, "jpegtoimage: colortype %d is not supported\n", color_type); + return image; + } + cvtCxToPx = convert_32s_CXPX_LUT[nr_comp]; + bit_depth = jpeg_get_bit_depth(jpeg, info); + + switch (bit_depth) { + case 1: + case 2: + case 4: + case 8: + cvtXXTo32s = convert_XXu32s_C1R_LUT[bit_depth]; + break; + case 16: /* 16 bpp is specific to JPEG */ + cvtXXTo32s = convert_16u32s_C1R; + break; + default: + fprintf(stderr, "jpegtoimage: bit depth %d is not supported\n", bit_depth); + return image; + } + + for (i = 0; i < height; ++i) { + rows[i] = (OPJ_BYTE*)malloc(jpeg_get_rowbytes(jpeg, info)); + if (rows[i] == NULL) { + fprintf(stderr, "jpegtoimage: memory out\n"); + return image; + } + } + jpeg_read_image(jpeg, rows); + + /* Create image */ + memset(cmptparm, 0, sizeof(cmptparm)); + for (i = 0; i < nr_comp; ++i) { + /* bits_per_pixel: 8 or 16 */ + cmptparm[i].prec = (OPJ_UINT32)bit_depth; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = (OPJ_UINT32)params->subsampling_dx; + cmptparm[i].dy = (OPJ_UINT32)params->subsampling_dy; + cmptparm[i].w = (OPJ_UINT32)width; + cmptparm[i].h = (OPJ_UINT32)height; + } + + image = opj_image_create(nr_comp, &cmptparm[0], + (nr_comp > 2U) ? OPJ_CLRSPC_SRGB : OPJ_CLRSPC_GRAY); + if (image == NULL) { + return image; + } + image->x0 = (OPJ_UINT32)params->image_offset_x0; + image->y0 = (OPJ_UINT32)params->image_offset_y0; + image->x1 = (OPJ_UINT32)(image->x0 + (width - 1) * (OPJ_UINT32) + params->subsampling_dx + 1); + image->y1 = (OPJ_UINT32)(image->y0 + (height - 1) * (OPJ_UINT32) + params->subsampling_dy + 1); + + row32s = (OPJ_INT32 *)malloc((size_t)width * nr_comp * sizeof(OPJ_INT32)); + if (row32s == NULL) { + return image; + } + *prow32s = row32s; + + /* Set alpha channel */ + image->comps[nr_comp - 1U].alpha = 1U - (nr_comp & 1U); + + for (i = 0; i < nr_comp; i++) { + planes[i] = image->comps[i].data; + } + + for (i = 0; i < height; ++i) { + cvtXXTo32s(rows[i], row32s, (OPJ_SIZE_T)width * nr_comp); + cvtCxToPx(row32s, planes, width); + planes[0] += width; + planes[1] += width; + planes[2] += width; + planes[3] += width; + } + + return image; + } +} +#endif + +opj_image_t *jpegtoimage(const char *read_idf, opj_cparameters_t * params) +{ +#if 0 + jpeg_structp jpeg = NULL; + jpeg_infop info = NULL; +#endif + JDIMENSION i; + JDIMENSION height; + JDIMENSION width; + JDIMENSION row_stride; + struct jpeg_decompress_struct cinfo = {0}; + struct jpeg_error_mgr jerr = {0}; + FILE *reader = NULL; + OPJ_BYTE** rows = NULL; + OPJ_INT32* row32s = NULL; + opj_image_t *image = NULL; + unsigned nr_comp; + int ret; + unsigned char *buffer; + opj_image_cmptparm_t cmptparm[4] = {0}; + + fprintf(stderr, "%s:%u (%s)\n", __FILE__, __LINE__, __func__); + + if ((reader = fopen(read_idf, "rb")) == NULL) { + fprintf(stderr, "jpegtoimage: can not open %s\n", read_idf); + return NULL; + } + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + jpeg_stdio_src(&cinfo, reader); + ret = jpeg_read_header(&cinfo, TRUE); + if (ret != JPEG_HEADER_OK) { + fprintf(stderr, "jpegtoimage: %s is no valid JPEG file\n", read_idf); + goto fin; + } + height = cinfo.image_height; + width = cinfo.image_width; + rows = (OPJ_BYTE**)calloc(height + 1, sizeof(OPJ_BYTE*)); + if (rows == NULL) { + fprintf(stderr, "jpegtoimage: memory out\n"); + return NULL; + } + jpeg_calc_output_dimensions(&cinfo); + nr_comp = (unsigned)cinfo.output_components; + row_stride = width * nr_comp; + buffer = malloc(row_stride); + jpeg_start_decompress(&cinfo); + while (cinfo.output_scanline < cinfo.output_height) { + jpeg_read_scanlines(&cinfo, &buffer, 1); + // Use the data in buffer as needed + } + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + free(buffer); + + for (i = 0; i < nr_comp; ++i) { + /* bits_per_pixel: 8 or 16 */ + cmptparm[i].prec = (OPJ_UINT32)8; + cmptparm[i].sgnd = 0; + cmptparm[i].dx = (OPJ_UINT32)params->subsampling_dx; + cmptparm[i].dy = (OPJ_UINT32)params->subsampling_dy; + cmptparm[i].w = (OPJ_UINT32)width; + cmptparm[i].h = (OPJ_UINT32)height; + } + image = opj_image_create(nr_comp, &cmptparm[0], + (nr_comp > 2U) ? OPJ_CLRSPC_SRGB : OPJ_CLRSPC_GRAY); + if (image == NULL) { + return image; + } + image->x0 = (OPJ_UINT32)params->image_offset_x0; + image->y0 = (OPJ_UINT32)params->image_offset_y0; + image->x1 = (OPJ_UINT32)(image->x0 + (width - 1) * (OPJ_UINT32) + params->subsampling_dx + 1); + image->y1 = (OPJ_UINT32)(image->y0 + (height - 1) * (OPJ_UINT32) + params->subsampling_dy + 1); + + row32s = (OPJ_INT32 *)malloc((size_t)width * nr_comp * sizeof(OPJ_INT32)); + if (row32s == NULL) { + return image; + } + +#if 0 + while (scan lines remain to be read) + jpeg_read_scanlines(...); /* Use jpeg12_read_scanlines() for + 12-bit data precision and + jpeg16_read_scanlines() for + 16-bit data precision. */ +#endif + +#if 0 + image = jpegtoimage_internal(params, reader, jpeg, info, &height, &rows, &row32s); +#endif +fin: + if (rows) { + for (i = 0; i < height; ++i) + free(rows[i]); + free(rows); + } + free(row32s); + + fclose(reader); + + return image; + +}/* jpegtoimage() */ + +#if 0 +static void convert_32s16u_C1R(const OPJ_INT32* pSrc, OPJ_BYTE* pDst, + OPJ_SIZE_T length) +{ + OPJ_SIZE_T i; + for (i = 0; i < length; i++) { + OPJ_UINT32 val = (OPJ_UINT32)pSrc[i]; + *pDst++ = (OPJ_BYTE)(val >> 8); + *pDst++ = (OPJ_BYTE)val; + } +} +#endif + +#if 0 +int imagetojpeg(opj_image_t * image, const char *write_idf) +{ +#if 0 + FILE * volatile writer = NULL; + jpeg_structp jpeg = NULL; + jpeg_infop info = NULL; + jpeg_bytep volatile row_buf = NULL; + int nr_comp, color_type; + volatile int prec; + jpeg_color_8 sig_bit; + OPJ_INT32 const* planes[4]; + int i; + OPJ_INT32* volatile buffer32s = NULL; +#endif + + volatile int fails = 1; + +#if 0 + memset(&sig_bit, 0, sizeof(sig_bit)); + prec = (int)image->comps[0].prec; + planes[0] = image->comps[0].data; + if (planes[0] == NULL) { + fprintf(stderr, + "imagetojpeg: planes[%d] == NULL.\n", 0); + fprintf(stderr, "\tAborting\n"); + return 1; + } + nr_comp = (int)image->numcomps; + + if (nr_comp > 4) { + nr_comp = 4; + } + for (i = 1; i < nr_comp; ++i) { + if (image->comps[0].dx != image->comps[i].dx) { + break; + } + if (image->comps[0].dy != image->comps[i].dy) { + break; + } + if (image->comps[0].prec != image->comps[i].prec) { + break; + } + if (image->comps[0].sgnd != image->comps[i].sgnd) { + break; + } + planes[i] = image->comps[i].data; + if (planes[i] == NULL) { + fprintf(stderr, + "imagetojpeg: planes[%d] == NULL.\n", i); + fprintf(stderr, "\tAborting\n"); + return 1; + } + } + if (i != nr_comp) { + fprintf(stderr, + "imagetojpeg: All components shall have the same subsampling, same bit depth, same sign.\n"); + fprintf(stderr, "\tAborting\n"); + return 1; + } + for (i = 0; i < nr_comp; ++i) { + clip_component(&(image->comps[i]), image->comps[0].prec); + } + if (prec > 8 && prec < 16) { + for (i = 0; i < nr_comp; ++i) { + scale_component(&(image->comps[i]), 16); + } + prec = 16; + } else if (prec < 8 && nr_comp > 1) { /* GRAY_ALPHA, RGB, RGB_ALPHA */ + for (i = 0; i < nr_comp; ++i) { + scale_component(&(image->comps[i]), 8); + } + prec = 8; + } else if ((prec > 1) && (prec < 8) && ((prec == 6) || + ((prec & 1) == 1))) { /* GRAY with non native precision */ + if ((prec == 5) || (prec == 6)) { + prec = 8; + } else { + prec++; + } + for (i = 0; i < nr_comp; ++i) { + scale_component(&(image->comps[i]), (OPJ_UINT32)prec); + } + } + + if (prec != 1 && prec != 2 && prec != 4 && prec != 8 && prec != 16) { + fprintf(stderr, "imagetojpeg: can not create %s\n\twrong bit_depth %d\n", + write_idf, prec); + return fails; + } + + writer = fopen(write_idf, "wb"); + + if (writer == NULL) { + return fails; + } + + /* Create and initialize the jpeg_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible with the one used at compile time, + * in case we are using dynamically linked libraries. REQUIRED. + */ + jpeg = jpeg_create_write_struct(JPEG_LIBJPEG_VER_STRING, + NULL, NULL, NULL); + /*jpeg_voidp user_error_ptr, user_error_fn, user_warning_fn); */ + + if (jpeg == NULL) { + goto fin; + } + + /* Allocate/initialize the image information data. REQUIRED + */ + info = jpeg_create_info_struct(jpeg); + + if (info == NULL) { + goto fin; + } + + /* Set error handling. REQUIRED if you are not supplying your own + * error handling functions in the jpeg_create_write_struct() call. + */ + if (setjmp(jpeg_jmpbuf(jpeg))) { + goto fin; + } + + /* I/O initialization functions is REQUIRED + */ + jpeg_init_io(jpeg, writer); + + /* Set the image information here. Width and height are up to 2^31, + * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on + * the color_type selected. color_type is one of JPEG_COLOR_TYPE_GRAY, + * JPEG_COLOR_TYPE_GRAY_ALPHA, JPEG_COLOR_TYPE_PALETTE, JPEG_COLOR_TYPE_RGB, + * or JPEG_COLOR_TYPE_RGB_ALPHA. interlace is either JPEG_INTERLACE_NONE or + * JPEG_INTERLACE_ADAM7, and the compression_type and filter_type MUST + * currently be JPEG_COMPRESSION_TYPE_BASE and JPEG_FILTER_TYPE_BASE. + * REQUIRED + * + * ERRORS: + * + * color_type == JPEG_COLOR_TYPE_PALETTE && bit_depth > 8 + * color_type == JPEG_COLOR_TYPE_RGB && bit_depth < 8 + * color_type == JPEG_COLOR_TYPE_GRAY_ALPHA && bit_depth < 8 + * color_type == JPEG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8 + * + */ + jpeg_set_compression_level(jpeg, Z_BEST_COMPRESSION); + + if (nr_comp >= 3) { /* RGB(A) */ + color_type = JPEG_COLOR_TYPE_RGB; + sig_bit.red = sig_bit.green = sig_bit.blue = (jpeg_byte)prec; + } else { /* GRAY(A) */ + color_type = JPEG_COLOR_TYPE_GRAY; + sig_bit.gray = (jpeg_byte)prec; + } + if ((nr_comp & 1) == 0) { /* ALPHA */ + color_type |= JPEG_COLOR_MASK_ALPHA; + sig_bit.alpha = (jpeg_byte)prec; + } + + jpeg_set_IHDR(jpeg, info, image->comps[0].w, image->comps[0].h, prec, color_type, + JPEG_INTERLACE_NONE, JPEG_COMPRESSION_TYPE_BASE, JPEG_FILTER_TYPE_BASE); + + jpeg_set_sBIT(jpeg, info, &sig_bit); + /* jpeg_set_gamma(jpeg, 2.2, 1./2.2); */ + /* jpeg_set_sRGB(jpeg, info, JPEG_sRGB_INTENT_PERCEPTUAL); */ + jpeg_write_info(jpeg, info); + + /* setup conversion */ + { + OPJ_SIZE_T rowStride; + jpeg_size_t jpeg_row_size; + + jpeg_row_size = jpeg_get_rowbytes(jpeg, info); + rowStride = ((OPJ_SIZE_T)image->comps[0].w * (OPJ_SIZE_T)nr_comp * + (OPJ_SIZE_T)prec + 7U) / 8U; + if (rowStride != (OPJ_SIZE_T)jpeg_row_size) { + fprintf(stderr, "Invalid JPEG row size\n"); + goto fin; + } + row_buf = (jpeg_bytep)malloc(jpeg_row_size); + if (row_buf == NULL) { + fprintf(stderr, "Can't allocate memory for JPEG row\n"); + goto fin; + } + buffer32s = (OPJ_INT32*)malloc((OPJ_SIZE_T)image->comps[0].w * + (OPJ_SIZE_T)nr_comp * sizeof(OPJ_INT32)); + if (buffer32s == NULL) { + fprintf(stderr, "Can't allocate memory for interleaved 32s row\n"); + goto fin; + } + } + + /* convert */ + { + OPJ_SIZE_T width = image->comps[0].w; + OPJ_UINT32 y; + convert_32s_PXCX cvtPxToCx = convert_32s_PXCX_LUT[nr_comp]; + convert_32sXXx_C1R cvt32sToPack = NULL; + OPJ_INT32 adjust = image->comps[0].sgnd ? 1 << (prec - 1) : 0; + jpeg_bytep row_buf_cpy = row_buf; + OPJ_INT32* buffer32s_cpy = buffer32s; + + switch (prec) { + case 1: + case 2: + case 4: + case 8: + cvt32sToPack = convert_32sXXu_C1R_LUT[prec]; + break; + case 16: + cvt32sToPack = convert_32s16u_C1R; + break; + default: + /* never here */ + break; + } + + for (y = 0; y < image->comps[0].h; ++y) { + cvtPxToCx(planes, buffer32s_cpy, width, adjust); + cvt32sToPack(buffer32s_cpy, row_buf_cpy, width * (OPJ_SIZE_T)nr_comp); + jpeg_write_row(jpeg, row_buf_cpy); + planes[0] += width; + planes[1] += width; + planes[2] += width; + planes[3] += width; + } + } + + jpeg_write_end(jpeg, info); + + fails = 0; + +fin: + if (jpeg) { + jpeg_destroy_write_struct(&jpeg, &info); + } + if (row_buf) { + free(row_buf); + } + if (buffer32s) { + free(buffer32s); + } + fclose(writer); + + if (fails) { + (void)remove(write_idf); /* ignore return value */ + } +#endif + + return fails; +}/* imagetojpeg() */ +#endif diff --git a/src/bin/jp2/opj_compress.c b/src/bin/jp2/opj_compress.c index c3d7f4fba..db24d3c85 100644 --- a/src/bin/jp2/opj_compress.c +++ b/src/bin/jp2/opj_compress.c @@ -532,10 +532,10 @@ static int get_file_format(char *filename) { unsigned int i; static const char *extension[] = { - "pgx", "pnm", "pgm", "ppm", "pbm", "pam", "bmp", "tif", "tiff", "raw", "yuv", "rawl", "tga", "png", "j2k", "jp2", "j2c", "jpc" + "pgx", "pnm", "pgm", "ppm", "pbm", "pam", "bmp", "jpg", "tif", "tiff", "raw", "yuv", "rawl", "tga", "png", "j2k", "jp2", "j2c", "jpc" }; static const int format[] = { - PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, TIF_DFMT, TIF_DFMT, RAW_DFMT, RAW_DFMT, RAWL_DFMT, TGA_DFMT, PNG_DFMT, J2K_CFMT, JP2_CFMT, J2K_CFMT, J2K_CFMT + PGX_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, PXM_DFMT, BMP_DFMT, JPEG_DFMT, TIF_DFMT, TIF_DFMT, RAW_DFMT, RAW_DFMT, RAWL_DFMT, TGA_DFMT, PNG_DFMT, J2K_CFMT, JP2_CFMT, J2K_CFMT, J2K_CFMT }; char * ext = strrchr(filename, '.'); if (ext == NULL) { @@ -665,6 +665,7 @@ static int parse_cmdline_encoder(int argc, char **argv, case PGX_DFMT: case PXM_DFMT: case BMP_DFMT: + case JPEG_DFMT: case TIF_DFMT: case RAW_DFMT: case RAWL_DFMT: @@ -674,7 +675,7 @@ static int parse_cmdline_encoder(int argc, char **argv, default: fprintf(stderr, "[ERROR] Unknown input file format: %s \n" - " Known file formats are *.pnm, *.pgm, *.ppm, *.pgx, *png, *.bmp, *.tif(f), *.raw, *.yuv or *.tga\n", + " Known file formats are *.pnm, *.pgm, *.ppm, *.pgx, *png, *.bmp, *,jpg, *.tif(f), *.raw, *.yuv or *.tga\n", infile); return 1; } @@ -2019,6 +2020,7 @@ int main(int argc, char **argv) case PGX_DFMT: case PXM_DFMT: case BMP_DFMT: + case JPEG_DFMT: case TIF_DFMT: case RAW_DFMT: case RAWL_DFMT: @@ -2099,6 +2101,17 @@ int main(int argc, char **argv) } break; +#ifdef OPJ_HAVE_LIBJPEG + case JPEG_DFMT: + image = jpegtoimage(parameters.infile, ¶meters); + if (!image) { + fprintf(stderr, "Unable to load jpeg file\n"); + ret = 1; + goto fin; + } + break; +#endif /* OPJ_HAVE_LIBJPEG */ + #ifdef OPJ_HAVE_LIBPNG case PNG_DFMT: image = pngtoimage(parameters.infile, ¶meters); diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt index b136fff18..cf9b16160 100644 --- a/thirdparty/CMakeLists.txt +++ b/thirdparty/CMakeLists.txt @@ -26,6 +26,24 @@ else(BUILD_THIRDPARTY) endif(ZLIB_FOUND) endif(BUILD_THIRDPARTY) +#------------ +# Try to find lib JPEG +if(BUILD_THIRDPARTY) + message(STATUS "We won't build JPEG lib from thirdparty") +else(BUILD_THIRDPARTY) + find_package(JPEG) + if(JPEG_FOUND) + message(STATUS "Your system seems to have a JPEG lib available, we will use it") + set(OPJ_HAVE_JPEG_H 1 PARENT_SCOPE) + set(OPJ_HAVE_LIBJPEG 1 PARENT_SCOPE) + set(JPEG_LIBNAME ${JPEG_LIBRARIES} PARENT_SCOPE) + set(JPEG_INCLUDE_DIRNAME ${JPEG_INCLUDE_DIR} PARENT_SCOPE) + else(JPEG_FOUND) # not found + set(OPJ_HAVE_JPEG_H 0 PARENT_SCOPE) + set(OPJ_HAVE_LIBJPEG 0 PARENT_SCOPE) + message(STATUS "JPEG lib not found") + endif(JPEG_FOUND) +endif(BUILD_THIRDPARTY) #------------ # Try to find lib PNG (which depends on zlib)