43#include "gtest/gtest.h"
58 const double NORM2_L[3] = { 1.965908, 4.122410, 8.416737 };
59 const double NORM2_H[3] = { 0.520218, 0.967216, 2.079257 };
62 const float GAIN_L[4] = { 1.0f, (float)std::sqrt(NORM2_L[0]),
63 (float)std::sqrt(NORM2_L[1]), (float)std::sqrt(NORM2_L[2]) };
64 const float GAIN_H[3] = { (float)std::sqrt(4.0 * NORM2_H[0]),
65 (float)std::sqrt(4.0 * NORM2_H[1]), (float)std::sqrt(4.0 * NORM2_H[2]) };
70 const float CB_SQRT_W[10] = { 0.0863f, 0.0863f, 0.0263f,
71 0.2564f, 0.2564f, 0.1362f,
72 0.4691f, 0.4691f, 0.3346f, 1.0f };
73 const float CR_SQRT_W[10] = { 0.1835f, 0.1835f, 0.0773f,
74 0.4130f, 0.4130f, 0.2598f,
75 0.6464f, 0.6464f, 0.5040f, 1.0f };
78 const std::vector<float> CB_W(CB_SQRT_W, CB_SQRT_W + 10);
79 const std::vector<float> CR_W(CR_SQRT_W, CR_SQRT_W + 10);
83 struct quant {
bool found;
ojph::ui8 style; std::vector<float> delta; };
87 int exp = v >> 11, mant = v & 0x7FF;
88 return std::ldexp(1.0f + (
float)mant / 2048.0f, -exp);
97 bool reversible =
false)
125 quant q = {
false, 0, std::vector<float>() };
129 while (pos + 4 <= len)
132 if (marker == 0xFF90)
break;
136 if (comp < 0 && marker == 0xFF5C)
138 else if (comp >= 0 && marker == 0xFF5D && p[q0++] == comp)
144 EXPECT_EQ(q.style & 0x1F, 2);
145 for (
ojph::ui32 i = 0; i < 1 + 3 * num_decomps; ++i, q0 += 2)
147 decode_delta((
ojph::ui16)((p[q0] << 8) | p[q0 + 1])));
150 pos += (size_t)seg_len + 2;
158 std::vector<float> expected(
float delta,
const std::vector<float>& w,
161 std::vector<float> e;
162 e.push_back(delta / (GAIN_L[n] * GAIN_L[n] * w[3 * n]));
165 float gl = GAIN_L[d], gh = GAIN_H[d - 1];
166 e.push_back(delta / (gh * gl * w[(d - 1) * 3 + 1]));
167 e.push_back(delta / (gl * gh * w[(d - 1) * 3 + 0]));
168 e.push_back(delta / (gh * gh * w[(d - 1) * 3 + 2]));
173 void expect_close(
const std::vector<float>& got,
174 const std::vector<float>& want)
176 ASSERT_EQ(got.size(), want.size());
177 for (
size_t i = 0; i < got.size(); ++i)
180 EXPECT_NEAR(got[i] / want[i], 1.0f, 1.5e-3f) <<
"subband " << i;
194 std::vector<float> w = CB_W;
201 quant q1 = find_quant(out, 1, n);
202 ASSERT_TRUE(q1.found);
203 expect_close(q1.delta, expected(0.02f, w, n));
206 EXPECT_FALSE(find_quant(out, 0, n).found);
207 quant q0 = find_quant(out, -1, n);
208 ASSERT_TRUE(q0.found);
209 expect_close(q0.delta, expected(0.01f, std::vector<float>(10, 1.0f), n));
215TEST(QuantWeights, ValuesInQcdForAllComponents)
218 std::vector<float> w = CB_W;
224 quant q = find_quant(out, -1, n);
225 ASSERT_TRUE(q.found);
226 expect_close(q.delta, expected(0.01f, w, n));
227 EXPECT_FALSE(find_quant(out, 0, n).found);
228 EXPECT_FALSE(find_quant(out, 1, n).found);
234TEST(QuantWeights, UnitWeightsMatchNoWeights)
237 std::vector<float> w(10, 1.0f);
247 quant qa = find_quant(a, 1, n), qb = find_quant(b, 1, n);
248 ASSERT_TRUE(qa.found && qb.found);
249 EXPECT_EQ(qa.delta, qb.delta);
255TEST(QuantWeights, FewerDecompositionLevels)
258 const float sqrt_w[4] = { 0.0863f, 0.0863f, 0.0263f, 1.0f };
259 std::vector<float> w(sqrt_w, sqrt_w + 4);
264 quant q = find_quant(out, 0, n);
265 ASSERT_TRUE(q.found);
266 expect_close(q.delta, expected(0.05f, w, n));
271TEST(QuantWeights, WrongNumberOfWeights)
273 std::vector<float> w(9, 1.0f);
277 }), std::runtime_error);
282TEST(QuantWeights, InvalidWeights)
284 std::vector<float> w(10, 1.0f);
289 }), std::runtime_error);
295TEST(QuantWeights, ReversibleRejected)
297 std::vector<float> w(10, 1.0f);
301 },
true), std::runtime_error);
316 const float QF = 50.0f;
317 const std::vector<float> UNIT(1 + 3 * NQ, 1.0f);
329 { make_headers(out, 3, NQ, configure); }
336 quant a = find_quant(out, comp, NQ), b = find_quant(ref, comp, NQ);
337 ASSERT_TRUE(a.found && b.found) <<
"component " << comp;
338 EXPECT_EQ(a.delta, b.delta) <<
"component " << comp;
344 quant a = find_quant(out, comp, NQ), b = find_quant(ref, comp, NQ);
345 ASSERT_TRUE(a.found && b.found) <<
"component " << comp;
346 EXPECT_NE(a.delta, b.delta) <<
"component " << comp;
354TEST(QuantMix, GlobalQfactorWithDeltaOnOneComponent)
362 expect_like_qfactor(out, ref, 0);
363 expect_like_qfactor(out, ref, 2);
364 expect_not_like_qfactor(out, ref, 1);
365 quant q = find_quant(out, 1, NQ);
366 expect_close(q.delta, expected(0.02f, UNIT, NQ));
372TEST(QuantMix, GlobalQfactorWithWeightsOnOneComponent)
374 std::vector<float> w = CB_W;
381 expect_like_qfactor(out, ref, 0);
382 expect_like_qfactor(out, ref, 1);
383 expect_not_like_qfactor(out, ref, 2);
384 quant q = find_quant(out, 2, NQ);
385 expect_close(q.delta, expected(0.02f, w, NQ));
391TEST(QuantMix, QfactorOnOneComponentDeltaElsewhere)
399 expect_like_qfactor(out, ref, 1);
401 EXPECT_FALSE(find_quant(out, 0, NQ).found);
402 EXPECT_FALSE(find_quant(out, 2, NQ).found);
403 quant q = find_quant(out, -1, NQ);
404 ASSERT_TRUE(q.found);
405 expect_close(q.delta, expected(0.01f, UNIT, NQ));
411TEST(QuantMix, QfactorOnOneComponentWeightsOnAnother)
413 std::vector<float> w = CB_W;
421 expect_like_qfactor(out, ref, 0);
422 EXPECT_FALSE(find_quant(out, 1, NQ).found);
423 quant q = find_quant(out, 2, NQ);
424 ASSERT_TRUE(q.found);
425 expect_close(q.delta, expected(0.03f, w, NQ));
431TEST(QuantMix, QfactorWinsOverDeltaOnSameComponent)
451 for (
int comp = 0; comp < 3; ++comp)
453 expect_like_qfactor(a, ref, comp);
454 expect_like_qfactor(b, ref, comp);
455 expect_like_qfactor(c, ref, comp);
462TEST(QuantMix, QfactorAndWeightsOnSameComponentRejected)
464 std::vector<float> w(1 + 3 * NQ, 1.0f);
469 }), std::runtime_error);
473 }), std::runtime_error);
481 const std::vector<float> W1 = CB_W;
482 const std::vector<float> W2 = CR_W;
488TEST(QuantDeltaWeights, GlobalDeltaWithWeightsOnOneComponent)
501 EXPECT_FALSE(find_quant(*out, 0, NQ).found);
502 EXPECT_FALSE(find_quant(*out, 2, NQ).found);
503 quant q = find_quant(*out, -1, NQ);
504 ASSERT_TRUE(q.found);
505 expect_close(q.delta, expected(0.01f, UNIT, NQ));
506 q = find_quant(*out, 1, NQ);
507 ASSERT_TRUE(q.found);
508 expect_close(q.delta, expected(0.02f, W1, NQ));
511 EXPECT_EQ(find_quant(a, 1, NQ).delta, find_quant(b, 1, NQ).delta);
512 EXPECT_EQ(find_quant(a, -1, NQ).delta, find_quant(b, -1, NQ).delta);
517TEST(QuantDeltaWeights, ComponentDeltaIndependentOfGlobalDelta)
528 EXPECT_EQ(find_quant(a, 1, NQ).delta, find_quant(b, 1, NQ).delta);
529 EXPECT_NE(find_quant(a, -1, NQ).delta, find_quant(b, -1, NQ).delta);
535TEST(QuantDeltaWeights, DefaultGlobalDeltaWithWeights)
541 quant q = find_quant(out, 2, NQ);
542 ASSERT_TRUE(q.found);
543 expect_close(q.delta, expected(0.02f, W1, NQ));
544 EXPECT_FALSE(find_quant(out, 0, NQ).found);
545 EXPECT_FALSE(find_quant(out, 1, NQ).found);
547 quant g = find_quant(out, -1, NQ);
548 ASSERT_TRUE(g.found);
549 expect_close(g.delta, expected(1.0f / 256.0f, UNIT, NQ));
555TEST(QuantDeltaWeights, DifferentWeightsOnDifferentComponents)
563 quant q0 = find_quant(out, 0, NQ), q2 = find_quant(out, 2, NQ);
564 ASSERT_TRUE(q0.found && q2.found);
565 expect_close(q0.delta, expected(0.02f, W1, NQ));
566 expect_close(q2.delta, expected(0.03f, W2, NQ));
567 EXPECT_FALSE(find_quant(out, 1, NQ).found);
568 expect_close(find_quant(out, -1, NQ).delta, expected(0.01f, UNIT, NQ));
573TEST(QuantDeltaWeights, WeightsReplacedOnSecondCall)
580 expect_close(find_quant(out, 1, NQ).delta, expected(0.04f, W2, NQ));
585TEST(QuantDeltaWeights, ComponentDeltaAfterWeights)
592 expect_close(find_quant(out, 1, NQ).delta, expected(0.04f, W1, NQ));
The object represent a codestream.
param_siz access_siz()
Returns the underlying SIZ marker segment object.
param_cod access_cod()
Returns the underlying COD marker segment object.
param_qcd access_qcd()
Returns the underlying QCD marker segment object.
void write_headers(outfile_base *file, const comment_exchange *comments=NULL, ui32 num_comments=0)
Writes codestream headers when the codestream is used for writing. This function should be called aft...
mem_outfile stores encoded j2k codestreams in memory
size_t get_used_size() const
Call this function to get the used size of the memory file.
void open(size_t initial_size=65536, bool clear_mem=false)
Call this function to open a memory file.
const ui8 * get_data()
Call this function to access memory file data.
void set_num_decomposition(ui32 num_decompositions)
void set_color_transform(bool color_transform)
void set_reversible(bool reversible)
Quantization parameters object.
void set_qfactor(float qfactor)
Sets Qfactor.
void set_irrev_quant(float delta)
Set the irreversible quantization base delta.
void set_tile_size(size s)
void set_component(ui32 comp_num, const point &downsampling, ui32 bit_depth, bool is_signed)
void set_num_components(ui32 num_comps)
void set_tile_offset(point offset)
void set_image_offset(point offset)
void set_image_extent(point extent)
TEST(TestExecutables, OpenJPHCompressNoArguments)