5
* Created by Jens Ayton on 2009-10-01.
6
* Copyright 2009 Jens Ayton. All rights reserved.
11
#include "FPMImageOperations.h"
14
const FPMGammaFactor kFPMGammaLinear = 1.0f;
15
const FPMGammaFactor kFPMGammaSRGB = 2.2f;
16
const FPMGammaFactor kFPMGammaTraditionalMac = 1.8f;
19
#ifndef FPM_GAMMA_USE_LUT
20
#define FPM_GAMMA_USE_LUT 0
24
void ApplyGammaDirect(FloatPixMapRef pm, FPMColor *pixel, FPMPoint coords, void *info)
26
FPMGammaFactor gamma = *(FPMGammaFactor *)info;
27
pixel->r = powf(pixel->r, gamma);
28
pixel->g = powf(pixel->g, gamma);
29
pixel->b = powf(pixel->b, gamma);
35
typedef struct ApplyGammaLUTInfo
43
FPM_INLINE float ApplyGammaOne(float value, ApplyGammaLUTInfo *info)
47
unsigned index = value * info->scale;
48
if (index < info->entries) value = info->lut[index];
54
void ApplyGammaLUT(FloatPixMapRef pm, FPMColor *pixel, FPMPoint coords, void *info)
56
pixel->r = ApplyGammaOne(pixel->r, info);
57
pixel->g = ApplyGammaOne(pixel->g, info);
58
pixel->b = ApplyGammaOne(pixel->b, info);
64
void FPMApplyGamma(FloatPixMapRef pm, FPMGammaFactor currentGamma, FPMGammaFactor desiredGamma, unsigned steps)
66
if (pm != NULL && currentGamma != desiredGamma && steps > 1)
68
FPMGammaFactor resultingGamma = currentGamma / desiredGamma;
71
if (steps >= FPMGetArea(pm) * 5) // 5 is a fudge factor; 3 would strictly minimize number of powf() calls.
73
// No point in building a LUT if picture is not much bigger than LUT.
74
FPMForEachPixelF(pm, ApplyGammaDirect, &resultingGamma);
78
static float *lookupTable = NULL;
79
static unsigned lastTableSize = 0;
80
static float lastGamma;
82
if (lastTableSize != steps || resultingGamma != lastGamma)
85
lookupTable = malloc(steps * sizeof (float));
86
if (lookupTable == NULL)
88
// Fallback: apply gamma the slow way.
89
FPMForEachPixelF(pm, ApplyGammaDirect, &resultingGamma);
94
for (i = 0; i < steps; i++)
96
lookupTable[i] = powf((float)i / (float)steps, resultingGamma);
100
ApplyGammaLUTInfo info =
107
FPMForEachPixelF(pm, ApplyGammaLUT, &info);
109
FPMForEachPixelF(pm, ApplyGammaDirect, &resultingGamma);