1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
<?php
/**
* @group Media
* @covers \PNGMetadataExtractor
*/
class PNGMetadataExtractorTest extends MediaWikiIntegrationTestCase {
private const FILE_PATH = __DIR__ . '/../../data/media/';
/**
* Tests zTXt tag (compressed textual metadata)
* @requires extension zlib
*/
public function testPngNativetZtxt() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'Png-native-test.png' );
$expected = "foo bar baz foo foo foo foof foo foo foo foo";
$this->assertArrayHasKey( 'text', $meta );
$meta = $meta['text'];
$this->assertArrayHasKey( 'Make', $meta );
$this->assertArrayHasKey( 'x-default', $meta['Make'] );
$this->assertEquals( $expected, $meta['Make']['x-default'] );
}
/**
* Test tEXt tag (Uncompressed textual metadata)
*/
public function testPngNativeText() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'Png-native-test.png' );
$expected = "Some long image desc";
$this->assertArrayHasKey( 'text', $meta );
$meta = $meta['text'];
$this->assertArrayHasKey( 'ImageDescription', $meta );
$this->assertArrayHasKey( 'x-default', $meta['ImageDescription'] );
$this->assertArrayHasKey( '_type', $meta['ImageDescription'] );
$this->assertEquals( $expected, $meta['ImageDescription']['x-default'] );
}
/**
* tEXt tags must be encoded iso-8859-1 (vs iTXt which are utf-8)
* Make sure non-ascii characters get converted properly
*/
public function testPngNativeTextNonAscii() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'Png-native-test.png' );
// Note the Copyright symbol here is a utf-8 one
// (aka \xC2\xA9) where in the file its iso-8859-1
// encoded as just \xA9.
$expected = "© 2010 Bawolff";
$this->assertArrayHasKey( 'text', $meta );
$meta = $meta['text'];
$this->assertArrayHasKey( 'Copyright', $meta );
$this->assertArrayHasKey( 'x-default', $meta['Copyright'] );
$this->assertEquals( $expected, $meta['Copyright']['x-default'] );
}
/**
* Given a normal static PNG, check the animation metadata returned.
*/
public function testStaticPngAnimationMetadata() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'Png-native-test.png' );
$this->assertSame( 0, $meta['frameCount'] );
$this->assertSame( 1, $meta['loopCount'] );
$this->assertSame( 0.0, $meta['duration'] );
}
/**
* Given an animated APNG image file
* check it gets animated metadata right.
*/
public function testApngAnimationMetadata() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'Animated_PNG_example_bouncing_beach_ball.png' );
$this->assertEquals( 20, $meta['frameCount'] );
// Note loop count of 0 = infinity
$this->assertSame( 0, $meta['loopCount'] );
$this->assertEqualsWithDelta( 1.5, $meta['duration'], 0.00001, '' );
}
public function testPngBitDepth8() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'Png-native-test.png' );
$this->assertEquals( 8, $meta['bitDepth'] );
}
public function testPngBitDepth1() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'1bit-png.png' );
$this->assertSame( 1, $meta['bitDepth'] );
}
public function testPngIndexColour() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'Png-native-test.png' );
$this->assertEquals( 'index-coloured', $meta['colorType'] );
}
public function testPngRgbColour() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'rgb-png.png' );
$this->assertEquals( 'truecolour-alpha', $meta['colorType'] );
}
public function testPngRgbNoAlphaColour() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'rgb-na-png.png' );
$this->assertEquals( 'truecolour', $meta['colorType'] );
}
public function testPngGreyscaleColour() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'greyscale-png.png' );
$this->assertEquals( 'greyscale-alpha', $meta['colorType'] );
}
public function testPngGreyscaleNoAlphaColour() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'greyscale-na-png.png' );
$this->assertEquals( 'greyscale', $meta['colorType'] );
}
/**
* T286273 -- tEXt chunk replaced by null bytes
*/
public function testPngInvalidChunk() {
$meta = PNGMetadataExtractor::getMetadata( self::FILE_PATH .
'tEXt-invalid-masked.png' );
$this->assertEquals( 10, $meta['width'] );
$this->assertEquals( 10, $meta['height'] );
}
/**
* T286273 -- oversize chunk
*/
public function testPngOversizeChunk() {
// Write a temporary file consisting of a normal PNG plus an extra tEXt chunk.
// Try to hold the chunk in memory only once.
$path = $this->getNewTempFile();
copy( self::FILE_PATH . '1bit-png.png', $path );
$chunkTypeAndData = "tEXtkey\0value" . str_repeat( '.', 10000000 );
$crc = crc32( $chunkTypeAndData );
$chunkLength = strlen( $chunkTypeAndData ) - 4;
$file = fopen( $path, 'r+' );
fseek( $file, -12, SEEK_END );
$iend = fread( $file, 12 );
fseek( $file, -12, SEEK_END );
fwrite( $file, pack( 'N', $chunkLength ) );
fwrite( $file, $chunkTypeAndData );
fwrite( $file, pack( 'N', $crc ) );
fwrite( $file, $iend );
fclose( $file );
// Extract the metadata
$meta = PNGMetadataExtractor::getMetadata( $path );
$this->assertEquals( 50, $meta['width'] );
$this->assertEquals( 50, $meta['height'] );
// Verify that the big chunk didn't end up in the metadata
$this->assertLessThan( 100000, strlen( serialize( $meta ) ) );
}
}
|