""" Android media.effect 组件 — Effect, EffectContext, EffectFactory, EffectUpdateListener 方法签名完全对齐 Android SDK """ from __future__ import annotations import os import math import threading from typing import Any, Callable, Dict, List, Optional, Tuple, Union from .._core import Stub, AndroidOnlyError from ..java.lang import RuntimeException # ═══════════════════════════════════════════════════════════════ # Effect 常量 # ═══════════════════════════════════════════════════════════════ EFFECT_AUTOFIX = "android.media.effect.effects.AutoFixEffect" EFFECT_BACKDROPPER = "android.media.effect.effects.BackDropperEffect" EFFECT_BITMAPOVERLAY = "android.media.effect.effects.BitmapOverlayEffect" EFFECT_BLACKWHITE = "android.media.effect.effects.BlackWhiteEffect" EFFECT_BRIGHTNESS = "android.media.effect.effects.BrightnessEffect" EFFECT_CONTRAST = "android.media.effect.effects.ContrastEffect" EFFECT_CROSSPROCESS = "android.media.effect.effects.CrossProcessEffect" EFFECT_DOCUMENTARY = "android.media.effect.effects.DocumentaryEffect" EFFECT_DUOTONE = "android.media.effect.effects.DuotoneEffect" EFFECT_FILLLIGHT = "android.media.effect.effects.FillLightEffect" EFFECT_FISHEYE = "android.media.effect.effects.FisheyeEffect" EFFECT_FLIP = "android.media.effect.effects.FlipEffect" EFFECT_GRAIN = "android.media.effect.effects.GrainEffect" EFFECT_GRAYSCALE = "android.media.effect.effects.GrayscaleEffect" EFFECT_LOMO = "android.media.effect.effects.LomoishEffect" EFFECT_NEGATIVE = "android.media.effect.effects.NegativeEffect" EFFECT_POSTERIZE = "android.media.effect.effects.PosterizeEffect" EFFECT_REDEYE = "android.media.effect.effects.RedEyeEffect" EFFECT_ROTATE = "android.media.effect.effects.RotateEffect" EFFECT_SATURATE = "android.media.effect.effects.SaturateEffect" EFFECT_SEPIA = "android.media.effect.effects.SepiaEffect" EFFECT_SHARPEN = "android.media.effect.effects.SharpenEffect" EFFECT_TEMPERATURE = "android.media.effect.effects.TemperatureEffect" EFFECT_TINT = "android.media.effect.effects.TintEffect" EFFECT_VIGNETTE = "android.media.effect.effects.VignetteEffect" class EffectUpdateListener: """EffectUpdateListener — 效果更新监听器""" def onEffectUpdated(self, effect: "Effect", info: Any) -> None: """当效果状态更新时调用""" pass class Effect(Stub): """Effect — 图像效果基类""" def __init__(self, effect_type: str = ""): super().__init__() self._type = effect_type self._parameters: Dict[str, Any] = {} self._update_listener: Optional[EffectUpdateListener] = None self._listener_lock = threading.Lock() def apply(self, input_id: int, output_id: int) -> None: """应用效果到输入表面,输出到输出表面""" raise AndroidOnlyError("Effect.apply() 仅在 Android 设备上可用") def setParameter(self, param_key: str, value: Any) -> None: """设置效果参数""" self._parameters[param_key] = value def getParameter(self, param_key: str) -> Any: """获取效果参数值""" return self._parameters.get(param_key, None) def getName(self) -> str: """获取效果名称""" return self._type def setUpdateListener(self, listener: Optional[EffectUpdateListener]) -> None: """设置更新监听器""" with self._listener_lock: self._update_listener = listener def getUpdateListener(self) -> Optional[EffectUpdateListener]: """获取当前更新监听器""" with self._listener_lock: return self._update_listener def release(self) -> None: """释放效果资源""" self._parameters.clear() self._update_listener = None def toString(self) -> str: return f"Effect(type={self._type})" class EffectContext(Stub): """EffectContext — 效果上下文,管理 GL 资源和效果生命周期""" _instance_counter = 0 _instances: Dict[int, "EffectContext"] = {} _instances_lock = threading.Lock() def __init__(self): super().__init__() with EffectContext._instances_lock: EffectContext._instance_counter += 1 self._context_id = EffectContext._instance_counter EffectContext._instances[self._context_id] = self self._effects: Dict[str, Effect] = {} self._effects_lock = threading.Lock() self._released = False @staticmethod def createWithCurrentGlContext() -> "EffectContext": """使用当前 GL 上下文创建 EffectContext""" ctx = EffectContext() return ctx def getFactory(self) -> "EffectFactory": """获取与此上下文关联的 EffectFactory""" if self._released: raise RuntimeException("EffectContext 已被释放") return EffectFactory(self) def createEffect(self, effect_type: str) -> Effect: """创建指定类型的效果""" if self._released: raise RuntimeException("EffectContext 已被释放") factory = self.getFactory() return factory.createEffect(effect_type) def getEffect(self, name: str) -> Optional[Effect]: """获取已创建的指定名称的效果""" with self._effects_lock: return self._effects.get(name, None) def getAllEffects(self) -> List[Effect]: """获取所有已创建的效果列表""" with self._effects_lock: return list(self._effects.values()) def release(self) -> None: """释放 EffectContext 及其所有效果""" if self._released: return self._released = True with self._effects_lock: for effect in self._effects.values(): effect.release() self._effects.clear() with EffectContext._instances_lock: EffectContext._instances.pop(self._context_id, None) def isReleased(self) -> bool: """检查是否已释放""" return self._released def getContextId(self) -> int: return self._context_id def toString(self) -> str: return f"EffectContext(id={self._context_id}, released={self._released})" class EffectFactory(Stub): """EffectFactory — 效果工厂,用于创建各种 Effect 实例""" # 效果类型常量 EFFECT_AUTOFIX = EFFECT_AUTOFIX EFFECT_BACKDROPPER = EFFECT_BACKDROPPER EFFECT_BITMAPOVERLAY = EFFECT_BITMAPOVERLAY EFFECT_BLACKWHITE = EFFECT_BLACKWHITE EFFECT_BRIGHTNESS = EFFECT_BRIGHTNESS EFFECT_CONTRAST = EFFECT_CONTRAST EFFECT_CROSSPROCESS = EFFECT_CROSSPROCESS EFFECT_DOCUMENTARY = EFFECT_DOCUMENTARY EFFECT_DUOTONE = EFFECT_DUOTONE EFFECT_FILLLIGHT = EFFECT_FILLLIGHT EFFECT_FISHEYE = EFFECT_FISHEYE EFFECT_FLIP = EFFECT_FLIP EFFECT_GRAIN = EFFECT_GRAIN EFFECT_GRAYSCALE = EFFECT_GRAYSCALE EFFECT_LOMO = EFFECT_LOMO EFFECT_NEGATIVE = EFFECT_NEGATIVE EFFECT_POSTERIZE = EFFECT_POSTERIZE EFFECT_REDEYE = EFFECT_REDEYE EFFECT_ROTATE = EFFECT_ROTATE EFFECT_SATURATE = EFFECT_SATURATE EFFECT_SEPIA = EFFECT_SEPIA EFFECT_SHARPEN = EFFECT_SHARPEN EFFECT_TEMPERATURE = EFFECT_TEMPERATURE EFFECT_TINT = EFFECT_TINT EFFECT_VIGNETTE = EFFECT_VIGNETTE _EFFECT_NAMES: List[str] = [ EFFECT_AUTOFIX, EFFECT_BACKDROPPER, EFFECT_BITMAPOVERLAY, EFFECT_BLACKWHITE, EFFECT_BRIGHTNESS, EFFECT_CONTRAST, EFFECT_CROSSPROCESS, EFFECT_DOCUMENTARY, EFFECT_DUOTONE, EFFECT_FILLLIGHT, EFFECT_FISHEYE, EFFECT_FLIP, EFFECT_GRAIN, EFFECT_GRAYSCALE, EFFECT_LOMO, EFFECT_NEGATIVE, EFFECT_POSTERIZE, EFFECT_REDEYE, EFFECT_ROTATE, EFFECT_SATURATE, EFFECT_SEPIA, EFFECT_SHARPEN, EFFECT_TEMPERATURE, EFFECT_TINT, EFFECT_VIGNETTE, ] def __init__(self, context: EffectContext): super().__init__() self._context = context def createEffect(self, effect_type: str) -> Effect: """创建指定类型的效果""" if effect_type not in self._EFFECT_NAMES: raise IllegalArgumentException(f"不支持的效果类型: {effect_type}") effect = Effect(effect_type) with self._context._effects_lock: self._context._effects[effect_type] = effect return effect def isEffectSupported(self, effect_type: str) -> bool: """检查效果类型是否被支持""" return effect_type in self._EFFECT_NAMES def getSupportedEffects(self) -> List[str]: """获取所有支持的效果类型列表""" return list(self._EFFECT_NAMES) def toString(self) -> str: return f"EffectFactory(context_id={self._context.getContextId()})" IllegalArgumentException = type("IllegalArgumentException", (RuntimeException,), {}) class AutoFixEffect(Effect): """AutoFixEffect — 自动修复效果,调整对比度/亮度平衡""" def __init__(self): super().__init__(EFFECT_AUTOFIX) self._scale = 0.5 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "scale": self._scale = max(0.0, min(1.0, float(value))) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "scale": return self._scale return super().getParameter(param_key) class BackDropperEffect(Effect): """BackDropperEffect — 背景替换效果""" def __init__(self): super().__init__(EFFECT_BACKDROPPER) self._source_id = 0 self._background_id = 0 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "source": self._source_id = int(value) elif param_key == "background": self._background_id = int(value) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "source": return self._source_id if param_key == "background": return self._background_id return super().getParameter(param_key) class BitmapOverlayEffect(Effect): """BitmapOverlayEffect — 位图覆盖效果""" def __init__(self): super().__init__(EFFECT_BITMAPOVERLAY) self._bitmap: Any = None def setParameter(self, param_key: str, value: Any) -> None: if param_key == "bitmap": self._bitmap = value super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "bitmap": return self._bitmap return super().getParameter(param_key) class BlackWhiteEffect(Effect): """BlackWhiteEffect — 黑白效果""" def __init__(self): super().__init__(EFFECT_BLACKWHITE) self._black = 0.0 self._white = 1.0 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "black": self._black = max(0.0, min(1.0, float(value))) elif param_key == "white": self._white = max(0.0, min(1.0, float(value))) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "black": return self._black if param_key == "white": return self._white return super().getParameter(param_key) class BrightnessEffect(Effect): """BrightnessEffect — 亮度调整效果""" def __init__(self): super().__init__(EFFECT_BRIGHTNESS) self._brightness = 0.0 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "brightness": self._brightness = max(-1.0, min(1.0, float(value))) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "brightness": return self._brightness return super().getParameter(param_key) class ContrastEffect(Effect): """ContrastEffect — 对比度调整效果""" def __init__(self): super().__init__(EFFECT_CONTRAST) self._contrast = 1.0 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "contrast": self._contrast = max(0.0, float(value)) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "contrast": return self._contrast return super().getParameter(param_key) class CrossProcessEffect(Effect): """CrossProcessEffect — 交叉冲印效果""" def __init__(self): super().__init__(EFFECT_CROSSPROCESS) class DocumentaryEffect(Effect): """DocumentaryEffect — 纪录片风格效果""" def __init__(self): super().__init__(EFFECT_DOCUMENTARY) class DuotoneEffect(Effect): """DuotoneEffect — 双色调效果""" def __init__(self): super().__init__(EFFECT_DUOTONE) self._first_color = 0xFFFF0000 self._second_color = 0xFF0000FF def setParameter(self, param_key: str, value: Any) -> None: if param_key in ("first_color", "second_color"): setattr(self, f"_{param_key}", int(value) & 0xFFFFFFFF) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "first_color": return self._first_color if param_key == "second_color": return self._second_color return super().getParameter(param_key) class FillLightEffect(Effect): """FillLightEffect — 填充光效果(人脸照明增强)""" def __init__(self): super().__init__(EFFECT_FILLLIGHT) self._strength = 0.0 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "strength": self._strength = max(0.0, min(1.0, float(value))) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "strength": return self._strength return super().getParameter(param_key) class FisheyeEffect(Effect): """FisheyeEffect — 鱼眼效果""" def __init__(self): super().__init__(EFFECT_FISHEYE) self._scale = 0.5 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "scale": self._scale = max(0.0, min(1.0, float(value))) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "scale": return self._scale return super().getParameter(param_key) class FlipEffect(Effect): """FlipEffect — 翻转效果""" def __init__(self): super().__init__(EFFECT_FLIP) self._horizontal = True self._vertical = False def setParameter(self, param_key: str, value: Any) -> None: if param_key == "horizontal": self._horizontal = bool(value) elif param_key == "vertical": self._vertical = bool(value) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "horizontal": return self._horizontal if param_key == "vertical": return self._vertical return super().getParameter(param_key) class GrainEffect(Effect): """GrainEffect — 颗粒效果""" def __init__(self): super().__init__(EFFECT_GRAIN) self._intensity = 0.5 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "intensity": self._intensity = max(0.0, min(1.0, float(value))) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "intensity": return self._intensity return super().getParameter(param_key) class GrayscaleEffect(Effect): """GrayscaleEffect — 灰度效果""" def __init__(self): super().__init__(EFFECT_GRAYSCALE) class LomoishEffect(Effect): """LomoishEffect — LOMO 风格效果""" def __init__(self): super().__init__(EFFECT_LOMO) class NegativeEffect(Effect): """NegativeEffect — 底片效果""" def __init__(self): super().__init__(EFFECT_NEGATIVE) class PosterizeEffect(Effect): """PosterizeEffect — 色调分离效果""" def __init__(self): super().__init__(EFFECT_POSTERIZE) class RedEyeEffect(Effect): """RedEyeEffect — 红眼消除效果""" def __init__(self): super().__init__(EFFECT_REDEYE) class RotateEffect(Effect): """RotateEffect — 旋转效果""" def __init__(self): super().__init__(EFFECT_ROTATE) self._angle = 0.0 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "angle": self._angle = float(value) % 360.0 super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "angle": return self._angle return super().getParameter(param_key) class SaturateEffect(Effect): """SaturateEffect — 饱和度调整效果""" def __init__(self): super().__init__(EFFECT_SATURATE) self._scale = 1.0 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "scale": self._scale = max(0.0, float(value)) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "scale": return self._scale return super().getParameter(param_key) class SepiaEffect(Effect): """SepiaEffect — 棕褐色效果""" def __init__(self): super().__init__(EFFECT_SEPIA) class SharpenEffect(Effect): """SharpenEffect — 锐化效果""" def __init__(self): super().__init__(EFFECT_SHARPEN) self._scale = 0.5 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "scale": self._scale = max(0.0, float(value)) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "scale": return self._scale return super().getParameter(param_key) class TemperatureEffect(Effect): """TemperatureEffect — 色温效果""" def __init__(self): super().__init__(EFFECT_TEMPERATURE) self._scale = 0.5 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "scale": self._scale = max(0.0, min(1.0, float(value))) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "scale": return self._scale return super().getParameter(param_key) class TintEffect(Effect): """TintEffect — 色调效果""" def __init__(self): super().__init__(EFFECT_TINT) self._tint_color = 0xFF000000 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "tint": self._tint_color = int(value) & 0xFFFFFFFF super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "tint": return self._tint_color return super().getParameter(param_key) class VignetteEffect(Effect): """VignetteEffect — 暗角效果""" def __init__(self): super().__init__(EFFECT_VIGNETTE) self._scale = 0.5 def setParameter(self, param_key: str, value: Any) -> None: if param_key == "scale": self._scale = max(0.0, min(1.0, float(value))) super().setParameter(param_key, value) def getParameter(self, param_key: str) -> Any: if param_key == "scale": return self._scale return super().getParameter(param_key)