Passed
Push — develop ( d3878a...248214 )
by Jens
02:17
created

Image::loopThroughBodyAndCalculatePixels()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 39
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 15
nc 6
nop 8
dl 0
loc 39
rs 8.439
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * Image
4
 *
5
 * @Author : Jens Kooij
6
 * @Version: 1.0
7
 * @package: JNS MVC
8
 * @Licence: http://creativecommons.org/licenses/by-nc-nd/3.0/ Attribution-NonCommercial-NoDerivs 3.0 Unported
9
 */
10
11
namespace CloudControl\Cms\images {
12
13
    class Image
14
    {
15
        /**
16
         * @var resource
17
         */
18
        private $_imageResource;
19
20
        /**
21
         * Load the a image resource into $this->_imageResource
22
         * automagically :-)
23
         *
24
         * @param resource|string $imageContainer
25
         *
26
         * @throws \Exception
27
         */
28
        public function loadImage($imageContainer)
29
        {
30
            if ($this->createImageResourceFromResource($imageContainer) ||
31
                $this->createImageResourceFromFile($imageContainer) ||
32
                $this->createImageResourceFromString($imageContainer)
33
            ) {
34
                return;
35
            }
36
37
            throw new \RuntimeException('Could not create image resource, accepted inputs are: "resource of type (gd)", path_to_image and "string". <br /><pre>' . var_export($imageContainer,
38
                    true) . '</pre>');
39
        }
40
41
        /**
42
         * @param $imageContainer
43
         * @return bool
44
         */
45
        private function createImageResourceFromResource($imageContainer)
46
        {
47
            if (is_resource($imageContainer) && get_resource_type($imageContainer) === 'gd') {
48
                $this->_imageResource = $imageContainer;
49
                return true;
50
            }
51
            return false;
52
        }
53
54
        /**
55
         * @param $imageContainer
56
         * @return bool
57
         * @throws \Exception
58
         */
59
        private function createImageResourceFromFile($imageContainer)
60
        {
61
            if (is_string($imageContainer) && file_exists($imageContainer)) {
62
                if ($this->getImageMimeType($imageContainer) === IMAGETYPE_BMP) {
63
                    $this->_imageResource = $this->createImageFromBmp($imageContainer);
64
                } else {
65
                    $imageContent = file_get_contents($imageContainer);
66
                    $this->_imageResource = imagecreatefromstring($imageContent);
67
                }
68
                return true;
69
            }
70
            return false;
71
        }
72
73
        /**
74
         * @param $imageContainer
75
         * @return bool
76
         */
77
        private function createImageResourceFromString($imageContainer)
78
        {
79
            if (is_string($imageContainer)) {
80
                $this->_imageResource = imagecreatefromstring($imageContainer);
81
                return true;
82
            }
83
            return false;
84
        }
85
86
        /**
87
         * Saves the image to a file
88
         *
89
         * @param string $path
90
         * @param int $mimeTypeConstantValue
91
         * @param int $quality
92
         * @param resource $imageResource If no resource is given, uses $this->_imageResource
93
         *
94
         * @return bool
95
         * @throws \Exception
96
         */
97
        public function saveImage($path, $mimeTypeConstantValue, $quality = 100, $imageResource = null)
98
        {
99
            if ($imageResource === null) {
100
                $imageResource = $this->getImageResource();
101
            }
102
103
            if ($mimeTypeConstantValue == IMAGETYPE_GIF) {
104
                return imagegif($imageResource, $path);
105
            }
106
107
            if ($mimeTypeConstantValue == IMAGETYPE_JPEG) {
108
                return imagejpeg($imageResource, $path, $quality);
109
            }
110
111
            if ($mimeTypeConstantValue == IMAGETYPE_PNG) {
112
                return imagepng($imageResource, $path, ((int)($quality / 10) - 1));
113
            }
114
115
            throw new \RuntimeException('Not a valid mimetypeconstant given see function documentation');
116
        }
117
118
        /**
119
         * Returns either the Mime-Type Constant value
120
         * or the default extension for the detected mime-type;
121
         *
122
         * @see http://www.php.net/manual/en/function.image-type-to-mime-type.php
123
         *
124
         * @param string $imagePath
125
         * @param bool $getExtension
126
         *
127
         * @return integer
128
         */
129
        public function getImageMimeType($imagePath, $getExtension = false)
130
        {
131
            if (function_exists('exif_imagetype')) {
132
                $exif = exif_imagetype($imagePath);
133
            } else {
134
                if ((list($width, $height, $type, $attr) = getimagesize($imagePath)) !== false) {
135
                    $exif = $type;
136
                } else {
137
                    $exif = false;
138
                }
139
            }
140
141
            return $getExtension ? image_type_to_extension($exif) : $exif;
142
        }
143
144
        /**
145
         * Create Image resource from Bitmap
146
         *
147
         * @see       http://www.php.net/manual/en/function.imagecreatefromwbmp.php#86214
148
         * @author    alexander at alexauto dot nl
149
         *
150
         * @param    string $pathToBitmapFile
151
         *
152
         * @return  resource
153
         * @throws \Exception
154
         */
155
        public function createImageFromBmp($pathToBitmapFile)
156
        {
157
            $bitmapFileData = $this->getBitmapFileData($pathToBitmapFile);
158
159
            $temp = unpack("H*", $bitmapFileData);
160
            $hex = $temp[1];
161
            $header = substr($hex, 0, 108);
162
            list($width, $height) = $this->calculateWidthAndHeight($header);
163
164
            //    Define starting X and Y 
165
            $x = 0;
166
            $y = 1;
167
168
            $image = imagecreatetruecolor($width, $height);
169
170
            //    Grab the body from the image 
171
            $body = substr($hex, 108);
172
173
            //    Calculate if padding at the end-line is needed. Divided by two to keep overview. 1 byte = 2 HEX-chars
174
            $bodySize = (strlen($body) / 2);
175
            $headerSize = ($width * $height);
176
177
            //    Use end-line padding? Only when needed 
178
            $usePadding = ($bodySize > ($headerSize * 3) + 4);
179
            $this->loopThroughBodyAndCalculatePixels($bodySize, $x, $width, $usePadding, $y, $height, $body, $image);
180
181
            unset($body);
182
183
            return $image;
184
        }
185
186
        /**
187
         * Returns the image resource
188
         * @return resource
189
         * @throws \Exception
190
         */
191
        final public function getImageResource()
192
        {
193
            if (is_resource($this->_imageResource) && get_resource_type($this->_imageResource) === 'gd') {
194
                return $this->_imageResource;
195
            }
196
197
            throw new \RuntimeException('Image resource is not set. Use $this->LoadImage to load an image into the resource');
198
        }
199
200
        /**
201
         * @param $pathToBitmapFile
202
         * @throws \Exception
203
         * @return bool|string
204
         */
205
        private function getBitmapFileData($pathToBitmapFile)
206
        {
207
            $fileHandle = fopen($pathToBitmapFile, "rb");
208
            if ($fileHandle === false) {
209
                throw new \RuntimeException('Could not open bitmapfile ' . $pathToBitmapFile);
210
            }
211
            $bitmapFileData = fread($fileHandle, 10);
212
            while (!feof($fileHandle) && ($bitmapFileData <> "")) {
213
                $bitmapFileData .= fread($fileHandle, 1024);
214
            }
215
216
            return $bitmapFileData;
217
        }
218
219
        /**
220
         * @param string $header
221
         *
222
         * @return array
223
         */
224
        private function calculateWidthAndHeight($header)
225
        {
226
            $width = null;
227
            $height = null;
228
229
            //    Structure: http://www.fastgraph.com/help/bmp_header_format.html
230
            if (0 === strpos($header, '424d')) {
231
                //    Cut it in parts of 2 bytes
232
                $header_parts = str_split($header, 2);
233
                //    Get the width        4 bytes
234
                $width = hexdec($header_parts[19] . $header_parts[18]);
235
                //    Get the height        4 bytes
236
                $height = hexdec($header_parts[23] . $header_parts[22]);
237
                //    Unset the header params
238
                unset($header_parts);
239
240
                return array($width, $height);
241
            }
242
243
            return array($width, $height);
244
        }
245
246
        /**
247
         * Loop through the data in the body of the bitmap
248
         * file and calculate each individual pixel based on the
249
         * bytes
250
         * @param integer $bodySize
251
         * @param integer $x
252
         * @param $width
253
         * @param boolean $usePadding
254
         * @param integer $y
255
         * @param $height
256
         * @param string $body
257
         * @param resource $image
258
         */
259
        private function loopThroughBodyAndCalculatePixels(
260
            $bodySize,
261
            $x,
262
            $width,
263
            $usePadding,
264
            $y,
265
            $height,
266
            $body,
267
            $image
268
        )
269
        {
270
//    Using a for-loop with index-calculation instead of str_split to avoid large memory consumption
271
            //    Calculate the next DWORD-position in the body
272
            for ($i = 0; $i < $bodySize; $i += 3) {
273
                //    Calculate line-ending and padding
274
                if ($x >= $width) {
275
                    //    If padding needed, ignore image-padding. Shift i to the ending of the current 32-bit-block
276
                    if ($usePadding) {
277
                        $i += $width % 4;
278
                    }
279
                    //    Reset horizontal position
280
                    $x = 0;
281
                    //    Raise the height-position (bottom-up)
282
                    $y++;
283
                    //    Reached the image-height? Break the for-loop
284
                    if ($y > $height) {
285
                        break;
286
                    }
287
                }
288
                //    Calculation of the RGB-pixel (defined as BGR in image-data). Define $iPos as absolute position in the body
289
                $iPos = $i * 2;
290
                $r = hexdec($body[$iPos + 4] . $body[$iPos + 5]);
291
                $g = hexdec($body[$iPos + 2] . $body[$iPos + 3]);
292
                $b = hexdec($body[$iPos] . $body[$iPos + 1]);
293
                //    Calculate and draw the pixel
294
                $color = imagecolorallocate($image, (int)$r, (int)$g, (int)$b);
295
                imagesetpixel($image, $x, $height - $y, $color);
296
                //    Raise the horizontal position
297
                $x++;
298
            }
299
        }
300
    }
301
}