Completed
Push — vendor/getid3 ( 69b815...49c253 )
by Pauli
04:26 queued 01:37
created

getid3_gif::Analyze()   F

Complexity

Conditions 15
Paths 361

Size

Total Lines 169

Duplication

Lines 6
Ratio 3.55 %

Importance

Changes 0
Metric Value
cc 15
nc 361
nop 0
dl 6
loc 169
rs 2.4566
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/////////////////////////////////////////////////////////////////
4
/// getID3() by James Heinrich <[email protected]>               //
5
//  available at https://github.com/JamesHeinrich/getID3       //
6
//            or https://www.getid3.org                        //
7
//            or http://getid3.sourceforge.net                 //
8
//  see readme.txt for more details                            //
9
/////////////////////////////////////////////////////////////////
10
//                                                             //
11
// module.graphic.gif.php                                      //
12
// module for analyzing GIF Image files                        //
13
// dependencies: NONE                                          //
14
//                                                            ///
15
/////////////////////////////////////////////////////////////////
16
17
/**
18
 * @link https://www.w3.org/Graphics/GIF/spec-gif89a.txt
19
 * @link http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
20
 */
21
class getid3_gif extends getid3_handler
22
{
23
	/**
24
	 * @return bool
25
	 */
26
	public function Analyze() {
27
		$info = &$this->getid3->info;
28
29
		$info['fileformat']                  = 'gif';
30
		$info['video']['dataformat']         = 'gif';
31
		$info['video']['lossless']           = true;
32
		$info['video']['pixel_aspect_ratio'] = (float) 1;
33
34
		$this->fseek($info['avdataoffset']);
35
		$GIFheader = $this->fread(13);
36
		$offset = 0;
37
38
		$info['gif']['header']['raw']['identifier']            =                              substr($GIFheader, $offset, 3);
39
		$offset += 3;
40
41
		$magic = 'GIF';
42 View Code Duplication
		if ($info['gif']['header']['raw']['identifier'] != $magic) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
43
			$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($info['gif']['header']['raw']['identifier']).'"');
44
			unset($info['fileformat']);
45
			unset($info['gif']);
46
			return false;
47
		}
48
49
		//if (!$this->getid3->option_extra_info) {
50
		//	$this->warning('GIF Extensions and Global Color Table not returned due to !getid3->option_extra_info');
51
		//}
52
53
		$info['gif']['header']['raw']['version']               =                              substr($GIFheader, $offset, 3);
54
		$offset += 3;
55
		$info['gif']['header']['raw']['width']                 = getid3_lib::LittleEndian2Int(substr($GIFheader, $offset, 2));
56
		$offset += 2;
57
		$info['gif']['header']['raw']['height']                = getid3_lib::LittleEndian2Int(substr($GIFheader, $offset, 2));
58
		$offset += 2;
59
		$info['gif']['header']['raw']['flags']                 = getid3_lib::LittleEndian2Int(substr($GIFheader, $offset, 1));
60
		$offset += 1;
61
		$info['gif']['header']['raw']['bg_color_index']        = getid3_lib::LittleEndian2Int(substr($GIFheader, $offset, 1));
62
		$offset += 1;
63
		$info['gif']['header']['raw']['aspect_ratio']          = getid3_lib::LittleEndian2Int(substr($GIFheader, $offset, 1));
64
		$offset += 1;
65
66
		$info['video']['resolution_x']                         = $info['gif']['header']['raw']['width'];
67
		$info['video']['resolution_y']                         = $info['gif']['header']['raw']['height'];
68
		$info['gif']['version']                                = $info['gif']['header']['raw']['version'];
69
		$info['gif']['header']['flags']['global_color_table']  = (bool) ($info['gif']['header']['raw']['flags'] & 0x80);
70
		if ($info['gif']['header']['raw']['flags'] & 0x80) {
71
			// Number of bits per primary color available to the original image, minus 1
72
			$info['gif']['header']['bits_per_pixel']  = 3 * ((($info['gif']['header']['raw']['flags'] & 0x70) >> 4) + 1);
73
		} else {
74
			$info['gif']['header']['bits_per_pixel']  = 0;
75
		}
76
		$info['gif']['header']['flags']['global_color_sorted'] = (bool) ($info['gif']['header']['raw']['flags'] & 0x40);
77
		if ($info['gif']['header']['flags']['global_color_table']) {
78
			// the number of bytes contained in the Global Color Table. To determine that
79
			// actual size of the color table, raise 2 to [the value of the field + 1]
80
			$info['gif']['header']['global_color_size'] = pow(2, ($info['gif']['header']['raw']['flags'] & 0x07) + 1);
81
			$info['video']['bits_per_sample']           = ($info['gif']['header']['raw']['flags'] & 0x07) + 1;
82
		} else {
83
			$info['gif']['header']['global_color_size'] = 0;
84
		}
85
		if ($info['gif']['header']['raw']['aspect_ratio'] != 0) {
86
			// Aspect Ratio = (Pixel Aspect Ratio + 15) / 64
87
			$info['gif']['header']['aspect_ratio'] = ($info['gif']['header']['raw']['aspect_ratio'] + 15) / 64;
88
		}
89
90
		if ($info['gif']['header']['flags']['global_color_table']) {
91
			$GIFcolorTable = $this->fread(3 * $info['gif']['header']['global_color_size']);
92
			if ($this->getid3->option_extra_info) {
93
				$offset = 0;
94
				for ($i = 0; $i < $info['gif']['header']['global_color_size']; $i++) {
95
					$red   = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
96
					$green = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
97
					$blue  = getid3_lib::LittleEndian2Int(substr($GIFcolorTable, $offset++, 1));
98
					$info['gif']['global_color_table'][$i] = (($red << 16) | ($green << 8) | ($blue));
99
					$info['gif']['global_color_table_rgb'][$i] = sprintf('%02X%02X%02X', $red, $green, $blue);
100
				}
101
			}
102
		}
103
104
		// Image Descriptor
105
		$info['gif']['animation']['animated'] = false;
106
		while (!feof($this->getid3->fp)) {
107
			$NextBlockTest = $this->fread(1);
108
			switch ($NextBlockTest) {
109
110
/*
111
				case ',': // ',' - Image separator character
112
					$ImageDescriptorData = $NextBlockTest.$this->fread(9);
113
					$ImageDescriptor = array();
114
					$ImageDescriptor['image_left']   = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 1, 2));
115
					$ImageDescriptor['image_top']    = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 3, 2));
116
					$ImageDescriptor['image_width']  = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 5, 2));
117
					$ImageDescriptor['image_height'] = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 7, 2));
118
					$ImageDescriptor['flags_raw']    = getid3_lib::LittleEndian2Int(substr($ImageDescriptorData, 9, 1));
119
					$ImageDescriptor['flags']['use_local_color_map'] = (bool) ($ImageDescriptor['flags_raw'] & 0x80);
120
					$ImageDescriptor['flags']['image_interlaced']    = (bool) ($ImageDescriptor['flags_raw'] & 0x40);
121
					$info['gif']['image_descriptor'][] = $ImageDescriptor;
122
123
					if ($ImageDescriptor['flags']['use_local_color_map']) {
124
125
						$this->warning('This version of getID3() cannot parse local color maps for GIFs');
126
						return true;
127
128
					}
129
					$RasterData = array();
130
					$RasterData['code_size']        = getid3_lib::LittleEndian2Int($this->fread(1));
131
					$RasterData['block_byte_count'] = getid3_lib::LittleEndian2Int($this->fread(1));
132
					$info['gif']['raster_data'][count($info['gif']['image_descriptor']) - 1] = $RasterData;
133
134
					$CurrentCodeSize = $RasterData['code_size'] + 1;
135
					for ($i = 0; $i < pow(2, $RasterData['code_size']); $i++) {
136
						$DefaultDataLookupTable[$i] = chr($i);
137
					}
138
					$DefaultDataLookupTable[pow(2, $RasterData['code_size']) + 0] = ''; // Clear Code
139
					$DefaultDataLookupTable[pow(2, $RasterData['code_size']) + 1] = ''; // End Of Image Code
140
141
					$NextValue = $this->GetLSBits($CurrentCodeSize);
142
					echo 'Clear Code: '.$NextValue.'<BR>';
143
144
					$NextValue = $this->GetLSBits($CurrentCodeSize);
145
					echo 'First Color: '.$NextValue.'<BR>';
146
147
					$Prefix = $NextValue;
148
					$i = 0;
149
					while ($i++ < 20) {
150
						$NextValue = $this->GetLSBits($CurrentCodeSize);
151
						echo $NextValue.'<br>';
152
					}
153
					echo 'escaping<br>';
154
					return true;
155
					break;
156
*/
157
158
				case '!':
159
					// GIF Extension Block
160
					$ExtensionBlockData = $NextBlockTest.$this->fread(2);
161
					$ExtensionBlock = array();
162
					$ExtensionBlock['function_code']  = getid3_lib::LittleEndian2Int(substr($ExtensionBlockData, 1, 1));
163
					$ExtensionBlock['byte_length']    = getid3_lib::LittleEndian2Int(substr($ExtensionBlockData, 2, 1));
164
					$ExtensionBlock['data']           = (($ExtensionBlock['byte_length'] > 0) ? $this->fread($ExtensionBlock['byte_length']) : null);
0 ignored issues
show
Bug introduced by
It seems like $ExtensionBlock['byte_length'] can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
165
166
					if (substr($ExtensionBlock['data'], 0, 11) == 'NETSCAPE2.0') { // Netscape Application Block (NAB)
167
						$ExtensionBlock['data'] .= $this->fread(4);
168
						if (substr($ExtensionBlock['data'], 11, 2) == "\x03\x01") {
169
							$info['gif']['animation']['animated']   = true;
170
							$info['gif']['animation']['loop_count'] = getid3_lib::LittleEndian2Int(substr($ExtensionBlock['data'], 13, 2));
171
						} else {
172
							$this->warning('Expecting 03 01 at offset '.($this->ftell() - 4).', found "'.getid3_lib::PrintHexBytes(substr($ExtensionBlock['data'], 11, 2)).'"');
173
						}
174
					}
175
176
					if ($this->getid3->option_extra_info) {
177
						$info['gif']['extension_blocks'][] = $ExtensionBlock;
178
					}
179
					break;
180
181
				case ';':
182
					$info['gif']['terminator_offset'] = $this->ftell() - 1;
183
					// GIF Terminator
184
					break;
185
186
				default:
187
					break;
188
189
190
			}
191
		}
192
193
		return true;
194
	}
195
196
	/**
197
	 * @param int $bits
198
	 *
199
	 * @return float|int
200
	 */
201
	public function GetLSBits($bits) {
202
		static $bitbuffer = '';
203
		while (strlen($bitbuffer) < $bits) {
204
			$bitbuffer = str_pad(decbin(ord($this->fread(1))), 8, '0', STR_PAD_LEFT).$bitbuffer;
205
		}
206
		$value = bindec(substr($bitbuffer, 0 - $bits));
207
		$bitbuffer = substr($bitbuffer, 0, 0 - $bits);
208
209
		return $value;
210
	}
211
212
}
213