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
|
// Copyright (c) 2017-2023 California Institute of Technology ("Caltech"). U.S.
// Government sponsorship acknowledged. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
// mrcal images. These are completely uninteresting, and don't do anything
// better that other image read/write APIS. If you have image libraries running,
// use those. If not, the ones defined here should be light and painless
// I support several image types:
// - "uint8": 8-bit grayscale
// - "uint16": 16-bit grayscale (using the system endian-ness)
// - "bgr": 24-bit BGR color
//
// Each type defines several functions in the MRCAL_IMAGE_DECLARE() macro:
//
// - mrcal_image_TYPE_t container image
// - mrcal_image_TYPE_at(mrcal_image_TYPE_t* image, int x, int y)
// - mrcal_image_TYPE_at_const(const mrcal_image_TYPE_t* image, int x, int y)
// - mrcal_image_TYPE_t mrcal_image_TYPE_crop(mrcal_image_TYPE_t* image, in x0, int y0, int w, int h)
// - mrcal_image_TYPE_save (const char* filename, const mrcal_image_TYPE_t* image);
// - mrcal_image_TYPE_load( mrcal_image_TYPE_t* image, const char* filename);
//
// And there's a generic load function:
// mrcal_image_anytype_load(// output
// mrcal_image_void_t* image,
// int* bits_per_pixel,
// int* channels,
// // input
// const char* filename);
//
// The image-loading functions require a few notes:
//
// An image structure to fill in is given. image->data will be allocated to the
// proper size. It is the caller's responsibility to free(image->data) when
// they're done. Usage sample:
//
// mrcal_image_uint8_t image;
// mrcal_image_uint8_load(&image, image_filename);
// .... do stuff ...
// free(image.data);
//
// mrcal_image_uint8_load() converts images to 8-bpp grayscale. Color and
// palettized images are accepted. mrcal_image_uint8_load(a 16-bit image) will
// apply stretch equalization
//
// mrcal_image_uint16_load() does NOT convert images. The images being read must
// already be stored as 16bpp grayscale images
//
// mrcal_image_bgr_load() converts images to 24-bpp color
#include <stdint.h>
#include <stdbool.h>
typedef struct { uint8_t bgr[3]; } mrcal_bgr_t;
#define MRCAL_IMAGE_TYPE_DECLARE(T, Tname) \
typedef struct \
{ \
union \
{ \
/* in pixels */ \
struct {int w, h;}; \
struct {int width, height;}; \
struct {int cols, rows;}; \
}; \
int stride; /* in bytes */ \
T* data; \
} mrcal_image_ ## Tname ## _t;
#define MRCAL_IMAGE_ACCESSORS_DEFINE(T, Tname) \
static inline \
T* mrcal_image_ ## Tname ## _at(mrcal_image_ ## Tname ## _t* image, int x, int y) \
{ \
return &image->data[x + y*image->stride / sizeof(T)]; \
} \
\
static inline \
const T* mrcal_image_ ## Tname ## _at_const(const mrcal_image_ ## Tname ## _t* image, int x, int y) \
{ \
return &image->data[x + y*image->stride / sizeof(T)]; \
} \
\
static inline \
mrcal_image_ ## Tname ## _t \
mrcal_image_ ## Tname ## _crop(mrcal_image_ ## Tname ## _t* image, \
int x0, int y0, \
int w, int h) \
{ \
/* no designated initializers; ancient c++ compilers complain */ \
mrcal_image_ ## Tname ## _t out; \
out.w = w; \
out.h = h; \
out.stride = image->stride; \
out.data = mrcal_image_ ## Tname ## _at(image,x0,y0); \
return out; \
}
#define MRCAL_IMAGE_DECLARE(T, Tname) \
MRCAL_IMAGE_TYPE_DECLARE( T, Tname) \
MRCAL_IMAGE_ACCESSORS_DEFINE(T, Tname)
#define MRCAL_IMAGE_SAVE_LOAD_DECLARE(T, Tname) \
bool mrcal_image_ ## Tname ## _save (const char* filename, const mrcal_image_ ## Tname ## _t* image); \
bool mrcal_image_ ## Tname ## _load( mrcal_image_ ## Tname ## _t* image, const char* filename);
// Common images types
MRCAL_IMAGE_DECLARE(uint8_t, uint8);
MRCAL_IMAGE_DECLARE(uint16_t, uint16);
MRCAL_IMAGE_DECLARE(mrcal_bgr_t, bgr);
MRCAL_IMAGE_SAVE_LOAD_DECLARE(uint8_t, uint8);
MRCAL_IMAGE_SAVE_LOAD_DECLARE(uint16_t, uint16);
MRCAL_IMAGE_SAVE_LOAD_DECLARE(mrcal_bgr_t, bgr);
// Generic image type. Need to cast it to a specific type before using it for
// anything
MRCAL_IMAGE_TYPE_DECLARE(void, void);
// Uncommon types. Not everything supports these
MRCAL_IMAGE_DECLARE(int8_t, int8);
MRCAL_IMAGE_DECLARE(int16_t, int16);
MRCAL_IMAGE_DECLARE(int32_t, int32);
MRCAL_IMAGE_DECLARE(uint32_t, uint32);
MRCAL_IMAGE_DECLARE(int64_t, int64);
MRCAL_IMAGE_DECLARE(uint64_t, uint64);
MRCAL_IMAGE_DECLARE(float, float);
MRCAL_IMAGE_DECLARE(double, double);
// Load the image into whatever type is stored on disk
bool mrcal_image_anytype_load(// output
mrcal_image_void_t* image,
int* bits_per_pixel,
int* channels,
// input
const char* filename);
#ifdef __cplusplus
}
#endif
|