WordPress.org

Make WordPress Core

Ticket #16434: ico2_2.php

File ico2_2.php, 26.8 KB (added by brandondove, 2 years ago)

ImageICO PHP library

Line 
1<?php
2/**
3 * @package com.jpexs.image.ico
4 *
5 * JPEXS ICO Image functions
6 * @version 2.2
7 * @author JPEXS
8 * @copyright (c) JPEXS 2004-2012
9 *
10 * Webpage: http://www.jpexs.com
11 * Email: jpexs@jpexs.com
12 *
13 * If you like my script, you can donate... visit my webpages or email me for more info.
14 *
15 *        Version changes:
16 *          2012-02-18 v2.2 - License changed to GNU/GPL v3
17 *          2009-02-23 v2.1 - redesigned sourcecode, phpdoc included, all internal functions and global variables have prefix "jpexs_"
18 *                     v2.0 - For icons with Alpha channel now you can set background color
19 *                          - ImageCreateFromExeIco added
20 *                          - Fixed ICO_MAX_SIZE and ICO_MAX_COLOR values
21 *
22 * TODO list:
23 *      - better error handling
24 *      - better internal function handling
25 *      - class encapsulation
26 *
27 * License:
28 *  This program is free software: you can redistribute it and/or modify
29 *  it under the terms of the GNU General Public License as published by
30 *  the Free Software Foundation, either version 3 of the License, or
31 *  (at your option) any later version.
32 *
33 *  This program is distributed in the hope that it will be useful,
34 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
35 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
36 *  GNU General Public License for more details.
37 *
38 *  You should have received a copy of the GNU General Public License
39 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
40 */
41
42/** TrueColor images constant  */
43define("ICO_TRUE_COLOR", 0x1000000);
44/** XPColor images constant (Alpha channel) */
45define("ICO_XP_COLOR", 4294967296);
46/** Image with maximum colors */
47define("ICO_MAX_COLOR", -2);
48/** Image with maximal size */
49define("ICO_MAX_SIZE", -2);
50
51
52/** TrueColor images constant
53 * @deprecated Deprecated since version 2.1, please use ICO_ constants
54 */
55define("TRUE_COLOR", 0x1000000);
56/** XPColor images constant (Alpha channel)
57 * @deprecated Deprecated since version 2.1, please use ICO_ constants
58 */
59define("XP_COLOR", 4294967296);
60/** Image with maximum colors
61 * @deprecated Deprecated since version 2.1, please use ICO_ constants
62 */
63define("MAX_COLOR", -2);
64/** Image with maximal size
65 * @deprecated Deprecated since version 2.1, please use ICO_ constants
66 */
67define("MAX_SIZE", -2);
68
69
70/**
71 * Reads image from a ICO file
72 *
73 * @param string $filename Target ico file to load
74 * @param int $icoColorCount Icon color count (For multiple icons ico file) - 2,16,256, ICO_TRUE_COLOR, ICO_XP_COLOR or ICO_MAX_COLOR
75 * @param int $icoSize Icon width (For multiple icons ico file) or ICO_MAX_SIZE
76 * @param int $alphaBgR Background color R value for alpha-channel images (Default is White)
77 * @param int $alphaBgG Background color G value for alpha-channel images (Default is White)
78 * @param int $alphaBgB Background color B value for alpha-channel images (Default is White)
79 * @return resource Image resource
80 */
81function imageCreateFromIco($filename,$icoColorCount=16,$icoSize=16,$alphaBgR=255,$alphaBgG=255,$alphaBgB=255)
82{
83$Ikona=jpexs_GetIconsInfo($filename);
84
85$IconID=-1;
86
87$ColMax=-1;
88$SizeMax=-1;
89
90for($p=0;$p<count($Ikona);$p++)
91{
92$Ikona[$p]["NumberOfColors"]=pow(2,$Ikona[$p]["Info"]["BitsPerPixel"]);
93};
94
95
96for($p=0;$p<count($Ikona);$p++)
97{
98
99if(($ColMax==-1)or($Ikona[$p]["NumberOfColors"]>=$Ikona[$ColMax]["NumberOfColors"]))
100if(($icoSize==$Ikona[$p]["Width"])or($icoSize==ICO_MAX_SIZE))
101 {
102  $ColMax=$p;
103 };
104
105if(($SizeMax==-1)or($Ikona[$p]["Width"]>=$Ikona[$SizeMax]["Width"]))
106if(($icoColorCount==$Ikona[$p]["NumberOfColors"])or($icoColorCount==ICO_MAX_COLOR))
107 {
108   $SizeMax=$p;
109 };
110
111
112if($Ikona[$p]["NumberOfColors"]==$icoColorCount)
113if($Ikona[$p]["Width"]==$icoSize)
114 {
115
116 $IconID=$p;
117 };
118};
119
120  if($icoColorCount==ICO_MAX_COLOR) $IconID=$ColMax;
121  if($icoSize==ICO_MAX_SIZE) $IconID=$SizeMax;
122
123$ColName=$icoColorCount;
124
125if($icoSize==ICO_MAX_SIZE) $icoSize="Max";
126if($ColName==ICO_TRUE_COLOR) $ColName="True";
127if($ColName==ICO_XP_COLOR) $ColName="XP";
128if($ColName==ICO_MAX_COLOR) $ColName="Max";
129if($IconID==-1) die("Icon with $ColName colors and $icoSize x $icoSize size doesn't exist in this file!");
130
131
132jpexs_readIcon($filename,$IconID,$Ikona);
133
134 $biBitCount=$Ikona[$IconID]["Info"]["BitsPerPixel"];
135
136
137  if($Ikona[$IconID]["Info"]["BitsPerPixel"]==0)
138  {
139  $Ikona[$IconID]["Info"]["BitsPerPixel"]=24;
140  };
141
142 $biBitCount=$Ikona[$IconID]["Info"]["BitsPerPixel"];
143 if($biBitCount==0) $biBitCount=1;
144
145
146$Ikona[$IconID]["BitCount"]=$Ikona[$IconID]["Info"]["BitsPerPixel"];
147
148
149
150if($Ikona[$IconID]["BitCount"]>=24)
151{
152$img=imagecreatetruecolor($Ikona[$IconID]["Width"],$Ikona[$IconID]["Height"]);
153if($Ikona[$IconID]["BitCount"]==32):
154  $backcolor=imagecolorallocate($img,$alphaBgR,$alphaBgG,$alphaBgB);
155  imagefilledrectangle($img,0,0,$Ikona[$IconID]["Width"]-1,$Ikona[$IconID]["Height"]-1,$backcolor);
156endif;
157for($y=0;$y<$Ikona[$IconID]["Height"];$y++)
158for($x=0;$x<$Ikona[$IconID]["Width"];$x++)
159 {
160 $R=$Ikona[$IconID]["Data"][$x][$y]["r"];
161 $G=$Ikona[$IconID]["Data"][$x][$y]["g"];
162 $B=$Ikona[$IconID]["Data"][$x][$y]["b"];
163 if($Ikona[$IconID]["BitCount"]==32)
164 {
165 $Alpha=127-round($Ikona[$IconID]["Data"][$x][$y]["alpha"]*127/255);
166 if($Ikona[$IconID]["Maska"][$x][$y]==1) $Alpha=127;
167 $color=imagecolorexactalpha($img,$R,$G,$B,$Alpha);
168 if($color==-1) $color=imagecolorallocatealpha($img,$R,$G,$B,$Alpha);
169 }
170 else
171 {
172 $color=imagecolorexact($img,$R,$G,$B);
173 if($color==-1) $color=imagecolorallocate($img,$R,$G,$B);
174 };
175
176 imagesetpixel($img,$x,$y,$color);
177
178 };
179
180}
181else
182{
183$img=imagecreate($Ikona[$IconID]["Width"],$Ikona[$IconID]["Height"]);
184for($p=0;$p<count($Ikona[$IconID]["Paleta"]);$p++)
185 $Paleta[$p]=imagecolorallocate($img,$Ikona[$IconID]["Paleta"][$p]["r"],$Ikona[$IconID]["Paleta"][$p]["g"],$Ikona[$IconID]["Paleta"][$p]["b"]);
186
187for($y=0;$y<$Ikona[$IconID]["Height"];$y++)
188for($x=0;$x<$Ikona[$IconID]["Width"];$x++)
189 {
190 imagesetpixel($img,$x,$y,$Paleta[$Ikona[$IconID]["Data"][$x][$y]]);
191 };
192};
193$IsTransparent=false; 
194for($y=0;$y<$Ikona[$IconID]["Height"];$y++)
195for($x=0;$x<$Ikona[$IconID]["Width"];$x++)
196 if($Ikona[$IconID]["Maska"][$x][$y]==1)
197  {
198   $IsTransparent=true;
199   break;
200  };
201if($Ikona[$IconID]["BitCount"]==32)
202{
203 imagealphablending($img, false);
204 if(function_exists("imagesavealpha"))
205  imagesavealpha($img,true);
206};
207
208if($IsTransparent)
209 {
210  if(($Ikona[$IconID]["BitCount"]>=24)or(imagecolorstotal($img)>=256))
211   {
212   $img2=imagecreatetruecolor(imagesx($img),imagesy($img));
213   imagecopy($img2,$img,0,0,0,0,imagesx($img),imagesy($img));
214   imagedestroy($img);
215   $img=$img2;
216   imagetruecolortopalette($img,true,255);
217
218   };
219    $Pruhledna=imagecolorallocate($img,0,0,0);
220    for($y=0;$y<$Ikona[$IconID]["Height"];$y++)
221     for($x=0;$x<$Ikona[$IconID]["Width"];$x++)
222      if($Ikona[$IconID]["Maska"][$x][$y]==1)
223       {
224        imagesetpixel($img,$x,$y,$Pruhledna);
225       };
226  imagecolortransparent($img,$Pruhledna);
227 };
228
229return $img;
230
231
232};
233
234
235
236
237function jpexs_readIcon($filename,$id,&$Ikona)
238{
239global $jpexs_currentBit;
240
241$f=fopen($filename,"rb");
242
243fseek($f,6+$id*16);
244  $Width=jpexs_freadbyte($f);
245  $Height=jpexs_freadbyte($f);
246fseek($f,6+$id*16+12);
247$OffSet=jpexs_freaddword($f);
248fseek($f,$OffSet);
249
250$p=$id;
251
252  $Ikona[$p]["Info"]["HeaderSize"]=jpexs_freadlngint($f);
253  $Ikona[$p]["Info"]["ImageWidth"]=jpexs_freadlngint($f);
254  $Ikona[$p]["Info"]["ImageHeight"]=jpexs_freadlngint($f);
255  $Ikona[$p]["Info"]["NumberOfImagePlanes"]=jpexs_freadword($f);
256  $Ikona[$p]["Info"]["BitsPerPixel"]=jpexs_freadword($f);
257  $Ikona[$p]["Info"]["CompressionMethod"]=jpexs_freadlngint($f);
258  $Ikona[$p]["Info"]["SizeOfBitmap"]=jpexs_freadlngint($f);
259  $Ikona[$p]["Info"]["HorzResolution"]=jpexs_freadlngint($f);
260  $Ikona[$p]["Info"]["VertResolution"]=jpexs_freadlngint($f);
261  $Ikona[$p]["Info"]["NumColorUsed"]=jpexs_freadlngint($f);
262  $Ikona[$p]["Info"]["NumSignificantColors"]=jpexs_freadlngint($f);
263
264
265 $biBitCount=$Ikona[$p]["Info"]["BitsPerPixel"];
266
267 if($Ikona[$p]["Info"]["BitsPerPixel"]<=8)
268  {
269
270 $barev=pow(2,$biBitCount);
271
272  for($b=0;$b<$barev;$b++)
273    {
274    $Ikona[$p]["Paleta"][$b]["b"]=jpexs_freadbyte($f);
275    $Ikona[$p]["Paleta"][$b]["g"]=jpexs_freadbyte($f);
276    $Ikona[$p]["Paleta"][$b]["r"]=jpexs_freadbyte($f);
277    jpexs_freadbyte($f);
278    };
279
280$Zbytek=(4-ceil(($Width/(8/$biBitCount)))%4)%4;
281
282
283for($y=$Height-1;$y>=0;$y--)
284    {
285     $jpexs_currentBit=0;
286     for($x=0;$x<$Width;$x++)
287      {
288         $C=jpexs_freadbits($f,$biBitCount);
289         $Ikona[$p]["Data"][$x][$y]=$C;
290      };
291
292    if($jpexs_currentBit!=0) {jpexs_freadbyte($f);};
293    for($g=0;$g<$Zbytek;$g++)
294     jpexs_freadbyte($f);
295     };
296
297}
298elseif($biBitCount==24)
299{
300 $Zbytek=$Width%4;
301
302   for($y=$Height-1;$y>=0;$y--)
303    {
304     for($x=0;$x<$Width;$x++)
305      {
306       $B=jpexs_freadbyte($f);
307       $G=jpexs_freadbyte($f);
308       $R=jpexs_freadbyte($f);
309       $Ikona[$p]["Data"][$x][$y]["r"]=$R;
310       $Ikona[$p]["Data"][$x][$y]["g"]=$G;
311       $Ikona[$p]["Data"][$x][$y]["b"]=$B;
312      }
313    for($z=0;$z<$Zbytek;$z++)
314     jpexs_freadbyte($f);
315   };
316}
317elseif($biBitCount==32)
318{
319 $Zbytek=$Width%4;
320
321   for($y=$Height-1;$y>=0;$y--)
322    {
323     for($x=0;$x<$Width;$x++)
324      {
325       $B=jpexs_freadbyte($f);
326       $G=jpexs_freadbyte($f);
327       $R=jpexs_freadbyte($f);
328       $Alpha=jpexs_freadbyte($f);
329       $Ikona[$p]["Data"][$x][$y]["r"]=$R;
330       $Ikona[$p]["Data"][$x][$y]["g"]=$G;
331       $Ikona[$p]["Data"][$x][$y]["b"]=$B;
332       $Ikona[$p]["Data"][$x][$y]["alpha"]=$Alpha;
333      }
334    for($z=0;$z<$Zbytek;$z++)
335     jpexs_freadbyte($f);
336   };
337};
338
339
340//Maska
341$Zbytek=(4-ceil(($Width/(8)))%4)%4;
342for($y=$Height-1;$y>=0;$y--)
343    {
344     $jpexs_currentBit=0;
345     for($x=0;$x<$Width;$x++)
346      {
347         $C=jpexs_freadbits($f,1);
348         $Ikona[$p]["Maska"][$x][$y]=$C;
349      };
350    if($jpexs_currentBit!=0) {jpexs_freadbyte($f);};
351    for($g=0;$g<$Zbytek;$g++)
352     jpexs_freadbyte($f);
353     };
354//--------------
355
356fclose($f);
357
358};
359
360function jpexs_GetIconsInfo($filename)
361{
362global $jpexs_currentBit;
363
364$f=fopen($filename,"rb");
365
366$Reserved=jpexs_freadword($f);
367$Type=jpexs_freadword($f);
368$Count=jpexs_freadword($f);
369for($p=0;$p<$Count;$p++)
370 {
371  $Ikona[$p]["Width"]=jpexs_freadbyte($f);
372  $Ikona[$p]["Height"]=jpexs_freadbyte($f);
373  $Ikona[$p]["ColorCount"]=jpexs_freadword($f);
374 if($Ikona[$p]["ColorCount"]==0) $Ikona[$p]["ColorCount"]=256;
375  $Ikona[$p]["Planes"]=jpexs_freadword($f);
376  $Ikona[$p]["BitCount"]=jpexs_freadword($f);
377  $Ikona[$p]["BytesInRes"]=jpexs_freaddword($f);
378  $Ikona[$p]["ImageOffset"]=jpexs_freaddword($f);
379 };
380
381if(!feof($f)):
382  for($p=0;$p<$Count;$p++)
383   {
384    fseek($f,$Ikona[$p]["ImageOffset"]+14);
385    $Ikona[$p]["Info"]["BitsPerPixel"]=jpexs_freadword($f);
386   };
387endif;
388fclose($f);
389return $Ikona;
390};
391
392
393
394
395/**
396 * Reads image from a icon in exe file
397 * @param string $filename Target exefile
398 * @param int $icoIndex Index of the icon in exefile
399 * @param int $icoColorCount Icon color count (For multiple icons ico file) - 2,16,256, ICO_TRUE_COLOR, ICO_XP_COLOR or ICO_MAX_COLOR
400 * @param int $icoSize Icon width (For multiple icons ico file) or ICO_MAX_SIZE
401 * @param int $alphaBgR Background color R value for alpha-channel images (Default is White)
402 * @param int $alphaBgG Background color G value for alpha-channel images (Default is White)
403 * @param int $alphaBgB Background color B value for alpha-channel images (Default is White)
404 * @return resource Image resource or false on error
405 */
406function imageCreateFromExeIco($filename,$icoIndex,$icoColorCount=16,$icoSize=16,$alphaBgR=255,$alphaBgG=255,$alphaBgB=255)
407{
408 $ok=saveExeIcon($filename,"icotemp.dat",$icoIndex);
409 if(!$ok):
410  $im=false;
411 else:
412   $im=imageCreateFromIco("icotemp.dat",$icoColorCount,$icoSize,$alphaBgR,$alphaBgG,$alphaBgB);
413   unlink("icotemp.dat");
414 endif;
415 return $im;
416};
417
418
419/**
420 * Saves icon(s) from the exe file
421 * @global int $jpexs_StartOfRsrc Internal reserved variable
422 * @global int $jpexs_ImageBase Internal reserved variable
423 * @global int $jpexs_ResVirtualAddress Internal reserved variable
424 * @param string $filename Target exefile
425 * @param string $icoFileNameOrPath Filename to save ico or path (Default "") Path if you want more than 1 icon. If "", the filename is "$icoIndex.ico"
426 * @param int|array $iconIndex Index(es) of the icon in exefile  (Default -1) If -1, all icons are saved, Can be an array of indexes.
427 * @return boolean True on successful save
428 */
429function saveExeIcon($filename,$icoFileNameOrPath="",$iconIndex=-1) /*-1 for all,or can be array*/
430{
431  global $jpexs_f,$jpexs_StartOfRsrc,$jpexs_ImageBase,$jpexs_ResVirtualAddress;
432  $jpexs_f=fopen($filename,"r");
433  $MZ=fread($jpexs_f,2);
434  if($MZ!="MZ") NotValidExe();
435  fseek($jpexs_f,60);
436  $OffsetToNewHeader=jpexs_freaddword($jpexs_f);
437  fseek($jpexs_f,$OffsetToNewHeader);
438  $PE=fread($jpexs_f,2);
439  if($PE!="PE") NotValidExe();
440  fread($jpexs_f,4);
441  $NumberOfSections=jpexs_freadword($jpexs_f);
442  fseek($jpexs_f,ftell($jpexs_f)+12);
443  $SizeOfOptionalHeader=jpexs_freadword($jpexs_f);
444  $PosMagic=ftell($jpexs_f)+2;
445  fseek($jpexs_f,$PosMagic+$SizeOfOptionalHeader);
446
447  for($p=0;$p<$NumberOfSections;$p++):
448    $SectionName[$p]=trim(fread($jpexs_f,8));
449    $VirtualSize[$p]=jpexs_freaddword($jpexs_f);
450    $VirtualAddress[$p]=jpexs_freaddword($jpexs_f);
451    $PhysicalSize[$p]=jpexs_freaddword($jpexs_f);
452    $PhysicalOffset[$p]=jpexs_freaddword($jpexs_f);
453    fread($jpexs_f,16);
454    if($SectionName[$p]==".rsrc"):
455      $jpexs_ResVirtualAddress=$VirtualAddress[$p];
456      fseek($jpexs_f,$PhysicalOffset[$p]);
457      $jpexs_StartOfRsrc=$PhysicalOffset[$p];
458      jpexs_readResDirectoryEntry($R,$PhysicalOffset[$p]);
459      $IconCount=null;
460      $Ikona=null;
461      while (list ($key, $val) = each ($R["Subdir"])):
462        if($key==14):
463          $r=0;
464          while (list ($key2, $val2) = each ($R["Subdir"][$key]["Subdir"])):
465             while (list ($key3, $val3) = each ($R["Subdir"][$key]["Subdir"][$key2]["Subdir"])):
466               fseek($jpexs_f,$val3["DataOffset"]);
467               $Reserved=jpexs_freadword($jpexs_f);
468               $Type=jpexs_freadword($jpexs_f);
469               $ic=jpexs_freadword($jpexs_f);
470               $IconCount[]=$ic;
471               for($s=0;$s<$ic;$s++)
472                {
473                 $Ikona[$r][$s]["Width"]=jpexs_freadbyte($jpexs_f);
474                 $Ikona[$r][$s]["Height"]=jpexs_freadbyte($jpexs_f);
475                 $Ikona[$r][$s]["ColorCount"]=jpexs_freadword($jpexs_f);
476                 $Ikona[$r][$s]["Planes"]=jpexs_freadword($jpexs_f);
477                 $Ikona[$r][$s]["BitCount"]=jpexs_freadword($jpexs_f);
478                 $Ikona[$r][$s]["BytesInRes"]=jpexs_freaddword($jpexs_f);
479                 $Ikona[$r][$s]["IconId"]=jpexs_freadword($jpexs_f);
480                };
481               fseek($jpexs_f,$val3["DataOffset"]);
482               $r++;
483             endwhile;
484          endwhile;
485        endif;
486      endwhile;
487
488      reset ($R["Subdir"]);
489
490      while (list ($key, $val) = each ($R["Subdir"])):
491        if($key==3):
492          while (list ($key2, $val2) = each ($R["Subdir"][$key]["Subdir"])):
493          for($r=0;$r<count($Ikona);$r++):
494           for($s=0;$s<count($Ikona[$r]);$s++):
495             while (list ($key3, $val3) = each ($R["Subdir"][$key]["Subdir"][$Ikona[$r][$s]["IconId"]]["Subdir"])):
496               if(($iconIndex==$r)or($iconIndex==-1)or((is_array($iconIndex))and(in_array($r,$iconIndex)))):
497                 fseek($jpexs_f,$val3["DataOffset"]);
498                 $Ikona[$r][$s]["Data"]=fread($jpexs_f,$val3["DataSize"]);
499                 $Ikona[$r][$s]["DataSize"]=$val3["DataSize"];
500               endif;
501             endwhile;
502           endfor;
503           endfor;
504          endwhile;
505        endif;
506      endwhile;
507      $ok=false;
508      for($r=0;$r<count($Ikona);$r++):
509        if(($iconIndex==$r)or($iconIndex==-1)or((is_array($iconIndex))and(in_array($r,$iconIndex)))):
510          $savefile=$icoFileNameOrPath;
511          if($icoFileNameOrPath=="")
512           {
513             $savefile="$r.ico";
514           }
515           else
516           {
517            if(($iconIndex==-1)or(is_array($iconIndex)))
518              $savefile=$icoFileNameOrPath."$r.ico";
519           };
520          $f2=fopen($savefile,"w");
521          fwrite($f2,jpexs_inttoword(0));
522          fwrite($f2,jpexs_inttoword(1));
523          fwrite($f2,jpexs_inttoword(count($Ikona[$r])));
524          $Offset=6+16*count($Ikona[$r]);
525          for($s=0;$s<count($Ikona[$r]);$s++):
526            fwrite($f2,jpexs_inttobyte($Ikona[$r][$s]["Width"]));
527            fwrite($f2,jpexs_inttobyte($Ikona[$r][$s]["Height"]));
528            fwrite($f2,jpexs_inttoword($Ikona[$r][$s]["ColorCount"]));
529            fwrite($f2,jpexs_inttoword($Ikona[$r][$s]["Planes"]));
530            fwrite($f2,jpexs_inttoword($Ikona[$r][$s]["BitCount"]));
531            fwrite($f2,jpexs_inttodword($Ikona[$r][$s]["BytesInRes"]));
532            fwrite($f2,jpexs_inttodword($Offset));
533            $Offset+=$Ikona[$r][$s]["DataSize"];
534          endfor;
535          for($s=0;$s<count($Ikona[$r]);$s++):
536            fwrite($f2,$Ikona[$r][$s]["Data"]);
537          endfor;
538          fclose($f2);
539          $ok=true;
540        endif;
541      endfor;
542      return $ok;
543    endif;
544  endfor;
545
546  fclose($jpexs_f);
547};
548
549/**
550 * Internal function for reading exe icons
551 */
552function jpexs_readResDirectoryEntry(&$parentRes,$offset)
553{
554global $jpexs_f,$jpexs_StartOfRsrc,$jpexs_ImageBase,$jpexs_ResVirtualAddress;
555$lastPos=ftell($jpexs_f);
556$Res=null;
557fseek($jpexs_f,$offset);
558//IMAGE_RESOURCE_DIRECTORY
559      $Characteristics=jpexs_freaddword($jpexs_f);
560      $TimeDateStamp=jpexs_freaddword($jpexs_f);
561      $MajorVersion=jpexs_freadword($jpexs_f);
562      $MinorVersion=jpexs_freadword($jpexs_f);
563      $NumberOfNamedEntries=jpexs_freadword($jpexs_f);
564      $NumberOfIdEntries=jpexs_freadword($jpexs_f);
565      for($q=0;$q<$NumberOfNamedEntries+$NumberOfIdEntries;$q++):
566        //IMAGE_RESOURCE_DIRECTORY_ENTRY
567        $ResName=jpexs_freaddword($jpexs_f);
568        $lastPos2=ftell($jpexs_f);
569        if($ResName>=0x80000000):
570          //String Name
571          $ResNameOffset=$ResName-0x80000000;
572          fseek($jpexs_f,$jpexs_StartOfRsrc+$ResNameOffset);
573          $StringLength=jpexs_freadword($jpexs_f);
574          $Identificator=(fread($jpexs_f,$StringLength*2));
575          fseek($jpexs_f,$lastPos2);
576        else:
577          //Integer Id
578          $Identificator=$ResName;
579        endif;
580
581        $ResOffsetToData=jpexs_freaddword($jpexs_f);
582        if($ResOffsetToData>=0x80000000):
583          $SubResOffset=$ResOffsetToData-0x80000000;
584          jpexs_readResDirectoryEntry($Res["$Identificator"],$jpexs_StartOfRsrc+$SubResOffset);
585        else:
586          $RawDataOffset=$ResOffsetToData;
587          $lastPos2=ftell($jpexs_f);
588          fseek($jpexs_f,$jpexs_StartOfRsrc+$RawDataOffset);
589          //IMAGE_RESOURCE_DATA_ENTRY
590          $OffsetToData=jpexs_freaddword($jpexs_f);
591          $Res["$Identificator"]["DataOffset"]=$jpexs_StartOfRsrc-$jpexs_ResVirtualAddress+$OffsetToData;
592          $Res["$Identificator"]["DataSize"]=jpexs_freaddword($jpexs_f);
593          $CodePage=jpexs_freaddword($jpexs_f);
594          $Reserved=jpexs_freaddword($jpexs_f);
595          fseek($jpexs_f,$lastPos2);
596        endif;
597      endfor;
598fseek($jpexs_f,$lastPos);
599$parentRes["Subdir"]=$Res;
600};
601
602/**
603 * Creates ico file from image resource(s)
604 * @param resource|array $images Target Image resource (Can be array of image resources)
605 * @param string $filename Target ico file to save icon to, If ommited or "", image is written to snadard output - use header("Content-type: image/x-icon"); */
606function imageIco($images,$filename="")
607{
608
609if(is_array($images))
610{
611$ImageCount=count($images);
612$Image=$images;
613}
614else
615{
616$Image[0]=$images;
617$ImageCount=1;
618};
619
620
621$WriteToFile=false;
622
623if($filename!="")
624{
625$WriteToFile=true;
626};
627
628
629$ret="";
630
631$ret.=jpexs_inttoword(0); //PASSWORD
632$ret.=jpexs_inttoword(1); //SOURCE
633$ret.=jpexs_inttoword($ImageCount); //ICONCOUNT
634
635
636for($q=0;$q<$ImageCount;$q++)
637{
638$img=$Image[$q];
639
640$Width=imagesx($img);
641$Height=imagesy($img);
642
643$ColorCount=imagecolorstotal($img);
644
645$Transparent=imagecolortransparent($img);
646$IsTransparent=$Transparent!=-1;
647
648
649if($IsTransparent) $ColorCount--;
650
651if($ColorCount==0) {$ColorCount=0; $BitCount=24;};
652if(($ColorCount>0)and($ColorCount<=2)) {$ColorCount=2; $BitCount=1;};
653if(($ColorCount>2)and($ColorCount<=16)) { $ColorCount=16; $BitCount=4;};
654if(($ColorCount>16)and($ColorCount<=256)) { $ColorCount=0; $BitCount=8;};
655
656
657
658
659
660//ICONINFO:
661$ret.=jpexs_inttobyte($Width);//
662$ret.=jpexs_inttobyte($Height);//
663$ret.=jpexs_inttobyte($ColorCount);//
664$ret.=jpexs_inttobyte(0);//RESERVED
665
666$Planes=0;
667if($BitCount>=8) $Planes=1;
668
669$ret.=jpexs_inttoword($f,$Planes);//PLANES
670if($BitCount>=8) $WBitCount=$BitCount;
671if($BitCount==4) $WBitCount=0;
672if($BitCount==1) $WBitCount=0;
673$ret.=jpexs_inttoword($WBitCount);//BITS
674
675$Zbytek=(4-($Width/(8/$BitCount))%4)%4;
676$ZbytekMask=(4-($Width/8)%4)%4;
677
678$PalSize=0;
679
680$Size=40+($Width/(8/$BitCount)+$Zbytek)*$Height+(($Width/8+$ZbytekMask) * $Height);
681if($BitCount<24)
682 $Size+=pow(2,$BitCount)*4;
683$IconId=1;
684$ret.=jpexs_inttodword($Size); //SIZE
685$OffSet=6+16*$ImageCount+$FullSize;
686$ret.=jpexs_inttodword(6+16*$ImageCount+$FullSize);//OFFSET
687$FullSize+=$Size;
688//-------------
689
690};
691
692
693for($q=0;$q<$ImageCount;$q++)
694{
695$img=$Image[$q];
696$Width=imagesx($img);
697$Height=imagesy($img);
698$ColorCount=imagecolorstotal($img);
699
700$Transparent=imagecolortransparent($img);
701$IsTransparent=$Transparent!=-1;
702
703if($IsTransparent) $ColorCount--;
704if($ColorCount==0) {$ColorCount=0; $BitCount=24;};
705if(($ColorCount>0)and($ColorCount<=2)) {$ColorCount=2; $BitCount=1;};
706if(($ColorCount>2)and($ColorCount<=16)) { $ColorCount=16; $BitCount=4;};
707if(($ColorCount>16)and($ColorCount<=256)) { $ColorCount=0; $BitCount=8;};
708
709
710
711//ICONS
712$ret.=jpexs_inttodword(40);//HEADSIZE
713$ret.=jpexs_inttodword($Width);//
714$ret.=jpexs_inttodword(2*$Height);//
715$ret.=jpexs_inttoword(1); //PLANES
716$ret.=jpexs_inttoword($BitCount);   //
717$ret.=jpexs_inttodword(0);//Compress method
718
719
720$ZbytekMask=($Width/8)%4;
721
722$Zbytek=($Width/(8/$BitCount))%4;
723$Size=($Width/(8/$BitCount)+$Zbytek)*$Height+(($Width/8+$ZbytekMask) * $Height);
724
725$ret.=jpexs_inttodword($Size);//SIZE
726
727$ret.=jpexs_inttodword(0);//HPIXEL_M
728$ret.=jpexs_inttodword(0);//V_PIXEL_M
729$ret.=jpexs_inttodword($ColorCount); //UCOLORS
730$ret.=jpexs_inttodword(0); //DCOLORS
731//---------------
732
733
734$CC=$ColorCount;
735if($CC==0) $CC=256;
736
737if($BitCount<24)
738{
739 $ColorTotal=imagecolorstotal($img);
740 if($IsTransparent) $ColorTotal--;
741
742 for($p=0;$p<$ColorTotal;$p++)
743  {
744   $color=imagecolorsforindex($img,$p);
745   $ret.=jpexs_inttobyte($color["blue"]);
746   $ret.=jpexs_inttobyte($color["green"]);
747   $ret.=jpexs_inttobyte($color["red"]);
748   $ret.=jpexs_inttobyte(0); //RESERVED
749  };
750
751 $CT=$ColorTotal;
752 for($p=$ColorTotal;$p<$CC;$p++)
753  {
754   $ret.=jpexs_inttobyte(0);
755   $ret.=jpexs_inttobyte(0);
756   $ret.=jpexs_inttobyte(0);
757   $ret.=jpexs_inttobyte(0); //RESERVED
758  };
759};
760
761
762
763
764
765
766if($BitCount<=8)
767{
768
769 for($y=$Height-1;$y>=0;$y--)
770 {
771  $bWrite="";
772  for($x=0;$x<$Width;$x++)
773   {
774   $color=imagecolorat($img,$x,$y);
775   if($color==$Transparent)
776    $color=imagecolorexact($img,0,0,0);
777   if($color==-1) $color=0;
778   if($color>pow(2,$BitCount)-1) $color=0;
779
780   $bWrite.=jpexs_decbinx($color,$BitCount);
781   if(strlen($bWrite)==8)
782    {
783     $ret.=jpexs_inttobyte(bindec($bWrite));
784     $bWrite="";
785    };
786   };
787
788  if((strlen($bWrite)<8)and(strlen($bWrite)!=0))
789    {
790     $sl=strlen($bWrite);
791     for($t=0;$t<8-$sl;$t++)
792      $sl.="0";
793     $ret.=jpexs_inttobyte(bindec($bWrite));
794    };
795  for($z=0;$z<$Zbytek;$z++)
796   $ret.=jpexs_inttobyte(0);
797 };
798};
799
800
801
802if($BitCount>=24)
803{
804 for($y=$Height-1;$y>=0;$y--)
805 {
806  for($x=0;$x<$Width;$x++)
807   {
808   $color=imagecolorsforindex($img,imagecolorat($img,$x,$y));
809   $ret.=jpexs_inttobyte($color["blue"]);
810   $ret.=jpexs_inttobyte($color["green"]);
811   $ret.=jpexs_inttobyte($color["red"]);
812   if($BitCount==32)
813    $ret.=jpexs_inttobyte(0);//Alpha for ICO_XP_COLORS
814   };
815  for($z=0;$z<$Zbytek;$z++)
816   $ret.=jpexs_inttobyte(0);
817 };
818};
819
820
821//MASK
822
823 for($y=$Height-1;$y>=0;$y--)
824 {
825  $byteCount=0;
826  $bOut="";
827  for($x=0;$x<$Width;$x++)
828   {
829    if(($Transparent!=-1)and(imagecolorat($img,$x,$y)==$Transparent))
830     {
831      $bOut.="1";
832     }
833     else
834     {
835      $bOut.="0";
836     };
837   };
838  for($p=0;$p<strlen($bOut);$p+=8)
839  {
840   $byte=bindec(substr($bOut,$p,8));
841   $byteCount++;
842   $ret.=jpexs_inttobyte($byte);
843  };
844 $Zbytek=$byteCount%4;
845  for($z=0;$z<$Zbytek;$z++)
846   {
847   $ret.=jpexs_inttobyte(0xff);
848   };
849 };
850
851//------------------
852
853};//q
854
855
856
857
858
859if($WriteToFile)
860{
861 $f=fopen($filename,"w");
862 fwrite($f,$ret);
863 fclose($f);
864}
865else
866{
867 echo $ret;
868};
869
870};
871
872
873
874
875/*
876* Internal functions:
877*-------------------------
878* jpexs_inttobyte($n) - returns chr(n)
879* jpexs_inttodword($n) - returns dword (n)
880* jpexs_inttoword($n) - returns word(n)
881* jpexs_freadbyte($file) - reads 1 byte from $file
882* jpexs_freadword($file) - reads 2 bytes (1 word) from $file
883* jpexs_freaddword($file) - reads 4 bytes (1 dword) from $file
884* jpexs_freadlngint($file) - same as freaddword($file)
885* jpexs_decbin8($d) - returns binary string of d zero filled to 8
886* jpexs_RetBits($byte,$start,$len) - returns bits $start->$start+$len from $byte
887* jpexs_freadbits($file,$count) - reads next $count bits from $file
888*/
889
890
891function jpexs_decbin8($d)
892{
893return jpexs_decbinx($d,8);
894};
895
896function jpexs_decbinx($d,$n)
897{
898$bin=decbin($d);
899$sbin=strlen($bin);
900for($j=0;$j<$n-$sbin;$j++)
901 $bin="0$bin";
902return $bin;
903};
904
905function jpexs_retBits($byte,$start,$len)
906{
907$bin=jpexs_decbin8($byte);
908$r=bindec(substr($bin,$start,$len));
909return $r;
910
911};
912
913
914
915$jpexs_currentBit=0;
916function jpexs_freadbits($f,$count)
917{
918 global $jpexs_currentBit,$jpexs_SMode;
919 $Byte=jpexs_freadbyte($f);
920 $LastCBit=$jpexs_currentBit;
921 $jpexs_currentBit+=$count;
922 if($jpexs_currentBit==8)
923  {
924   $jpexs_currentBit=0;
925  }
926 else
927  {
928   fseek($f,ftell($f)-1);
929  };
930 return jpexs_retBits($Byte,$LastCBit,$count);
931};
932
933
934function jpexs_freadbyte($f)
935{
936 return ord(fread($f,1));
937};
938
939function jpexs_freadword($f)
940{
941 $b1=jpexs_freadbyte($f);
942 $b2=jpexs_freadbyte($f);
943 return $b2*256+$b1;
944};
945
946
947function jpexs_freadlngint($f)
948{
949return jpexs_freaddword($f);
950};
951
952function jpexs_freaddword($f)
953{
954 $b1=jpexs_freadword($f);
955 $b2=jpexs_freadword($f);
956 return $b2*65536+$b1;
957};
958
959function jpexs_inttobyte($n)
960{
961return chr($n);
962};
963
964function jpexs_inttodword($n)
965{
966return chr($n & 255).chr(($n >> 8) & 255).chr(($n >> 16) & 255).chr(($n >> 24) & 255);
967};
968
969function jpexs_inttoword($n)
970 {
971 return chr($n & 255).chr(($n >> 8) & 255);
972 };
973
974?>