%% options copyright owner = Dirk Krause copyright year = 2017-xxxx SPDX-License-Identifier: BSD-3-Clause %% module #include "dk4conf.h" #if DK4_HAVE_JPEGLIB_H #ifndef DK4MEM_H_INCLUDED #include "dk4mem.h" #endif #ifndef DK4MAASZ_H_INCLUDED #include "dk4maasz.h" #endif #ifndef DK4BIFTY_H_INCLUDED #include "dk4bifty.h" #endif #ifndef DK4BIF_H_INCLUDED #include "dk4bif.h" #endif #ifndef BIF_H_INCLUDED #include "bif.h" #endif #ifndef JPEGLIB_H_INCLUDED #include #define JPEGLIB_H_INCLUDED 1 #endif #if DK4_HAVE_SETJMP_H #ifndef SETJMP_H_INCLUDED #include #define SETJMP_H_INCLUDED 1 #endif #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif $!trace-include /** Error manager for jpeglib. */ typedef struct { struct jpeg_error_mgr errmgr; /**< Default error manager. */ #if DK4_HAVE_SETJMP_H jmp_buf jump_buf; /**< Longjump buffer. */ #endif } dk4_bif_jpeg_error_mgr; /** Routine called instead of simple exit on failures. @param cinfo Object containing address of error manager. */ static void dk4bifjpb_error_exit(j_common_ptr cinfo) { dk4_bif_jpeg_error_mgr *errmgr; /* Error manager structure */ $? "+ dk4bifjpb_error_exit" errmgr = (dk4_bif_jpeg_error_mgr *)(cinfo->err); if (NULL != errmgr) { longjmp(errmgr->jump_buf, 1); } $? "- dk4bifjpb_error_exit" } void dk4bifjpeg_nc_release_per_frame_data( void *tsdata, dk4_bif_frame_t *frptr ) { JSAMPLE **rptr; /* Array of row pointers */ dk4_bif_jpeg_per_frame_t *jfptr; /* Per-frame data */ JDIMENSION i; /* Traverse all lines */ $? "+ dk4bifjpeg_nc_release_per_frame_data" #if DK4_USE_ASSERT assert(NULL != tsdata); assert(NULL != frptr); #endif jfptr = (dk4_bif_jpeg_per_frame_t *)tsdata; if (NULL != jfptr) { rptr = jfptr->rows; if (NULL != rptr) { $? ". have rows" for (i = 0; (dk4_bif_dim_t)i < frptr->dim_y; i++) { $? ". release row %u", (unsigned)i if (NULL != *rptr) { dk4mem_free(*rptr); } rptr++; } $? ". release rows" dk4mem_free(jfptr->rows); } $? ". release jfptr" dk4mem_free(jfptr); } $? "- dk4bifjpeg_nc_release_per_frame_data" } /** Transfer information from JPEG structures into BIF structures. @param bifp Bitmap image file to modify. @param pfd Per-frame data structure to modify. @param cinfo JPEG decompression structure (data source). @param sov Flag: Set output variables in cinfo. */ static void dk4bifjpeg_transfer_header_data( dk4_bif_t *bifp, dk4_bif_jpeg_per_frame_t *pfd, struct jpeg_decompress_struct *cinfo, int sov ) { $? "+ dk4bifjpeg_transfer_header_data" #if DK4_USE_ASSERT assert(NULL != bifp); assert(NULL != pfd); assert(NULL != cinfo); #endif bifp->cf->dim_x = cinfo->image_width; $? ". w = %u", (unsigned)(bifp->cf->dim_x) bifp->cf->dim_y = cinfo->image_height; $? ". h = %u", (unsigned)(bifp->cf->dim_y) bifp->cf->l_bdepth = BITS_IN_JSAMPLE; $? ". library bit depth = %u", (unsigned)(bifp->cf->l_bdepth) bifp->cf->r_bdepth = BITS_IN_JSAMPLE; $? ". requested bit depth = %u", (unsigned)(bifp->cf->r_bdepth) $? ". background = %u", (unsigned)(MAXJSAMPLE) bifp->cf->bg[0] = MAXJSAMPLE; bifp->cf->bg[1] = MAXJSAMPLE; bifp->cf->bg[2] = MAXJSAMPLE; bifp->cf->bg[3] = MAXJSAMPLE; bifp->cf->bglbd[0] = MAXJSAMPLE; bifp->cf->bglbd[1] = MAXJSAMPLE; bifp->cf->bglbd[2] = MAXJSAMPLE; bifp->cf->bglbd[3] = MAXJSAMPLE; dk4pxres_setup(&(bifp->cf->resampler), MAXJSAMPLE, MAXJSAMPLE); bifp->cf->n_comp = cinfo->out_color_components; $? ". color components = %u", (unsigned)(bifp->cf->n_comp) bifp->cf->hbg = 0; bifp->cf->res_x = -1.0; bifp->cf->res_y = -1.0; if (0 != cinfo->saw_JFIF_marker) { if ((0 < cinfo->X_density) && (0 < cinfo->Y_density)) { bifp->cf->res_x = (double)(cinfo->X_density); bifp->cf->res_y = (double)(cinfo->Y_density); $? ". x resolution = %g", bifp->cf->res_x $? ". y resolution = %g", bifp->cf->res_y if (2 == cinfo->density_unit) { $? ". resolution is in cm" bifp->cf->res_x *= 2.54; bifp->cf->res_y *= 2.54; $? ". x resolution = %g", bifp->cf->res_x $? ". y resolution = %g", bifp->cf->res_y } if (1 != cinfo->density_unit) { bifp->cf->res_x = -1.0; bifp->cf->res_y = -1.0; } } } switch (cinfo->jpeg_color_space) { case JCS_GRAYSCALE: { $? ". color space = JCS_GRAYSCALE" bifp->cf->l_cs = DK4_CS_GRAY; bifp->cf->f_cs = DK4_CS_GRAY; if (0 != sov) { cinfo->out_color_space = JCS_GRAYSCALE; } } break; case JCS_CMYK: { $? ". color space = JCS_CMYK" bifp->cf->l_cs = DK4_CS_CMYK; bifp->cf->f_cs = DK4_CS_CMYK; if (0 != sov) { cinfo->out_color_space = JCS_CMYK; } } break; /* 2018-03-20 If the library internal color space is JCS_YCCK or JCS_YCbCr the library functions to access pixel data deliver RGB values. So the default branch sets the color space to RGB. */ #if 0 case JCS_RGB: { $? ". color space = JCS_RGB" bifp->cf->l_cs = DK4_CS_RGB; bifp->cf->f_cs = DK4_CS_RGB; } break; case JCS_YCCK: { $? ". color space = JCS_YCCK" bifp->cf->l_cs = DK4_CS_CMYK; bifp->cf->f_cs = DK4_CS_CMYK; } break; case JCS_YCbCr: { $? ". color space = JCS_YCbCr" bifp->cf->l_cs = DK4_CS_CMYK; bifp->cf->f_cs = DK4_CS_CMYK; } break; #endif default: { $? ". color space = UNKNOWN" bifp->cf->l_cs = DK4_CS_RGB; bifp->cf->f_cs = DK4_CS_RGB; if (0 != sov) { cinfo->out_color_space = JCS_RGB; } } break; } pfd->num_comp = cinfo->out_color_components; $? ". color components = %u", (unsigned)(pfd->num_comp) pfd->is_adobe = ((0 != cinfo->saw_Adobe_marker) ? 1 : 0); $? ". adobe marker = %u", (unsigned)(pfd->is_adobe) $? "- dk4bifjpeg_transfer_header_data" } dk4_bif_t * dk4bifjpeg_nc_open_file( FILE *fipo, dkChar const *fn, int honly, dk4_cs_conv_ctx_t const *pcsctx, dk4_bif_jpg_clobbered_t *jpgcp, dk4_er_t *erp ) { struct jpeg_decompress_struct cinfo; /* Jpeglib reader */ dk4_bif_jpeg_error_mgr errmgr; /* Jpeglib error man */ dk4_er_t er; /* Error report */ JSAMPLE **xrptr = NULL; /* Travers rows */ dk4_bif_jpeg_per_frame_t *pfd = NULL; /* Per-frame data */ size_t bpl = 0; /* Bits per line */ size_t i = 0; /* Traverse rows */ $? "+ dk4bifjpeg_nc_open_file \"%!ds\" honly=%d", TR_STR(fn), honly /* Create bif and frame for one-frame image */ jpgcp->back = dk4biftool_nc_new_for_one_frame( fn, DK4_BIF_TYPE_JPEG, honly, pcsctx, erp ); if (NULL == jpgcp->back) { goto finished; } $? ". bif structure for one frame created" /* Allocate per-frame data structure */ pfd = dk4mem_new(dk4_bif_jpeg_per_frame_t,1,NULL); if (NULL == pfd) { goto finished; } (jpgcp->back->cf)->tsdata = pfd; $? ". Per-frame data structure created" /* Initialize per-frame data structure components */ pfd->rows = NULL; pfd->num_comp = 0; pfd->is_adobe = 0; /* Set up error management */ cinfo.err = jpeg_std_error(&(errmgr.errmgr)); errmgr.errmgr.error_exit = dk4bifjpb_error_exit; $? ". error management setup done" /* Code below calls setjmp on error */ if (0 != setjmp(errmgr.jump_buf)) { $? "! setjmp return from error" dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); goto finished; } /* Create decompression structure */ jpgcp->st = 1; jpeg_create_decompress(&cinfo); $? ". decompression structure created" /* Specify data source */ jpeg_stdio_src(&cinfo, fipo); $? ". data source is input file" /* Read JPEG header data */ jpeg_read_header(&cinfo, TRUE); $? ". header was read" /* Transfer header data to bif structures. */ dk4bifjpeg_transfer_header_data(jpgcp->back, pfd, &cinfo, 1); $? ". data transfered from JPEG to BIF structures" /* When reading just the header we are done here */ if (0 != honly) { jpgcp->ok = 1; $? ". just reading header, we are done" goto finished; } /* Start decompression */ jpeg_start_decompress(&cinfo); $? ". decompression started" /* Header data are now corrected if necessary, read information again */ dk4bifjpeg_transfer_header_data(jpgcp->back, pfd, &cinfo, 0); $? ". data transferred from JPEG to BIF structures again" /* Allocate memory for image data */ dk4error_init(&er); bpl = dk4ma_size_t_mul(jpgcp->back->cf->dim_x, jpgcp->back->cf->n_comp, &er); if (DK4_E_NONE != er.ec) { dk4error_copy(erp, &er); goto finished; } pfd->rows = dk4mem_new(JSAMPROW,jpgcp->back->cf->dim_y,erp); if (NULL == pfd->rows) { goto finished; } xrptr = pfd->rows; for (i = 0; i < (size_t)(jpgcp->back->cf->dim_y); i++) { *(xrptr++) = NULL; } xrptr = pfd->rows; for (i = 0; i < (size_t)(jpgcp->back->cf->dim_y); i++) { *xrptr = dk4mem_new(JSAMPLE,bpl,erp); if (NULL == *xrptr) { goto finished; } xrptr++; } $? ". memory for rows allocated" /* Read and decompress data */ xrptr = pfd->rows; for (i = 0; i < (size_t)(jpgcp->back->cf->dim_y); i++) { jpeg_read_scanlines(&cinfo, xrptr, 1); xrptr++; } $? ". input data was read" /* Finish decompression */ jpeg_finish_decompress(&cinfo); $? ". decompression was finished, success" /* Everything done, success */ jpgcp->ok = 1; finished: /* Destroy decompression structure */ if (0 < jpgcp->st) { jpeg_destroy_decompress(&cinfo); } if (0 == jpgcp->ok) { if (NULL != jpgcp->back) { dk4bif_close(jpgcp->back); jpgcp->back = NULL; } } $? "- dk4bifjpeg_nc_open_file %d", TR_IPTR(jpgcp->back) return jpgcp->back; } int dk4bifjpeg_nc_get_original_pixel( dk4_px_t *dptr, size_t szdptr, dk4_bif_t const *bif, dk4_bif_dim_t rowno, dk4_bif_dim_t colno ) { dk4_er_t er; /* Error report for math op */ dk4_bif_jpeg_per_frame_t *pfd = NULL; /* Per-frame data */ size_t spos; /* Number of values per row */ size_t i; /* Traverse all components */ int back = 0; $? "+ dk4bifjpeg_nc_get_original_pixel" #if DK4_USE_ASSERT assert(NULL != dptr); assert(0 < szdptr); assert(NULL != bif); #endif pfd = (dk4_bif_jpeg_per_frame_t *)((bif->cf)->tsdata); if (NULL != pfd) { if (NULL != pfd->rows) { dk4error_init(&er); spos = dk4ma_size_t_mul(colno, pfd->num_comp, &er); (void)dk4ma_size_t_add(spos, pfd->num_comp, &er); if (DK4_E_NONE == er.ec) { if (szdptr >= pfd->num_comp) { for (i = 0; i < pfd->num_comp; i++) { dptr[i] = ((pfd->rows)[rowno])[spos + i]; } back = 1; } } } } $? "- dk4bifjpeg_nc_get_original_pixel %d", back return back; } #endif /* if DK4_HAVE_JPEGLIB_H */ /* vim: set ai sw=4 ts=4 : */