/* * CINELERRA * Copyright (C) 2008 Adam Williams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "fadeengine.h" #include "vframe.h" #include FadeUnit::FadeUnit(FadeEngine *server) : LoadClient(server) { this->engine = server; } FadeUnit::~FadeUnit() { } #define APPLY_FADE(equivalent, \ input_rows, \ output_rows, \ max, \ type, \ temp_type, \ chroma_zero, \ components) \ { \ temp_type opacity = (temp_type)(alpha * max); \ temp_type transparency = (temp_type)(max - opacity); \ temp_type product = (temp_type) (chroma_zero * transparency); \ \ for(int i = row1; i < row2; i++) \ { \ type *in_row = (type*)input_rows[i]; \ type *out_row = (type*)output_rows[i]; \ \ for(int j = 0; j < width; j++, out_row += components, in_row += components) \ { \ if(components == 3) \ { \ out_row[0] = \ (type)((temp_type)in_row[0] * opacity / max); \ out_row[1] = \ (type)(((temp_type)in_row[1] * opacity + \ product) / max); \ out_row[2] = \ (type)(((temp_type)in_row[2] * opacity + \ product) / max); \ } \ else \ { \ if(!equivalent) \ { \ out_row[0] = in_row[0]; \ out_row[1] = in_row[1]; \ out_row[2] = in_row[2]; \ } \ \ if(in_row[3] == max) \ out_row[3] = opacity; \ else \ out_row[3] = \ (type)((temp_type)in_row[3] * opacity / max); \ } \ } \ } \ } void FadeUnit::process_package(LoadPackage *package) { FadePackage *pkg = (FadePackage*)package; VFrame *output = engine->output; VFrame *input = engine->input; float alpha = engine->alpha; int row1 = pkg->out_row1; int row2 = pkg->out_row2; unsigned char **in_rows = input->get_rows(); unsigned char **out_rows = output->get_rows(); int width = input->get_w(); if(input->get_rows()[0] == output->get_rows()[0]) { switch(input->get_color_model()) { case BC_RGB888: APPLY_FADE(1, out_rows, in_rows, 0xff, unsigned char, uint16_t, 0x0, 3); break; case BC_RGBA8888: APPLY_FADE(1, out_rows, in_rows, 0xff, unsigned char, uint16_t, 0x0, 4); break; case BC_RGB_FLOAT: APPLY_FADE(1, out_rows, in_rows, 1.0, float, float, 0x0, 3); break; case BC_RGBA_FLOAT: APPLY_FADE(1, out_rows, in_rows, 1.0, float, float, 0x0, 4); break; case BC_RGB161616: APPLY_FADE(1, out_rows, in_rows, 0xffff, uint16_t, uint32_t, 0x0, 3); break; case BC_RGBA16161616: APPLY_FADE(1, out_rows, in_rows, 0xffff, uint16_t, uint32_t, 0x0, 4); break; case BC_YUV888: APPLY_FADE(1, out_rows, in_rows, 0xff, unsigned char, uint16_t, 0x80, 3); break; case BC_YUVA8888: APPLY_FADE(1, out_rows, in_rows, 0xff, unsigned char, uint16_t, 0x80, 4); break; case BC_YUV161616: APPLY_FADE(1, out_rows, in_rows, 0xffff, uint16_t, uint32_t, 0x8000, 3); break; case BC_YUVA16161616: APPLY_FADE(1, out_rows, in_rows, 0xffff, uint16_t, uint32_t, 0x8000, 4); break; } } else { switch(input->get_color_model()) { case BC_RGB888: APPLY_FADE(0, out_rows, in_rows, 0xff, unsigned char, uint16_t, 0x0, 3); break; case BC_RGBA8888: APPLY_FADE(0, out_rows, in_rows, 0xff, unsigned char, uint16_t, 0x0, 4); break; case BC_RGB_FLOAT: APPLY_FADE(0, out_rows, in_rows, 1.0, float, float, 0x0, 3); break; case BC_RGBA_FLOAT: APPLY_FADE(0, out_rows, in_rows, 1.0, float, float, 0x0, 4); break; case BC_RGB161616: APPLY_FADE(0, out_rows, in_rows, 0xffff, uint16_t, uint32_t, 0x0, 3); break; case BC_RGBA16161616: APPLY_FADE(0, out_rows, in_rows, 0xffff, uint16_t, uint32_t, 0x0, 4); break; case BC_YUV888: APPLY_FADE(0, out_rows, in_rows, 0xff, unsigned char, uint16_t, 0x80, 3); break; case BC_YUVA8888: APPLY_FADE(0, out_rows, in_rows, 0xff, unsigned char, uint16_t, 0x80, 4); break; case BC_YUV161616: APPLY_FADE(0, out_rows, in_rows, 0xffff, uint16_t, uint32_t, 0x8000, 3); break; case BC_YUVA16161616: APPLY_FADE(0, out_rows, in_rows, 0xffff, uint16_t, uint32_t, 0x8000, 4); break; } } } FadeEngine::FadeEngine(int cpus) : LoadServer(cpus, cpus) { } FadeEngine::~FadeEngine() { } void FadeEngine::do_fade(VFrame *output, VFrame *input, float alpha) { this->output = output; this->input = input; this->alpha = alpha; // Sanity if(alpha == 1) output->copy_from(input); else process_packages(); } void FadeEngine::init_packages() { for(int i = 0; i < get_total_packages(); i++) { FadePackage *package = (FadePackage*)get_package(i); package->out_row1 = input->get_h() * i / get_total_packages(); package->out_row2 = input->get_h() * (i + 1) / get_total_packages(); } } LoadClient* FadeEngine::new_client() { return new FadeUnit(this); } LoadPackage* FadeEngine::new_package() { return new FadePackage; } FadePackage::FadePackage() { }