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 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
|
/*! \file
* \noop Copyright 2006-2016 Christian Stigen Larsen
* \noop Copyright 2020-2024 Christoph Raitzig
*
* \brief Functions that work directly with images.
*
* Call decompress_jpeg() or decompress_png() to read an input image from a stream and print it.
* Which is called does not matter in regards to functionality, if decompress_jpeg() fails decompress_png() is called and vice versa.
* For efficiency call the function that is most likely to work.
*
* All other functions in this file are called by decompress_jpeg() or decompress_png() or one of the functions they call.
*
* \author Christian Stigen Larsen
* \author Christoph Raitzig
* \copyright Distributed under the GNU General Public License (GPL) v2.
*/
#ifndef INC_JP2A_IMAGE_H
#define INC_JP2A_IMAGE_H
#include "config.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <stdint.h>
#include "jpeglib.h"
#include "png.h"
#include "webp/decode.h"
#include <setjmp.h>
#include "html.h"
/*! \enum Orientation
* \brief Image orientation
*
* The displayed image orientation can differ from how the image is stored in a file based on Exif metadata.
*/
typedef enum {
HORIZONTAL,
MIRROR_HORIZONTAL,
ROTATE_180,
MIRROR_VERTICAL,
MIRROR_HORIZONTAL_ROTATE_90,
ROTATE_270,
MIRROR_HORIZONTAL_ROTATE_270,
ROTATE_90
} Orientation;
/*! \struct Image_
* \brief Holds a decompressed image.
*
* #pixel, #red, #green, #blue, #alpha and #yadds are arrays of size #width * #height.
*/
typedef struct Image_ {
int width; //!< width
int height; //!< height
Orientation orientation; //!< orientation
int switch_x_y; //!< whether stored x-y-dimensions differ from displayed ones due to a rotation
int src_width; //!< width in source orientation - differs from width if x and y dimensions are switched
int src_height; //!< height in source orientation - differs from height if x and y dimensions are switched
float *pixel; //!< luminosities (i.e. gray values)
float *red; //!< red part
float *green; //!< green part
float *blue; //!< blue part
float *alpha; //!< opacities
int *yadds; //!< how many scanlines were used for a pixel, used by normalize()
float resize_y; //!< Factor by which the output image is resized from the input image in the y dimension (height). For example for an output height of 40 and input height of 80 this equals approximately 0.5.
float resize_x; //!< Factor by which the output image is resized from the input image in the x dimension (width). For example for an output width of 50 and input height of 100 this equals approximately 2.0.
int *lookup_resx; //!< where to start and end using pixels of the input image to calculate a pixel of the output image along the x axis
} Image;
/*!
* \typedef Image
* \brief See #Image_
*/
/*! \struct my_jpeg_error_mgr
* \brief This struct is used for custom error handling with libjpeg.
*/
typedef struct my_jpeg_error_mgr {
struct jpeg_error_mgr pub; //!< libjpeg's error manager
jmp_buf setjmp_buffer; //!< where to jump to if an error occurs
} my_jpeg_error_mgr;
/*!
* \typedef my_jpeg_error_mgr
* \brief See #my_jpeg_error_mgr
*/
/*!
* \brief Pointer to a #my_jpeg_error_mgr.
*/
typedef struct my_jpeg_error_mgr *my_jpeg_error_ptr;
/*!
* \brief WebP image data struct
*/
typedef struct {
uint8_t* data;
size_t size;
} webp_data;
/*! \struct error_collector
* \brief Contains and collects errors that occur while decompressing an image.
*
* With this struct decompress_jpeg(), decompress_png() and decompress_webp() can be called recursively since #jpeg_status, #png_status and #webp_status can be used to determine whether a previous call failed or not.
*/
typedef struct error_collector {
my_jpeg_error_mgr *jpeg_error; //!< contains information about a JPEG decompression error
char *png_error_msg; //!< error message for a PNG decompression error
char *webp_error_msg; //!< error message for a WebP decompression error
int jpeg_status; //!< true if an error occurred during JPEG decompression, false otherwise
int png_status; //!< true if an error occurred during PNG decompression, false otherwise
int webp_status; //!< true if an error occurred during WebP decompression, false otherwise
} error_collector;
/*!
* \typedef error_collector
* \brief See #error_collector
*/
/*!
* \brief Prints the top margin of an image
*
* \param image Image
* \param f output stream
*/
void print_margin_top(const Image *image, FILE *f);
/*!
* \brief Prints the bottom margin of an image
*
* \param image Image
* \param f output stream
*/
void print_margin_bottom(const Image *image, FILE *f);
/*!
* \brief Prints the start margin of an image
*
* \param image Image
* \param f output stream
*/
void print_margin_start(const Image *image, FILE *f);
/*!
* \brief Prints the top or bottom of a border around an image.
*
* \param width width of the output image
*/
void print_border(const int width);
/*!
* \brief Prints an image.
*
* Calls print_image_colors() or print_image_no_colors().
*
* \param image the output image
* \param f the stream to print to
*/
void print_image(Image *image, FILE *f);
/*!
* \brief Prints an image with color.
*
* \param image the output image
* \param chars the character palette
* \param f the stream to print to
*/
void print_image_colors(const Image* const image, const int chars, FILE *f);
/*!
* \brief Prints an image without color.
*
* \param image the output image
* \param chars the character palette
* \param f the stream to print to
*/
void print_image_no_colors(const Image* const image, const int chars, FILE *f);
/*!
* \brief Clears the image (i.e. sets all pixels to black, alpha to max)
*
* \param i the image
*/
void clear(Image* i);
/*!
* \brief Normalizes the image.
*
* After decompressing the image into RAM the G/RGB values must not be between 0 and 1. The functions normalizes them so that they are.
*
* \param i the image
*/
void normalize(Image* i);
/*!
* \brief Prints a progress bar.
*
* \param progress The progress. Between 0 and 1 where 0 is 0% and 1 is 100%
*/
void print_progress(float progress);
/*!
* \brief Prints some information about the image and how it will be printed.
*
* \param jpg contains information about the JPEG image
* \param orientation image orientation (read from Exif metadata)
*/
void print_info_jpeg(const struct jpeg_decompress_struct* jpg, const Orientation orientation);
/*!
* \brief Prints some information about the image and how it will be printed.
*
* \param png_ptr necessary for calling libpng functions
* \param info_ptr contains information about the PNG image
*/
void print_info_png(const png_structp png_ptr, const png_infop info_ptr);
/*!
* \brief Prints some information about the image and how it will be printed.
*
* \param config WebP decoding information
*/
void print_info_webp(WebPDecoderConfig* config);
/*!
* \brief Processes a scanline of a JPEG image.
*
* \param jpg contains information about the JPEG image
* \param scanline the scanline
* \param i the output image
*/
void process_scanline_jpeg(const struct jpeg_decompress_struct *jpg,
const JSAMPLE* scanline, Image* i);
/*!
* \brief Processes a scanline of a PNG image.
*
* Supports a bit-depth of 8 and G, GA, RGB and RGBA.
*
* \param row scanline (i.e. the row of pixels)
* \param current_y the current height
* \param color_components the number of color components (e.g. 4 for RGBA)
* \param i the output image
*/
void process_scanline_png(const png_bytep row, const int current_y, const int color_components, Image* i);
/*!
* \brief Frees allocated memory of an image.
*
* \param i the image
*/
void free_image(Image* i);
/*!
* \brief Allocates memory for holding the pixels etc. Sets the width and height.
*
* \param i the image
* \param switch_x_y whether to switch x and y dimensions, this is the case when the stored pixels differ from the displayed pixels due to a rotation
*/
void malloc_image(Image* i, int switch_x_y);
/*!
* \brief Sets internal values necessary for processing scanlines.
*
* \param i the struct to hold the output image
* \param src_width width of the source image
* \param src_height height of the source image
*/
void init_image(Image *i, int src_width, int src_height);
/*!
* \brief Get the image orientation
*
* Determine the image orientation from EXIF metadata.
*
* Rewinds the file.
*
* \param imageFP image file pointer
*/
Orientation get_orientation(FILE *imageFP);
/*!
* \brief Decompresses and prints an image.
*
* Calls decompress_webp() if the image is not a JPEG image.
* Instead prints errors if there was an error when decompressing this image as JPEG previously.
*
* \param fin input stream, has to be seekable
* \param fout stream to print the image to
* \param errors contains previous errors and is used to save errors
*/
void decompress_jpeg(FILE *fin, FILE *fout, error_collector *errors);
/*!
* \brief Callback for errors while decompressing a JPEG image.
*
* \param jerr contains information about the error
*/
void jpeg_error_exit(j_common_ptr jerr);
/*!
* \brief Decompresses and prints an image.
*
* Calls decompress_jpeg() if the image is not a PNG image.
* Instead prints errors if there was an error when decompressing this image as PNG previously.
*
* \param fin input stream, has to be seekable
* \param fout stream to print the image to
* \param errors contains previous errors and is used to save errors
*/
void decompress_png(FILE *fin, FILE *fout, error_collector *errors);
/*!
* \brief Read WebP image into a buffer
*
* \param fp input stream
*/
webp_data* get_webp_data(FILE *fp);
/*!
* \brief Free WebP image buffer
*
* \param data WebP data
*/
void free_webp_data(webp_data* data);
/*!
* \brief Decompresses and prints an image.
*
* Calls decompress_png() if the image is not a WebP image.
* Instead prints errors if there was an error when decompressing this image as WebP previously.
*
* \param fin input stream, has to be seekable
* \param fout stream to print the image to
* \param errors contains previous errors and is used to save errors
*/
void decompress_webp(FILE *fp, FILE *fout, error_collector *errors);
/*!
* \brief Prints errors.
*
* Checks what errors have occurred and prints their error messages.
*
* \param errors the collected errors
*/
void print_errors(error_collector *errors);
#endif
|