joomla-2.5 /plugins/system/jch_optimize/cache/css-sprite-gen.inc.php

Language PHP Lines 685
MD5 Hash 7e44d608dc875e67bc62e1d1589461a7 Estimated Cost $12,364 (why?)
Repository https://bitbucket.org/organicdevelopment/joomla-2.5.git View Raw File View Project SPDX
  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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
<?php
/**
 * This is a slightly modified version of the original class bearing the same file and
 * class name. This is originally from the online css sprite generator found at
 * http://spritegen.website-performance.org/ 
 *
 * @copyright Copyright (C) 2007-2009, Project Fondue (Ed Eliot, Stuart Colville
 *              & Cyril Doussin). All rights reserved.
 * @license Software License Agreement (BSD License)
 */
class CssSpriteGen {
    protected $sImageLibrary;
    protected $aImageTypes = array();
    protected $aFormValues = array();
    protected $aFormErrors = array();
    protected $sZipFolder = '';
    protected $bTransparent;
    protected $sCss;
    protected $sTempSpriteName;
    protected $bValidImages;
    protected $aBackground = array();
    protected $aPosition = array();

    public function __construct($ImageLibrary, $aFormValues) {
        if ($ImageLibrary == 'imagick') {
            $this->sImageLibrary = 'imagick';

            // what image formats does the installed version of Imagick support
            // probably overkill to call as PNG, GIF, JPEG surely supported but done for completeness
            try {
                // Fixes #473915 as queryformats no longer works as a static method.
                $oImagick = new Imagick();
                $aImageFormats = $oImagick->queryFormats();
            } catch (ImagickException $e) {
                error_log($e->getMessage());
            }

            // store supported formats for populating drop downs etc later
            if (in_array('PNG', $aImageFormats)) {
                $this->aImageTypes[] = 'PNG';
            }
            if (in_array('GIF', $aImageFormats)) {
                $this->aImageTypes[] = 'GIF';
            }
            if (in_array('JPG', $aImageFormats)) {
                $this->aImageTypes[] = 'JPG';
            }
        } else {
            $this->sImageLibrary = 'gd';

            // get info about installed GD library to get image types (some versions of GD don't include GIF support)
            $oGD = gd_info();

            // store supported formats for populating drop downs etc later
            if (@$oGD['PNG Support']) {
                $this->aImageTypes[] = 'PNG';
            }
            if (@$oGD['GIF Create Support']) {
                $this->aImageTypes[] = 'GIF';
            }
            if (@$oGD['JPG Support']) {
                $this->aImageTypes[] = 'JPG';
            }
        }

        $this->aFormValues  =   $aFormValues;
        $this->aFormValues  = array(
            'path'=> '',
            'sub' => '',
            'file-regex' => '',
            'wrap-columns' => $aFormValues['wrap-columns'],
            'build-direction' => $aFormValues['build-direction'],
            'use-transparency' => 'on',
            'use-optipng' => '',
            'vertical-offset' => 50,
            'horizontal-offset' => 50,
            'background' => '',
            'image-output' => $aFormValues['image-output'],
            'image-num-colours' => 'true-colour',
            'image-quality' => 75,
            'width-resize' => 100,
            'height-resize' => 100,
            'ignore-duplicates' => 'merge',
            'class-prefix' => '',
            'selector-prefix' => '',
            'selector-suffix' => '',
            'add-width-height-to-css' => 'off'
         );

    }

    public function GetImageTypes() {
        return $this->aImageTypes;
    }

      public function CreateSprite($aFilePaths) {
         // set up variable defaults used when calculating offsets etc
         $aFilesInfo = array();
         $aFilesMD5 = array();
         $bResize = false;
         if ($this->aFormValues['build-direction'] == 'horizontal') {
            $iRowCount = 1;
            $iTotalWidth = 0;
            $iTotalHeight = 0;
            $aMaxRowHeight = array();
            $iMaxVOffset = 0;
         } else {
            $iColumnCount = 1;
            $iTotalWidth = 0;
            $iTotalHeight = 0;
            $aMaxColumnWidth = array();
            $iMaxHOffset = 0;
         }
         $iMaxWidth = 0;
         $iMaxHeight = 0;
         $i = 0;
         $k = 0;
         $bValidImages = false;
         $sOutputFormat = strtolower($this->aFormValues['image-output']);

         // read the contents of the directory passed
         //$oDir = dir($sFolderMD5);

         /*******************************************/
         /* this section calculates all offsets etc */
         /*******************************************/

         // loop through directory (files will be processed in whatever the OS's default file ordering scheme is)
         // save to array so we can sort alphabetically
        /* $aFiles = array();

         while (false !== ($sFile = $oDir->read())) {
            $aFiles[] = $sFile;
         }

         sort($aFiles);*/

          foreach ($aFilePaths as $sFilePath) {
            $sFilePath	=	plgSystemJCH_Optimize::getFilepath($sFilePath);
            // do we want to scale down the source images
            // scaling up isn't supported as that would result in poorer quality images
            $bResize = ($this->aFormValues['width-resize'] != 100 && $this->aFormValues['height-resize'] != 100);

            // grab path information
            //$sFilePath = $sFolderMD5.$sFile;
            $aPathParts = pathinfo($sFilePath);
            $sFile  =   $aPathParts['basename'];

            // are we matching filenames against a regular expression
            // if so it's likely not all images from the ZIP file will end up in the generated sprite image
            if (!empty($this->aFormValues['file-regex'])) {
               // forward slashes should be escaped - it's likely not doing this might be a security risk also
               // one might be able to break out and change the modifiers (to for example run PHP code)
               $this->aFormValues['file-regex'] = str_replace('/', '\/', $this->aFormValues['file-regex']);

               // if the regular expression matches grab the first match and store for use as the class name
               if (preg_match('/^'.$this->aFormValues['file-regex'].'$/i', $sFile, $aMatches)) {
                  $sFileClass = $aMatches[1];
               } else {
                  $sFileClass = '';
               }
            } else { // not using regular expressions - set the class name to the base part of the filename (excluding extension)
               $sFileClass = $aPathParts['basename'];
            }

            // format the class name - it should only contain certain characters
            // this strips out any which aren't
            $sFileClass = $this->FormatClassName($sFileClass);

            $iImageType = @exif_imagetype($sFilePath);

            // if we've got an empty class name then the file wasn't valid and shouldn't be included in the sprite image
            // the file also isn't valid if its extension doesn't match one of the image formats supported by the tool
            if (
               !empty($sFileClass) &&
               isset($aPathParts['extension']) &&
               in_array(strtoupper($aPathParts['extension']), $this->aImageTypes) &&
               in_array($iImageType, array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG)) &&
               substr($sFile, 0, 1) != '.'
            ) {
               // grab the file extension
               $sExtension = $aPathParts['extension'];

               // get MD5 of file (this can be used to compare if a file's content is exactly the same as another's)
               $sFileMD5 = md5(file_get_contents($sFilePath));
              
               // check if this file's MD5 already exists in array of MD5s recorded so far
               // if so it's a duplicate of another file in the ZIP
               if (($sKey = array_search($sFileMD5, $aFilesMD5)) !== false) {
                  // do we want to drop duplicate files and merge CSS rules
                  // if so CSS will end up like .filename1, .filename2 { }
                  if ($this->aFormValues['ignore-duplicates'] == 'merge') {

                     if (isset($aFilesInfo[$sKey]['class'])) {
                        $aFilesInfo[$sKey]['class'] = $aFilesInfo[$sKey]['class'].
                           $this->aFormValues['selector-suffix'].', '.
                           $this->aFormValues['selector-prefix'].'.'.
                           $this->aFormValues['class-prefix'].$sFileClass;

                        $this->aBackground[$k] = $sKey;
                        $k++;
                        continue;
                     }
                  }
               }else{
                     $this->aBackground[$k] = $i;
                     $k++;
               }

               // add MD5 to array to check future files against
               $aFilesMD5[$i] = $sFileMD5;
               // store generated class selector details
               $aFilesInfo[$i]['class'] = ".{$this->aFormValues['class-prefix']}$sFileClass";

               // store file path information and extension
               $aFilesInfo[$i]['path'] = $sFilePath;
               $aFilesInfo[$i]['ext'] = $sExtension;
               // get dimensions of image
               $aImageInfo = getimagesize($sFilePath);
               $iWidth = $aImageInfo[0];
               $iHeight = $aImageInfo[1];

               if ($this->aFormValues['build-direction'] == 'horizontal') {
                  // get the current width of the sprite image - after images processed so far
                  $iCurrentWidth = $iTotalWidth + $this->aFormValues['horizontal-offset'] + $iWidth;

                  // store the maximum width reached so far
                  // if we're on a new column current height might be less than the maximum
                  if ($iMaxWidth < $iCurrentWidth) {
                     $iMaxWidth = $iCurrentWidth;
                  }
               } else {
                  // get the current height of the sprite image - after images processed so far
                  $iCurrentHeight = $iTotalHeight + $this->aFormValues['vertical-offset'] + $iHeight;

                  // store the maximum height reached so far
                  // if we're on a new column current height might be less than the maximum
                  if ($iMaxHeight < $iCurrentHeight) {
                     $iMaxHeight = $iCurrentHeight;
                  }
               }

               // store the original width and height of the image
               // we'll need this later if the image is to be resized
               $aFilesInfo[$i]['original-width'] = $iWidth;
               $aFilesInfo[$i]['original-height'] = $iHeight;

               // store the width and height of the image
               // if we're resizing they'll be less than the original
               $aFilesInfo[$i]['width'] = $bResize ? round(($iWidth / 100) * $this->aFormValues['width-resize']) : $iWidth;
               $aFilesInfo[$i]['height'] = $bResize ? round(($iHeight / 100) * $this->aFormValues['height-resize']) : $iHeight;

               if ($this->aFormValues['build-direction'] == 'horizontal') {
                  // opera (9.0 and below) has a bug which prevents it recognising  offsets of less than -2042px
                  // all subsequent values are treated as -2042px
                  // if we've hit 2000 pixels and we care about this (as set in the interface) then wrap to a new row
                  // increment row count and reset current height
                  if (
                     ($iTotalWidth + $this->aFormValues['horizontal-offset']) >= 2000 &&
                     !empty($this->aFormValues['wrap-columns'])
                  ) {
                     $iRowCount++;
                     $iTotalWidth = 0;
                  }

                  // if the current image is higher than any other in the current row then set the maximum height to that
                  // it will be used to set the height of the current row
                  if ($aFilesInfo[$i]['height'] > $iMaxHeight) {
                     $iMaxHeight = $aFilesInfo[$i]['height'];
                  }

                  // keep track of the height of rows added so far
                  $aMaxRowHeight[$iRowCount] = $iMaxHeight;
                  // calculate the current maximum vertical offset so far
                  $iMaxVOffset = $this->aFormValues['vertical-offset'] * ($iRowCount - 1);

                  // get the x position of current image in overall sprite
                  $aFilesInfo[$i]['x'] = $iTotalWidth;
                  $iTotalWidth += ($aFilesInfo[$i]['width'] + $this->aFormValues['horizontal-offset']);
                  // get the y position of current image in overall sprite
                  if ($iRowCount == 1) {
                     $aFilesInfo[$i]['y'] = 0;
                  } else {
                     $aFilesInfo[$i]['y'] = (
                        $this->aFormValues['vertical-offset'] *
                        ($iRowCount - 1) +
                        (array_sum($aMaxRowHeight) - $aMaxRowHeight[$iRowCount])
                     );
                  }
                  $aFilesInfo[$i]['currentCombinedWidth'] = $iTotalWidth;
                  $aFilesInfo[$i]['rowNumber'] = $iRowCount;
               } else {
                  if (
                     // opera (9.0 and below) has a bug which prevents it recognising  offsets of less than -2042px
                     // all subsequent values are treated as -2042px
                     // if we've hit 2000 pixels and we care about this (as set in the interface) then wrap to a new column
                     // increment column count and reset current height
                     ($iTotalHeight + $this->aFormValues['vertical-offset']) >= 2000 &&
                     !empty($this->aFormValues['wrap-columns'])
                  ) {
                     $iColumnCount++;
                     $iTotalHeight = 0;
                  }

                  // if the current image is wider than any other in the current column then set the maximum width to that
                  // it will be used to set the width of the current column
                  if ($aFilesInfo[$i]['width'] > $iMaxWidth) {
                     $iMaxWidth = $aFilesInfo[$i]['width'];
                  }

                  // keep track of the width of columns added so far
                  $aMaxColumnWidth[$iColumnCount] = $iMaxWidth;
                  // calculate the current maximum horizontal offset so far
                  $iMaxHOffset = $this->aFormValues['horizontal-offset'] * ($iColumnCount - 1);

                  // get the y position of current image in overall sprite
                  $aFilesInfo[$i]['y'] = $iTotalHeight;
                  $iTotalHeight += ($aFilesInfo[$i]['height'] + $this->aFormValues['vertical-offset']);
                  // get the x position of current image in overall sprite
                  if ($iColumnCount == 1) {
                     $aFilesInfo[$i]['x'] = 0;
                  } else {
                     $aFilesInfo[$i]['x'] = (
                        $this->aFormValues['horizontal-offset'] *
                        ($iColumnCount - 1) +
                        (array_sum($aMaxColumnWidth) - $aMaxColumnWidth[$iColumnCount])
                     );
                  }
                  $aFilesInfo[$i]['currentCombinedHeight'] = $iTotalHeight;
                  $aFilesInfo[$i]['columnNumber'] = $iColumnCount;
               }
                
               $i++;
               
            }else{
                $this->aBackground[$k] = null;
                $k++;
            }
            if($i > 30){
                   break;
               }
         }

         // close the dir handle
         //$oDir->close();

         /*******************************************/
         /* this section generates the sprite image */
         /* and CSS rules                           */
         /*******************************************/

         // if $i is greater than 1 then we managed to generate enough info to create a sprite
         if ($i > 1) {
            // if Imagick throws an exception we want the script to terminate cleanly so that
            // temporary files are cleaned up
            try {
               // get the sprite width and height
               if ($this->aFormValues['build-direction'] == 'horizontal') {
                  $iSpriteWidth = $iMaxWidth - $this->aFormValues['horizontal-offset'];
                  $iSpriteHeight = array_sum($aMaxRowHeight) + $iMaxVOffset;
               } else {
                  $iSpriteHeight = $iMaxHeight - $this->aFormValues['vertical-offset'];
                  $iSpriteWidth = array_sum($aMaxColumnWidth) + $iMaxHOffset;
               }

               // get background colour - remove # if added
               $sBgColour = str_replace('#', '', $this->aFormValues['background']);
               // convert 3 digit hex values to 6 digit equivalent
               if (strlen($sBgColour) == 3) {
                  $sBgColour = substr($sBgColour, 0, 1).
                     substr($sBgColour, 0, 1).
                     substr($sBgColour, 1, 1).
                     substr($sBgColour, 1, 1).
                     substr($sBgColour, 2, 1).
                     substr($sBgColour, 2, 1);
               }
               // should the image be transparent
               $this->bTransparent = (
                  !empty($this->aFormValues['use-transparency']) &&
                  in_array($this->aFormValues['image-output'], array('GIF', 'PNG'))
               );

               // if using Imagick library create new instance of library class
               if ($this->sImageLibrary == 'imagick') {
                  $oSprite = new Imagick();

                  // create a new image - set background according to transparency
                  if (!empty($this->aFormValues['background'])) {
                     $oSprite->newImage($iSpriteWidth, $iSpriteHeight, new ImagickPixel("#$sBgColour"), $sOutputFormat);
                  } else {
                     if ($this->bTransparent) {
                        $oSprite->newImage($iSpriteWidth, $iSpriteHeight, new ImagickPixel('#000000'), $sOutputFormat);
                     } else {
                        $oSprite->newImage($iSpriteWidth, $iSpriteHeight, new ImagickPixel('#ffffff'), $sOutputFormat);
                     }
                  }
               } else { // using GD - do the same thing
                  if ($this->bTransparent && !empty($this->aFormValues['background'])) {
                     $oSprite = imagecreate($iSpriteWidth, $iSpriteHeight);
                  } else {
                     $oSprite = imagecreatetruecolor($iSpriteWidth, $iSpriteHeight);
                  }
               }

               // check for transparency option
               if ($this->bTransparent) {
                  if ($this->sImageLibrary == 'imagick') {
                     // set background colour to transparent
                     // if no background colour use black
                     if (!empty($this->aFormValues['background'])) {
                        $oSprite->paintTransparentImage(new ImagickPixel("#$sBgColour"), 0.0, 0);
                     } else {
                        $oSprite->paintTransparentImage(new ImagickPixel("#000000"), 0.0, 0);
                     }
                  } else { // using GD - do the same thing
                     if (!empty($this->aFormValues['background'])) {
                        $iBgColour = hexdec($sBgColour);
                        $iBgColour = imagecolorallocate(
                           $oSprite,
                           0xFF & ($iBgColour >> 0x10),
                           0xFF & ($iBgColour >> 0x8),
                           0xFF & $iBgColour
                        );
                     } else {
                        $iBgColour = imagecolorallocate($oSprite, 0, 0, 0);
                     }
                     imagecolortransparent($oSprite, $iBgColour);
                  }
               } else {
                  // set background colour if not using transparency and using GD
                  if ($this->sImageLibrary != 'imagick') {
                     if (empty($sBgColour)) {
                        $sBgColour = 'ffffff';
                     }
                     $iBgColour = hexdec($sBgColour);
                     $iBgColour = imagecolorallocate(
                        $oSprite, 0xFF & ($iBgColour >> 0x10),
                        0xFF & ($iBgColour >> 0x8),
                        0xFF & $iBgColour
                     );
                     imagefill($oSprite, 0, 0, $iBgColour);
                  }
               }

               // initalise variable to store CSS rules
               $this->aCss = array();

               // loop through file info for valid images
               for ($i = 0; $i < count($aFilesInfo); $i++) {
                  // create a new image object for current file
                  if (!$oCurrentImage = $this->CreateImage($aFilesInfo[$i]['path'], $aFilesInfo[$i]['ext'])) {
                     // if we've got here then a valid but corrupt image was found
                     // at this stage we've already allocated space for the image so create
                     // a blank one to fill the space instead
                     // this should happen very rarely
                     $oCurrentImage = new Imagick();

                     $oCurrentImage->newImage(
                        $aFilesInfo[$i]['original-width'],
                        $aFilesInfo[$i]['original-height'],
                        new ImagickPixel('#ffffff')
                     );
                  }

                  // if resizing get image width and height and resample to new dimensions (percentage of original)
                  // and copy to sprite image
                  if ($bResize) {
                     if ($this->sImageLibrary == 'imagick') {
                        // resample image should work but doesn't seem to - using thumbnailImage instead
                        // which achieves the same effect
                        $oCurrentImage->thumbnailImage($aFilesInfo[$i]['width'], $aFilesInfo[$i]['height']);
                     } else {
                        imagecopyresampled(
                           $oSprite,
                           $oCurrentImage,
                           $aFilesInfo[$i]['x'],
                           $aFilesInfo[$i]['y'], 0, 0,
                           $aFilesInfo[$i]['width'],
                           $aFilesInfo[$i]['height'],
                           $aFilesInfo[$i]['original-width'],
                           $aFilesInfo['original-height']
                        );
                     }
                  }

                  // copy image to sprite
                  if ($this->sImageLibrary == 'imagick') {
                     $oSprite->compositeImage(
                        $oCurrentImage,
                        $oCurrentImage->getImageCompose(),
                        $aFilesInfo[$i]['x'],
                        $aFilesInfo[$i]['y']
                     );
                  } else {
                     // if using GD and already resized the image will have been copied as part of the resize
                     if (!$bResize) {
                        imagecopy(
                           $oSprite,
                           $oCurrentImage,
                           $aFilesInfo[$i]['x'],
                           $aFilesInfo[$i]['y'],
                           0, 0,
                           $aFilesInfo[$i]['width'],
                           $aFilesInfo[$i]['height']
                        );
                     }
                  }

                  // get CSS x & y values
                  $iX = $aFilesInfo[$i]['x'] != 0 ? '-'.$aFilesInfo[$i]['x'].'px' : '0';
                  $iY = $aFilesInfo[$i]['y'] != 0 ? '-'.$aFilesInfo[$i]['y'].'px' : '0';
                  $this->aPosition[$i] = $iX.' '.$iY;
                  // create CSS rules and append to overall CSS rules
                  $this->sCss .= "{$this->aFormValues['selector-prefix']}{$aFilesInfo[$i]['class']} {$this->aFormValues['selector-suffix']}{ background-position: $iX $iY; ";

                  // If add widths and heights the sprite image width and height are added to the CSS
                  if ($this->aFormValues['add-width-height-to-css'] == 'on'){
                     $this->sCss .= "width: {$aFilesInfo[$i]['width']}px; height: {$aFilesInfo[$i]['height']}px;";
                  }

                  $this->sCss .= " } \n";
                  // destroy object created for current image to save memory
                  if ($this->sImageLibrary == 'imagick') {
                     $oCurrentImage->destroy();
                  } else {
                     imagedestroy($oCurrentImage);
                  }
               }
                jimport('joomla.filesytem.folder');
                $path   =   JPATH_ROOT.DS.'images'.DS.'jch-optimize';
                JFolder::create($path);
               // create a unqiue filename for sprite image
               $sSpriteMD5  =   md5(implode($aFilesMD5).implode($this->aFormValues));
               $this->sTempSpriteName = $path.DS.'csg-'.$sSpriteMD5.".$sOutputFormat";
               // write image to file (deleted by cron script after a limited time period)
               if (!file_exists($this->sTempSpriteName)){
                    $this->WriteImage($oSprite, $sOutputFormat, $this->sTempSpriteName);
               }
               // destroy object created for sprite image to save memory
               if ($this->sImageLibrary == 'imagick') {
                  $oSprite->destroy();
               } else {
                  imagedestroy($oSprite);
               }

               // set flag to indicate valid images created
               $this->bValidImages = true;
            } catch (ImagickException $e) {
               error_log($e->getMessage());
            }
         }
      }

    protected function FormatClassName($sClassName) {
        $aExtensions = array();

        foreach ($this->aImageTypes as $sType) {
            $aExtensions[] = ".$sType";
        }

        return preg_replace("/[^a-z0-9_-]+/i", '', str_ireplace($aExtensions, '', $sClassName));
    }

    protected function CreateImage($sFile, $sExtension) {
        if ($this->sImageLibrary == 'imagick') {
            try {
                // Imagick auto detects file extension when creating object from image
                $oImage = new Imagick();

                $oImage->readImage($sFile);
                return $oImage;
            } catch (ImagickException $e) {
                return false;
            }
        } else {
            // we need to tell GD what type of image it's creating an object from
            switch ($sExtension) {
                case 'jpg':
                case 'jpeg':
                    return @imagecreatefromjpeg($sFile);
                case 'gif':
                    return @imagecreatefromgif($sFile);
                case 'png':
                    return @imagecreatefrompng($sFile);
            }
        }
    }

      protected function WriteImage($oImage, $sExtension, $sFilename) {
         if ($this->sImageLibrary == 'imagick') {
            try {
               // check if we want to resample image to lower number of colours (to reduce file size)
               if (in_array($sExtension, array('gif', 'png')) && $this->aFormValues['image-num-colours'] != 'true-colour') {
                  $oImage->quantizeImage($this->aFormValues['image-num-colours'], Imagick::COLORSPACE_RGB, 0, false, false);
               }
               // if we're creating a JEPG set image quality - 0% - 100%
               if (in_array($sExtension, array('jpg', 'jpeg'))) {
                  $oImage->setCompression(Imagick::COMPRESSION_JPEG);
                  $oImage->SetCompressionQuality($this->aFormValues['image-quality']);
               }
               // write out image to file
               $oImage->writeImage($sFilename);
            } catch (ImagickException $e) {
               error_log($e->getMessage());
            }
         } else {
            // check if we want to resample image to lower number of colours (to reduce file size)
            if (in_array($sExtension, array('gif', 'png'))  && $this->aFormValues['image-num-colours'] != 'true-colour') {
               imagetruecolortopalette($oImage, true, $this->aFormValues['image-num-colours']);
            }
            switch ($sExtension) {
               case 'jpg':
               case 'jpeg':
                  // GD takes quality setting in main creation function
                  imagejpeg($oImage, $sFilename, $this->aFormValues['image-quality']);
                  break;
               case 'gif':
                  // force colour palette to 256 colours if saving sprite image as GIF
                  // this will happen anyway (as GIFs can't be more than 256 colours)
                  // but the quality will be better if pre-forcing
                  if (
                     $this->bTransparent &&
                     (
                        $this->aFormValues['image-num-colours'] == -1 ||
                        $this->aFormValues['image-num-colours'] > 256
                     )
                  ) {
                     imagetruecolortopalette($oImage, true, 256);
                  }
                  imagegif($oImage, $sFilename);
                  break;
               case 'png':
                  imagepng($oImage, $sFilename);
                  break;
            }
         }

         // if using a PNG and option selected further compress sprite image using OptiPNG
         // this can result in more than 50% saving in file size with little loss in quality
         if (
            $sExtension == 'png' &&
            !empty($this->aFormValues['use-optipng']) &&
            ConfigHelper::Get('/binaries/optipng')
         ) {
            // this probably won't work with PHP safe mode enabled
            // no real alternative - you'll have to enable to use
            shell_exec(ConfigHelper::Get('/binaries/optipng')." $sFilename");
         }
      }

    public function ValidImages() {
        return $this->bValidImages;
    }

    public function GetSpriteFilename() {
        $aFileParts = pathinfo($this->sTempSpriteName);
        return $aFileParts['basename'];
    }

    public function GetSpriteHash() {
        //return md5($this->GetSpriteFilename().ConfigHelper::Get('/checksum'));
    }

    public function GetCss() {
        return $this->aCss;
    }

    public function GetAllErrors() {
        return $this->aFormErrors;
    }

    public function GetZipFolder() {
        return $this->sZipFolder;
    }

    public function GetCssBackground(){
        $aCssBackground = array();
        foreach($this->aBackground as $background){
            $aCssBackground[] = @$this->aPosition[$background];
        }
        return $aCssBackground;
    }
}
?>
Back to Top