2024年4月6日发(作者:衣晓灵)
/* ref:/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h */
#include
#include
#include
#include "timing.h"
#include
#include
#ifndef _MAX_DRIVE
#define _MAX_DRIVE 3
#endif
#ifndef _MAX_FNAME
#define _MAX_FNAME 256
#endif
#ifndef _MAX_EXT
#define _MAX_EXT 256
#endif
#ifndef _MAX_DIR
#define _MAX_DIR 256
#endif
#ifdef _MSC_VER
#endif
#ifndef MIN
#define MIN(a, b) ( (a) > (b) ? (b) : (a) )
#endif
#ifndef _NEAR
#define _NEAR(x) ( (int) ( (x) + .5) )
#endif
#ifndef PREV
#define PREV(x) ( (int) (x) )
#endif
#ifndef NEXT
#define NEXT(x) (MIN( (int) (x) + 1, lut3d->lutsize - 1 ) )
#endif
#ifndef R
#define R 0
#endif
#ifndef G
#define G 1
#endif
#ifndef B
#define B 2
#endif
#ifndef A
#define A 3
#endif
#ifndef MAX_LEVEL
#define MAX_LEVEL 64
#endif
enum interp_mode {
INTERPOLATE_NEAREST,
INTERPOLATE_TRILINEAR,
INTERPOLATE_TETRAHEDRAL,
NB_INTERP_MODE
};
struct rgbvec {
float r, g, b;
};
/* 3D LUT don't often go up to level 32 */
typedef struct LUT3DContext {
uint8_t rgba_map[4];
int step;
struct rgbvec lut[MAX_LEVEL][MAX_LEVEL][MAX_LEVEL];
int lutsize;
} LUT3DContext;
#ifdef _MSC_VER
int strcasecmp(const char *s1, char *s2) {
while (toupper((unsigned char)*s1) == toupper((unsigned char)*s2++))
if (*s1++ == 0x00)
return (0);
return (toupper((unsigned char)*s1) - toupper((unsigned char) *--s2));
}
#endif
static inline float lerpf(float v0, float v1, float f) {
return (v0 + (v1 - v0) * f);
}
static inline struct rgbvec lerp(const struct rgbvec *v0, const struct rgbvec *v1, float f) {
struct rgbvec v = {
lerpf(v0->r, v1->r, f), lerpf(v0->g, v1->g, f), lerpf(v0->b, v1->b, f)
};
return (v);
}
/**
* Get the nearest defined point
*/
static inline struct rgbvec interp_nearest(const LUT3DContext *lut3d,
const struct rgbvec *s) {
return (lut3d->lut[_NEAR(s->r)][_NEAR(s->g)][_NEAR(s->b)]);
}
/**
* Interpolate using the 8 vertices of a cube
* @see /wiki/Trilinear_interpolation
*/
static inline struct rgbvec interp_trilinear(const LUT3DContext *lut3d,
const struct rgbvec *s) {
const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)};
const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)};
const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]};
const struct rgbvec c000 = lut3d->lut[prev[0]][prev[1]][prev[2]];
const struct rgbvec c001 = lut3d->lut[prev[0]][prev[1]][next[2]];
const struct rgbvec c010 = lut3d->lut[prev[0]][next[1]][prev[2]];
const struct rgbvec c011 = lut3d->lut[prev[0]][next[1]][next[2]];
const struct rgbvec c100 = lut3d->lut[next[0]][prev[1]][prev[2]];
const struct rgbvec c101 = lut3d->lut[next[0]][prev[1]][next[2]];
const struct rgbvec c110 = lut3d->lut[next[0]][next[1]][prev[2]];
const struct rgbvec c111 = lut3d->lut[next[0]][next[1]][next[2]];
const struct rgbvec c00 = lerp(&c000, &c100, d.r);
const struct rgbvec c10 = lerp(&c010, &c110, d.r);
const struct rgbvec c01 = lerp(&c001, &c101, d.r);
const struct rgbvec c11 = lerp(&c011, &c111, d.r);
const struct rgbvec c0 = lerp(&c00, &c10, d.g);
2024年4月6日发(作者:衣晓灵)
/* ref:/serge-rgb/TinyJPEG/blob/master/tiny_jpeg.h */
#include
#include
#include
#include "timing.h"
#include
#include
#ifndef _MAX_DRIVE
#define _MAX_DRIVE 3
#endif
#ifndef _MAX_FNAME
#define _MAX_FNAME 256
#endif
#ifndef _MAX_EXT
#define _MAX_EXT 256
#endif
#ifndef _MAX_DIR
#define _MAX_DIR 256
#endif
#ifdef _MSC_VER
#endif
#ifndef MIN
#define MIN(a, b) ( (a) > (b) ? (b) : (a) )
#endif
#ifndef _NEAR
#define _NEAR(x) ( (int) ( (x) + .5) )
#endif
#ifndef PREV
#define PREV(x) ( (int) (x) )
#endif
#ifndef NEXT
#define NEXT(x) (MIN( (int) (x) + 1, lut3d->lutsize - 1 ) )
#endif
#ifndef R
#define R 0
#endif
#ifndef G
#define G 1
#endif
#ifndef B
#define B 2
#endif
#ifndef A
#define A 3
#endif
#ifndef MAX_LEVEL
#define MAX_LEVEL 64
#endif
enum interp_mode {
INTERPOLATE_NEAREST,
INTERPOLATE_TRILINEAR,
INTERPOLATE_TETRAHEDRAL,
NB_INTERP_MODE
};
struct rgbvec {
float r, g, b;
};
/* 3D LUT don't often go up to level 32 */
typedef struct LUT3DContext {
uint8_t rgba_map[4];
int step;
struct rgbvec lut[MAX_LEVEL][MAX_LEVEL][MAX_LEVEL];
int lutsize;
} LUT3DContext;
#ifdef _MSC_VER
int strcasecmp(const char *s1, char *s2) {
while (toupper((unsigned char)*s1) == toupper((unsigned char)*s2++))
if (*s1++ == 0x00)
return (0);
return (toupper((unsigned char)*s1) - toupper((unsigned char) *--s2));
}
#endif
static inline float lerpf(float v0, float v1, float f) {
return (v0 + (v1 - v0) * f);
}
static inline struct rgbvec lerp(const struct rgbvec *v0, const struct rgbvec *v1, float f) {
struct rgbvec v = {
lerpf(v0->r, v1->r, f), lerpf(v0->g, v1->g, f), lerpf(v0->b, v1->b, f)
};
return (v);
}
/**
* Get the nearest defined point
*/
static inline struct rgbvec interp_nearest(const LUT3DContext *lut3d,
const struct rgbvec *s) {
return (lut3d->lut[_NEAR(s->r)][_NEAR(s->g)][_NEAR(s->b)]);
}
/**
* Interpolate using the 8 vertices of a cube
* @see /wiki/Trilinear_interpolation
*/
static inline struct rgbvec interp_trilinear(const LUT3DContext *lut3d,
const struct rgbvec *s) {
const int prev[] = {PREV(s->r), PREV(s->g), PREV(s->b)};
const int next[] = {NEXT(s->r), NEXT(s->g), NEXT(s->b)};
const struct rgbvec d = {s->r - prev[0], s->g - prev[1], s->b - prev[2]};
const struct rgbvec c000 = lut3d->lut[prev[0]][prev[1]][prev[2]];
const struct rgbvec c001 = lut3d->lut[prev[0]][prev[1]][next[2]];
const struct rgbvec c010 = lut3d->lut[prev[0]][next[1]][prev[2]];
const struct rgbvec c011 = lut3d->lut[prev[0]][next[1]][next[2]];
const struct rgbvec c100 = lut3d->lut[next[0]][prev[1]][prev[2]];
const struct rgbvec c101 = lut3d->lut[next[0]][prev[1]][next[2]];
const struct rgbvec c110 = lut3d->lut[next[0]][next[1]][prev[2]];
const struct rgbvec c111 = lut3d->lut[next[0]][next[1]][next[2]];
const struct rgbvec c00 = lerp(&c000, &c100, d.r);
const struct rgbvec c10 = lerp(&c010, &c110, d.r);
const struct rgbvec c01 = lerp(&c001, &c101, d.r);
const struct rgbvec c11 = lerp(&c011, &c111, d.r);
const struct rgbvec c0 = lerp(&c00, &c10, d.g);