X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=futatabi%2Fycbcr_converter.cpp;h=2d2f32f6077e72ae4cd5894634227b853161bfd6;hb=e15251d2787cb8e6b677af801de6180e55171763;hp=ef402a57d3926a974317db8e3b0bb52faafc1f7a;hpb=32b87c91cf51d730ff5abc8347884219918fad66;p=nageru diff --git a/futatabi/ycbcr_converter.cpp b/futatabi/ycbcr_converter.cpp index ef402a5..2d2f32f 100644 --- a/futatabi/ycbcr_converter.cpp +++ b/futatabi/ycbcr_converter.cpp @@ -1,13 +1,16 @@ #include "ycbcr_converter.h" +#include "exif_parser.h" #include "flags.h" #include "jpeg_frame.h" +#include #include +#include #include -using namespace std; using namespace movit; +using namespace std; namespace { @@ -53,12 +56,12 @@ YCbCrConverter::YCbCrConverter(YCbCrConverter::OutputMode output_mode, ResourceP // sources with no conversion, so we ought to have had false here. // However, in the off chance that we're actually getting real MJPEG, // we don't want to crush its blacks (or whites) by clamping. All of - // our processing is fades, so if we're in limited-range input, we'll - // stay in limited-range output. (Fading between limited-range and - // full-range sources will be broken, of course.) There will be some - // slight confusion in the parts of the algorithms dealing with RGB, - // but they're small and we'll manage. - ycbcr_format.full_range = true; + // our processing is fades or other linear operations, so if we're in + // limited-range input, we'll stay in limited-range output. (Fading + // between limited-range and full-range sources will be broken, + // of course.) There will be some slight confusion in the parts of the + // algorithms dealing with RGB, but they're small and we'll manage. + ycbcr_format.full_range = false; YCbCrFormat ycbcr_output_format = ycbcr_format; ycbcr_output_format.chroma_subsampling_x = 1; @@ -77,19 +80,23 @@ YCbCrConverter::YCbCrConverter(YCbCrConverter::OutputMode output_mode, ResourceP semiplanar_chain->set_dither_bits(8); semiplanar_chain->finalize(); - // Fade chains. + // Fade chains. These include white balance adjustments. for (bool first_input_is_semiplanar : { false, true }) { for (bool second_input_is_semiplanar : { false, true }) { FadeChain &fade_chain = fade_chains[first_input_is_semiplanar][second_input_is_semiplanar]; fade_chain.chain.reset(new EffectChain(global_flags.width, global_flags.height, resource_pool)); - fade_chain.input[0] = (movit::YCbCrInput *)fade_chain.chain->add_input( + fade_chain.input[0] = (YCbCrInput *)fade_chain.chain->add_input( new YCbCrInput(inout_format, ycbcr_format, global_flags.width, global_flags.height, first_input_is_semiplanar ? YCBCR_INPUT_SPLIT_Y_AND_CBCR : YCBCR_INPUT_PLANAR)); - fade_chain.input[1] = (movit::YCbCrInput *)fade_chain.chain->add_input( + fade_chain.input[1] = (YCbCrInput *)fade_chain.chain->add_input( new YCbCrInput(inout_format, ycbcr_format, global_flags.width, global_flags.height, second_input_is_semiplanar ? YCBCR_INPUT_SPLIT_Y_AND_CBCR : YCBCR_INPUT_PLANAR)); - fade_chain.mix_effect = (movit::MixEffect *)fade_chain.chain->add_effect( - new MixEffect, fade_chain.input[0], fade_chain.input[1]); + fade_chain.wb_effect[0] = (WhiteBalanceEffect *)fade_chain.chain->add_effect( + new WhiteBalanceEffect, fade_chain.input[0]); + fade_chain.wb_effect[1] = (WhiteBalanceEffect *)fade_chain.chain->add_effect( + new WhiteBalanceEffect, fade_chain.input[1]); + fade_chain.mix_effect = (MixEffect *)fade_chain.chain->add_effect( + new MixEffect, fade_chain.wb_effect[0], fade_chain.wb_effect[1]); setup_outputs(output_mode, inout_format, ycbcr_output_format, fade_chain.chain.get()); fade_chain.chain->set_dither_bits(8); fade_chain.chain->finalize(); @@ -103,17 +110,21 @@ YCbCrConverter::YCbCrConverter(YCbCrConverter::OutputMode output_mode, ResourceP fade_chain.chain.reset(new EffectChain(global_flags.width, global_flags.height, resource_pool)); ycbcr_format.chroma_subsampling_x = 1; - fade_chain.input[0] = (movit::YCbCrInput *)fade_chain.chain->add_input( + fade_chain.input[0] = (YCbCrInput *)fade_chain.chain->add_input( new YCbCrInput(inout_format, ycbcr_format, global_flags.width, global_flags.height, YCBCR_INPUT_INTERLEAVED)); ycbcr_format.chroma_subsampling_x = 2; - fade_chain.input[1] = (movit::YCbCrInput *)fade_chain.chain->add_input( + fade_chain.input[1] = (YCbCrInput *)fade_chain.chain->add_input( new YCbCrInput(inout_format, ycbcr_format, global_flags.width, global_flags.height, second_input_is_semiplanar ? YCBCR_INPUT_SPLIT_Y_AND_CBCR : YCBCR_INPUT_PLANAR)); - fade_chain.mix_effect = (movit::MixEffect *)fade_chain.chain->add_effect( - new MixEffect, fade_chain.input[0], fade_chain.input[1]); + fade_chain.wb_effect[0] = (WhiteBalanceEffect *)fade_chain.chain->add_effect( + new WhiteBalanceEffect, fade_chain.input[0]); + fade_chain.wb_effect[1] = (WhiteBalanceEffect *)fade_chain.chain->add_effect( + new WhiteBalanceEffect, fade_chain.input[1]); + fade_chain.mix_effect = (MixEffect *)fade_chain.chain->add_effect( + new MixEffect, fade_chain.wb_effect[0], fade_chain.wb_effect[1]); setup_outputs(output_mode, inout_format, ycbcr_output_format, fade_chain.chain.get()); fade_chain.chain->set_dither_bits(8); fade_chain.chain->finalize(); @@ -138,11 +149,15 @@ EffectChain *YCbCrConverter::prepare_chain_for_fade(shared_ptr frame, sha setup_input_for_frame(secondary_frame, ycbcr_format, fade_chain.input[1]); bool ok = fade_chain.mix_effect->set_float("strength_first", 1.0f - fade_alpha); ok |= fade_chain.mix_effect->set_float("strength_second", fade_alpha); + RGBTriplet neutral_color0 = get_neutral_color(frame->exif_data); + RGBTriplet neutral_color1 = get_neutral_color(secondary_frame->exif_data); + ok |= fade_chain.wb_effect[0]->set_vec3("neutral_color", (float *)&neutral_color0); + ok |= fade_chain.wb_effect[1]->set_vec3("neutral_color", (float *)&neutral_color1); assert(ok); return fade_chain.chain.get(); } -EffectChain *YCbCrConverter::prepare_chain_for_fade_from_texture(GLuint tex, unsigned width, unsigned height, std::shared_ptr secondary_frame, float fade_alpha) +EffectChain *YCbCrConverter::prepare_chain_for_fade_from_texture(GLuint tex, RGBTriplet tex_neutral_color, unsigned width, unsigned height, std::shared_ptr secondary_frame, float fade_alpha) { const FadeChain &fade_chain = interleaved_fade_chains[secondary_frame->is_semiplanar]; { @@ -163,6 +178,9 @@ EffectChain *YCbCrConverter::prepare_chain_for_fade_from_texture(GLuint tex, uns setup_input_for_frame(secondary_frame, ycbcr_format, fade_chain.input[1]); bool ok = fade_chain.mix_effect->set_float("strength_first", 1.0f - fade_alpha); ok |= fade_chain.mix_effect->set_float("strength_second", fade_alpha); + RGBTriplet neutral_color1 = get_neutral_color(secondary_frame->exif_data); + ok |= fade_chain.wb_effect[0]->set_vec3("neutral_color", (float *)&tex_neutral_color); + ok |= fade_chain.wb_effect[1]->set_vec3("neutral_color", (float *)&neutral_color1); assert(ok); return fade_chain.chain.get(); }