/* Copyright (C) 2017-2020, Dirk Krause SPDX-License-Identifier: BSD-3-Clause */ /* WARNING: This file was generated by the dkct program (see http://dktools.sourceforge.net/ for details). Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk4bifp.ctr */ /** @file dk4bifp.c The dk4bifp module. */ #line 8 "dk4bifp.ctr" #include "dk4conf.h" #if DK4_HAVE_PNG_H #ifndef PNG_H_INCLUDED #include #define PNG_H_INCLUDED 1 #endif #if DK4_HAVE_SETJMP_H #ifndef SETJMP_H_INCLUDED #include #define SETJMP_H_INCLUDED 1 #endif #endif #ifndef DK4TYPES_H_INCLUDED #include "dk4types.h" #endif #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 DK4UNUSED_H_INCLUDED #include "dk4unused.h" #endif #if DK4_HAVE_ASSERT_H #ifndef ASSERT_H_INCLUDED #include #define ASSERT_H_INCLUDED 1 #endif #endif #line 63 "dk4bifp.ctr" /** User defined error handler for libpng functions. @param pfptr Pointer to per-frame structure containing a jump buffer. @param error_msg Libpng error message, ignored here. */ static void dk4bifpng_i_error_fn( dk4_bif_png_per_frame_t *pfptr, png_const_charp DK4_ARG_UNUSED(error_msg) ) { DK4_UNUSED_ARG(error_msg) if (NULL != pfptr) { if (2 > pfptr->had_error) { pfptr->had_error = 2; } longjmp(pfptr->jump_buf, 1); } } /** User defined error handler for libpng functions. @param pfptr Pointer to per-frame structure containing a jump buffer. @param error_msg Libpng error message, ignored here. */ static void dk4bifpng_i_warning_fn( dk4_bif_png_per_frame_t *pfptr, png_const_charp DK4_ARG_UNUSED(error_msg) ) { DK4_UNUSED_ARG(error_msg) if (NULL != pfptr) { if (1 > pfptr->had_error) { pfptr->had_error = 1; } } } /** Allocate new per-frame data structure. @param erp Error report, may be NULL. @return Valid pointer on success, NULL on error. */ static dk4_bif_png_per_frame_t * dk4bifpng_tsdata_new(dk4_er_t *erp) { dk4_bif_png_per_frame_t *back = NULL; #line 120 "dk4bifp.ctr" back = dk4mem_new(dk4_bif_png_per_frame_t,1,erp); if (NULL != back) { back->rows = NULL; back->dblxdpi = -1.0; back->dblydpi = -1.0; back->rowbytes = 0UL; back->w = 0UL; back->h = 0UL; back->xdpi = 0UL; back->ydpi = 0UL; back->ct = 0; back->im = 0; back->cm = 0; back->fm = 0; back->ch = 0; back->ip = 0; back->bd = 0; back->had_error = 0; } #line 140 "dk4bifp.ctr" return back; } void dk4bifpng_nc_release_per_frame_data( void *tsdata ) { png_bytep *rp; /* Current row to release */ dk4_bif_png_per_frame_t *ppngfr; /* Per-frame data */ png_uint_32 i; /* Current row index */ #line 154 "dk4bifp.ctr" #if DK4_USE_ASSERT assert(NULL != tsdata); #endif ppngfr = (dk4_bif_png_per_frame_t *)tsdata; if (NULL != ppngfr->rows) { rp = ppngfr->rows; for (i = 0UL; i < ppngfr->h; i++) { dk4mem_release(*rp); rp++; } dk4mem_release(ppngfr->rows); } dk4mem_release(ppngfr); #line 168 "dk4bifp.ctr" } void dk4bifpng_nc_release_per_file_data( void *tsdata ) { #line 178 "dk4bifp.ctr" #if DK4_USE_ASSERT assert(NULL != tsdata); #endif dk4mem_release(tsdata); #line 183 "dk4bifp.ctr" } dk4_bif_t * dk4bifpng_nc_open_file( FILE *fipo, dkChar const *fn, int honly, dk4_cs_conv_ctx_t const *pcsctx, dk4_bif_png_clobbered_t *pngcp, dk4_er_t *erp ) { unsigned char pngsig[8]; /* Buffer for PNG signature */ dk4_px_resample_t pxres; /* Pixel resampler */ png_color_16p bgp = NULL; /* Background data */ png_structp ppngread = NULL; /* PNG reader structure */ png_infop ppnginfo = NULL; /* PNG info structure */ size_t i; #line 204 "dk4bifp.ctr" #if DK4_USE_ASSERT assert(NULL != fipo); #endif /* Create bif and frame for one-frame image */ pngcp->back = dk4biftool_nc_new_for_one_frame( fn, DK4_BIF_TYPE_PNG, honly, pcsctx, erp ); if (NULL == pngcp->back) { goto finished; } /* Allocate per-frame data structure */ (pngcp->back->cf)->tsdata = dk4bifpng_tsdata_new(erp); if (NULL == (pngcp->back->cf)->tsdata) { goto finished; } pngcp->pfrpng = (dk4_bif_png_per_frame_t *)((pngcp->back->cf)->tsdata); /* Check PNG signature */ if (8 != fread(pngsig, 1, 8, fipo)) { goto finished; } if (!png_check_sig(pngsig, 8)) { goto finished; } /* Create PNG reader structure */ if (0 == setjmp(pngcp->pfrpng->jump_buf)) { ppngread = png_create_read_struct( PNG_LIBPNG_VER_STRING, (png_voidp)pngcp->pfrpng, (png_error_ptr)dk4bifpng_i_error_fn, (png_error_ptr)dk4bifpng_i_warning_fn ); if (NULL == ppngread) { dk4error_set_elsize_nelem( erp, DK4_E_MEMORY_ALLOCATION_FAILED, sizeof(png_structp), 1 ); goto finished; } } else { pngcp->pfrpng->had_error = 2; goto finished; } /* Create PNG info structure */ if (0 == setjmp(pngcp->pfrpng->jump_buf)) { ppnginfo = png_create_info_struct(ppngread); if (NULL == ppnginfo) { dk4error_set_elsize_nelem( erp, DK4_E_MEMORY_ALLOCATION_FAILED, sizeof(png_infop), 1 ); goto finished; } } else { pngcp->pfrpng->had_error = 2; goto finished; } /* First reading pass (header information) */ if (0 == setjmp(pngcp->pfrpng->jump_buf)) { /* Initialize PNG IO with file */ png_init_io(ppngread, fipo); /* Set number of bytes used in signature check */ png_set_sig_bytes(ppngread, 8); /* Read information from file header */ png_read_info(ppngread, ppnginfo); png_get_IHDR( ppngread, ppnginfo, &(pngcp->pfrpng->w), &(pngcp->pfrpng->h), &(pngcp->pfrpng->bd), &(pngcp->pfrpng->ct), &(pngcp->pfrpng->im), &(pngcp->pfrpng->cm), &(pngcp->pfrpng->fm) ); (pngcp->back->cf)->bg[0] = dk4pxbit_get_max(pngcp->pfrpng->bd); (pngcp->back->cf)->bg[1] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bg[2] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bglbd[0] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bglbd[1] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bglbd[2] = (pngcp->back->cf)->bg[0]; pngcp->pfrpng->ch = png_get_channels(ppngread, ppnginfo); /* Read resolution */ if (png_get_valid(ppngread, ppnginfo, PNG_INFO_pHYs)) { #if DK4_HAVE_PNG_GET_PIXELS_PER_INCH pngcp->pfrpng->xdpi = pngcp->pfrpng->ydpi = png_get_pixels_per_inch( ppngread, ppnginfo ); pngcp->pfrpng->xdpi = png_get_x_pixels_per_inch( ppngread, ppnginfo ); pngcp->pfrpng->ydpi = png_get_y_pixels_per_inch( ppngread, ppnginfo ); pngcp->pfrpng->dblxdpi = (double)(pngcp->pfrpng->xdpi); pngcp->pfrpng->dblydpi = (double)(pngcp->pfrpng->ydpi); #else pngcp->pfrpng->xdpi = pngcp->pfrpng->ydpi = png_get_pixels_per_meter( ppngread, ppnginfo ); pngcp->pfrpng->xdpi = png_get_x_pixels_per_meter( ppngread, ppnginfo ); pngcp->pfrpng->ydpi = png_get_y_pixels_per_meter( ppngread, ppnginfo ); pngcp->pfrpng->dblxdpi = 0.0254 * (double)(pngcp->pfrpng->xdpi); pngcp->pfrpng->dblydpi = 0.0254 * (double)(pngcp->pfrpng->ydpi); pngcp->pfrpng->xdpi = (png_uint_32)(pngcp->pfrpng->dblxdpi); pngcp->pfrpng->ydpi = (png_uint_32)(pngcp->pfrpng->dblydpi); #endif } /* Require palette to RGB conversion if necessary */ if (PNG_COLOR_TYPE_PALETTE == pngcp->pfrpng->ct) { png_set_palette_to_rgb(ppngread); } /* Require mask to alpha conversion if necessary */ if(png_get_valid(ppngread, ppnginfo, PNG_INFO_tRNS)) { png_set_tRNS_to_alpha(ppngread); } /* Set up automatic interlace handling */ if (PNG_INTERLACE_ADAM7 == pngcp->pfrpng->im) { pngcp->pfrpng->ip = png_set_interlace_handling(ppngread); } /* Update information */ png_read_update_info(ppngread, ppnginfo); png_get_IHDR( ppngread, ppnginfo, &(pngcp->pfrpng->w), &(pngcp->pfrpng->h), &(pngcp->pfrpng->bd), &(pngcp->pfrpng->ct), &(pngcp->pfrpng->im), &(pngcp->pfrpng->cm), &(pngcp->pfrpng->fm) ); (pngcp->back->cf)->bg[0] = dk4pxbit_get_max(pngcp->pfrpng->bd); (pngcp->back->cf)->bg[1] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bg[2] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bglbd[0] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bglbd[1] = (pngcp->back->cf)->bg[1]; (pngcp->back->cf)->bglbd[2] = (pngcp->back->cf)->bg[2]; pngcp->pfrpng->ch = png_get_channels(ppngread, ppnginfo); /* Pass data upwards to frame structure */ (pngcp->back->cf)->res_x = pngcp->pfrpng->dblxdpi; (pngcp->back->cf)->res_y = pngcp->pfrpng->dblydpi; (pngcp->back->cf)->dim_x = (dk4_bif_dim_t)(pngcp->pfrpng->w); (pngcp->back->cf)->dim_y = (dk4_bif_dim_t)(pngcp->pfrpng->h); (pngcp->back->cf)->l_bdepth = (pngcp->back->cf)->r_bdepth = pngcp->pfrpng->bd; dk4pxres_setup(&((pngcp->back->cf)->resampler), pngcp->pfrpng->bd, pngcp->pfrpng->bd); (pngcp->back->cf)->bg[0] = dk4pxbit_get_max(pngcp->pfrpng->bd); (pngcp->back->cf)->bg[1] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bg[2] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bglbd[0] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bglbd[1] = (pngcp->back->cf)->bg[1]; (pngcp->back->cf)->bglbd[2] = (pngcp->back->cf)->bg[2]; switch (pngcp->pfrpng->ct) { case PNG_COLOR_TYPE_GRAY : { (pngcp->back->cf)->l_cs = (pngcp->back->cf)->f_cs = DK4_CS_GRAY; (pngcp->back->cf)->n_comp = 1; } break; case PNG_COLOR_TYPE_GRAY_ALPHA : { (pngcp->back->cf)->l_cs = (pngcp->back->cf)->f_cs = DK4_CS_GRAY_ALPHA; (pngcp->back->cf)->n_comp = 2; } break; case PNG_COLOR_TYPE_PALETTE : { (pngcp->back->cf)->l_cs = (pngcp->back->cf)->f_cs = DK4_CS_RGB; (pngcp->back->cf)->n_comp = 3; } break; case PNG_COLOR_TYPE_RGB : { (pngcp->back->cf)->l_cs = (pngcp->back->cf)->f_cs = DK4_CS_RGB; (pngcp->back->cf)->n_comp = 3; } break; case PNG_COLOR_TYPE_RGB_ALPHA : { (pngcp->back->cf)->l_cs = (pngcp->back->cf)->f_cs = DK4_CS_RGB_ALPHA; (pngcp->back->cf)->n_comp = 4; } break; default : { pngcp->pfrpng->had_error = 2; goto finished; } break; } if ((pngcp->back->cf)->n_comp != (size_t)(pngcp->pfrpng->ch)) { pngcp->pfrpng->had_error = 2; goto finished; } } else { pngcp->pfrpng->had_error = 2; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); goto finished; } /* Second reading pass (image data) */ if (0 != honly) { pngcp->ok = 1; goto finished; } if (0 == setjmp(pngcp->pfrpng->jump_buf)) { pngcp->pfrpng->rowbytes = png_get_rowbytes(ppngread, ppnginfo); pngcp->pfrpng->rows = dk4mem_new(png_bytep,(size_t)(pngcp->pfrpng->h),erp); if (NULL == pngcp->pfrpng->rows) { goto finished; } /* Initialize row pointers */ for (i = 0; i < (size_t)(pngcp->pfrpng->h); i++) { (pngcp->pfrpng->rows)[i] = NULL; } /* Allocate row pointers */ for (i = 0; i < (size_t)(pngcp->pfrpng->h); i++) { (pngcp->pfrpng->rows)[i] = dk4mem_new(png_byte,(size_t)(pngcp->pfrpng->rowbytes), erp); if (NULL == (pngcp->pfrpng->rows)[i]) { goto finished; } } /* Now read image */ png_read_image(ppngread, pngcp->pfrpng->rows); if (png_get_bKGD(ppngread, ppnginfo, &bgp)) { if (NULL != bgp) { (pngcp->back->cf)->bg[0] = bgp->red; (pngcp->back->cf)->bg[1] = bgp->green; (pngcp->back->cf)->bg[2] = bgp->blue; (pngcp->back->cf)->bglbd[0] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bglbd[1] = (pngcp->back->cf)->bg[1]; (pngcp->back->cf)->bglbd[2] = (pngcp->back->cf)->bg[2]; /* Colors in pngcp->background chunk are always 8 bit, so we need to rescale. */ dk4pxres_init(&pxres); dk4pxres_setup(&pxres, 8, pngcp->pfrpng->bd); dk4pxres_multiple(&((pngcp->back->cf)->bg[0]), 4, &pxres); dk4pxres_multiple(&((pngcp->back->cf)->bglbd[0]), 4, &pxres); #line 453 "dk4bifp.ctr" #line 454 "dk4bifp.ctr" #line 455 "dk4bifp.ctr" #line 456 "dk4bifp.ctr" #line 457 "dk4bifp.ctr" #line 458 "dk4bifp.ctr" (pngcp->back->cf)->hbg = 1; switch ((pngcp->back->cf)->l_cs) { case DK4_CS_GRAY_ALPHA : case DK4_CS_GRAY : { (pngcp->back->cf)->bg[0] = dk4cs_mix_rgb_to_gray( (pngcp->back->cf)->bg[0], (pngcp->back->cf)->bg[1], (pngcp->back->cf)->bg[2], &(pngcp->back->cs_ctx) ); (pngcp->back->cf)->bg[1] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bg[2] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bglbd[0] = (pngcp->back->cf)->bg[0]; (pngcp->back->cf)->bglbd[1] = (pngcp->back->cf)->bg[1]; (pngcp->back->cf)->bglbd[2] = (pngcp->back->cf)->bg[2]; } } } } pngcp->ok = 1; } else { pngcp->pfrpng->had_error = 2; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); goto finished; } /* Indicate success */ pngcp->ok = 1; /* Clean up and return */ finished: /* Release PNG file reader resources from libpng */ if (NULL != ppngread) { if (NULL != ppnginfo) { #if DK4_HAVE_SETJMP_H if (0 == setjmp(pngcp->pfrpng->jump_buf)) { #endif png_destroy_info_struct(ppngread,&(ppnginfo)); #if DK4_HAVE_SETJMP_H } else { #line 502 "dk4bifp.ctr" } #endif ppnginfo = NULL; } else { } #if DK4_HAVE_SETJMP_H if (0 == setjmp(pngcp->pfrpng->jump_buf)) { #endif png_destroy_read_struct( &(ppngread), (png_infopp)NULL, (png_infopp)NULL ); #if DK4_HAVE_SETJMP_H } else { #line 517 "dk4bifp.ctr" } #endif ppngread = NULL; } else { } /* Release result if any error occured. */ if ((NULL != pngcp->back) && (0 == pngcp->ok)) { #line 526 "dk4bifp.ctr" dk4bif_close(pngcp->back); pngcp->back = NULL; dk4error_set_simple_error_code(erp, DK4_E_SYNTAX); } #line 531 "dk4bifp.ctr" return pngcp->back; } int dk4bifpng_nc_get_original_pixel( dk4_px_t *dptr, dk4_bif_t const *bif, dk4_bif_dim_t rowno, dk4_bif_dim_t colno ) { dk4_er_t er; /* Error report for math operations */ dk4_bif_png_per_frame_t *pfrpng; /* Per-frame data */ png_bytep rowptr; /* Address of row data */ size_t si; /* Start index of pixel data in row */ size_t vi; /* Index of current sample in row */ size_t i; /* Traverse all components */ int back = 0; #line 552 "dk4bifp.ctr" #if DK4_USE_ASSERT assert(NULL != dptr); assert(NULL != bif); #endif pfrpng = (dk4_bif_png_per_frame_t *)((bif->cf)->tsdata); dk4error_init(&er); si = dk4ma_size_t_mul(colno, pfrpng->ch, &er); if ((DK4_E_NONE == er.ec) && ((SIZE_MAX - (size_t)(pfrpng->ch)) >= si)) { vi = si; #line 561 "dk4bifp.ctr" rowptr = (pfrpng->rows)[rowno]; for (i = 0; i < (size_t)(pfrpng->ch); i++) { *(dptr++) = dk4bifpackedbits_get_element( rowptr, vi++, pfrpng->bd, pfrpng->rowbytes ); } back = 1; } #line 570 "dk4bifp.ctr" return back; } #endif /* if DK4_HAVE_PNG_H */ /* vim: set ai sw=4 ts=4 : */