Process icon/picture elements: filter, crop, optional RMBG, base64, XML fragments.
| 227 | |
| 228 | # ======================== Icon/Picture processor ======================== |
| 229 | class IconPictureProcessor(BaseProcessor): |
| 230 | """Process icon/picture elements: filter, crop, optional RMBG, base64, XML fragments.""" |
| 231 | |
| 232 | # Types that use RMBG for background removal; others keep original crop |
| 233 | RMBG_TYPES = {"icon", "logo", "symbol", "emoji", "button", "arrow"} |
| 234 | |
| 235 | |
| 236 | # Types that keep background (crop only) |
| 237 | KEEP_BG_TYPES = { |
| 238 | "picture", "photo", "chart", "function_graph", "screenshot", "image", "diagram", |
| 239 | "graph", "line graph", "bar graph", "heatmap", "scatter plot", "histogram", "pie chart" |
| 240 | } |
| 241 | |
| 242 | # Max element area ratio (skip if element area > this fraction of image) |
| 243 | MAX_AREA_RATIO = 0.75 |
| 244 | |
| 245 | |
| 246 | def __init__( |
| 247 | self, |
| 248 | config=None, |
| 249 | rmbg_model_path: str = None, |
| 250 | ): |
| 251 | super().__init__(config) |
| 252 | self._rmbg_model: Optional[RMBGModel] = None |
| 253 | self._rmbg_model_path = rmbg_model_path |
| 254 | |
| 255 | def load_rmbg_model(self): |
| 256 | """Load RMBG model.""" |
| 257 | if self._rmbg_model is None: |
| 258 | self._rmbg_model = RMBGModel(self._rmbg_model_path) |
| 259 | if not self._rmbg_model.is_loaded: |
| 260 | self._rmbg_model.load() |
| 261 | |
| 262 | def load_model(self): |
| 263 | """Alias: load RMBG model.""" |
| 264 | self.load_rmbg_model() |
| 265 | |
| 266 | def process(self, context: ProcessingContext) -> ProcessingResult: |
| 267 | """Process icon/picture elements in context.""" |
| 268 | self._log("Processing Icon/Picture elements") |
| 269 | self.load_rmbg_model() |
| 270 | |
| 271 | # Load image |
| 272 | if not context.image_path or not os.path.exists(context.image_path): |
| 273 | return ProcessingResult( |
| 274 | success=False, |
| 275 | error_message="Invalid image path" |
| 276 | ) |
| 277 | |
| 278 | original_image = Image.open(context.image_path).convert("RGB") |
| 279 | cv2_image = cv2.imread(context.image_path) |
| 280 | |
| 281 | # Filter elements to process |
| 282 | elements_to_process = self._get_elements_to_process(context.elements) |
| 283 | |
| 284 | self._log(f"Elements to process: {len(elements_to_process)}") |
| 285 | |
| 286 | processed_count = 0 |
no outgoing calls
no test coverage detected