/* Given an area in the output image, calculate the bounding box for the * corresponding pixels in the input image. */ void im__transform_invert_rect( const Transformation *trn, const Rect *in, /* In output space */ Rect *out ) /* In input space */ { transform_rect( trn, im__transform_invert_point, in, out ); }
/* Given an area in the input image, calculate the bounding box for those * pixels in the output image. */ void vips__transform_forward_rect( const VipsTransformation *trn, const Rect *in, /* In input space */ Rect *out ) /* In output space */ { transform_rect( trn, vips__transform_forward_point, in, out ); }
image_transform& image_transform::operator*=(const image_transform& other) { opacity *= other.opacity; brightness *= other.brightness; contrast *= other.contrast; saturation *= other.saturation; // TODO (fix) auto aspect_ratio = 1.0; std::array<double, 2> rotated; auto orig_x = other.fill_translation[0]; auto orig_y = other.fill_translation[1] / aspect_ratio; rotated[0] = orig_x * std::cos(angle) - orig_y * std::sin(angle); rotated[1] = orig_x * std::sin(angle) + orig_y * std::cos(angle); rotated[1] *= aspect_ratio; anchor[0] += other.anchor[0] * fill_scale[0]; anchor[1] += other.anchor[1] * fill_scale[1]; fill_translation[0] += rotated[0] * fill_scale[0]; fill_translation[1] += rotated[1] * fill_scale[1]; fill_scale[0] *= other.fill_scale[0]; fill_scale[1] *= other.fill_scale[1]; clip_translation[0] += other.clip_translation[0] * clip_scale[0]; clip_translation[1] += other.clip_translation[1] * clip_scale[1]; clip_scale[0] *= other.clip_scale[0]; clip_scale[1] *= other.clip_scale[1]; angle += other.angle; transform_rect(crop, other.crop); transform_corners(perspective, other.perspective); levels.min_input = std::max(levels.min_input, other.levels.min_input); levels.max_input = std::min(levels.max_input, other.levels.max_input); levels.min_output = std::max(levels.min_output, other.levels.min_output); levels.max_output = std::min(levels.max_output, other.levels.max_output); levels.gamma *= other.levels.gamma; chroma.enable |= other.chroma.enable; chroma.show_mask |= other.chroma.show_mask; chroma.target_hue = std::max(other.chroma.target_hue, chroma.target_hue); chroma.min_saturation = std::max(other.chroma.min_saturation, chroma.min_saturation); chroma.min_brightness = std::max(other.chroma.min_brightness, chroma.min_brightness); chroma.hue_width = std::max(other.chroma.hue_width, chroma.hue_width); chroma.softness = std::max(other.chroma.softness, chroma.softness); chroma.spill_suppress = std::max(other.chroma.spill_suppress, chroma.spill_suppress); chroma.spill_suppress_saturation = std::min(other.chroma.spill_suppress_saturation, chroma.spill_suppress_saturation); is_key |= other.is_key; invert |= other.invert; is_mix |= other.is_mix; blend_mode = std::max(blend_mode, other.blend_mode); layer_depth += other.layer_depth; return *this; }
void transform_corners(corners& self, const corners& other) { transform_rect(self, other); self.ur[0] *= other.ur[0]; self.ur[1] += other.ur[1]; self.ll[0] += other.ll[0]; self.ll[1] *= other.ll[1]; // TODO: figure out the math to compose perspective transforms correctly. }
frame_transform& frame_transform::operator*=(const frame_transform &other) { volume *= other.volume; opacity *= other.opacity; brightness *= other.brightness; contrast *= other.contrast; saturation *= other.saturation; // TODO: can this be done in any way without knowing the aspect ratio of the // actual video mode? Thread local to the rescue auto aspect_ratio = detail::get_current_aspect_ratio(); aspect_ratio *= fill_scale[0] / fill_scale[1]; boost::array<double, 2> rotated; auto orig_x = other.fill_translation[0]; auto orig_y = other.fill_translation[1] / aspect_ratio; rotated[0] = orig_x * std::cos(angle) - orig_y * std::sin(angle); rotated[1] = orig_x * std::sin(angle) + orig_y * std::cos(angle); rotated[1] *= aspect_ratio; anchor[0] += other.anchor[0]*fill_scale[0]; anchor[1] += other.anchor[1]*fill_scale[1]; fill_translation[0] += rotated[0] * fill_scale[0]; fill_translation[1] += rotated[1] * fill_scale[1]; fill_scale[0] *= other.fill_scale[0]; fill_scale[1] *= other.fill_scale[1]; clip_translation[0] += other.clip_translation[0]*clip_scale[0]; clip_translation[1] += other.clip_translation[1]*clip_scale[1]; clip_scale[0] *= other.clip_scale[0]; clip_scale[1] *= other.clip_scale[1]; angle += other.angle; transform_rect(crop, other.crop); transform_corners(perspective, other.perspective); levels.min_input = std::max(levels.min_input, other.levels.min_input); levels.max_input = std::min(levels.max_input, other.levels.max_input); levels.min_output = std::max(levels.min_output, other.levels.min_output); levels.max_output = std::min(levels.max_output, other.levels.max_output); levels.gamma *= other.levels.gamma; field_mode = static_cast<field_mode::type>(field_mode & other.field_mode); is_key |= other.is_key; is_mix |= other.is_mix; return *this; }