21use PHPUnit\Framework\Attributes\DataProvider;
28use PHPUnit\Framework\TestCase;
35 use MemoryStreamToTempFileStream;
39 protected const W =
'width';
40 protected const H =
'height';
46 protected function setUp(): void
49 $this->images =
new Images(
56 $img = __DIR__ .
'/img/robot.jpg';
57 $this->assertFileExists($img);
58 $getimagesize = getimagesize($img);
59 $original_width = $getimagesize[0];
60 $original_height = $getimagesize[1];
61 $this->assertSame(600, $original_width);
62 $this->assertSame(800, $original_height);
67 $thumbnail_converter = $this->images->thumbnail(
71 $this->assertTrue($thumbnail_converter->isOK());
72 $this->assertNotInstanceOf(\Throwable::class, $thumbnail_converter->getThrowableIfAny());
73 $converted_stream = $thumbnail_converter->getStream();
75 $getimagesizefromstring = getimagesizefromstring((
string) $converted_stream);
77 $this->assertSame(75, $getimagesizefromstring[0]);
78 $this->assertSame(100, $getimagesizefromstring[1]);
83 $img = __DIR__ .
'/img/robot.jpg';
84 $this->assertFileExists($img);
85 $getimagesize = getimagesize($img);
86 $original_width = $getimagesize[0];
87 $original_height = $getimagesize[1];
88 $this->assertSame(600, $original_width);
89 $this->assertSame(800, $original_height);
94 $thumbnail_converter = $this->images->croppedSquare(
98 $this->assertTrue($thumbnail_converter->isOK());
99 $this->assertNotInstanceOf(\Throwable::class, $thumbnail_converter->getThrowableIfAny());
103 $this->assertEquals(200, $getimagesizefromstring[self::W]);
104 $this->assertEquals(200, $getimagesizefromstring[self::H]);
115 #[DataProvider('getImageSizesByWidth')]
124 $this->assertEquals($width, $dimensions[self::W]);
125 $this->assertEquals($height, $dimensions[self::H]);
128 $resized = $this->images->resizeByWidth($stream, self::BY_WIDTH_FINAL);
129 $this->assertTrue($resized->isOK());
132 $this->assertEquals($final_width, $new_dimensions[self::W]);
133 $this->assertEquals($final_height, $new_dimensions[self::H]);
137 round($width > $height),
138 round($final_width > $final_height)
141 round($width / $height),
142 round($new_dimensions[self::W] / $new_dimensions[self::H])
150 $new_dimensions[self::W] > $new_dimensions[self::H]
156 yield [400, 300, self::BY_HEIGHT_FINAL, 1008];
157 yield [300, 400, self::BY_HEIGHT_FINAL, 567];
158 yield [200, 200, self::BY_HEIGHT_FINAL, 756];
159 yield [248, 845, self::BY_HEIGHT_FINAL, 221];
163 #[DataProvider('getImageSizesByHeight')]
170 $stream = $this->createTestImageStream($width, $height);
171 $dimensions = $this->getImageSizeFromStream($stream);
172 $this->assertEquals($width, $dimensions[self::W]);
173 $this->assertEquals($height, $dimensions[self::H]);
176 $resized = $this->images->resizeByHeight($stream, self::BY_HEIGHT_FINAL);
177 $this->assertTrue($resized->isOK());
178 $new_dimensions = $this->getImageSizeFromStream($resized->getStream());
180 $this->assertEquals($final_width, $new_dimensions[self::W]);
181 $this->assertEquals($final_height, $new_dimensions[self::H]);
185 round($width > $height),
186 round($final_width > $final_height)
189 round($width / $height),
190 round($new_dimensions[self::W] / $new_dimensions[self::H])
198 $new_dimensions[self::W] > $new_dimensions[self::H]
204 yield [1024, 768, 300, 100,
true];
205 yield [1024, 768, 300, 100,
false];
206 yield [1024, 768, 100, 300,
true];
207 yield [1024, 768, 100, 300,
false];
208 yield [400, 300, 500, 400,
true];
209 yield [400, 300, 500, 400,
false];
212 #[DataProvider('getImageSizesByFixed')]
220 $stream = $this->createTestImageStream($width, $height);
221 $dimensions = $this->getImageSizeFromStream($stream);
222 $this->assertEquals($width, $dimensions[self::W]);
223 $this->assertEquals($height, $dimensions[self::H]);
225 $by_fixed = $this->images->resizeToFixedSize($stream, $final_width, $final_height, $crop);
226 $this->assertTrue($by_fixed->isOK());
227 $new_dimensions = $this->getImageSizeFromStream($by_fixed->getStream());
229 $this->assertEquals($final_width, $new_dimensions[self::W]);
230 $this->assertEquals($final_height, $new_dimensions[self::H]);
236 yield [$options, self::IMAGE_JPEG, 75];
237 yield [$options->withPngOutput()->withQuality(22), self::IMAGE_PNG, 0];
238 yield [$options->withJpgOutput()->withQuality(100), self::IMAGE_JPEG, 100];
239 yield [$options->withFormat(
'png')->withQuality(50), self::IMAGE_PNG, 0];
240 yield [$options->withFormat(
'jpg')->withQuality(87), self::IMAGE_JPEG, 87];
241 yield [$options->withQuality(5)->withJpgOutput(), self::IMAGE_JPEG, 5];
242 yield [$options->withQuality(10)->withJpgOutput(), self::IMAGE_JPEG, 10];
243 yield [$options->withQuality(35)->withJpgOutput(), self::IMAGE_JPEG, 35];
244 yield [$options->withQuality(0)->withWebPOutput(), self::IMAGE_WEBP, 0];
245 yield [$options->withQuality(100)->withWebPOutput(), self::IMAGE_WEBP, 100];
249 #[DataProvider('getImageOptions')]
252 string $expected_mime_type,
253 int $expected_quality
255 $resized = $this->images->resizeToFixedSize(
256 $this->createTestImageStream(10, 10),
263 $this->assertSame($expected_mime_type, $this->getImageTypeFromStream($resized->getStream()));
264 $this->assertSame($expected_quality, $this->getImageQualityFromStream($resized->getStream()));
272 $this->assertSame(
'jpg', $options->
getFormat());
273 $this->assertSame(75, $options->
getQuality());
276 $this->assertSame(
'png', $png->getFormat());
277 $this->assertSame(
'jpg', $options->
getFormat());
279 $this->assertSame(
'png', $png_explicit->getFormat());
282 $this->assertSame(
'jpg', $jpg->getFormat());
284 $this->assertSame(
'jpg', $jpg_explicit->getFormat());
286 $this->assertSame(
'jpg', $jpeg->getFormat());
290 $this->assertSame(5, $low->getQuality());
291 $this->assertSame(75, $options->
getQuality());
301 #[DataProvider('getWrongFormats')]
305 $this->expectException(\InvalidArgumentException::class);
316 #[DataProvider('getWrongQualites')]
320 $this->expectException(\InvalidArgumentException::class);
326 $jpg = $this->createTestImageStream(10, 10);
327 $png = $this->images->convertToFormat(
332 $this->assertSame(self::IMAGE_PNG, $this->getImageTypeFromStream($png->getStream()));
333 $size = $this->getImageSizeFromStream($png->getStream());
334 $this->assertEquals(10, $size[self::W]);
335 $this->assertEquals(10, $size[self::H]);
338 $jpg = $this->createTestImageStream(10, 10);
339 $png = $this->images->convertToFormat(
346 $this->assertSame(self::IMAGE_PNG, $this->getImageTypeFromStream($png->getStream()));
347 $size = $this->getImageSizeFromStream($png->getStream());
348 $this->assertEquals(20, $size[self::W]);
349 $this->assertEquals(20, $size[self::H]);
354 $false_stream = Streams::ofString(
'false');
365 $this->assertFalse($resized->isOK());
366 $this->assertInstanceOf(\Throwable::class, $resized->getThrowableIfAny());
385 private function colorDiff(
string $hex_color_one,
string $hex_color_two):
int
387 preg_match(
'/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i', $hex_color_one, $rgb_one);
388 preg_match(
'/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i', $hex_color_two, $rgb_two);
390 return abs(hexdec($rgb_one[1]) - hexdec($rgb_two[1]))
391 + abs(hexdec($rgb_one[2]) - hexdec($rgb_two[2]))
392 + abs(hexdec($rgb_one[3]) - hexdec($rgb_two[3]));
395 #[DataProvider('getColors')]
398 $transparent_png = __DIR__ .
'/img/transparent.png';
399 $this->assertFileExists($transparent_png);
400 $png = Streams::ofResource(fopen($transparent_png,
'rb'));
403 ->withThrowOnError(
true)
404 ->withFixedDimensions(100, 100);
406 if ($color !==
null) {
407 $converter_options = $converter_options->withBackgroundColor($color);
416 $converter =
new ImageConverter($converter_options, $output_options, $png);
417 $this->assertTrue($converter->isOK());
418 $converted_stream = $converter->getStream();
419 $gd_image = imagecreatefromstring((
string) $converted_stream);
420 $colors = imagecolorsforindex($gd_image, imagecolorat($gd_image, 1, 1));
422 $color_in_converted_picture = sprintf(
"#%02x%02x%02x", $colors[
'red'], $colors[
'green'], $colors[
'blue']);
423 $color_diff = $this->colorDiff($color, $color_in_converted_picture);
425 $this->assertLessThan(3, $color_diff);
430 $img = $this->createTestImageStream(10, 10);
432 $output_path = __DIR__ .
'/img/output.jpg';
434 ->withThrowOnError(
true)
435 ->withMakeTemporaryFiles(
false)
436 ->withFixedDimensions(100, 100)
437 ->withOutputPath($output_path);
443 $converter =
new ImageConverter($converter_options, $output_options, $img);
444 $this->assertTrue($converter->isOK());
446 $this->assertFileExists($output_path);
447 $stream = $converter->getStream();
448 $this->assertEquals($output_path, $stream->getMetadata(
'uri'));
450 unlink($output_path);
455 $file =
'https://upload.wikimedia.org/wikipedia/commons/5/5e/Jan_Vermeer_-_The_Art_of_Painting_-_Google_Art_Project.jpg';
457 curl_setopt($curl, CURLOPT_URL, $file);
458 curl_setopt($curl, CURLOPT_RETURNTRANSFER,
true);
459 curl_setopt($curl, CURLOPT_USERAGENT,
'PHPUnit/1.0');
460 $string = curl_exec($curl);
463 $img = Streams::ofString($string);
464 $this->assertInstanceOf(FileStream::class, $img);
469 ->withKeepAspectRatio(
true)
471 ->withThrowOnError(
true);
475 ->withFormat(ImageOutputOptions::FORMAT_PNG);
477 $converter =
new ImageConverter($converter_options, $output_options, $img);
478 $this->assertTrue($converter->isOK());
484 if (!class_exists(
'Imagick')) {
485 $this->markTestSkipped(
'Imagick not installed');
491 $getimagesizefromstring = getimagesizefromstring((
string) $stream);
493 self::W => (
int) round($getimagesizefromstring[0]),
494 self::H => (
int) round($getimagesizefromstring[1])
500 return finfo_buffer(finfo_open(FILEINFO_MIME_TYPE), $stream->read(255));
506 $img = new \Imagick();
507 $img->readImageBlob((
string) $stream);
509 return $img->getImageCompressionQuality();
514 $img = new \Imagick();
515 $img->newImage($width, $height,
new \ImagickPixel(
'black'));
516 $img->setImageFormat(
'jpg');
518 $stream = Streams::ofString($img->getImageBlob());
Stream factory which enables the user to create streams without the knowledge of the concrete class.
static ofResource($resource)
Wraps an already created resource with the stream abstraction.
withFormat(string $format)
@description set the desired output format.
withPngOutput()
@description set the output format to PNG
withJpgOutput()
@description set the output format to JPG
withQuality(int $image_quality)
@description set the image compression quality.
resizeToFixedSize(FileStream $stream, int $width, int $height, bool $crop_or_otherwise_squeeze=true, ?ImageOutputOptions $image_output_options=null)
@description Creates an image from the given stream, resized to width and height given.
testImageThumbnailActualImage()
static getWrongQualites()
static getImageSizesByHeight()
colorDiff(string $hex_color_one, string $hex_color_two)
testBackgroundColor(?string $color)
createTestImageStream(int $width, int $height)
testResizeToFitWidth(int $width, int $height, int $final_width, int $final_height)
getImageQualityFromStream(FileStream $stream)
getImageTypeFromStream(FileStream $stream)
testResizeToFitHeight(int $width, int $height, int $final_height, int $final_width)
testImageOutputOptionSanity()
testResizeByFixedSize(int $width, int $height, int $final_width, int $final_height, bool $crop)
testWrongQualities(int $quality)
static getImageSizesByFixed()
testImageSquareActualImage()
static getImageSizesByWidth()
getImageSizeFromStream(FileStream $stream)
testImageOutputOptions(ImageOutputOptions $options, string $expected_mime_type, int $expected_quality)
testWrongFormats(string $format)
The base interface for all filesystem streams.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...