| 374 | |
| 375 | |
| 376 | void processImageOperation(ImageOperation const& operation, Image& image, ImageReferenceCallback refCallback) { |
| 377 | if (image.bytesPerPixel() == 3) { |
| 378 | // Convert to an image format that has alpha so certain operations function properly |
| 379 | image = image.convert(image.pixelFormat() == PixelFormat::BGR24 ? PixelFormat::BGRA32 : PixelFormat::RGBA32); |
| 380 | } |
| 381 | if (auto op = operation.ptr<HueShiftImageOperation>()) { |
| 382 | image.forEachPixel([&op](unsigned, unsigned, Vec4B& pixel) { |
| 383 | if (pixel[3] != 0) |
| 384 | pixel = Color::hueShiftVec4B(pixel, op->hueShiftAmount); |
| 385 | }); |
| 386 | } else if (auto op = operation.ptr<SaturationShiftImageOperation>()) { |
| 387 | processSaturationShift(image, op); |
| 388 | } else if (auto op = operation.ptr<BrightnessMultiplyImageOperation>()) { |
| 389 | image.forEachPixel([&op](unsigned, unsigned, Vec4B& pixel) { |
| 390 | if (pixel[3] != 0) { |
| 391 | Color color = Color::rgba(pixel); |
| 392 | color.setValue(clamp(color.value() * op->brightnessMultiply, 0.0f, 1.0f)); |
| 393 | pixel = color.toRgba(); |
| 394 | } |
| 395 | }); |
| 396 | } else if (auto op = operation.ptr<FadeToColorImageOperation>()) { |
| 397 | image.forEachPixel([&op](unsigned, unsigned, Vec4B& pixel) { |
| 398 | pixel[0] = op->rTable[pixel[0]]; |
| 399 | pixel[1] = op->gTable[pixel[1]]; |
| 400 | pixel[2] = op->bTable[pixel[2]]; |
| 401 | }); |
| 402 | } else if (auto op = operation.ptr<ScanLinesImageOperation>()) { |
| 403 | image.forEachPixel([&op](unsigned, unsigned y, Vec4B& pixel) { |
| 404 | if (y % 2 == 0) { |
| 405 | pixel[0] = op->fade1.rTable[pixel[0]]; |
| 406 | pixel[1] = op->fade1.gTable[pixel[1]]; |
| 407 | pixel[2] = op->fade1.bTable[pixel[2]]; |
| 408 | } else { |
| 409 | pixel[0] = op->fade2.rTable[pixel[0]]; |
| 410 | pixel[1] = op->fade2.gTable[pixel[1]]; |
| 411 | pixel[2] = op->fade2.bTable[pixel[2]]; |
| 412 | } |
| 413 | }); |
| 414 | } else if (auto op = operation.ptr<SetColorImageOperation>()) { |
| 415 | image.forEachPixel([&op](unsigned, unsigned, Vec4B& pixel) { |
| 416 | pixel[0] = op->color[0]; |
| 417 | pixel[1] = op->color[1]; |
| 418 | pixel[2] = op->color[2]; |
| 419 | }); |
| 420 | } else if (auto op = operation.ptr<ColorReplaceImageOperation>()) { |
| 421 | image.forEachPixel([&op](unsigned, unsigned, Vec4B& pixel) { |
| 422 | if (auto m = op->colorReplaceMap.maybe(pixel)) |
| 423 | pixel = *m; |
| 424 | }); |
| 425 | |
| 426 | } else if (auto op = operation.ptr<AlphaMaskImageOperation>()) { |
| 427 | if (op->maskImages.empty()) |
| 428 | return; |
| 429 | |
| 430 | if (!refCallback) |
| 431 | throw StarException("Missing image ref callback during AlphaMaskImageOperation in ImageProcessor::process"); |
| 432 | |
| 433 | List<Image const*> maskImages; |
no test coverage detected