@@ -344,65 +344,29 @@ static void GetCombinedEntropyUnrefined_MIPS32(const uint32_t X[],
ASM_END_COMMON_0 \
ASM_END_COMMON_1

#define ADD_VECTOR(A, B, OUT, SIZE, EXTRA_SIZE) do { \
const uint32_t* pa = (const uint32_t*)(A); \
const uint32_t* pb = (const uint32_t*)(B); \
uint32_t* pout = (uint32_t*)(OUT); \
const uint32_t* const LoopEnd = pa + (SIZE); \
assert((SIZE) % 4 == 0); \
ASM_START \
ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout) \
ASM_END_0 \
if ((EXTRA_SIZE) > 0) { \
const int last = (EXTRA_SIZE); \
int i; \
for (i = 0; i < last; ++i) pout[i] = pa[i] + pb[i]; \
} \
} while (0)

#define ADD_VECTOR_EQ(A, OUT, SIZE, EXTRA_SIZE) do { \
const uint32_t* pa = (const uint32_t*)(A); \
uint32_t* pout = (uint32_t*)(OUT); \
const uint32_t* const LoopEnd = pa + (SIZE); \
assert((SIZE) % 4 == 0); \
ASM_START \
ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout) \
ASM_END_1 \
if ((EXTRA_SIZE) > 0) { \
const int last = (EXTRA_SIZE); \
int i; \
for (i = 0; i < last; ++i) pout[i] += pa[i]; \
} \
} while (0)

static void HistogramAdd_MIPS32(const VP8LHistogram* const a,
const VP8LHistogram* const b,
VP8LHistogram* const out) {
static void AddVector_MIPS32(const uint32_t* pa, const uint32_t* pb,
uint32_t* pout, int size) {
uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
const int extra_cache_size = VP8LHistogramNumCodes(a->palette_code_bits_)
- (NUM_LITERAL_CODES + NUM_LENGTH_CODES);
assert(a->palette_code_bits_ == b->palette_code_bits_);

if (b != out) {
ADD_VECTOR(a->literal_, b->literal_, out->literal_,
NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
ADD_VECTOR(a->distance_, b->distance_, out->distance_,
NUM_DISTANCE_CODES, 0);
ADD_VECTOR(a->red_, b->red_, out->red_, NUM_LITERAL_CODES, 0);
ADD_VECTOR(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES, 0);
ADD_VECTOR(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
} else {
ADD_VECTOR_EQ(a->literal_, out->literal_,
NUM_LITERAL_CODES + NUM_LENGTH_CODES, extra_cache_size);
ADD_VECTOR_EQ(a->distance_, out->distance_, NUM_DISTANCE_CODES, 0);
ADD_VECTOR_EQ(a->red_, out->red_, NUM_LITERAL_CODES, 0);
ADD_VECTOR_EQ(a->blue_, out->blue_, NUM_LITERAL_CODES, 0);
ADD_VECTOR_EQ(a->alpha_, out->alpha_, NUM_LITERAL_CODES, 0);
}
const uint32_t end = ((size) / 4) * 4;
const uint32_t* const LoopEnd = pa + end;
int i;
ASM_START
ADD_TO_OUT(0, 4, 8, 12, 1, pa, pb, pout)
ASM_END_0
for (i = end; i < size; ++i) pout[i] = pa[i] + pb[i];
}

static void AddVectorEq_MIPS32(const uint32_t* pa, uint32_t* pout, int size) {
uint32_t temp0, temp1, temp2, temp3, temp4, temp5, temp6, temp7;
const uint32_t end = ((size) / 4) * 4;
const uint32_t* const LoopEnd = pa + end;
int i;
ASM_START
ADD_TO_OUT(0, 4, 8, 12, 0, pa, pout, pout)
ASM_END_1
for (i = end; i < size; ++i) pout[i] += pa[i];
}

#undef ADD_VECTOR_EQ
#undef ADD_VECTOR
#undef ASM_END_1
#undef ASM_END_0
#undef ASM_END_COMMON_1
@@ -422,7 +386,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitMIPS32(void) {
VP8LExtraCostCombined = ExtraCostCombined_MIPS32;
VP8LGetEntropyUnrefined = GetEntropyUnrefined_MIPS32;
VP8LGetCombinedEntropyUnrefined = GetCombinedEntropyUnrefined_MIPS32;
VP8LHistogramAdd = HistogramAdd_MIPS32;
VP8LAddVector = AddVector_MIPS32;
VP8LAddVectorEq = AddVectorEq_MIPS32;
}

#else // !WEBP_USE_MIPS32
@@ -170,12 +170,13 @@ static void CollectColorRedTransforms_SSE2(const uint32_t* argb, int stride,

//------------------------------------------------------------------------------

// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But
// that's ok since the histogram values are less than 1<<28 (max picture size).
#define LINE_SIZE 16 // 8 or 16
static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out,
int size) {
int i;
assert(size % LINE_SIZE == 0);
for (i = 0; i < size; i += LINE_SIZE) {
for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) {
const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
#if (LINE_SIZE == 16)
@@ -195,12 +196,14 @@ static void AddVector_SSE2(const uint32_t* a, const uint32_t* b, uint32_t* out,
_mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
#endif
}
for (; i < size; ++i) {
out[i] = a[i] + b[i];
}
}

static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) {
int i;
assert(size % LINE_SIZE == 0);
for (i = 0; i < size; i += LINE_SIZE) {
for (i = 0; i + LINE_SIZE <= size; i += LINE_SIZE) {
const __m128i a0 = _mm_loadu_si128((const __m128i*)&a[i + 0]);
const __m128i a1 = _mm_loadu_si128((const __m128i*)&a[i + 4]);
#if (LINE_SIZE == 16)
@@ -220,35 +223,11 @@ static void AddVectorEq_SSE2(const uint32_t* a, uint32_t* out, int size) {
_mm_storeu_si128((__m128i*)&out[i + 12], _mm_add_epi32(a3, b3));
#endif
}
}
#undef LINE_SIZE

// Note we are adding uint32_t's as *signed* int32's (using _mm_add_epi32). But
// that's ok since the histogram values are less than 1<<28 (max picture size).
static void HistogramAdd_SSE2(const VP8LHistogram* const a,
const VP8LHistogram* const b,
VP8LHistogram* const out) {
int i;
const int literal_size = VP8LHistogramNumCodes(a->palette_code_bits_);
assert(a->palette_code_bits_ == b->palette_code_bits_);
if (b != out) {
AddVector_SSE2(a->literal_, b->literal_, out->literal_, NUM_LITERAL_CODES);
AddVector_SSE2(a->red_, b->red_, out->red_, NUM_LITERAL_CODES);
AddVector_SSE2(a->blue_, b->blue_, out->blue_, NUM_LITERAL_CODES);
AddVector_SSE2(a->alpha_, b->alpha_, out->alpha_, NUM_LITERAL_CODES);
} else {
AddVectorEq_SSE2(a->literal_, out->literal_, NUM_LITERAL_CODES);
AddVectorEq_SSE2(a->red_, out->red_, NUM_LITERAL_CODES);
AddVectorEq_SSE2(a->blue_, out->blue_, NUM_LITERAL_CODES);
AddVectorEq_SSE2(a->alpha_, out->alpha_, NUM_LITERAL_CODES);
}
for (i = NUM_LITERAL_CODES; i < literal_size; ++i) {
out->literal_[i] = a->literal_[i] + b->literal_[i];
}
for (i = 0; i < NUM_DISTANCE_CODES; ++i) {
out->distance_[i] = a->distance_[i] + b->distance_[i];
for (; i < size; ++i) {
out[i] += a[i];
}
}
#undef LINE_SIZE

//------------------------------------------------------------------------------
// Entropy
@@ -675,7 +654,8 @@ WEBP_TSAN_IGNORE_FUNCTION void VP8LEncDspInitSSE2(void) {
VP8LTransformColor = TransformColor_SSE2;
VP8LCollectColorBlueTransforms = CollectColorBlueTransforms_SSE2;
VP8LCollectColorRedTransforms = CollectColorRedTransforms_SSE2;
VP8LHistogramAdd = HistogramAdd_SSE2;
VP8LAddVector = AddVector_SSE2;
VP8LAddVectorEq = AddVectorEq_SSE2;
VP8LCombinedShannonEntropy = CombinedShannonEntropy_SSE2;
VP8LVectorMismatch = VectorMismatch_SSE2;
VP8LBundleColorMap = BundleColorMap_SSE2;
@@ -1389,4 +1389,4 @@ static WEBP_INLINE uint32_t func_hadd_uh_u32(v8u16 in) {
} while (0)
#define AVER_UB2_UB(...) AVER_UB2(v16u8, __VA_ARGS__)

#endif /* WEBP_DSP_MSA_MACRO_H_ */
#endif // WEBP_DSP_MSA_MACRO_H_
@@ -0,0 +1,70 @@
// Copyright 2018 Google Inc. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the COPYING file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
// -----------------------------------------------------------------------------

#ifndef WEBP_DSP_QUANT_H_
#define WEBP_DSP_QUANT_H_

#include "src/dsp/dsp.h"
#include "src/webp/types.h"

#if defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) && \
!defined(WEBP_HAVE_NEON_RTCD)
#include <arm_neon.h>

#define IsFlat IsFlat_NEON

static uint32x2_t horizontal_add_uint32x4(const uint32x4_t a) {
const uint64x2_t b = vpaddlq_u32(a);
return vadd_u32(vreinterpret_u32_u64(vget_low_u64(b)),
vreinterpret_u32_u64(vget_high_u64(b)));
}

static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
int thresh) {
const int16x8_t tst_ones = vdupq_n_s16(-1);
uint32x4_t sum = vdupq_n_u32(0);

for (int i = 0; i < num_blocks; ++i) {
// Set DC to zero.
const int16x8_t a_0 = vsetq_lane_s16(0, vld1q_s16(levels), 0);
const int16x8_t a_1 = vld1q_s16(levels + 8);

const uint16x8_t b_0 = vshrq_n_u16(vtstq_s16(a_0, tst_ones), 15);
const uint16x8_t b_1 = vshrq_n_u16(vtstq_s16(a_1, tst_ones), 15);

sum = vpadalq_u16(sum, b_0);
sum = vpadalq_u16(sum, b_1);

levels += 16;
}
return thresh >= (int32_t)vget_lane_u32(horizontal_add_uint32x4(sum), 0);
}

#else

#define IsFlat IsFlat_C

static WEBP_INLINE int IsFlat(const int16_t* levels, int num_blocks,
int thresh) {
int score = 0;
while (num_blocks-- > 0) { // TODO(skal): refine positional scoring?
int i;
for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC
score += (levels[i] != 0);
if (score > thresh) return 0;
}
levels += 16;
}
return 1;
}

#endif // defined(WEBP_USE_NEON) && !defined(WEBP_ANDROID_NEON) &&
// !defined(WEBP_HAVE_NEON_RTCD)

#endif // WEBP_DSP_QUANT_H_
@@ -21,6 +21,7 @@

#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)

//------------------------------------------------------------------------------
// Row import
@@ -138,7 +139,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
if (yscale) {
for (x_out = 0; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -153,6 +154,7 @@ void WebPRescalerExportRowShrink_C(WebPRescaler* const wrk) {
}
}

#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER

@@ -209,6 +209,7 @@ static void ExportRowExpand_MIPS32(WebPRescaler* const wrk) {
}
}

#if 0 // disabled for now. TODO(skal): make match the C-code
static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) {
const int x_out_max = wrk->dst_width * wrk->num_channels;
uint8_t* dst = wrk->dst;
@@ -273,6 +274,7 @@ static void ExportRowShrink_MIPS32(WebPRescaler* const wrk) {
);
}
}
#endif // 0

//------------------------------------------------------------------------------
// Entry point
@@ -283,7 +285,7 @@ WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPS32(void) {
WebPRescalerImportRowExpand = ImportRowExpand_MIPS32;
WebPRescalerImportRowShrink = ImportRowShrink_MIPS32;
WebPRescalerExportRowExpand = ExportRowExpand_MIPS32;
WebPRescalerExportRowShrink = ExportRowShrink_MIPS32;
// WebPRescalerExportRowShrink = ExportRowShrink_MIPS32;
}

#else // !WEBP_USE_MIPS32
@@ -20,10 +20,12 @@

#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)

//------------------------------------------------------------------------------
// Row export

#if 0 // disabled for now. TODO(skal): make match the C-code
static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
int i;
const int x_out_max = wrk->dst_width * wrk->num_channels;
@@ -106,7 +108,7 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
}
for (i = 0; i < (x_out_max & 0x3); ++i) {
const uint32_t frac = (uint32_t)MULT_FIX(*frow++, yscale);
const int v = (int)MULT_FIX(*irow - frac, wrk->fxy_scale);
const int v = (int)MULT_FIX_FLOOR(*irow - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
*dst++ = v;
*irow++ = frac; // new fractional start
@@ -154,13 +156,14 @@ static void ExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
);
}
for (i = 0; i < (x_out_max & 0x3); ++i) {
const int v = (int)MULT_FIX(*irow, wrk->fxy_scale);
const int v = (int)MULT_FIX_FLOOR(*irow, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
*dst++ = v;
*irow++ = 0;
}
}
}
#endif // 0

static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
int i;
@@ -294,6 +297,7 @@ static void ExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
}
}

#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER

@@ -304,7 +308,7 @@ extern void WebPRescalerDspInitMIPSdspR2(void);

WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMIPSdspR2(void) {
WebPRescalerExportRowExpand = ExportRowExpand_MIPSdspR2;
WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2;
// WebPRescalerExportRowShrink = ExportRowShrink_MIPSdspR2;
}

#else // !WEBP_USE_MIPS_DSP_R2
@@ -22,6 +22,7 @@

#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)

#define CALC_MULT_FIX_16(in0, in1, in2, in3, scale, shift, dst) do { \
v4u32 tmp0, tmp1, tmp2, tmp3; \
@@ -262,6 +263,7 @@ static void RescalerExportRowExpand_MIPSdspR2(WebPRescaler* const wrk) {
}
}

#if 0 // disabled for now. TODO(skal): make match the C-code
static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
uint8_t* dst, int length,
const uint32_t yscale,
@@ -341,7 +343,7 @@ static WEBP_INLINE void ExportRowShrink_0(const uint32_t* frow, uint32_t* irow,
}
for (x_out = 0; x_out < length; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX(frow[x_out], yscale);
const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac;
@@ -426,6 +428,7 @@ static void RescalerExportRowShrink_MIPSdspR2(WebPRescaler* const wrk) {
ExportRowShrink_1(irow, dst, x_out_max, wrk);
}
}
#endif // 0

//------------------------------------------------------------------------------
// Entry point
@@ -434,7 +437,7 @@ extern void WebPRescalerDspInitMSA(void);

WEBP_TSAN_IGNORE_FUNCTION void WebPRescalerDspInitMSA(void) {
WebPRescalerExportRowExpand = RescalerExportRowExpand_MIPSdspR2;
WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2;
// WebPRescalerExportRowShrink = RescalerExportRowShrink_MIPSdspR2;
}

#else // !WEBP_USE_MSA
@@ -22,6 +22,7 @@

#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX_C(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
#define MULT_FIX_FLOOR_C(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)

#define LOAD_32x4(SRC, DST) const uint32x4_t DST = vld1q_u32((SRC))
#define LOAD_32x8(SRC, DST0, DST1) \
@@ -35,8 +36,11 @@

#if (WEBP_RESCALER_RFIX == 32)
#define MAKE_HALF_CST(C) vdupq_n_s32((int32_t)((C) >> 1))
#define MULT_FIX(A, B) /* note: B is actualy scale>>1. See MAKE_HALF_CST */ \
// note: B is actualy scale>>1. See MAKE_HALF_CST
#define MULT_FIX(A, B) \
vreinterpretq_u32_s32(vqrdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
#define MULT_FIX_FLOOR(A, B) \
vreinterpretq_u32_s32(vqdmulhq_s32(vreinterpretq_s32_u32((A)), (B)))
#else
#error "MULT_FIX/WEBP_RESCALER_RFIX need some more work"
#endif
@@ -135,8 +139,8 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
const uint32x4_t A1 = MULT_FIX(in1, yscale_half);
const uint32x4_t B0 = vqsubq_u32(in2, A0);
const uint32x4_t B1 = vqsubq_u32(in3, A1);
const uint32x4_t C0 = MULT_FIX(B0, fxy_scale_half);
const uint32x4_t C1 = MULT_FIX(B1, fxy_scale_half);
const uint32x4_t C0 = MULT_FIX_FLOOR(B0, fxy_scale_half);
const uint32x4_t C1 = MULT_FIX_FLOOR(B1, fxy_scale_half);
const uint16x4_t D0 = vmovn_u32(C0);
const uint16x4_t D1 = vmovn_u32(C1);
const uint8x8_t E = vmovn_u16(vcombine_u16(D0, D1));
@@ -145,7 +149,7 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
}
for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (uint32_t)MULT_FIX_C(frow[x_out], yscale);
const int v = (int)MULT_FIX_C(irow[x_out] - frac, wrk->fxy_scale);
const int v = (int)MULT_FIX_FLOOR_C(irow[x_out] - frac, fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -170,6 +174,12 @@ static void RescalerExportRowShrink_NEON(WebPRescaler* const wrk) {
}
}

#undef MULT_FIX_FLOOR_C
#undef MULT_FIX_C
#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER

//------------------------------------------------------------------------------

extern void WebPRescalerDspInitNEON(void);
@@ -25,6 +25,7 @@

#define ROUNDER (WEBP_RESCALER_ONE >> 1)
#define MULT_FIX(x, y) (((uint64_t)(x) * (y) + ROUNDER) >> WEBP_RESCALER_RFIX)
#define MULT_FIX_FLOOR(x, y) (((uint64_t)(x) * (y)) >> WEBP_RESCALER_RFIX)

// input: 8 bytes ABCDEFGH -> output: A0E0B0F0C0G0D0H0
static void LoadTwoPixels_SSE2(const uint8_t* const src, __m128i* out) {
@@ -224,6 +225,35 @@ static WEBP_INLINE void ProcessRow_SSE2(const __m128i* const A0,
_mm_storel_epi64((__m128i*)dst, G);
}

static WEBP_INLINE void ProcessRow_Floor_SSE2(const __m128i* const A0,
const __m128i* const A1,
const __m128i* const A2,
const __m128i* const A3,
const __m128i* const mult,
uint8_t* const dst) {
const __m128i mask = _mm_set_epi32(0xffffffffu, 0, 0xffffffffu, 0);
const __m128i B0 = _mm_mul_epu32(*A0, *mult);
const __m128i B1 = _mm_mul_epu32(*A1, *mult);
const __m128i B2 = _mm_mul_epu32(*A2, *mult);
const __m128i B3 = _mm_mul_epu32(*A3, *mult);
const __m128i D0 = _mm_srli_epi64(B0, WEBP_RESCALER_RFIX);
const __m128i D1 = _mm_srli_epi64(B1, WEBP_RESCALER_RFIX);
#if (WEBP_RESCALER_RFIX < 32)
const __m128i D2 =
_mm_and_si128(_mm_slli_epi64(B2, 32 - WEBP_RESCALER_RFIX), mask);
const __m128i D3 =
_mm_and_si128(_mm_slli_epi64(B3, 32 - WEBP_RESCALER_RFIX), mask);
#else
const __m128i D2 = _mm_and_si128(B2, mask);
const __m128i D3 = _mm_and_si128(B3, mask);
#endif
const __m128i E0 = _mm_or_si128(D0, D2);
const __m128i E1 = _mm_or_si128(D1, D3);
const __m128i F = _mm_packs_epi32(E0, E1);
const __m128i G = _mm_packus_epi16(F, F);
_mm_storel_epi64((__m128i*)dst, G);
}

static void RescalerExportRowExpand_SSE2(WebPRescaler* const wrk) {
int x_out;
uint8_t* const dst = wrk->dst;
@@ -322,12 +352,12 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
const __m128i G1 = _mm_or_si128(D1, F3);
_mm_storeu_si128((__m128i*)(irow + x_out + 0), G0);
_mm_storeu_si128((__m128i*)(irow + x_out + 4), G1);
ProcessRow_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
ProcessRow_Floor_SSE2(&E0, &E1, &E2, &E3, &mult_xy, dst + x_out);
}
}
for (; x_out < x_out_max; ++x_out) {
const uint32_t frac = (int)MULT_FIX(frow[x_out], yscale);
const int v = (int)MULT_FIX(irow[x_out] - frac, wrk->fxy_scale);
const int v = (int)MULT_FIX_FLOOR(irow[x_out] - frac, wrk->fxy_scale);
assert(v >= 0 && v <= 255);
dst[x_out] = v;
irow[x_out] = frac; // new fractional start
@@ -352,6 +382,7 @@ static void RescalerExportRowShrink_SSE2(WebPRescaler* const wrk) {
}
}

#undef MULT_FIX_FLOOR
#undef MULT_FIX
#undef ROUNDER

@@ -207,4 +207,4 @@ static WEBP_INLINE int VP8RGBToV(int r, int g, int b, int rounding) {
} // extern "C"
#endif

#endif /* WEBP_DSP_YUV_H_ */
#endif // WEBP_DSP_YUV_H_
@@ -458,7 +458,7 @@ static void MergeJobs(const SegmentJob* const src, SegmentJob* const dst) {
dst->uv_alpha += src->uv_alpha;
}

// initialize the job struct with some TODOs
// initialize the job struct with some tasks to perform
static void InitSegmentJob(VP8Encoder* const enc, SegmentJob* const job,
int start_row, int end_row) {
WebPGetWorkerInterface()->Init(&job->worker);
@@ -67,7 +67,7 @@ static int CostModelBuild(CostModel* const m, int xsize, int cache_bits,

// The following code is similar to VP8LHistogramCreate but converts the
// distance to plane code.
VP8LHistogramInit(histo, cache_bits);
VP8LHistogramInit(histo, cache_bits, /*init_arrays=*/ 1);
while (VP8LRefsCursorOk(&c)) {
VP8LHistogramAddSinglePixOrCopy(histo, c.cur_pos, VP8LDistanceToPlaneCode,
xsize);
@@ -715,6 +715,7 @@ static int CalculateBestCacheSize(const uint32_t* argb, int quality,
for (i = 0; i <= cache_bits_max; ++i) {
histos[i] = VP8LAllocateHistogram(i);
if (histos[i] == NULL) goto Error;
VP8LHistogramInit(histos[i], i, /*init_arrays=*/ 1);
if (i == 0) continue;
cc_init[i] = VP8LColorCacheInit(&hashers[i], i);
if (!cc_init[i]) goto Error;
@@ -79,4 +79,4 @@ extern const uint16_t VP8FixedCostsI4[NUM_BMODES][NUM_BMODES][NUM_BMODES];
} // extern "C"
#endif

#endif /* WEBP_ENC_COST_ENC_H_ */
#endif // WEBP_ENC_COST_ENC_H_

Large diffs are not rendered by default.

@@ -44,6 +44,7 @@ typedef struct {
double literal_cost_; // Cached values of dominant entropy costs:
double red_cost_; // literal, red & blue.
double blue_cost_;
uint8_t is_used_[5]; // 5 for literal, red, blue, alpha, distance
} VP8LHistogram;

// Collection of histograms with fixed capacity, allocated as one
@@ -67,7 +68,9 @@ void VP8LHistogramCreate(VP8LHistogram* const p,
int VP8LGetHistogramSize(int palette_code_bits);

// Set the palette_code_bits and reset the stats.
void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits);
// If init_arrays is true, the arrays are also filled with 0's.
void VP8LHistogramInit(VP8LHistogram* const p, int palette_code_bits,
int init_arrays);

// Collect all the references into a histogram (without reset)
void VP8LHistogramStoreRefs(const VP8LBackwardRefs* const refs,
@@ -83,6 +86,9 @@ void VP8LFreeHistogramSet(VP8LHistogramSet* const histo);
// using 'cache_bits'. Return NULL in case of memory error.
VP8LHistogramSet* VP8LAllocateHistogramSet(int size, int cache_bits);

// Set the histograms in set to 0.
void VP8LHistogramSetClear(VP8LHistogramSet* const set);

// Allocate and initialize histogram object with specified 'cache_bits'.
// Returns NULL in case of memory error.
// Special case of VP8LAllocateHistogramSet, with size equals 1.
@@ -113,7 +119,7 @@ double VP8LBitsEntropy(const uint32_t* const array, int n);

// Estimate how many bits the combined entropy of literals and distance
// approximately maps to.
double VP8LHistogramEstimateBits(const VP8LHistogram* const p);
double VP8LHistogramEstimateBits(VP8LHistogram* const p);

#ifdef __cplusplus
}
@@ -128,7 +128,7 @@ static void ImportLine(const uint8_t* src, int src_stride,
for (; i < total_len; ++i) dst[i] = dst[len - 1];
}

void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32) {
void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32) {
const VP8Encoder* const enc = it->enc_;
const int x = it->x_, y = it->y_;
const WebPPicture* const pic = enc->pic_;
@@ -16,10 +16,6 @@
#include "src/enc/vp8i_enc.h"
#include "src/dsp/yuv.h"

static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) {
return (0xff000000u | (r << 16) | (g << 8) | b);
}

//------------------------------------------------------------------------------
// Helper: clean up fully transparent area to help compressibility.

@@ -195,6 +191,10 @@ void WebPCleanupTransparentAreaLossless(WebPPicture* const pic) {
#define BLEND_10BIT(V0, V1, ALPHA) \
((((V0) * (1020 - (ALPHA)) + (V1) * (ALPHA)) * 0x101 + 1024) >> 18)

static WEBP_INLINE uint32_t MakeARGB32(int r, int g, int b) {
return (0xff000000u | (r << 16) | (g << 8) | b);
}

void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) {
const int red = (background_rgb >> 16) & 0xff;
const int green = (background_rgb >> 8) & 0xff;
@@ -208,39 +208,44 @@ void WebPBlendAlpha(WebPPicture* pic, uint32_t background_rgb) {
const int U0 = VP8RGBToU(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF);
const int V0 = VP8RGBToV(4 * red, 4 * green, 4 * blue, 4 * YUV_HALF);
const int has_alpha = pic->colorspace & WEBP_CSP_ALPHA_BIT;
if (!has_alpha || pic->a == NULL) return; // nothing to do
uint8_t* y_ptr = pic->y;
uint8_t* u_ptr = pic->u;
uint8_t* v_ptr = pic->v;
uint8_t* a_ptr = pic->a;
if (!has_alpha || a_ptr == NULL) return; // nothing to do
for (y = 0; y < pic->height; ++y) {
// Luma blending
uint8_t* const y_ptr = pic->y + y * pic->y_stride;
uint8_t* const a_ptr = pic->a + y * pic->a_stride;
for (x = 0; x < pic->width; ++x) {
const int alpha = a_ptr[x];
const uint8_t alpha = a_ptr[x];
if (alpha < 0xff) {
y_ptr[x] = BLEND(Y0, y_ptr[x], a_ptr[x]);
y_ptr[x] = BLEND(Y0, y_ptr[x], alpha);
}
}
// Chroma blending every even line
if ((y & 1) == 0) {
uint8_t* const u = pic->u + (y >> 1) * pic->uv_stride;
uint8_t* const v = pic->v + (y >> 1) * pic->uv_stride;
uint8_t* const a_ptr2 =
(y + 1 == pic->height) ? a_ptr : a_ptr + pic->a_stride;
for (x = 0; x < uv_width; ++x) {
// Average four alpha values into a single blending weight.
// TODO(skal): might lead to visible contouring. Can we do better?
const int alpha =
const uint32_t alpha =
a_ptr[2 * x + 0] + a_ptr[2 * x + 1] +
a_ptr2[2 * x + 0] + a_ptr2[2 * x + 1];
u[x] = BLEND_10BIT(U0, u[x], alpha);
v[x] = BLEND_10BIT(V0, v[x], alpha);
u_ptr[x] = BLEND_10BIT(U0, u_ptr[x], alpha);
v_ptr[x] = BLEND_10BIT(V0, v_ptr[x], alpha);
}
if (pic->width & 1) { // rightmost pixel
const int alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]);
u[x] = BLEND_10BIT(U0, u[x], alpha);
v[x] = BLEND_10BIT(V0, v[x], alpha);
const uint32_t alpha = 2 * (a_ptr[2 * x + 0] + a_ptr2[2 * x + 0]);
u_ptr[x] = BLEND_10BIT(U0, u_ptr[x], alpha);
v_ptr[x] = BLEND_10BIT(V0, v_ptr[x], alpha);
}
} else {
u_ptr += pic->uv_stride;
v_ptr += pic->uv_stride;
}
memset(a_ptr, 0xff, pic->width);
memset(a_ptr, 0xff, pic->width); // reset alpha value to opaque
a_ptr += pic->a_stride;
y_ptr += pic->y_stride;
}
} else {
uint32_t* argb = pic->argb;
@@ -177,12 +177,15 @@ static uint8_t NearLosslessComponent(uint8_t value, uint8_t predict,
}
}

static WEBP_INLINE uint8_t NearLosslessDiff(uint8_t a, uint8_t b) {
return (uint8_t)((((int)(a) - (int)(b))) & 0xff);
}

// Quantize every component of the difference between the actual pixel value and
// its prediction to a multiple of a quantization (a power of 2, not larger than
// max_quantization which is a power of 2, smaller than max_diff). Take care if
// value and predict have undergone subtract green, which means that red and
// blue are represented as offsets from green.
#define NEAR_LOSSLESS_DIFF(a, b) (uint8_t)((((int)(a) - (int)(b))) & 0xff)
static uint32_t NearLossless(uint32_t value, uint32_t predict,
int max_quantization, int max_diff,
int used_subtract_green) {
@@ -199,7 +202,7 @@ static uint32_t NearLossless(uint32_t value, uint32_t predict,
}
if ((value >> 24) == 0 || (value >> 24) == 0xff) {
// Preserve transparency of fully transparent or fully opaque pixels.
a = NEAR_LOSSLESS_DIFF(value >> 24, predict >> 24);
a = NearLosslessDiff(value >> 24, predict >> 24);
} else {
a = NearLosslessComponent(value >> 24, predict >> 24, 0xff, quantization);
}
@@ -212,16 +215,15 @@ static uint32_t NearLossless(uint32_t value, uint32_t predict,
// The amount by which green has been adjusted during quantization. It is
// subtracted from red and blue for compensation, to avoid accumulating two
// quantization errors in them.
green_diff = NEAR_LOSSLESS_DIFF(new_green, value >> 8);
green_diff = NearLosslessDiff(new_green, value >> 8);
}
r = NearLosslessComponent(NEAR_LOSSLESS_DIFF(value >> 16, green_diff),
r = NearLosslessComponent(NearLosslessDiff(value >> 16, green_diff),
(predict >> 16) & 0xff, 0xff - new_green,
quantization);
b = NearLosslessComponent(NEAR_LOSSLESS_DIFF(value, green_diff),
b = NearLosslessComponent(NearLosslessDiff(value, green_diff),
predict & 0xff, 0xff - new_green, quantization);
return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}
#undef NEAR_LOSSLESS_DIFF
#endif // (WEBP_NEAR_LOSSLESS == 1)

// Stores the difference between the pixel and its prediction in "out".
@@ -15,6 +15,7 @@
#include <math.h>
#include <stdlib.h> // for abs()

#include "src/dsp/quant.h"
#include "src/enc/vp8i_enc.h"
#include "src/enc/cost_enc.h"

@@ -977,19 +978,6 @@ static void SwapOut(VP8EncIterator* const it) {
SwapPtr(&it->yuv_out_, &it->yuv_out2_);
}

static score_t IsFlat(const int16_t* levels, int num_blocks, score_t thresh) {
score_t score = 0;
while (num_blocks-- > 0) { // TODO(skal): refine positional scoring?
int i;
for (i = 1; i < 16; ++i) { // omit DC, we're only interested in AC
score += (levels[i] != 0);
if (score > thresh) return 0;
}
levels += 16;
}
return 1;
}

static void PickBestIntra16(VP8EncIterator* const it, VP8ModeScore* rd) {
const int kNumBlocks = 16;
VP8SegmentInfo* const dqm = &it->enc_->dqm_[it->mb_->segment_];
@@ -32,7 +32,7 @@ extern "C" {
// version numbers
#define ENC_MAJ_VERSION 1
#define ENC_MIN_VERSION 0
#define ENC_REV_VERSION 0
#define ENC_REV_VERSION 2

enum { MAX_LF_LEVELS = 64, // Maximum loop filter level
MAX_VARIABLE_LEVEL = 67, // last (inclusive) level with variable cost
@@ -278,7 +278,7 @@ int VP8IteratorIsDone(const VP8EncIterator* const it);
// Import uncompressed samples from source.
// If tmp_32 is not NULL, import boundary samples too.
// tmp_32 is a 32-bytes scratch buffer that must be aligned in memory.
void VP8IteratorImport(VP8EncIterator* const it, uint8_t* tmp_32);
void VP8IteratorImport(VP8EncIterator* const it, uint8_t* const tmp_32);
// export decimated samples
void VP8IteratorExport(const VP8EncIterator* const it);
// go to next macroblock. Returns false if not finished.
@@ -515,4 +515,4 @@ void WebPCleanupTransparentAreaLossless(WebPPicture* const pic);
} // extern "C"
#endif

#endif /* WEBP_ENC_VP8I_ENC_H_ */
#endif // WEBP_ENC_VP8I_ENC_H_
@@ -462,6 +462,7 @@ static int GetHuffBitLengthsAndCodes(
for (i = 0; i < histogram_image_size; ++i) {
const VP8LHistogram* const histo = histogram_image->histograms[i];
HuffmanTreeCode* const codes = &huffman_codes[5 * i];
assert(histo != NULL);
for (k = 0; k < 5; ++k) {
const int num_symbols =
(k == 0) ? VP8LHistogramNumCodes(histo->palette_code_bits_) :
@@ -809,6 +810,7 @@ static WebPEncodingError EncodeImageNoHuffman(VP8LBitWriter* const bw,
err = VP8_ENC_ERROR_OUT_OF_MEMORY;
goto Error;
}
VP8LHistogramSetClear(histogram_image);

// Build histogram image and symbols from backward references.
VP8LHistogramStoreRefs(refs, histogram_image->histograms[0]);
@@ -1248,14 +1250,20 @@ static WebPEncodingError MakeInputImageCopy(VP8LEncoder* const enc) {
const WebPPicture* const picture = enc->pic_;
const int width = picture->width;
const int height = picture->height;
int y;

err = AllocateTransformBuffer(enc, width, height);
if (err != VP8_ENC_OK) return err;
if (enc->argb_content_ == kEncoderARGB) return VP8_ENC_OK;
for (y = 0; y < height; ++y) {
memcpy(enc->argb_ + y * width,
picture->argb + y * picture->argb_stride,
width * sizeof(*enc->argb_));

{
uint32_t* dst = enc->argb_;
const uint32_t* src = picture->argb;
int y;
for (y = 0; y < height; ++y) {
memcpy(dst, src, width * sizeof(*dst));
dst += width;
src += picture->argb_stride;
}
}
enc->argb_content_ = kEncoderARGB;
assert(enc->current_width_ == width);
@@ -115,4 +115,4 @@ void VP8LColorSpaceTransform(int width, int height, int bits, int quality,
} // extern "C"
#endif

#endif /* WEBP_ENC_VP8LI_ENC_H_ */
#endif // WEBP_ENC_VP8LI_ENC_H_
@@ -40,4 +40,4 @@ int WebPAnimEncoderRefineRect(
} // extern "C"
#endif

#endif /* WEBP_MUX_ANIMI_H_ */
#endif // WEBP_MUX_ANIMI_H_
@@ -69,12 +69,12 @@ void WebPMuxDelete(WebPMux* mux) {
if (idx == (INDEX)) { \
err = ChunkAssignData(&chunk, data, copy_data, tag); \
if (err == WEBP_MUX_OK) { \
err = ChunkSetNth(&chunk, (LIST), nth); \
err = ChunkSetHead(&chunk, (LIST)); \
} \
return err; \
}

static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag, uint32_t nth,
static WebPMuxError MuxSet(WebPMux* const mux, uint32_t tag,
const WebPData* const data, int copy_data) {
WebPChunk chunk;
WebPMuxError err = WEBP_MUX_NOT_FOUND;
@@ -190,7 +190,7 @@ WebPMuxError WebPMuxSetChunk(WebPMux* mux, const char fourcc[4],
if (err != WEBP_MUX_OK && err != WEBP_MUX_NOT_FOUND) return err;

// Add the given chunk.
return MuxSet(mux, tag, 1, chunk_data, copy_data);
return MuxSet(mux, tag, chunk_data, copy_data);
}

// Creates a chunk from given 'data' and sets it as 1st chunk in 'chunk_list'.
@@ -202,7 +202,7 @@ static WebPMuxError AddDataToChunkList(
ChunkInit(&chunk);
err = ChunkAssignData(&chunk, data, copy_data, tag);
if (err != WEBP_MUX_OK) goto Err;
err = ChunkSetNth(&chunk, chunk_list, 1);
err = ChunkSetHead(&chunk, chunk_list);
if (err != WEBP_MUX_OK) goto Err;
return WEBP_MUX_OK;
Err:
@@ -266,14 +266,14 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
int copy_data) {
WebPMuxImage wpi;
WebPMuxError err;
const WebPData* const bitstream = &info->bitstream;

// Sanity checks.
if (mux == NULL || info == NULL) return WEBP_MUX_INVALID_ARGUMENT;

if (info->id != WEBP_CHUNK_ANMF) return WEBP_MUX_INVALID_ARGUMENT;

if (bitstream->bytes == NULL || bitstream->size > MAX_CHUNK_PAYLOAD) {
if (info->bitstream.bytes == NULL ||
info->bitstream.size > MAX_CHUNK_PAYLOAD) {
return WEBP_MUX_INVALID_ARGUMENT;
}

@@ -287,7 +287,7 @@ WebPMuxError WebPMuxPushFrame(WebPMux* mux, const WebPMuxFrameInfo* info,
}

MuxImageInit(&wpi);
err = SetAlphaAndImageChunks(bitstream, copy_data, &wpi);
err = SetAlphaAndImageChunks(&info->bitstream, copy_data, &wpi);
if (err != WEBP_MUX_OK) goto Err;
assert(wpi.img_ != NULL); // As SetAlphaAndImageChunks() was successful.

@@ -342,7 +342,7 @@ WebPMuxError WebPMuxSetAnimationParams(WebPMux* mux,
// Set the animation parameters.
PutLE32(data, params->bgcolor);
PutLE16(data + 4, params->loop_count);
return MuxSet(mux, kChunks[IDX_ANIM].tag, 1, &anim, 1);
return MuxSet(mux, kChunks[IDX_ANIM].tag, &anim, 1);
}

WebPMuxError WebPMuxSetCanvasSize(WebPMux* mux,
@@ -540,7 +540,7 @@ static WebPMuxError CreateVP8XChunk(WebPMux* const mux) {
PutLE24(data + 4, width - 1); // canvas width.
PutLE24(data + 7, height - 1); // canvas height.

return MuxSet(mux, kChunks[IDX_VP8X].tag, 1, &vp8x, 1);
return MuxSet(mux, kChunks[IDX_VP8X].tag, &vp8x, 1);
}

// Cleans up 'mux' by removing any unnecessary chunks.
@@ -14,6 +14,7 @@
#ifndef WEBP_MUX_MUXI_H_
#define WEBP_MUX_MUXI_H_

#include <assert.h>
#include <stdlib.h>
#include "src/dec/vp8i_dec.h"
#include "src/dec/vp8li_dec.h"
@@ -28,7 +29,7 @@ extern "C" {

#define MUX_MAJ_VERSION 1
#define MUX_MIN_VERSION 0
#define MUX_REV_VERSION 0
#define MUX_REV_VERSION 2

// Chunk object.
typedef struct WebPChunk WebPChunk;
@@ -126,11 +127,14 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag);
WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
int copy_data, uint32_t tag);

// Sets 'chunk' at nth position in the 'chunk_list'.
// nth = 0 has the special meaning "last of the list".
// Sets 'chunk' as the only element in 'chunk_list' if it is empty.
// On success ownership is transferred from 'chunk' to the 'chunk_list'.
WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
uint32_t nth);
WebPMuxError ChunkSetHead(WebPChunk* const chunk, WebPChunk** const chunk_list);
// Sets 'chunk' at last position in the 'chunk_list'.
// On success ownership is transferred from 'chunk' to the 'chunk_list'.
// *chunk_list also points towards the last valid element of the initial
// *chunk_list.
WebPMuxError ChunkAppend(WebPChunk* const chunk, WebPChunk*** const chunk_list);

// Releases chunk and returns chunk->next_.
WebPChunk* ChunkRelease(WebPChunk* const chunk);
@@ -143,13 +147,13 @@ void ChunkListDelete(WebPChunk** const chunk_list);

// Returns size of the chunk including chunk header and padding byte (if any).
static WEBP_INLINE size_t SizeWithPadding(size_t chunk_size) {
assert(chunk_size <= MAX_CHUNK_PAYLOAD);
return CHUNK_HEADER_SIZE + ((chunk_size + 1) & ~1U);
}

// Size of a chunk including header and padding.
static WEBP_INLINE size_t ChunkDiskSize(const WebPChunk* chunk) {
const size_t data_size = chunk->data_.size;
assert(data_size < MAX_CHUNK_PAYLOAD);
return SizeWithPadding(data_size);
}

@@ -227,4 +231,4 @@ WebPMuxError MuxValidate(const WebPMux* const mux);
} // extern "C"
#endif

#endif /* WEBP_MUX_MUXI_H_ */
#endif // WEBP_MUX_MUXI_H_
@@ -111,27 +111,6 @@ WebPChunk* ChunkSearchList(WebPChunk* first, uint32_t nth, uint32_t tag) {
return ((nth > 0) && (iter > 0)) ? NULL : first;
}

// Outputs a pointer to 'prev_chunk->next_',
// where 'prev_chunk' is the pointer to the chunk at position (nth - 1).
// Returns true if nth chunk was found.
static int ChunkSearchListToSet(WebPChunk** chunk_list, uint32_t nth,
WebPChunk*** const location) {
uint32_t count = 0;
assert(chunk_list != NULL);
*location = chunk_list;

while (*chunk_list != NULL) {
WebPChunk* const cur_chunk = *chunk_list;
++count;
if (count == nth) return 1; // Found.
chunk_list = &cur_chunk->next_;
*location = chunk_list;
}

// *chunk_list is ok to be NULL if adding at last location.
return (nth == 0 || (count == nth - 1)) ? 1 : 0;
}

//------------------------------------------------------------------------------
// Chunk writer methods.

@@ -156,23 +135,39 @@ WebPMuxError ChunkAssignData(WebPChunk* chunk, const WebPData* const data,
return WEBP_MUX_OK;
}

WebPMuxError ChunkSetNth(WebPChunk* chunk, WebPChunk** chunk_list,
uint32_t nth) {
WebPMuxError ChunkSetHead(WebPChunk* const chunk,
WebPChunk** const chunk_list) {
WebPChunk* new_chunk;

if (!ChunkSearchListToSet(chunk_list, nth, &chunk_list)) {
assert(chunk_list != NULL);
if (*chunk_list != NULL) {
return WEBP_MUX_NOT_FOUND;
}

new_chunk = (WebPChunk*)WebPSafeMalloc(1ULL, sizeof(*new_chunk));
if (new_chunk == NULL) return WEBP_MUX_MEMORY_ERROR;
*new_chunk = *chunk;
chunk->owner_ = 0;
new_chunk->next_ = *chunk_list;
new_chunk->next_ = NULL;
*chunk_list = new_chunk;
return WEBP_MUX_OK;
}

WebPMuxError ChunkAppend(WebPChunk* const chunk,
WebPChunk*** const chunk_list) {
assert(chunk_list != NULL && *chunk_list != NULL);

if (**chunk_list == NULL) {
ChunkSetHead(chunk, *chunk_list);
} else {
WebPChunk* last_chunk = **chunk_list;
while (last_chunk->next_ != NULL) last_chunk = last_chunk->next_;
ChunkSetHead(chunk, &last_chunk->next_);
*chunk_list = &last_chunk->next_;
}
return WEBP_MUX_OK;
}

//------------------------------------------------------------------------------
// Chunk deletion method(s).

@@ -232,9 +227,11 @@ void MuxImageInit(WebPMuxImage* const wpi) {
WebPMuxImage* MuxImageRelease(WebPMuxImage* const wpi) {
WebPMuxImage* next;
if (wpi == NULL) return NULL;
ChunkDelete(wpi->header_);
ChunkDelete(wpi->alpha_);
ChunkDelete(wpi->img_);
// There should be at most one chunk of header_, alpha_, img_ but we call
// ChunkListDelete to be safe
ChunkListDelete(&wpi->header_);
ChunkListDelete(&wpi->alpha_);
ChunkListDelete(&wpi->img_);
ChunkListDelete(&wpi->unknown_);

next = wpi->next_;
@@ -59,6 +59,7 @@ static WebPMuxError ChunkVerifyAndAssign(WebPChunk* chunk,
// Sanity checks.
if (data_size < CHUNK_HEADER_SIZE) return WEBP_MUX_NOT_ENOUGH_DATA;
chunk_size = GetLE32(data + TAG_SIZE);
if (chunk_size > MAX_CHUNK_PAYLOAD) return WEBP_MUX_BAD_DATA;

{
const size_t chunk_disk_size = SizeWithPadding(chunk_size);
@@ -102,6 +103,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
const uint8_t* const last = bytes + size;
WebPChunk subchunk;
size_t subchunk_size;
WebPChunk** unknown_chunk_list = &wpi->unknown_;
ChunkInit(&subchunk);

assert(chunk->tag_ == kChunks[IDX_ANMF].tag);
@@ -116,7 +118,7 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
if (size < hdr_size) goto Fail;
ChunkAssignData(&subchunk, &temp, copy_data, chunk->tag_);
}
ChunkSetNth(&subchunk, &wpi->header_, 1);
ChunkSetHead(&subchunk, &wpi->header_);
wpi->is_partial_ = 1; // Waiting for ALPH and/or VP8/VP8L chunks.

// Rest of the chunks.
@@ -133,18 +135,23 @@ static int MuxImageParse(const WebPChunk* const chunk, int copy_data,
switch (ChunkGetIdFromTag(subchunk.tag_)) {
case WEBP_CHUNK_ALPHA:
if (wpi->alpha_ != NULL) goto Fail; // Consecutive ALPH chunks.
if (ChunkSetNth(&subchunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Fail;
if (ChunkSetHead(&subchunk, &wpi->alpha_) != WEBP_MUX_OK) goto Fail;
wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
break;
case WEBP_CHUNK_IMAGE:
if (ChunkSetNth(&subchunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Fail;
if (wpi->img_ != NULL) goto Fail; // Only 1 image chunk allowed.
if (ChunkSetHead(&subchunk, &wpi->img_) != WEBP_MUX_OK) goto Fail;
if (!MuxImageFinalize(wpi)) goto Fail;
wpi->is_partial_ = 0; // wpi is completely filled.
break;
case WEBP_CHUNK_UNKNOWN:
if (wpi->is_partial_) goto Fail; // Encountered an unknown chunk
// before some image chunks.
if (ChunkSetNth(&subchunk, &wpi->unknown_, 0) != WEBP_MUX_OK) goto Fail;
if (wpi->is_partial_) {
goto Fail; // Encountered an unknown chunk
// before some image chunks.
}
if (ChunkAppend(&subchunk, &unknown_chunk_list) != WEBP_MUX_OK) {
goto Fail;
}
break;
default:
goto Fail;
@@ -175,6 +182,9 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
const uint8_t* data;
size_t size;
WebPChunk chunk;
// Stores the end of the chunk lists so that it is faster to append data to
// their ends.
WebPChunk** chunk_list_ends[WEBP_CHUNK_NIL + 1] = { NULL };
ChunkInit(&chunk);

// Sanity checks.
@@ -187,7 +197,7 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
size = bitstream->size;

if (data == NULL) return NULL;
if (size < RIFF_HEADER_SIZE) return NULL;
if (size < RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE) return NULL;
if (GetLE32(data + 0) != MKFOURCC('R', 'I', 'F', 'F') ||
GetLE32(data + CHUNK_HEADER_SIZE) != MKFOURCC('W', 'E', 'B', 'P')) {
return NULL;
@@ -196,22 +206,24 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
mux = WebPMuxNew();
if (mux == NULL) return NULL;

if (size < RIFF_HEADER_SIZE + TAG_SIZE) goto Err;

tag = GetLE32(data + RIFF_HEADER_SIZE);
if (tag != kChunks[IDX_VP8].tag &&
tag != kChunks[IDX_VP8L].tag &&
tag != kChunks[IDX_VP8X].tag) {
goto Err; // First chunk should be VP8, VP8L or VP8X.
}

riff_size = SizeWithPadding(GetLE32(data + TAG_SIZE));
if (riff_size > MAX_CHUNK_PAYLOAD || riff_size > size) {
goto Err;
} else {
if (riff_size < size) { // Redundant data after last chunk.
size = riff_size; // To make sure we don't read any data beyond mux_size.
}
riff_size = GetLE32(data + TAG_SIZE);
if (riff_size > MAX_CHUNK_PAYLOAD) goto Err;

// Note this padding is historical and differs from demux.c which does not
// pad the file size.
riff_size = SizeWithPadding(riff_size);
if (riff_size < CHUNK_HEADER_SIZE) goto Err;
if (riff_size > size) goto Err;
// There's no point in reading past the end of the RIFF chunk.
if (size > riff_size + CHUNK_HEADER_SIZE) {
size = riff_size + CHUNK_HEADER_SIZE;
}

end = data + size;
@@ -226,7 +238,6 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
while (data != end) {
size_t data_size;
WebPChunkId id;
WebPChunk** chunk_list;
if (ChunkVerifyAndAssign(&chunk, data, size, riff_size,
copy_data) != WEBP_MUX_OK) {
goto Err;
@@ -236,11 +247,11 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
switch (id) {
case WEBP_CHUNK_ALPHA:
if (wpi->alpha_ != NULL) goto Err; // Consecutive ALPH chunks.
if (ChunkSetNth(&chunk, &wpi->alpha_, 1) != WEBP_MUX_OK) goto Err;
if (ChunkSetHead(&chunk, &wpi->alpha_) != WEBP_MUX_OK) goto Err;
wpi->is_partial_ = 1; // Waiting for a VP8 chunk.
break;
case WEBP_CHUNK_IMAGE:
if (ChunkSetNth(&chunk, &wpi->img_, 1) != WEBP_MUX_OK) goto Err;
if (ChunkSetHead(&chunk, &wpi->img_) != WEBP_MUX_OK) goto Err;
if (!MuxImageFinalize(wpi)) goto Err;
wpi->is_partial_ = 0; // wpi is completely filled.
PushImage:
@@ -257,9 +268,13 @@ WebPMux* WebPMuxCreateInternal(const WebPData* bitstream, int copy_data,
default: // A non-image chunk.
if (wpi->is_partial_) goto Err; // Encountered a non-image chunk before
// getting all chunks of an image.
chunk_list = MuxGetChunkListFromId(mux, id); // List to add this chunk.
if (ChunkSetNth(&chunk, chunk_list, 0) != WEBP_MUX_OK) goto Err;
if (chunk_list_ends[id] == NULL) {
chunk_list_ends[id] =
MuxGetChunkListFromId(mux, id); // List to add this chunk.
}
if (ChunkAppend(&chunk, &chunk_list_ends[id]) != WEBP_MUX_OK) goto Err;
if (id == WEBP_CHUNK_VP8X) { // grab global specs
if (data_size < CHUNK_HEADER_SIZE + VP8X_CHUNK_SIZE) goto Err;
mux->canvas_width_ = GetLE24(data + 12) + 1;
mux->canvas_height_ = GetLE24(data + 15) + 1;
}
@@ -385,6 +400,10 @@ static WebPMuxError SynthesizeBitstream(const WebPMuxImage* const wpi,
uint8_t* const data = (uint8_t*)WebPSafeMalloc(1ULL, size);
if (data == NULL) return WEBP_MUX_MEMORY_ERROR;

// There should be at most one alpha_ chunk and exactly one img_ chunk.
assert(wpi->alpha_ == NULL || wpi->alpha_->next_ == NULL);
assert(wpi->img_ != NULL && wpi->img_->next_ == NULL);

// Main RIFF header.
dst = MuxEmitRiffHeader(data, size);

@@ -187,4 +187,4 @@ static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) {
} // extern "C"
#endif

#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_
#endif // WEBP_UTILS_BIT_READER_INL_UTILS_H_
@@ -172,4 +172,4 @@ static WEBP_INLINE void VP8LFillBitWindow(VP8LBitReader* const br) {
} // extern "C"
#endif

#endif /* WEBP_UTILS_BIT_READER_UTILS_H_ */
#endif // WEBP_UTILS_BIT_READER_UTILS_H_
@@ -248,6 +248,7 @@ int VP8LBitWriterClone(const VP8LBitWriter* const src,
dst->bits_ = src->bits_;
dst->used_ = src->used_;
dst->error_ = src->error_;
dst->cur_ = dst->buf_ + current_size;
return 1;
}

@@ -151,4 +151,4 @@ static WEBP_INLINE void VP8LPutBits(VP8LBitWriter* const bw,
} // extern "C"
#endif

#endif /* WEBP_UTILS_BIT_WRITER_UTILS_H_ */
#endif // WEBP_UTILS_BIT_WRITER_UTILS_H_
@@ -29,4 +29,4 @@ WEBP_FILTER_TYPE WebPEstimateBestFilter(const uint8_t* data,
} // extern "C"
#endif

#endif /* WEBP_UTILS_FILTERS_UTILS_H_ */
#endif // WEBP_UTILS_FILTERS_UTILS_H_
@@ -261,9 +261,15 @@ static void CleanupParams(SmoothParams* const p) {

int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
int strength) {
const int radius = 4 * strength / 100;
int radius = 4 * strength / 100;

if (strength < 0 || strength > 100) return 0;
if (data == NULL || width <= 0 || height <= 0) return 0; // bad params

// limit the filter size to not exceed the image dimensions
if (2 * radius + 1 > width) radius = (width - 1) >> 1;
if (2 * radius + 1 > height) radius = (height - 1) >> 1;

if (radius > 0) {
SmoothParams p;
memset(&p, 0, sizeof(p));
@@ -32,4 +32,4 @@ int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride,
} // extern "C"
#endif

#endif /* WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_ */
#endif // WEBP_UTILS_QUANT_LEVELS_DEC_UTILS_H_
@@ -33,4 +33,4 @@ int QuantizeLevels(uint8_t* const data, int width, int height, int num_levels,
} // extern "C"
#endif

#endif /* WEBP_UTILS_QUANT_LEVELS_UTILS_H_ */
#endif // WEBP_UTILS_QUANT_LEVELS_UTILS_H_
@@ -60,4 +60,4 @@ static WEBP_INLINE int VP8RandomBits(VP8Random* const rg, int num_bits) {
} // extern "C"
#endif

#endif /* WEBP_UTILS_RANDOM_UTILS_H_ */
#endif // WEBP_UTILS_RANDOM_UTILS_H_
@@ -98,4 +98,4 @@ int WebPRescalerHasPendingOutput(const WebPRescaler* const rescaler) {
} // extern "C"
#endif

#endif /* WEBP_UTILS_RESCALER_UTILS_H_ */
#endif // WEBP_UTILS_RESCALER_UTILS_H_
@@ -87,4 +87,4 @@ WEBP_EXTERN const WebPWorkerInterface* WebPGetWorkerInterface(void);
} // extern "C"
#endif

#endif /* WEBP_UTILS_THREAD_UTILS_H_ */
#endif // WEBP_UTILS_THREAD_UTILS_H_
@@ -107,19 +107,6 @@ static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
PutLE16(data + 2, (int)(val >> 16));
}

// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either
// based on table or not. Can be used as fallback if clz() is not available.
#define WEBP_NEED_LOG_TABLE_8BIT
extern const uint8_t WebPLogTable8bit[256];
static WEBP_INLINE int WebPLog2FloorC(uint32_t n) {
int log_value = 0;
while (n >= 256) {
log_value += 8;
n >>= 8;
}
return log_value + WebPLogTable8bit[n];
}

// Returns (int)floor(log2(n)). n must be > 0.
// use GNU builtins where available.
#if defined(__GNUC__) && \
@@ -138,6 +125,19 @@ static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
return first_set_bit;
}
#else // default: use the C-version.
// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either
// based on table or not. Can be used as fallback if clz() is not available.
#define WEBP_NEED_LOG_TABLE_8BIT
extern const uint8_t WebPLogTable8bit[256];
static WEBP_INLINE int WebPLog2FloorC(uint32_t n) {
int log_value = 0;
while (n >= 256) {
log_value += 8;
n >>= 8;
}
return log_value + WebPLogTable8bit[n];
}

static WEBP_INLINE int BitsLog2Floor(uint32_t n) { return WebPLog2FloorC(n); }
#endif

@@ -175,4 +175,4 @@ WEBP_EXTERN int WebPGetColorPalette(const struct WebPPicture* const pic,
} // extern "C"
#endif

#endif /* WEBP_UTILS_UTILS_H_ */
#endif // WEBP_UTILS_UTILS_H_
@@ -42,6 +42,12 @@ WEBP_EXTERN int WebPGetDecoderVersion(void);
// This function will also validate the header, returning true on success,
// false otherwise. '*width' and '*height' are only valid on successful return.
// Pointers 'width' and 'height' can be passed NULL if deemed irrelevant.
// Note: The following chunk sequences (before the raw VP8/VP8L data) are
// considered valid by this function:
// RIFF + VP8(L)
// RIFF + VP8X + (optional chunks) + VP8(L)
// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose.
WEBP_EXTERN int WebPGetInfo(const uint8_t* data, size_t data_size,
int* width, int* height);

@@ -425,6 +431,12 @@ WEBP_EXTERN VP8StatusCode WebPGetFeaturesInternal(
// Returns VP8_STATUS_OK when the features are successfully retrieved. Returns
// VP8_STATUS_NOT_ENOUGH_DATA when more data is needed to retrieve the
// features from headers. Returns error in other cases.
// Note: The following chunk sequences (before the raw VP8/VP8L data) are
// considered valid by this function:
// RIFF + VP8(L)
// RIFF + VP8X + (optional chunks) + VP8(L)
// ALPH + VP8 <-- Not a valid WebP format: only allowed for internal purpose.
// VP8(L) <-- Not a valid WebP format: only allowed for internal purpose.
static WEBP_INLINE VP8StatusCode WebPGetFeatures(
const uint8_t* data, size_t data_size,
WebPBitstreamFeatures* features) {
@@ -491,4 +503,4 @@ WEBP_EXTERN VP8StatusCode WebPDecode(const uint8_t* data, size_t data_size,
} // extern "C"
#endif

#endif /* WEBP_WEBP_DECODE_H_ */
#endif // WEBP_WEBP_DECODE_H_
@@ -360,4 +360,4 @@ WEBP_EXTERN void WebPAnimDecoderDelete(WebPAnimDecoder* dec);
} // extern "C"
#endif

#endif /* WEBP_WEBP_DEMUX_H_ */
#endif // WEBP_WEBP_DEMUX_H_
@@ -542,4 +542,4 @@ WEBP_EXTERN int WebPEncode(const WebPConfig* config, WebPPicture* picture);
} // extern "C"
#endif

#endif /* WEBP_WEBP_ENCODE_H_ */
#endif // WEBP_WEBP_ENCODE_H_
@@ -84,4 +84,4 @@ typedef enum {
// overflow a uint32_t.
#define MAX_CHUNK_PAYLOAD (~0U - CHUNK_HEADER_SIZE - 1)

#endif /* WEBP_WEBP_FORMAT_CONSTANTS_H_ */
#endif // WEBP_WEBP_FORMAT_CONSTANTS_H_
@@ -527,4 +527,4 @@ WEBP_EXTERN void WebPAnimEncoderDelete(WebPAnimEncoder* enc);
} // extern "C"
#endif

#endif /* WEBP_WEBP_MUX_H_ */
#endif // WEBP_WEBP_MUX_H_
@@ -95,4 +95,4 @@ static WEBP_INLINE int WebPDataCopy(const WebPData* src, WebPData* dst) {
} // extern "C"
#endif

#endif /* WEBP_WEBP_MUX_TYPES_H_ */
#endif // WEBP_WEBP_MUX_TYPES_H_
@@ -49,4 +49,4 @@ typedef long long int int64_t;
// Macro to check ABI compatibility (same major revision number)
#define WEBP_ABI_IS_INCOMPATIBLE(a, b) (((a) >> 8) != ((b) >> 8))

#endif /* WEBP_WEBP_TYPES_H_ */
#endif // WEBP_WEBP_TYPES_H_
@@ -8,6 +8,10 @@ Paul Schneider <paultschneider@mac.com>
Bill Anderson <wja@ilm.com>
Wojciech Jarosz <wjarosz@ucsd.edu>
Andrew Kunz <akunz@ilm.com>
Piotr Stanczyk <pstanczyk@ilm.com>
Peter Hillman <peterh@weta.co.nz>
Nick Porcino <nick.porcino@gmail.com>
Kimball Thurston

Contributors:
-------------
@@ -20,6 +24,10 @@ Rodrigo Damazio <rdamazio@lsi.usp.br>
Greg Ward <gward@lmi.net>
Joseph Goldstone <joseph@lp.com>
Loren Carpenter, Pixar Animation Studios
Nicholas Yue <yue.nicholas@gmail.com>
Yunfeng Bai (ILM)
Pascal Jette (Autodesk)
Karl Rasche, DreamWorks Animation <Karl.Rasche@dreamworks.com>

Win32 build system:
-------------------
@@ -5,15 +5,75 @@

project(openexr CXX)

if(UNIX)
if(APPLE)
set(HAVE_POSIX_SEMAPHORES 0) # Unnamed semaphores are not supported: https://github.com/opencv/opencv/issues/9361

if(NOT HAVE_CXX11)
ocv_check_compiler_flag(CXX "-std=c++11" HAVE_STD_CXX11 "${OpenCV_SOURCE_DIR}/cmake/checks/cxx11.cpp")
if(HAVE_STD_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
else()
include(CheckIncludeFile)
check_include_file(semaphore.h HAVE_POSIX_SEMAPHORES)
if(BUILD_OPENEXR)
message(WARNING "OpenCV: builtin OpenEXR requires C++11 support. OpenEXR is disabled.")
endif()
return()
endif()
endif()



set(ILMBASE_VERSION_MAJOR "2")
set(ILMBASE_VERSION_MINOR "3")
set(ILMBASE_VERSION_PATCH "0")

set(ILMBASE_VERSION "${ILMBASE_VERSION_MAJOR}.${ILMBASE_VERSION_MINOR}.${ILMBASE_VERSION_PATCH}")
set(ILMBASE_VERSION_API ${ILMBASE_VERSION_MAJOR}_${ILMBASE_VERSION_MINOR})

set(OPENEXR_VERSION_MAJOR "2")
set(OPENEXR_VERSION_MINOR "3")
set(OPENEXR_VERSION_PATCH "0")

set(OPENEXR_VERSION "${OPENEXR_VERSION_MAJOR}.${OPENEXR_VERSION_MINOR}.${OPENEXR_VERSION_PATCH}")
set(OPENEXR_VERSION_API ${OPENEXR_VERSION_MAJOR}_${OPENEXR_VERSION_MINOR})

set(OPENEXR_VERSION "${OPENEXR_VERSION}" PARENT_SCOPE)

if(WIN32)
set(HAVE_COMPLETE_IOMANIP 1)
set(OPENEXR_IMF_HAVE_COMPLETE_IOMANIP 1)
set(PLATFORM_WINDOWS 1)
elseif(APPLE)
set(HAVE_POSIX_SEMAPHORES 0) # Unnamed semaphores are not supported: https://github.com/opencv/opencv/issues/9361
if(DARWIN)
set(OPENEXR_IMF_HAVE_DARWIN 1)
endif()
elseif(UNIX)
include(CheckIncludeFile)
check_include_file(semaphore.h HAVE_POSIX_SEMAPHORES)
endif()

set(ILMBASE_VERSION_API "opencv")
set(ILMBASE_INTERNAL_NAMESPACE_CUSTOM 1)
set(IMATH_INTERNAL_NAMESPACE "Imath_${ILMBASE_VERSION_API}")
set(IEX_INTERNAL_NAMESPACE "Iex_${ILMBASE_VERSION_API}")
set(ILMTHREAD_INTERNAL_NAMESPACE "IlmThread_${ILMBASE_VERSION_API}")

set(ILMBASE_NAMESPACE_CUSTOM 0)
set(IMATH_NAMESPACE "Imath")
set(IEX_NAMESPACE "Iex")
set(ILMTHREAD_NAMESPACE "IlmThread")
set(ILMBASE_VERSION_STRING "\"${ILMBASE_VERSION}\"" )
set(ILMBASE_PACKAGE_STRING "\"IlmBase ${ILMBASE_VERSION}\"" )


set(OPENEXR_VERSION_API "opencv")
set(OPENEXR_IMF_INTERNAL_NAMESPACE_CUSTOM 1)
set(OPENEXR_IMF_INTERNAL_NAMESPACE "Imf_${ILMBASE_VERSION_API}")
set(OPENEXR_IMF_NAMESPACE_CUSTOM 0)
set(OPENEXR_IMF_NAMESPACE "Imf")

set(OPENEXR_VERSION_STRING "\"${OPENEXR_VERSION}\"" )
set(OPENEXR_PACKAGE_STRING "\"OpenEXR ${OPENEXR_VERSION}\"" )


configure_file("${CMAKE_CURRENT_SOURCE_DIR}/IlmBaseConfig.h.cmakein"
"${CMAKE_CURRENT_BINARY_DIR}/IlmBaseConfig.h" @ONLY)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/OpenEXRConfig.h.cmakein"
@@ -23,16 +83,15 @@ set(OPENEXR_INCLUDE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/Half"
"${CMAKE_CURRENT_SOURCE_DIR}/Iex"
"${CMAKE_CURRENT_SOURCE_DIR}/IlmThread"
"${CMAKE_CURRENT_SOURCE_DIR}/Imath"
"${CMAKE_CURRENT_SOURCE_DIR}/IlmImf")
"${CMAKE_CURRENT_SOURCE_DIR}/IlmImf"
"${CMAKE_CURRENT_BINARY_DIR}")

ocv_include_directories("${CMAKE_CURRENT_BINARY_DIR}" ${ZLIB_INCLUDE_DIRS} ${OPENEXR_INCLUDE_PATHS})

file(GLOB lib_srcs Half/half.cpp Iex/*.cpp IlmThread/*.cpp Imath/*.cpp IlmImf/*.cpp)
file(GLOB lib_hdrs Half/*.h Iex/Iex*.h IlmThread/IlmThread*.h Imath/Imath*.h IlmImf/*.h)
list(APPEND lib_hdrs "${CMAKE_CURRENT_BINARY_DIR}/IlmBaseConfig.h" "${CMAKE_CURRENT_BINARY_DIR}/OpenEXRConfig.h")

ocv_list_filterout(lib_srcs IlmImf/b44ExpLogTable.cpp)

if(WIN32)
ocv_list_filterout(lib_srcs Posix.*cpp)
else()
@@ -46,6 +105,10 @@ ocv_warnings_disable(CMAKE_CXX_FLAGS -Wshadow -Wunused -Wsign-compare -Wundef -W
-Wdeprecated-declarations -Wmisleading-indentation -Wdeprecated
-Wsuggest-override -Winconsistent-missing-override
-Wimplicit-fallthrough
-Wtautological-compare # clang
-Wmissing-prototypes # gcc/clang
-Wreorder
-Wunused-result
)
if(CV_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0)
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wclass-memaccess)
@@ -82,7 +145,6 @@ if(NOT BUILD_SHARED_LIBS)
ocv_install_target(IlmImf EXPORT OpenCVModules ARCHIVE DESTINATION ${OPENCV_3P_LIB_INSTALL_PATH} COMPONENT dev)
endif()

ocv_install_3rdparty_licenses(openexr LICENSE AUTHORS.ilmbase AUTHORS.openexr fix_msvc2013_errors.patch)
ocv_install_3rdparty_licenses(openexr LICENSE AUTHORS.ilmbase AUTHORS.openexr)

set(OPENEXR_INCLUDE_PATHS ${OPENEXR_INCLUDE_PATHS} PARENT_SCOPE)
set(OPENEXR_VERSION "1.7.1" PARENT_SCOPE)
@@ -1,3 +1,30 @@
Version 2.x.x
* Bumped version to track OpenEXR
(Piotr Stanczyk)

Version 2.0.1
* Bumped version to track OpenEXR
(Piotr Stanczyk)

Version 2.0.0
* Bumped version to track OpenEXR
(Piotr Stanczyk)
* Numerous minor fixes, missing includes etc

Version 1.1.0.beta.1
* Added new module PyIlmBase : python bindings for IlmBase
(Nick Rasmussen)
* Added git specific files
(Piotr Stanczyk)
* Minor fixes for newer gcc versions and OS X.
(misc)
* Preparation for OpenEXR v2 release { remove message for final release }
(Piotr Stanczyk)
* Updated the so verison to 10
(Piotr Stanczyk)
* Initial use of the CMake build system
(Nicholas Yue)

Version 1.0.3
* Added support for enabling/disabling large stack optimisations, used in
halfFunction.h.
@@ -1,5 +1,43 @@
Version 2.0.1
* Temporarily turning off optimisation code path
(Piotr Stanczyk)
* Added additional tests for future optimisation refactoring
(Piotr Stanczyk / Peter Hillman)
* Fixes for StringVectors
(Peter Hillman)
* Additional checks for type mismatches
(Peter Hillman)
* Fix for Composite Deep Scanline
(Brendan Bolles)

Version 2.0.0
* Updated Documentation
(Peter Hillman)
* Updated Namespacing mechanism
(Piotr Stanczyk)
* Fixes for succd & predd
(Peter Hillman)
* Fixes for FPE control registers
(Piotr Stanczyk)
* Additional checks and tests on DeepImages, scanlines and tiles
(Peter Hillman)
* Folded in Autodesk read optimisations for RGB(A) files
(Pascal Jette, Peter Hillman)
* Updated the bootstrap scripts to use libtoolize if glibtoolize isn't available on darwin.
(Nick Rasmussen)
* Numerous minor fixes, missing includes etc

Version 2.0.0.beta.1:
* Please read the separate file for v2 additions and changes.
* Added git specific files
(Piotr Stanczyk)
* Updated the so verison to 20
(Piotr Stanczyk)
* Initial use of the CMake build system
(Nicholas Yue)

Version 1.7.1:
* Updated the .so verison to 7.
* Updated the .so verison to 7.
(Piotr Stanczyk)

Version 1.7.0:
@@ -4,68 +4,68 @@
//

{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 1024, 2048, 3072, 4096, 5120, 6144, 7168,
8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360,
16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552,
24576, 25600, 26624, 27648, 28672, 29696, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 33792, 34816, 35840, 36864, 37888, 38912, 39936,
40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128,
49152, 50176, 51200, 52224, 53248, 54272, 55296, 56320,
57344, 58368, 59392, 60416, 61440, 62464, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 1024, 2048, 3072, 4096, 5120, 6144, 7168,
8192, 9216, 10240, 11264, 12288, 13312, 14336, 15360,
16384, 17408, 18432, 19456, 20480, 21504, 22528, 23552,
24576, 25600, 26624, 27648, 28672, 29696, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 33792, 34816, 35840, 36864, 37888, 38912, 39936,
40960, 41984, 43008, 44032, 45056, 46080, 47104, 48128,
49152, 50176, 51200, 52224, 53248, 54272, 55296, 56320,
57344, 58368, 59392, 60416, 61440, 62464, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};

Large diffs are not rendered by default.

@@ -2,9 +2,9 @@
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
//
// All rights reserved.
//
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -16,8 +16,8 @@
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -85,21 +85,10 @@
#ifndef _HALF_H_
#define _HALF_H_

#include "halfExport.h" // for definition of HALF_EXPORT
#include <iostream>

#if defined(OPENEXR_DLL)
#if defined(HALF_EXPORTS)
#define HALF_EXPORT __declspec(dllexport)
#else
#define HALF_EXPORT __declspec(dllimport)
#endif
#define HALF_EXPORT_CONST
#else
#define HALF_EXPORT
#define HALF_EXPORT_CONST const
#endif

class HALF_EXPORT half
class half
{
public:

@@ -208,45 +197,47 @@ class HALF_EXPORT half
// Access to the internal representation
//--------------------------------------

unsigned short bits () const;
void setBits (unsigned short bits);
HALF_EXPORT unsigned short bits () const;
HALF_EXPORT void setBits (unsigned short bits);


public:

union uif
{
unsigned int i;
float f;
unsigned int i;
float f;
};

private:

static short convert (int i);
static float overflow ();
HALF_EXPORT static short convert (int i);
HALF_EXPORT static float overflow ();

unsigned short _h;
unsigned short _h;

static HALF_EXPORT_CONST uif _toFloat[1 << 16];
static HALF_EXPORT_CONST unsigned short _eLut[1 << 9];
HALF_EXPORT static const uif _toFloat[1 << 16];
HALF_EXPORT static const unsigned short _eLut[1 << 9];
};



//-----------
// Stream I/O
//-----------

HALF_EXPORT std::ostream & operator << (std::ostream &os, half h);
HALF_EXPORT std::istream & operator >> (std::istream &is, half &h);
HALF_EXPORT std::ostream & operator << (std::ostream &os, half h);
HALF_EXPORT std::istream & operator >> (std::istream &is, half &h);


//----------
// Debugging
//----------

HALF_EXPORT void printBits (std::ostream &os, half h);
HALF_EXPORT void printBits (std::ostream &os, float f);
HALF_EXPORT void printBits (char c[19], half h);
HALF_EXPORT void printBits (char c[35], float f);
HALF_EXPORT void printBits (std::ostream &os, half h);
HALF_EXPORT void printBits (std::ostream &os, float f);
HALF_EXPORT void printBits (char c[19], half h);
HALF_EXPORT void printBits (char c[35], float f);


//-------------------------------------------------------------------------
@@ -266,7 +257,7 @@ HALF_EXPORT void printBits (char c[35], float f);
#define HALF_MAX 65504.0f // Largest positive half

#define HALF_EPSILON 0.00097656f // Smallest positive e for which
// half (1.0 + e) != half (1.0)
// half (1.0 + e) != half (1.0)
#else

#define HALF_MIN 5.96046448e-08 // Smallest positive half
@@ -276,35 +267,39 @@ HALF_EXPORT void printBits (char c[35], float f);
#define HALF_MAX 65504.0 // Largest positive half

#define HALF_EPSILON 0.00097656 // Smallest positive e for which
// half (1.0 + e) != half (1.0)
// half (1.0 + e) != half (1.0)
#endif


#define HALF_MANT_DIG 11 // Number of digits in mantissa
// (significand + hidden leading 1)
// (significand + hidden leading 1)

#define HALF_DIG 2 // Number of base 10 digits that
// can be represented without change
// can be represented without change

#define HALF_DECIMAL_DIG 5 // Number of base-10 digits that are
// necessary to uniquely represent all
// distinct values

#define HALF_RADIX 2 // Base of the exponent

#define HALF_MIN_EXP -13 // Minimum negative integer such that
// HALF_RADIX raised to the power of
// one less than that integer is a
// normalized half
// HALF_RADIX raised to the power of
// one less than that integer is a
// normalized half

#define HALF_MAX_EXP 16 // Maximum positive integer such that
// HALF_RADIX raised to the power of
// one less than that integer is a
// normalized half
// HALF_RADIX raised to the power of
// one less than that integer is a
// normalized half

#define HALF_MIN_10_EXP -4 // Minimum positive integer such
// that 10 raised to that power is
// a normalized half
// that 10 raised to that power is
// a normalized half

#define HALF_MAX_10_EXP 4 // Maximum positive integer such
// that 10 raised to that power is
// a normalized half
// that 10 raised to that power is
// a normalized half


//---------------------------------------------------------------------------
@@ -317,9 +312,9 @@ HALF_EXPORT void printBits (char c[35], float f);
// floating point number, whose bits are arranged as follows:
//
// 31 (msb)
// |
// |
// | 30 23
// | | |
// | | |
// | | | 22 0 (lsb)
// | | | | |
// X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX
@@ -363,7 +358,7 @@ HALF_EXPORT void printBits (char c[35], float f);
// Here is the bit-layout for a half number, h:
//
// 15 (msb)
// |
// |
// | 14 10
// | | |
// | | | 9 0 (lsb)
@@ -443,53 +438,53 @@ half::half (float f)

if (f == 0)
{
//
// Common special case - zero.
// Preserve the zero's sign bit.
//
//
// Common special case - zero.
// Preserve the zero's sign bit.
//

_h = (x.i >> 16);
_h = (x.i >> 16);
}
else
{
//
// We extract the combined sign and exponent, e, from our
// floating-point number, f. Then we convert e to the sign
// and exponent of the half number via a table lookup.
//
// For the most common case, where a normalized half is produced,
// the table lookup returns a non-zero value; in this case, all
// we have to do is round f's significand to 10 bits and combine
// the result with e.
//
// For all other cases (overflow, zeroes, denormalized numbers
// resulting from underflow, infinities and NANs), the table
// lookup returns zero, and we call a longer, non-inline function
// to do the float-to-half conversion.
//

register int e = (x.i >> 23) & 0x000001ff;

e = _eLut[e];

if (e)
{
//
// Simple case - round the significand, m, to 10
// bits and combine it with the sign and exponent.
//

register int m = x.i & 0x007fffff;
_h = e + ((m + 0x00000fff + ((m >> 13) & 1)) >> 13);
}
else
{
//
// Difficult case - call a function.
//

_h = convert (x.i);
}
//
// We extract the combined sign and exponent, e, from our
// floating-point number, f. Then we convert e to the sign
// and exponent of the half number via a table lookup.
//
// For the most common case, where a normalized half is produced,
// the table lookup returns a non-zero value; in this case, all
// we have to do is round f's significand to 10 bits and combine
// the result with e.
//
// For all other cases (overflow, zeroes, denormalized numbers
// resulting from underflow, infinities and NANs), the table
// lookup returns zero, and we call a longer, non-inline function
// to do the float-to-half conversion.
//

int e = (x.i >> 23) & 0x000001ff;

e = _eLut[e];

if (e)
{
//
// Simple case - round the significand, m, to 10
// bits and combine it with the sign and exponent.
//

int m = x.i & 0x007fffff;
_h = (unsigned short)(e + ((m + 0x00000fff + ((m >> 13) & 1)) >> 13));
}
else
{
//
// Difficult case - call a function.
//

_h = convert (x.i);
}
}
}

@@ -517,7 +512,7 @@ half::round (unsigned int n) const
//

if (n >= 10)
return *this;
return *this;

//
// Disassemble h into the sign, s,
@@ -544,13 +539,13 @@ half::round (unsigned int n) const

if (e >= 0x7c00)
{
//
// Overflow occurred -- truncate instead of rounding.
//
//
// Overflow occurred -- truncate instead of rounding.
//

e = _h;
e >>= 10 - n;
e <<= 10 - n;
e = _h;
e >>= 10 - n;
e <<= 10 - n;
}

//
@@ -568,7 +563,7 @@ half::round (unsigned int n) const
// Other inline functions
//-----------------------

inline half
inline half
half::operator - () const
{
half h;
@@ -657,7 +652,7 @@ half::operator /= (float f)
}


inline bool
inline bool
half::isFinite () const
{
unsigned short e = (_h >> 10) & 0x001f;
@@ -707,7 +702,7 @@ half::isInfinity () const
}


inline bool
inline bool
half::isNegative () const
{
return (_h & 0x8000) != 0;
@@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Copyright (c) 2008, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
@@ -32,23 +32,20 @@
//
///////////////////////////////////////////////////////////////////////////

#ifndef HALFEXPORT_H
#define HALFEXPORT_H

#if defined(OPENEXR_DLL)
#if defined(HALF_EXPORTS)
#define HALF_EXPORT __declspec(dllexport)
#else
#define HALF_EXPORT __declspec(dllimport)
#endif
#define HALF_EXPORT_CONST
#else
#define HALF_EXPORT
#define HALF_EXPORT_CONST const
#endif

#ifndef INCLUDED_IMATHGLU_H
#define INCLUDED_IMATHGLU_H

#include <GL/gl.h>
#include <GL/glu.h>

#include "ImathVec.h"

inline
void
gluLookAt(const Imath::V3f &pos, const Imath::V3f &interest, const Imath::V3f &up)
{
gluLookAt(pos.x, pos.y, pos.z,
interest.x, interest.y, interest.z,
up.x, up.y, up.z);
}
#endif // #ifndef HALFEXPORT_H

#endif
@@ -2,9 +2,9 @@
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
//
// All rights reserved.
//
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -16,8 +16,8 @@
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -85,10 +85,10 @@

#include "half.h"

#include <IlmBaseConfig.h>
#ifndef ILMBASE_HAVE_LARGE_STACK
#include "IlmBaseConfig.h"
#ifndef ILMBASE_HAVE_LARGE_STACK
#include <string.h> // need this for memset
#else
#else
#endif

#include <float.h>
@@ -105,24 +105,25 @@ class halfFunction

template <class Function>
halfFunction (Function f,
half domainMin = -HALF_MAX,
half domainMax = HALF_MAX,
T defaultValue = 0,
T posInfValue = 0,
T negInfValue = 0,
T nanValue = 0);
half domainMin = -HALF_MAX,
half domainMax = HALF_MAX,
T defaultValue = 0,
T posInfValue = 0,
T negInfValue = 0,
T nanValue = 0);

#ifndef ILMBASE_HAVE_LARGE_STACK
~halfFunction () { delete [] _lut; }
~halfFunction () { delete [] _lut; }
#endif

//-----------
// Evaluation
//-----------

T operator () (half x) const;

private:

#ifdef ILMBASE_HAVE_LARGE_STACK
T _lut[1 << 16];
#else
@@ -138,31 +139,31 @@ class halfFunction
template <class T>
template <class Function>
halfFunction<T>::halfFunction (Function f,
half domainMin,
half domainMax,
T defaultValue,
T posInfValue,
T negInfValue,
T nanValue)
half domainMin,
half domainMax,
T defaultValue,
T posInfValue,
T negInfValue,
T nanValue)
{
#ifndef ILMBASE_HAVE_LARGE_STACK
_lut = new T[1<<16];
memset (_lut, 0 , (1<<16) * sizeof(T));
#endif

for (int i = 0; i < (1 << 16); i++)
{
half x;
x.setBits (i);

if (x.isNan())
_lut[i] = nanValue;
else if (x.isInfinity())
_lut[i] = x.isNegative()? negInfValue: posInfValue;
else if (x < domainMin || x > domainMax)
_lut[i] = defaultValue;
else
_lut[i] = f (x);
half x;
x.setBits (i);

if (x.isNan())
_lut[i] = nanValue;
else if (x.isInfinity())
_lut[i] = x.isNegative()? negInfValue: posInfValue;
else if (x < domainMin || x > domainMax)
_lut[i] = defaultValue;
else
_lut[i] = f (x);
}
}

@@ -2,9 +2,9 @@
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
//
// All rights reserved.
//
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -16,8 +16,8 @@
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -94,6 +94,15 @@ class numeric_limits <half>
static const bool traps = true;
static const bool tinyness_before = false;
static const float_round_style round_style = round_to_nearest;

#if __cplusplus >= 201103L

// C++11 additions.
static constexpr int max_digits10 = HALF_DECIMAL_DIG;
static half lowest () {return -HALF_MAX;}

#endif

};


This file was deleted.

@@ -2,9 +2,9 @@
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
//
// All rights reserved.
//
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -16,8 +16,8 @@
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -1,10 +1,10 @@
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Copyright (c) 2002-2012, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
//
// All rights reserved.
//
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -16,8 +16,8 @@
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -40,19 +40,27 @@
//
//---------------------------------------------------------------------

#include "IexExport.h"
#include "IexBaseExc.h"
#include "IexMacros.h"

namespace Iex {
namespace {
#ifdef PLATFORM_WINDOWS
#include <windows.h>
#endif

#include <stdlib.h>

IEX_INTERNAL_NAMESPACE_SOURCE_ENTER

StackTracer currentStackTracer = 0;

namespace {

StackTracer currentStackTracer = 0;

} // namespace


void
void
setStackTracer (StackTracer stackTracer)
{
currentStackTracer = stackTracer;
@@ -67,31 +75,31 @@ stackTracer ()


BaseExc::BaseExc (const char* s) throw () :
std::string (s? s: ""),
_message (s? s: ""),
_stackTrace (currentStackTracer? currentStackTracer(): "")
{
// empty
}


BaseExc::BaseExc (const std::string &s) throw () :
std::string (s),
_message (s),
_stackTrace (currentStackTracer? currentStackTracer(): "")
{
// empty
}


BaseExc::BaseExc (std::stringstream &s) throw () :
std::string (s.str()),
_message (s.str()),
_stackTrace (currentStackTracer? currentStackTracer(): "")
{
// empty
}


BaseExc::BaseExc (const BaseExc &be) throw () :
std::string (be),
_message (be._message),
_stackTrace (be._stackTrace)
{
// empty
@@ -107,23 +115,99 @@ BaseExc::~BaseExc () throw ()
const char *
BaseExc::what () const throw ()
{
return c_str();
return _message.c_str();
}


BaseExc &
BaseExc::assign (std::stringstream &s)
{
std::string::assign (s.str());
_message.assign (s.str());
return *this;
}

BaseExc &
BaseExc::append (std::stringstream &s)
{
std::string::append (s.str());
_message.append (s.str());
return *this;
}

const std::string &
BaseExc::message() const
{
return _message;
}

} // namespace Iex
BaseExc &
BaseExc::operator = (std::stringstream &s)
{
return assign (s);
}


BaseExc &
BaseExc::operator += (std::stringstream &s)
{
return append (s);
}


BaseExc &
BaseExc::assign (const char *s)
{
_message.assign(s);
return *this;
}


BaseExc &
BaseExc::operator = (const char *s)
{
return assign(s);
}


BaseExc &
BaseExc::append (const char *s)
{
_message.append(s);
return *this;
}


BaseExc &
BaseExc::operator += (const char *s)
{
return append(s);
}


const std::string &
BaseExc::stackTrace () const
{
return _stackTrace;
}


IEX_INTERNAL_NAMESPACE_SOURCE_EXIT


#ifdef PLATFORM_WINDOWS

#pragma optimize("", off)
void
iex_debugTrap()
{
if (0 != getenv("IEXDEBUGTHROW"))
::DebugBreak();
}
#else
void
iex_debugTrap()
{
// how to in Linux?
if (0 != ::getenv("IEXDEBUGTHROW"))
__builtin_trap();
}
#endif