Files
oak-editor/app/pluginSupport/image.cpp
T
Mike-Solar bb40b4923e style: unify identifier naming per updated conventions
Automated with clang-tidy readability-identifier-naming (config added to
.clang-tidy) plus scripted passes, per the updated rules now documented
in CONTRIBUTING.md:

- types (class/struct/enum/alias/template params): PascalCase
- functions, variables, members: snake_case (incl. rational -> Rational)
- private/protected members: trailing underscore; static member
  variables likewise (instance_, available_themes_)
- constants and enum values: snake_case (kLinear -> k_linear,
  F32P -> f32p); ALL_CAPS reserved for macros
- macros: OAK_ prefix (OLIVE_ADD_TEST/OLIVE_ASSERT/OLIVE_CONFIG ->
  OAK_ADD_TEST/OAK_ASSERT/OAK_CONFIG, GL_PREAMBLE -> OAK_GL_PREAMBLE,
  include guards -> OAK_*)
- file names: all lowercase (Current/Plugin/OliveHost/OliveClip/
  OlivePluginInstance -> current/plugin/olivehost/oliveclip/
  oliveplugininstance)
- getters share the member name sans underscore, setters set_foo()
- Qt and third-party (OpenFX) virtual overrides and framework callbacks
  keep their original names (exempt in .clang-tidy)

Manual follow-ups required where automation could not reach:
- string-based QMetaObject/SIGNAL/SLOT references updated to renamed
  methods (AddTask, CreatedFile, DeleteSpecificFile, moveSelectionUp, ...)
- macro bodies referencing renamed methods (OLIVE_CONFIG,
  NODE_DEFAULT_DESTRUCTOR, MANAGEDDISPLAYWIDGET_*)
- self-shadowing locals renamed where signals/methods became same-named
  (size_changed, worker_count, selected_items, import param, filters)
- third_party OFX member/namespace usages restored (OFX::Host::*,
  _created, _clipPrefsDirty, createInstance, clearPersistentMessage)
- STL protocol aliases restored (const_iterator) with .clang-tidy
  ignore rules; qHash overloads restored

Full build and test suite pass: ctest 4/4, ~1960 gtest cases green.
2026-07-19 16:10:54 +08:00

233 lines
6.3 KiB
C++

/*
* Oak Video Editor - Non-Linear Video Editor
* Copyright (C) 2026 Olive CE Team
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "image.h"
#include "ofxImageEffect.h"
#include <algorithm>
namespace olive
{
namespace plugin
{
static const char *pixel_depth_to_ofx(core::PixelFormat format)
{
switch (format) {
case core::PixelFormat::u8:
return kOfxBitDepthByte;
case core::PixelFormat::u16:
return kOfxBitDepthShort;
case core::PixelFormat::f16:
return kOfxBitDepthHalf;
case core::PixelFormat::f32:
return kOfxBitDepthFloat;
case core::PixelFormat::invalid:
case core::PixelFormat::count:
break;
}
return kOfxBitDepthNone;
}
static const char *components_to_ofx(int channel_count)
{
switch (channel_count) {
case 1:
return kOfxImageComponentAlpha;
case 3:
return kOfxImageComponentRGB;
case 4:
return kOfxImageComponentRGBA;
default:
break;
}
return kOfxImageComponentNone;
}
Image::Image(OFX::Host::ImageEffect::ClipInstance &clip_instance)
: OFX::Host::ImageEffect::Image(clip_instance)
, width_(0)
, height_(0)
, format_(core::PixelFormat::invalid)
, premultiplied_alpha_(false)
, channel_count_(0)
, row_bytes_(0)
, bounds_{ 0, 0, 0, 0 }
, rod_{ 0, 0, 0, 0 }
{
}
Image::Image(OFX::Host::ImageEffect::ClipInstance &clip_instance,
const VideoParams &params, const OfxRectI &bounds,
const OfxRectI &rod, bool clear)
: OFX::Host::ImageEffect::Image(clip_instance)
, width_(0)
, height_(0)
, format_(core::PixelFormat::invalid)
, premultiplied_alpha_(false)
, channel_count_(0)
, row_bytes_(0)
, bounds_{ 0, 0, 0, 0 }
, rod_{ 0, 0, 0, 0 }
{
allocate_from_params(params, bounds, rod, clear);
}
Image::~Image()
{
}
void Image::allocate_from_params(const VideoParams &params,
const OfxRectI &bounds, const OfxRectI &rod,
bool clear)
{
allocate(bounds.x2 - bounds.x1, bounds.y2 - bounds.y1, params.format(),
params.channel_count(), params.premultiplied_alpha(), bounds, rod,
clear);
}
void Image::ensure_allocated_from_params(const VideoParams &params,
const OfxRectI &bounds,
const OfxRectI &rod, bool clear)
{
bool same = (width_ == bounds.x2 - bounds.x1) &&
(height_ == bounds.y2 - bounds.y1) &&
(format_ == params.format()) &&
(channel_count_ == params.channel_count()) &&
(premultiplied_alpha_ == params.premultiplied_alpha()) &&
(bounds_.x1 == bounds.x1) && (bounds_.y1 == bounds.y1) &&
(bounds_.x2 == bounds.x2) && (bounds_.y2 == bounds.y2) &&
(rod_.x1 == rod.x1) && (rod_.y1 == rod.y1) &&
(rod_.x2 == rod.x2) && (rod_.y2 == rod.y2);
if (!same) {
allocate_from_params(params, bounds, rod, clear);
} else if (clear && !image_.empty()) {
std::fill(image_.begin(), image_.end(), 0);
}
}
void Image::allocate(int width, int height, core::PixelFormat format,
int channel_count, bool premultiplied_alpha,
const OfxRectI &bounds, const OfxRectI &rod, bool clear)
{
width_ = width;
height_ = height;
format_ = format;
channel_count_ = channel_count;
premultiplied_alpha_ = premultiplied_alpha;
bounds_ = bounds;
rod_ = rod;
int bytes_per_component = format_.byte_count();
row_bytes_ = width_ * channel_count_ * bytes_per_component;
int buffer_size = row_bytes_ * height_;
if (buffer_size < 0) {
buffer_size = 0;
}
image_.resize(static_cast<size_t>(buffer_size));
if (clear && !image_.empty()) {
std::fill(image_.begin(), image_.end(), 0);
}
setPointerProperty(kOfxImagePropData, image_.data());
setIntProperty(kOfxImagePropRowBytes, row_bytes_);
setIntProperty(kOfxImagePropBounds, bounds.x1, 0);
setIntProperty(kOfxImagePropBounds, bounds.y1, 1);
setIntProperty(kOfxImagePropBounds, bounds.x2, 2);
setIntProperty(kOfxImagePropBounds, bounds.y2, 3);
setIntProperty(kOfxImagePropRegionOfDefinition, rod.x1, 0);
setIntProperty(kOfxImagePropRegionOfDefinition, rod.y1, 1);
setIntProperty(kOfxImagePropRegionOfDefinition, rod.x2, 2);
setIntProperty(kOfxImagePropRegionOfDefinition, rod.y2, 3);
setStringProperty(kOfxImageEffectPropComponents,
components_to_ofx(channel_count_));
setStringProperty(kOfxImageEffectPropPixelDepth, pixel_depth_to_ofx(format_));
setStringProperty(kOfxImageEffectPropPreMultiplication,
premultiplied_alpha_ ? kOfxImagePreMultiplied :
kOfxImageUnPreMultiplied);
}
core::PixelFormat Image::pixel_format()
{
if (format_ != core::PixelFormat::invalid) {
return format_;
}
std::string type = getStringProperty(kOfxImageEffectPropPixelDepth);
if (type == kOfxBitDepthByte) {
format_ = core::PixelFormat::u8;
} else if (type == kOfxBitDepthShort) {
format_ = core::PixelFormat::u16;
} else if (type == kOfxBitDepthHalf) {
format_ = core::PixelFormat::f16;
} else if (type == kOfxBitDepthFloat) {
format_ = core::PixelFormat::f32;
} else {
format_ = core::PixelFormat::invalid;
}
return format_;
}
bool Image::premultiplied_alpha()
{
std::string premultiplied =
getStringProperty(kOfxImageEffectPropPreMultiplication);
premultiplied_alpha_ = (premultiplied == kOfxImagePreMultiplied);
return premultiplied_alpha_;
}
int Image::width()
{
int bounds[4] = { 0 };
getIntPropertyN(kOfxImagePropBounds, bounds, 4);
width_ = bounds[2] - bounds[0];
return width_;
}
int Image::height()
{
int bounds[4] = { 0 };
getIntPropertyN(kOfxImagePropBounds, bounds, 4);
height_ = bounds[3] - bounds[1];
return height_;
}
int Image::channel_count()
{
std::string type = getStringProperty(kOfxImageEffectPropComponents);
if (type == kOfxImageComponentAlpha) {
channel_count_ = 1;
} else if (type == kOfxImageComponentRGBA) {
channel_count_ = 4;
} else if (type == kOfxImageComponentRGB) {
channel_count_ = 3;
} else {
channel_count_ = 0;
}
return channel_count_;
}
} // namespace plugin
} // namespace olive