Manage Image Transform Effects in Presentations with PHP
Overview
Aspose.Slides represents picture adjustments as an ordered collection of image transform operations. For a picture frame, start with the frame’s Picture and access Picture::getImageTransform. The returned ImageTransformOperationCollection lets you append, enumerate, inspect, remove, and clear effects without rewriting the original image bytes.
This article demonstrates a complete workflow for brightness and contrast, color transformations, blur, transparency, ordered effect chains, effective values, removal, and PPTX round-trip verification.
Understand Effect Ownership and Image Reuse
An image resource and the picture that displays it are different objects:
- PPImage stores or references the source image data owned by the presentation.
- Picture belongs to a picture fill and refers to an image resource while storing the image transform collection.
- PictureFrame is the slide shape that owns the relevant picture fill, geometry, crop settings, and other frame-level formatting.
Therefore, image transform operations do not modify the bytes in PPImage. When the same PPImage is passed to ShapeCollection::addPictureFrame more than once, each new picture frame receives its own Picture and its own transform collection. Applying grayscale to one frame does not make the other frames grayscale, even though all of them reuse the same embedded image resource.
The same Picture::getImageTransform model is also used by other picture fills, such as a shape or slide background. The examples below focus on picture frames.
Use Valid Parameter Ranges and Units
The demonstrated methods use the following semantic ranges and units. Keep values in these ranges even if a particular library version does not reject every out-of-range value immediately; the target presentation format may normalize, omit, or reject invalid data during save or when PowerPoint opens the file.
| Operation | Parameters | Valid range and unit |
|---|---|---|
| addLuminanceEffect | brightness, contrast |
-100 through 100, percent; 0 leaves the component unchanged. |
| addGrayScaleEffect | None | No numeric parameters. Alpha is unchanged. |
| addDuotoneEffect | color1, color2 |
Two colors for dark and light pixels. RGB and alpha channels in java.awt.Color use 0 through 255. |
| addTintEffect | hue, amount |
Hue is 0 inclusive through 360 exclusive, in degrees; amount is -100 through 100, percent. |
| addHSLEffect | hue, saturation, luminance |
Hue is 0 inclusive through 360 exclusive, in degrees; saturation and luminance are -100 through 100, percent. |
| addColorReplaceEffect | color |
The replacement color uses channel values from 0 through 255. Existing alpha values are unchanged. |
| addBlurEffect | radius, grow |
Radius is nonnegative and is measured in points; grow is a Boolean that controls whether blurred content may extend outside the original bounds. |
| addAlphaModulateFixedEffect | amount |
Nonnegative percent. Use 0 through 100 for ordinary opacity scaling: 0 is fully transparent and 100 preserves the existing alpha. |
| addAlphaReplaceEffect | alpha |
0 through 100, percent opacity. |
| addAlphaBiLevelEffect | threshold |
0 through 100, percent alpha threshold. Values below it become transparent; values at or above it become opaque. |
For fixed alpha modulation, transparency and opacity are complementary. For example, 35% transparency corresponds to an alpha modulation amount of 65%.
Apply Brightness and Contrast
ImageTransformOperationCollection::addLuminanceEffect returns a Luminance operation. Its scalar settings are supplied when the operation is created. Luminance::getEffective returns calculated read-only values that can be inspected or logged.
The following example increases brightness by 15% and contrast by 20%, then renders a preview without modifying the embedded image:
use aspose\slides\ImageFormat;
use aspose\slides\Images;
use aspose\slides\Presentation;
use aspose\slides\ShapeType;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$sourceImage = Images::fromFile("photo.png");
try {
$image = $presentation->getImages()->addImage($sourceImage);
} finally {
if (!java_is_null($sourceImage)) {
$sourceImage->dispose();
}
}
$pictureFrame = $slide->getShapes()->addPictureFrame(ShapeType::Rectangle, 50, 50, 400, 260, $image);
$imageTransform = $pictureFrame->getPictureFormat()->getPicture()->getImageTransform();
$luminance = $imageTransform->addLuminanceEffect(15, 20);
$effectiveValues = $luminance->getEffective();
echo "Brightness: " . java_values($effectiveValues->getBrightness()) . "%" . PHP_EOL;
echo "Contrast: " . java_values($effectiveValues->getContrast()) . "%" . PHP_EOL;
$preview = $slide->getImage();
try {
$preview->save("brightness-contrast-preview.png", ImageFormat::Png);
} finally {
if (!java_is_null($preview)) {
$preview->dispose();
}
}
} finally {
$presentation->dispose();
}
Luminance is the standard DrawingML brightness and contrast effect. When those settings must remain editable after a PPTX round trip, reopen the saved presentation and verify both the operation type and its effective values.
Apply Color Transformations
Color effects can be applied independently to different picture frames that reuse one image resource. The following example creates five frames and applies grayscale, duotone, tint, HSL adjustment, and color replacement.
Duotone contains two independently editable color parameters: color1 maps dark pixels, while color2 maps light pixels. This makes it a useful example of an effect whose settings are more complex than a single scalar value.
use aspose\slides\Images;
use aspose\slides\Presentation;
use aspose\slides\SaveFormat;
use aspose\slides\ShapeType;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$sourceImage = Images::fromFile("photo.png");
try {
$image = $presentation->getImages()->addImage($sourceImage);
} finally {
if (!java_is_null($sourceImage)) {
$sourceImage->dispose();
}
}
$grayFrame = $slide->getShapes()->addPictureFrame(ShapeType::Rectangle, 20, 20, 180, 120, $image);
$grayFrame->getPictureFormat()->getPicture()->getImageTransform()->addGrayScaleEffect();
$duotoneFrame = $slide->getShapes()->addPictureFrame(ShapeType::Rectangle, 220, 20, 180, 120, $image);
$duotone = $duotoneFrame->getPictureFormat()->getPicture()->getImageTransform()->addDuotoneEffect();
$duotone->getColor1()->setColor(new Java("java.awt.Color", 0, 0, 128));
$duotone->getColor2()->setColor(new Java("java.awt.Color", 255, 215, 0));
$tintFrame = $slide->getShapes()->addPictureFrame(ShapeType::Rectangle, 420, 20, 180, 120, $image);
$tintFrame->getPictureFormat()->getPicture()->getImageTransform()->addTintEffect(210, 35);
$hslFrame = $slide->getShapes()->addPictureFrame(ShapeType::Rectangle, 120, 170, 180, 120, $image);
$hslFrame->getPictureFormat()->getPicture()->getImageTransform()->addHSLEffect(30, 20, -10);
$replacementFrame = $slide->getShapes()->addPictureFrame(ShapeType::Rectangle, 320, 170, 180, 120, $image);
$colorReplacement = $replacementFrame->getPictureFormat()->getPicture()->getImageTransform()->addColorReplaceEffect();
$colorReplacement->getColor()->setColor(new Java("java.awt.Color", 100, 149, 237));
$presentation->save("color-transformations.pptx", SaveFormat::Pptx);
} finally {
$presentation->dispose();
}
addColorReplaceEffect replaces every pixel’s color with one fixed color while preserving alpha. It is different from addColorChangeEffect, which maps one source color to another and exposes both source and target color formats.
Add Blur, Transparency, and Alpha Effects
addBlurEffect affects all color channels, including alpha. Set grow to true when the blurred edge may extend beyond the original picture bounds.
For uniform transparency, use addAlphaModulateFixedEffect. It multiplies every existing alpha value, so partially transparent pixels remain proportionally different. addAlphaReplaceEffect instead assigns one alpha value to all pixels. addAlphaBiLevelEffect converts alpha to two levels based on a threshold.
use aspose\slides\Images;
use aspose\slides\Presentation;
use aspose\slides\SaveFormat;
use aspose\slides\ShapeType;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$sourceImage = Images::fromFile("photo.png");
try {
$image = $presentation->getImages()->addImage($sourceImage);
} finally {
if (!java_is_null($sourceImage)) {
$sourceImage->dispose();
}
}
$blurredFrame = $slide->getShapes()->addPictureFrame(ShapeType::Rectangle, 20, 20, 200, 140, $image);
$blur = $blurredFrame->getPictureFormat()->getPicture()->getImageTransform()->addBlurEffect(4.5, true);
$blur->setRadius(5);
$transparentFrame = $slide->getShapes()->addPictureFrame(ShapeType::Rectangle, 240, 20, 200, 140, $image);
$alphaModulate = $transparentFrame->getPictureFormat()->getPicture()->getImageTransform()->addAlphaModulateFixedEffect(65);
$alphaModulate->setAmount(60);
$uniformAlphaFrame = $slide->getShapes()->addPictureFrame(ShapeType::Rectangle, 20, 180, 200, 140, $image);
$uniformAlphaFrame->getPictureFormat()->getPicture()->getImageTransform()->addAlphaReplaceEffect(55);
$binaryAlphaFrame = $slide->getShapes()->addPictureFrame(ShapeType::Rectangle, 240, 180, 200, 140, $image);
$alphaBiLevel = $binaryAlphaFrame->getPictureFormat()->getPicture()->getImageTransform()->addAlphaBiLevelEffect(50);
$alphaBiLevel->setThreshold(45);
$binaryAlphaFrame->getPictureFormat()->getPicture()->getImageTransform()->addAlphaInverseEffect();
$presentation->save("blur-and-alpha-effects.pptx", SaveFormat::Pptx);
} finally {
$presentation->dispose();
}
Other parameter-free alpha operations include addAlphaCeilingEffect, which makes every nonzero alpha fully opaque; addAlphaFloorEffect, which makes every alpha below 100% fully transparent; and addAlphaInverseEffect, which changes alpha to 100% - alpha.
Build an Ordered Effect Chain
Every add...Effect method appends a new operation to the end of the collection. The renderer uses the collection as an ordered pipeline: the output of operation 0 becomes the input of operation 1, and so on. Consequently, the same operations in a different order can produce a different image.
For example, grayscale followed by tint first removes chromatic information and then recolors the luminance result. Tint followed by grayscale removes the tint again. Similarly, alpha replacement can override alpha values calculated by earlier operations, while alpha modulation preserves their relative differences.
The following example builds a four-operation chain, saves it as PPTX, reopens the presentation, checks both the operation types and their order, and renders the reopened result:
use aspose\slides\ImageFormat;
use aspose\slides\Images;
use aspose\slides\Presentation;
use aspose\slides\SaveFormat;
use aspose\slides\ShapeType;
$presentation = new Presentation();
try {
$slide = $presentation->getSlides()->get_Item(0);
$sourceImage = Images::fromFile("photo.png");
try {
$image = $presentation->getImages()->addImage($sourceImage);
} finally {
if (!java_is_null($sourceImage)) {
$sourceImage->dispose();
}
}
$pictureFrame = $slide->getShapes()->addPictureFrame(ShapeType::Rectangle, 50, 50, 400, 260, $image);
$imageTransform = $pictureFrame->getPictureFormat()->getPicture()->getImageTransform();
$imageTransform->addGrayScaleEffect();
$imageTransform->addTintEffect(220, 25);
$imageTransform->addBlurEffect(2.5, false);
$imageTransform->addAlphaModulateFixedEffect(80);
$presentation->save("image-transform-chain.pptx", SaveFormat::Pptx);
} finally {
$presentation->dispose();
}
$reopenedPresentation = new Presentation("image-transform-chain.pptx");
try {
$reopenedShape = $reopenedPresentation->getSlides()->get_Item(0)->getShapes()->get_Item(0);
if (java_instanceof($reopenedShape, new JavaClass("com.aspose.slides.PictureFrame"))) {
$reopenedTransform = $reopenedShape->getPictureFormat()->getPicture()->getImageTransform();
$orderIsPreserved = java_values($reopenedTransform->size()) === 4 &&
java_instanceof($reopenedTransform->get_Item(0), new JavaClass("com.aspose.slides.GrayScale")) &&
java_instanceof($reopenedTransform->get_Item(1), new JavaClass("com.aspose.slides.Tint")) &&
java_instanceof($reopenedTransform->get_Item(2), new JavaClass("com.aspose.slides.Blur")) &&
java_instanceof($reopenedTransform->get_Item(3), new JavaClass("com.aspose.slides.AlphaModulateFixed"));
echo $orderIsPreserved ? "The effect chain was preserved." : "The effect chain changed during the round trip.";
$renderedSlide = $reopenedPresentation->getSlides()->get_Item(0)->getImage();
try {
$renderedSlide->save("reopened-effect-chain.png", ImageFormat::Png);
} finally {
if (!java_is_null($renderedSlide)) {
$renderedSlide->dispose();
}
}
} else {
echo "The reopened shape is not a picture frame.";
}
} finally {
$reopenedPresentation->dispose();
}
The collection does not impose a compatibility matrix that restricts color, alpha, and blur operations to separate chains. They can be combined, but combinations are not always useful. A fixed color replacement removes RGB variation produced by earlier color effects; grayscale after duotone removes the two selected colors; and alpha ceiling, floor, replacement, or bi-level operations can discard alpha detail created earlier. Build the chain according to the desired pixel-processing sequence rather than treating its items as unordered formatting flags.
Inspect Editable and Effective Values
An editable operation is the object stored in Picture::getImageTransform. Depending on the effect, it may expose writable members directly. For example, Blur exposes writable radius and grow values, AlphaModulateFixed exposes a writable amount, and AlphaBiLevel exposes a writable threshold. Color effects such as Duotone expose mutable ColorFormat objects.
Some operations, including Luminance, HSL, Tint, and AlphaReplace, do not expose their creation scalars as writable properties. To change those settings, remove the operation and add a replacement at the required position.
Effective data returned by getEffective() is calculated and read-only. It is useful for resolving theme-dependent colors and reading the normalized values that the renderer uses, but it is not another editing surface. The following example enumerates the chain and inspects effective values where the corresponding API provides them:
use aspose\slides\Presentation;
$presentation = new Presentation("image-transform-chain.pptx");
try {
$slide = $presentation->getSlides()->get_Item(0);
$pictureFrame = null;
$shapeCount = java_values($slide->getShapes()->size());
for ($index = 0; $index < $shapeCount; $index++) {
$shape = $slide->getShapes()->get_Item($index);
if (java_instanceof($shape, new JavaClass("com.aspose.slides.PictureFrame"))) {
$pictureFrame = $shape;
break;
}
}
if ($pictureFrame !== null) {
$imageTransform = $pictureFrame->getPictureFormat()->getPicture()->getImageTransform();
$effectCount = java_values($imageTransform->size());
for ($index = 0; $index < $effectCount; $index++) {
$operation = $imageTransform->get_Item($index);
echo $index . ": " . java_values($operation->getClass()->getSimpleName()) . PHP_EOL;
if (java_instanceof($operation, new JavaClass("com.aspose.slides.Luminance"))) {
$data = $operation->getEffective();
echo " Brightness: " . java_values($data->getBrightness()) . PHP_EOL;
echo " Contrast: " . java_values($data->getContrast()) . PHP_EOL;
} elseif (java_instanceof($operation, new JavaClass("com.aspose.slides.Duotone"))) {
$data = $operation->getEffective();
echo " Dark color: " . java_values($data->getColor1()->toString()) . PHP_EOL;
echo " Light color: " . java_values($data->getColor2()->toString()) . PHP_EOL;
} elseif (java_instanceof($operation, new JavaClass("com.aspose.slides.ColorReplace"))) {
$data = $operation->getEffective();
echo " Replacement color: " . java_values($data->getColor()->toString()) . PHP_EOL;
} elseif (java_instanceof($operation, new JavaClass("com.aspose.slides.HSL"))) {
$data = $operation->getEffective();
echo " HSL: " . java_values($data->getHue()) . ", " . java_values($data->getSaturation()) . ", " . java_values($data->getLuminance()) . PHP_EOL;
} elseif (java_instanceof($operation, new JavaClass("com.aspose.slides.Tint"))) {
$data = $operation->getEffective();
echo " Tint: " . java_values($data->getHue()) . ", " . java_values($data->getAmount()) . PHP_EOL;
} elseif (java_instanceof($operation, new JavaClass("com.aspose.slides.Blur"))) {
$data = $operation->getEffective();
echo " Blur radius: " . java_values($data->getRadius()) . " pt" . PHP_EOL;
} elseif (java_instanceof($operation, new JavaClass("com.aspose.slides.AlphaModulateFixed"))) {
$data = $operation->getEffective();
echo " Alpha amount: " . java_values($data->getAmount()) . "%" . PHP_EOL;
} elseif (java_instanceof($operation, new JavaClass("com.aspose.slides.AlphaReplace"))) {
$data = $operation->getEffective();
echo " Replacement alpha: " . java_values($data->getAlpha()) . "%" . PHP_EOL;
} elseif (java_instanceof($operation, new JavaClass("com.aspose.slides.AlphaBiLevel"))) {
$data = $operation->getEffective();
echo " Alpha threshold: " . java_values($data->getThreshold()) . "%" . PHP_EOL;
}
}
}
} finally {
$presentation->dispose();
}
Parameter-free effects such as grayscale, alpha ceiling, and alpha inverse still have an effective-data object, but there are no scalar settings to print. Their presence and position in the collection are the important information.
Remove or Clear Image Transforms
Use ImageTransformOperationCollection::removeAt to remove one operation by index. Because indexes shift after removal, search for the target first and remove it after enumeration. Use ImageTransformOperationCollection::clear to remove the entire chain.
use aspose\slides\Presentation;
use aspose\slides\SaveFormat;
$presentation = new Presentation("image-transform-chain.pptx");
try {
$slide = $presentation->getSlides()->get_Item(0);
$pictureFrame = null;
$shapeCount = java_values($slide->getShapes()->size());
for ($index = 0; $index < $shapeCount; $index++) {
$shape = $slide->getShapes()->get_Item($index);
if (java_instanceof($shape, new JavaClass("com.aspose.slides.PictureFrame"))) {
$pictureFrame = $shape;
break;
}
}
if ($pictureFrame !== null) {
$imageTransform = $pictureFrame->getPictureFormat()->getPicture()->getImageTransform();
$effectCount = java_values($imageTransform->size());
$blurIndex = -1;
for ($index = 0; $index < $effectCount; $index++) {
if (java_instanceof($imageTransform->get_Item($index), new JavaClass("com.aspose.slides.Blur"))) {
$blurIndex = $index;
break;
}
}
if ($blurIndex >= 0) {
$imageTransform->removeAt($blurIndex);
echo "The blur operation was removed." . PHP_EOL;
}
$imageTransform->clear();
echo "Remaining operations: " . java_values($imageTransform->size()) . PHP_EOL;
$presentation->save("image-transforms-cleared.pptx", SaveFormat::Pptx);
}
} finally {
$presentation->dispose();
}
Removing or clearing transforms changes only the picture formatting. It does not delete, recompress, or otherwise alter the reused PPImage resource.
Consider Presentation Formats and Export Targets
Image transforms originate in DrawingML, so PPTX is the preferred editable format for effect chains. Even with PPTX, not every operation has identical portability:
- Standard DrawingML operations such as luminance, grayscale, duotone, tint, HSL, blur, and common alpha operations have the best chance of surviving a PPTX round trip. Always reopen the generated file and inspect the collection when preservation is a requirement.
- The binary PPT format predates the full DrawingML effect model. Saving to PPT can omit unsupported operations, reduce a chain to a supported subset, or approximate the appearance. Do not use PPT as the verification format for a complex editable chain.
- Rendering to PNG, JPEG, TIFF, PDF, SVG, HTML, or other visual output applies the supported chain to the rendered appearance. Those outputs do not contain an editable
ImageTransformOperationCollection; raster formats flatten the result into pixels, and document or vector exports store their own rendering representation. - Effects do not make a linked image self-contained. Rendering a linked picture still depends on the linked resource being available when the presentation is loaded.
Different presentation consumers may render edge cases differently, especially when several alpha or color-quantizing operations are combined. For critical output, test both the editable round trip and the final export format with the same Aspose.Slides version used in production.
FAQ
Do image transform effects modify the embedded image data?
No. The operations belong to the Picture used by the picture fill. The underlying PPImage bytes remain unchanged.
Will two picture frames that reuse the same image share their effects?
No. Reusing a PPImage avoids duplicate image data, but each picture frame normally has a separate Picture and image transform collection.
Can color, blur, and alpha effects be combined?
Yes. The collection accepts them in one ordered chain. Consider what each operation does to the output of the previous one because replacement and threshold operations may discard earlier color or alpha detail.
Why are effective values read-only?
Effective data represents calculated values used for rendering, including resolved colors. Edit the operation stored in the transform collection where writable members exist; otherwise remove it and add a replacement with new creation parameters.
Which format should I use to preserve a transform chain?
Use PPTX and verify the file by reopening it. Legacy PPT cannot represent the full DrawingML effect model, and rendered export formats preserve appearance rather than editable transform operations.