providers
4 years ago
class-fast-image.php
8 years ago
class-folders-walker.php
7 years ago
class-folders.php
4 years ago
class-frontend.php
4 years ago
class-galleries.php
4 years ago
class-multilang.php
4 years ago
class-remote-library-api.php
4 years ago
class-remote-library.php
4 years ago
class-settings.php
4 years ago
class-tour.php
4 years ago
class-welcome.php
4 years ago
class-widgets.php
4 years ago
functions.php
4 years ago
class-fast-image.php
201 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Finds the dimensions or filetype of an image given its uri by fetching as little as needed |
| 4 | * |
| 5 | * Based on the FastImage class (https://github.com/tommoor/fastimage) |
| 6 | * |
| 7 | * @version 0.1 |
| 8 | */ |
| 9 | class Responsive_Lightbox_Fast_Image { |
| 10 | |
| 11 | private $strpos = 0; |
| 12 | private $str; |
| 13 | private $type; |
| 14 | private $handle; |
| 15 | |
| 16 | public function __construct( $uri = null ) { |
| 17 | if ( $uri ) |
| 18 | $this->load( $uri ); |
| 19 | } |
| 20 | |
| 21 | public function load( $uri ) { |
| 22 | if ( $this->handle ) |
| 23 | $this->close(); |
| 24 | |
| 25 | $this->handle = fopen( $uri, 'r' ); |
| 26 | } |
| 27 | |
| 28 | public function close() { |
| 29 | if ( $this->handle ) { |
| 30 | fclose( $this->handle ); |
| 31 | |
| 32 | $this->handle = null; |
| 33 | $this->type = null; |
| 34 | $this->str = null; |
| 35 | } |
| 36 | } |
| 37 | |
| 38 | public function get_size() { |
| 39 | $this->strpos = 0; |
| 40 | |
| 41 | if ( $this->get_type() ) |
| 42 | return array_values( $this->parse_size() ); |
| 43 | |
| 44 | return false; |
| 45 | } |
| 46 | |
| 47 | public function get_type() { |
| 48 | $this->strpos = 0; |
| 49 | |
| 50 | if ( ! $this->type ) { |
| 51 | switch ( $this->get_chars( 2 ) ) { |
| 52 | case "BM": |
| 53 | return $this->type = 'bmp'; |
| 54 | |
| 55 | case "GI": |
| 56 | return $this->type = 'gif'; |
| 57 | |
| 58 | case chr( 0xFF ) . chr( 0xd8 ): |
| 59 | return $this->type = 'jpeg'; |
| 60 | |
| 61 | case chr( 0x89 ) . 'P': |
| 62 | return $this->type = 'png'; |
| 63 | |
| 64 | default: |
| 65 | return false; |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | return $this->type; |
| 70 | } |
| 71 | |
| 72 | private function parse_size() { |
| 73 | $this->strpos = 0; |
| 74 | |
| 75 | switch ( $this->type ) { |
| 76 | case 'png': |
| 77 | return $this->parse_size_png(); |
| 78 | |
| 79 | case 'gif': |
| 80 | return $this->parse_size_gif(); |
| 81 | |
| 82 | case 'bmp': |
| 83 | return $this->parse_size_bmp(); |
| 84 | |
| 85 | case 'jpeg': |
| 86 | return $this->parse_size_jpeg(); |
| 87 | } |
| 88 | |
| 89 | return null; |
| 90 | } |
| 91 | |
| 92 | private function parse_size_png() { |
| 93 | $chars = $this->get_chars( 25 ); |
| 94 | |
| 95 | return unpack( "N*", substr( $chars, 16, 8 ) ); |
| 96 | } |
| 97 | |
| 98 | private function parse_size_gif() { |
| 99 | $chars = $this->get_chars( 11 ); |
| 100 | |
| 101 | return unpack( "S*", substr( $chars, 6, 4 ) ); |
| 102 | } |
| 103 | |
| 104 | private function parse_size_bmp() { |
| 105 | $chars = $this->get_chars( 29 ); |
| 106 | $chars = substr( $chars, 14, 14 ); |
| 107 | $type = unpack( 'C', $chars ); |
| 108 | |
| 109 | return ( reset( $type ) == 40 ) ? unpack( 'L*', substr( $chars, 4 ) ) : unpack( 'L*', substr( $chars, 4, 8 ) ); |
| 110 | } |
| 111 | |
| 112 | private function parse_size_jpeg() { |
| 113 | $state = null; |
| 114 | $i = 0; |
| 115 | |
| 116 | while ( true ) { |
| 117 | switch ( $state ) { |
| 118 | default: |
| 119 | $this->get_chars( 2 ); |
| 120 | $state = 'started'; |
| 121 | break; |
| 122 | |
| 123 | case 'started': |
| 124 | $b = $this->get_byte(); |
| 125 | if ( $b === false ) |
| 126 | return false; |
| 127 | |
| 128 | $state = $b == 0xFF ? 'sof' : 'started'; |
| 129 | break; |
| 130 | |
| 131 | case 'sof': |
| 132 | $b = $this->get_byte(); |
| 133 | if ( in_array( $b, range( 0xe0, 0xef ) ) ) |
| 134 | $state = 'skipframe'; |
| 135 | elseif ( in_array( $b, array_merge( range( 0xC0, 0xC3 ), range( 0xC5, 0xC7 ), range( 0xC9, 0xCB ), range( 0xCD, 0xCF ) ) ) ) |
| 136 | $state = 'readsize'; |
| 137 | elseif ( $b == 0xFF ) |
| 138 | $state = 'sof'; |
| 139 | else |
| 140 | $state = 'skipframe'; |
| 141 | break; |
| 142 | |
| 143 | case 'skipframe': |
| 144 | $skip = $this->read_int( $this->get_chars( 2 ) ) - 2; |
| 145 | $state = 'doskip'; |
| 146 | break; |
| 147 | |
| 148 | case 'doskip': |
| 149 | $this->get_chars( $skip ); |
| 150 | $state = 'started'; |
| 151 | break; |
| 152 | |
| 153 | case 'readsize': |
| 154 | $c = $this->get_chars( 7 ); |
| 155 | |
| 156 | return array( $this->read_int( substr( $c, 5, 2 ) ), $this->read_int( substr( $c, 3, 2 ) ) ); |
| 157 | } |
| 158 | } |
| 159 | } |
| 160 | |
| 161 | private function get_chars( $n ) { |
| 162 | $response = null; |
| 163 | |
| 164 | // do we need more data? |
| 165 | if ( $this->strpos + $n - 1 >= strlen( $this->str ) ) { |
| 166 | $end = ( $this->strpos + $n ); |
| 167 | |
| 168 | while ( strlen( $this->str ) < $end && $response !== false ) { |
| 169 | // read more from the file handle |
| 170 | $need = $end - ftell( $this->handle ); |
| 171 | |
| 172 | if ( $response = fread( $this->handle, $need ) ) |
| 173 | $this->str .= $response; |
| 174 | else |
| 175 | return false; |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | $result = substr( $this->str, $this->strpos, $n ); |
| 180 | $this->strpos += $n; |
| 181 | |
| 182 | return $result; |
| 183 | } |
| 184 | |
| 185 | private function get_byte() { |
| 186 | $c = $this->get_chars( 1 ); |
| 187 | $b = unpack( "C", $c ); |
| 188 | |
| 189 | return reset( $b ); |
| 190 | } |
| 191 | |
| 192 | private function read_int( $str ) { |
| 193 | $size = unpack( "C*", $str ); |
| 194 | |
| 195 | return ( $size[1] << 8 ) + $size[2]; |
| 196 | } |
| 197 | |
| 198 | public function __destruct() { |
| 199 | $this->close(); |
| 200 | } |
| 201 | } |