WordPress.org

Make WordPress Core

Ticket #16434: trac-16434-04.patch

File trac-16434-04.patch, 50.0 KB (added by TomAuger, 6 years ago)

Included ico2_3.php, "remove" functionality, and refactoring of get_favicon_thumbnail_img() to get_favicon_img()

  • wp-admin/favicon-upload.php

     
     1<?php
     2/**
     3 * Handles the uploading, cropping and scaling of favicons.
     4 *
     5 * @uses ico2_3.php JPEXS class for reading / writing .ICO files
     6 *
     7 * @package WordPress
     8 * @subpackage Administration
     9 * @since 3.4.1
     10 */
     11
     12// Bootstrap admin and all its goodies
     13require_once( 'admin.php' );
     14
     15// Bring in the JPEXS .ICO conversion library
     16require_once( ABSPATH . 'wp-admin/includes/ico2_3.php' );
     17
     18
     19define( 'FAVICON_SIZE', 32 ); // Width (and height) of the favicon (in pixels)
     20
     21/*      Upload is a 2-step process:     
     22 *      1. Process the uploaded file and show the crop UI
     23 *      2. Manipulate the pixel data, save to PNG and ICO and write to options.
     24 */
     25
     26if ( isset( $_POST['CROP_AND_SAVE'] ) ) {
     27        if ( isset( $_POST['attachment_id'] ) && is_numeric( $_POST['attachment_id'] ) ){
     28                $image_basename = process_crop_thumbnail( $_POST['attachment_id'] );
     29
     30                if ( is_wp_error( $image_basename ) ) {
     31                        include_once('./admin-header.php');
     32                        echo '<div class="wrap">';
     33                                echo '<h2>' . __( 'Image upload error' ) . '</h2>';
     34                                echo '<p>' . $image_basename->get_error_message() . '</p>';
     35                                echo '<p><a href="' . admin_url( 'options-general.php' ) . '">&laquo;' . __( 'Back to Settings &gt; General' ) . '</a></p>';
     36                        echo '</div><!-- .wrap -->';
     37                        include_once('./admin-footer.php');
     38                } else {
     39                        foreach ( array( $image_basename . '.png', $image_basename . '.ico' ) as $image_filename )
     40                                save_thumbnail_attachment( $image_filename, $attachment_id );
     41
     42                        // And save the basename out to options.
     43                        update_option( 'sitefavicon', basename( $image_basename ) );
     44                       
     45                        /** @TODO need to find a way to notify the user that the process has completed successfully - admin_notices? */
     46                        wp_redirect( admin_url( 'options-general.php' ) );
     47                }
     48        } else {
     49                return new WP_Error( 'attachment_id_missing', 'Form submission error.' );
     50        }
     51} elseif ( isset( $_REQUEST['REMOVE_FAVICON'] ) ) {
     52        remove_favicon();
     53} else {
     54        /** @TODO make sure that we trap for someone just pressing "Upload image" but with no image attached */
     55        // Enqueue the JS for the cropper...
     56        add_action( 'admin_enqueue_scripts', 'enqueue_cropper' );
     57        // ...and our own script for populating the crop form
     58        add_action( 'admin_footer', 'cropping_js', 10,  1);
     59       
     60        // Process the upload and create the attachment file in the media center
     61        $image_results = process_thumbnail_upload();
     62       
     63        include_once('./admin-header.php');
     64       
     65        // hack because image replication isn't fast enough. See https://wpcom.automattic.com/ticket/1294
     66        sleep( 2 );
     67
     68        echo '<div class="wrap">';
     69       
     70        if ( is_wp_error( $image_results ) )  {
     71                echo '<h2>' . __( 'Image upload error' ) . '</h2>';
     72                echo '<p>' . $image_results->get_error_message() . '</p>';
     73                echo '<p><a href="' . admin_url( 'options-general.php' ) . '">&laquo;' . __( 'Back to Settings &gt; General' ) . '</a></p>';
     74        } else {
     75                // Image upload successful.
     76                // Now we can hook in our javascript and provide the width/height of our image as the default crop size
     77                $crop_size = min( $image_results['width'], $image_results['height'] );
     78                echo '<script type="text/javascript">var jcrop_starting_size = ' . $crop_size . '; // Initialize jcrop crop area starting size</script>';
     79       
     80                echo '<h2>' . __( 'Crop uploaded image' ) . '</h2>';
     81                echo '<p>' . __( 'Choose the part of the image you want to use for your favicon.' ) . '</p>';
     82               
     83                echo '<form id="favicon-crop-form" method="post" action="' . $_SERVER['REQUEST_URI'] . '">'; // Point the form action back to this script
     84               
     85                        echo <<<CROP_FORM
     86                        <input type="hidden" name="x1" id="x1" />
     87                        <input type="hidden" name="y1" id="y1" />
     88                        <input type="hidden" name="x2" id="x2" />
     89                        <input type="hidden" name="y2" id="y2" />
     90                        <input type="hidden" name="width" id="width" />
     91                        <input type="hidden" name="height" id="height" />
     92                        <input type="hidden" name="attachment_id" id="attachment_id" value="{$image_results['attachment_id']}" />
     93                        <input type="hidden" name="scaling_factor" id="scaling_factor" value="{$image_results['scaling_factor']}" />
     94CROP_FORM;
     95               
     96                        echo '<img src="' . $image_results['src'] . '" id="upload" width="' . $image_results['width'] . '" height="' . $image_results['height'] . '" />';
     97               
     98                        echo '<p class="submit"><input type="submit" name="CROP_AND_SAVE" value="' . __( 'Crop image' ) . ' &raquo;" /></p>';
     99                echo '</form>';
     100        }
     101       
     102        echo '</div><!-- .wrap -->';
     103       
     104        include_once('./admin-footer.php');
     105}
     106
     107
     108/**
     109 * Process the image file upload and return a WP_Error or details about the attachment image file.
     110 *
     111 * @return mixed WP_Error | $image_results array
     112 */
     113function process_thumbnail_upload(){
     114        $file = wp_handle_upload( $_FILES['avatarfile'], array( 'action' => 'wp_upload_favicon') );
     115        if ( isset($file['error']) ) die( $file['error'] );
     116       
     117        $url = $file['url'];
     118        $file = $file['file'];
     119        $filename = basename($file);
     120       
     121        // Construct the object array
     122        $object = array(
     123                'post_title' => $filename,
     124                'post_content' => $url,
     125                'post_mime_type' => 'import',
     126                'guid' => $url
     127        );
     128
     129        // Save the data.  Also makes replication work
     130        $id = wp_insert_attachment($object, $file);
     131
     132        // Retrieve the image dimensions
     133        list( $orig_width, $orig_height, $type, $attr ) = getimagesize( $file );
     134       
     135        // Do we need to scale down the image so we can display it nicely in the interactive Crop tool?
     136        if ( $orig_width > 600 || $orig_height > 600 ) {
     137                $image = wp_create_thumbnail( $file, 600 );
     138                list( $width, $height, $type, $attr ) = getimagesize( $image );
     139               
     140                 // Update the attachment record to reflect the newly-scaled thumbnail image
     141                $thumb = basename( $image );
     142                $metadata = array( 'thumb' => $thumb );
     143                wp_update_attachment_metadata( $id, $metadata );
     144
     145                $url = str_replace( basename( $url ), $thumb, $url );
     146
     147                $scaling = $orig_width / $width;
     148        } else {
     149                // No scaling required; just copy original values.
     150                $width = $orig_width;
     151                $height = $orig_height;
     152                $scaling = 1;
     153        }
     154
     155        // Check image file format
     156        $image_type = exif_imagetype( get_attached_file( $id ) );
     157        if (! in_array( $image_type, array( IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_BMP ) ) )
     158                $error = new WP_Error( 'bad_file_format', __( 'Please only use PNG (.png), JPEG (.jpg) or BMP (.bmp) image files for favicons. ' ) );
     159       
     160        // return WP_Error or the $image_results array
     161        if ( $error ){
     162                return $error;
     163        } else {
     164                return array(
     165                        'attachment_id' => $id,
     166                        'src' => $url,
     167                        'width' => $width,
     168                        'height' => $height,
     169                        'scaling_factor' => $scaling
     170                );
     171        }
     172}
     173
     174/**
     175 * Create PNG and BMP image resources based on the form submission of the cropped thumbnail.
     176 *
     177 * @param int $attachment_id The ID of the original attachment's post record.
     178 * @return mixed WP_Error | Favicon file base name (ie: fully qualified file name without any TLA file extension)
     179 */
     180function process_crop_thumbnail( $attachment_id ){
     181        $src_file = get_attached_file( $attachment_id );
     182
     183        // Highly unlikely, but let's check
     184        if (! file_exists( $src_file ) )
     185                return new WP_Error( 'file_missing', __( 'Attachment image file missing (possible save error: check space on web server).' ) );
     186
     187        // Make sure we're still within accepted image types
     188        $image_type = exif_imagetype( $src_file );
     189        if (! $image_type || ! in_array( $image_type, array( IMAGETYPE_PNG, IMAGETYPE_JPEG, IMAGETYPE_BMP ) ) )
     190                return new WP_Error( 'bad_file_format', __( 'Please only use PNG (.png), JPEG (.jpg) or BMP (.bmp) image files for favicons. ' ) );
     191
     192        // Parse image file bytes
     193        $src_image = wp_load_image( $src_file );
     194        if ( !is_resource($src_image) )
     195                return new WP_Error( 'is_not_resource', __( 'Error loading image. You got me: I\'m stumped.' ) );
     196
     197        // We crop from the original, not the medium sized, display-only thumbnail
     198        $src_x = $_POST['x1'] * $_POST['scaling_factor'];
     199        $src_y = $_POST['y1'] * $_POST['scaling_factor'];
     200        $src_width = $_POST['width'] * $_POST['scaling_factor'];
     201        $src_height = $_POST['height'] * $_POST['scaling_factor'];
     202
     203        $dst_width = $dst_height = FAVICON_SIZE;
     204        // Avoid upscaling
     205        if ( $src_width < $dst_width || $src_height < $dst_height ) {
     206                $dst_width = $src_width;
     207                $dst_height = $src_height;
     208        }
     209
     210        $dst_image = wp_imagecreatetruecolor( $dst_width, $dst_height );
     211        if ( function_exists( 'imageantialias' ) ) imageantialias( $dst_image, true );
     212        imagealphablending( $dst_image, false );
     213        imagesavealpha( $dst_image, true );
     214        imagecopyresampled( $dst_image, $src_image, 0, 0, $src_x, $src_y, $dst_width, $dst_height, $src_width, $src_height );
     215        imagedestroy( $src_image );
     216
     217
     218        // Save the image in PNG and ICO formats
     219        $file_info = pathinfo( $src_file );
     220        $src_basename = basename( $src_file, '.' . $file_info['extension'] );
     221        $dst_filename = str_replace( $src_basename, $src_basename . '_' . FAVICON_SIZE . 'x' . FAVICON_SIZE, $src_file );
     222        // Strip the TLA from the filename
     223        $dst_filename = preg_replace( '/\\.[^\\.]+$/', '', $dst_filename );
     224
     225        $png_filename = $dst_filename . '.png';
     226        if (! imagepng( $dst_image, $png_filename, 0 ) )
     227                return new WP_Error( 'png_write_error', 'Error writing PNG favicon file.' );
     228       
     229        $ico_filename = $dst_filename . '.ico';
     230        imageIco( $dst_image, $ico_filename );
     231        /** @TODO refactor the ico2_3.php library to add error checking and possibly encapsulate the class */
     232        //if (! imageIco( $dst_image, $ico_filename ) )
     233                //return new WP_Error( 'ico_write_error', 'Error writing ICO favicon file.' );
     234
     235        imagedestroy( $dst_image );
     236
     237        return $dst_filename;
     238}
     239
     240/**
     241 * Creates an attachment post record for a newly created thumbnail
     242 *
     243 * @param string $file_name Fully qualified file name for the image asset file.
     244 * @param int $parent_attachment_id The ID of the original thumbnail's attachment post record
     245 *
     246 * @return int The ID of the newly-created thumbnail attachment post record
     247 */
     248function save_thumbnail_attachment( $file_name, $parent_attachment_id ){
     249        $file_info = pathinfo( $file_name ); // So we can get the TLA later on
     250       
     251        $file_name = apply_filters( 'wp_create_file_in_uploads', $file_name, $parent_attachment_id ); // For replication
     252
     253        $parent = get_post( $parent_attachment_id );
     254        $parent_url = $parent->guid;
     255       
     256        // Update the attachment
     257        $mimes = get_allowed_mime_types();
     258        $attachment_id = wp_insert_attachment( array(
     259                'ID' => $attachment_id,
     260                'post_title' => basename( $file_name ),
     261                'post_content' => $url,
     262                'post_mime_type' => $mimes[ $file_info['extension'] ],
     263                'guid' => $url,
     264                'context' => 'favicon'
     265        ), $file_name );
     266        wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $file_name ) );
     267       
     268        return $attachment_id;
     269}
     270
     271/**
     272 * Currently, doesn't actually "remove" the favicon images. It only deletes the option
     273 * that tells us there's a favicon, so the code isn't generated (or the default is used)
     274 */
     275function remove_favicon(){
     276        update_option( 'sitefavicon', false );
     277                       
     278        /** @TODO need to find a way to notify the user that the process has completed successfully - admin_notices? */
     279        wp_redirect( admin_url( 'options-general.php' ) );
     280}
     281
     282
     283/**
     284 * Called in admin_enqueue_scripts to add the cropper.js script and styles
     285 */
     286function enqueue_cropper(){
     287        wp_enqueue_script( 'jcrop', 'jquery' );
     288        wp_enqueue_style('jcrop'); // We can enqueue styles within the admin_enqueue_script action hook {@link http://wpdevel.wordpress.com/2011/12/12/use-wp_enqueue_scripts-not-wp_print_styles-to-enqueue-scripts-and-styles-for-the-frontend/}
     289}
     290
     291function cropping_js(){
     292        // Purely for coding convenience and legibility
     293        $favicon_size = FAVICON_SIZE;
     294       
     295        echo <<<CROP_JS
     296        <!-- Favicon cropping -->
     297        <script type="text/javascript">
     298                // Update the crop form
     299                function onEndCrop( coords ) {
     300                        jQuery( '#x1' ).val(coords.x);
     301                        jQuery( '#y1' ).val(coords.y);
     302                        jQuery( '#x2' ).val(coords.x2);
     303                        jQuery( '#y2' ).val(coords.y2);
     304                        jQuery( '#width' ).val(coords.w);
     305                        jQuery( '#height' ).val(coords.h);
     306                }
     307
     308                // with a supplied ratio
     309                jQuery(function($) {
     310                        if (! jcrop_starting_size) jcrop_starting_size = {$favicon_size}; // jcrop_starting_size should be set in the body once the image has been processed
     311
     312                        // Set up default values on the crop form
     313                        jQuery( '#x1' ).val(0);
     314                        jQuery( '#y1' ).val(0);
     315                        jQuery( '#x2' ).val(jcrop_starting_size);
     316                        jQuery( '#y2' ).val(jcrop_starting_size);
     317                        jQuery( '#width' ).val(jcrop_starting_size);
     318                        jQuery( '#height' ).val(jcrop_starting_size);
     319
     320                        // Initialize Jcrop
     321                        $('#upload').Jcrop({
     322                                aspectRatio: 1,
     323                                setSelect: [0, 0, jcrop_starting_size, jcrop_starting_size],
     324                                onSelect: onEndCrop
     325                        });
     326                });
     327        </script>
     328CROP_JS;
     329
     330}
     331 No newline at end of file
  • wp-admin/includes/ico2_3.php

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

     
     1(function($){
     2    $('#faviconfile').change(function(){
     3        // check the file extention
     4        if (! $.inArray( $(this).val().split('.').pop().toLowerCase() , /* valid file extentions */ ['gif','png','jpg','jpeg'] ) )
     5            $('#favicon-invalid-filetype').show();
     6        else
     7        {
     8            $('#faviconupload').submit();
     9        }
     10    });
     11
     12})(jQuery);
  • wp-admin/js/wp-favicon.js

     
     1(function($){
     2    $('#faviconfile').change(function(){
     3        // check the file extention
     4        if (! $.inArray( $(this).val().split('.').pop().toLowerCase() , /* valid file extentions */ ['gif','png','jpg','jpeg'] ) )
     5            $('#favicon-invalid-filetype').show();
     6        else
     7        {
     8            $('#faviconupload').submit();
     9        }
     10    });
     11
     12})(jQuery);
  • wp-admin/options-general.php

     
    8181        '<p>' . __('<a href="http://wordpress.org/support/" target="_blank">Support Forums</a>') . '</p>'
    8282);
    8383
     84wp_enqueue_script('wp-favicon');
     85
    8486include('./admin-header.php');
    8587?>
    8688
     
    8890<?php screen_icon(); ?>
    8991<h2><?php echo esc_html( $title ); ?></h2>
    9092
     93<form action="<?php echo admin_url('favicon-upload.php')?>" method="post" enctype="multipart/form-data" id="faviconupload">
     94        <input type="hidden" name="action" value="wp_upload_favicon" />
     95
     96        <table class="form-table">
     97                <tr valign="top">
     98                        <th scope="row"><label for="sitefavicon"><?php _e('Favicon') ?></label></th>
     99                        <td>
     100                                <?php
     101                                        // display the icon and the remove link if appropriate
     102                                        if ( has_custom_favicon() ){
     103                                                if ( $thumbnail = get_favicon_img() ) echo $thumbnail;
     104                                                echo "\t" . '<input type="submit" name="REMOVE_FAVICON" value="Remove Favicon" id="remove-favicon-button" />';
     105                                                echo ' <span class="description no-js">' . __( 'The image at right is used as your site\'s favicon. To change it, first remove this one.' ) . '</span>';
     106                                        } else {
     107                                ?>
     108                                        <input class="button" name="avatarfile" type="file" id="faviconfile" size="20" />
     109                                        <p class="submit no-js hide-if-js"><input type="submit" name="Submit" value="Upload Image &raquo;" id="faviconsubmit" /></p>
     110                                        <span class="description no-js"><?php _e('Click to upload your own custom icon ("favicon") for your blog. You\'ll be able to crop and scale it once it\'s uploaded.') ?></span>
     111                                <?php } ?>
     112                        </td>
     113                </tr>
     114        </table>
     115</form>
     116
    91117<form method="post" action="options.php">
    92118<?php settings_fields('general'); ?>
    93119
  • wp-includes/functions.php

     
    18451845                'png' => 'image/png',
    18461846                'bmp' => 'image/bmp',
    18471847                'tif|tiff' => 'image/tiff',
    1848                 'ico' => 'image/x-icon',
     1848                'ico' => 'image/vnd.microsoft.icon',
    18491849                'asf|asx|wax|wmv|wmx' => 'video/asf',
    18501850                'avi' => 'video/avi',
    18511851                'divx' => 'video/divx',
  • wp-includes/general-template.php

     
    15871587}
    15881588
    15891589/**
     1590 * Convenience function that echoes the HTML for the site's favicon icon.
     1591 * By default, automatically included in the header via the 'wp_head' action, which can be removed by themes if a custom favicon is desired.
     1592 *
     1593 * @uses generate_site_favicon_html() to do the actual heavy lifting
     1594 */
     1595function site_favicon(){
     1596        echo generate_site_favicon_html();
     1597}
     1598add_action( 'wp_head', 'site_favicon' );
     1599add_action( 'admin_head', 'site_favicon' );
     1600
     1601/**
     1602 * Return the HTML for the site's favicon icon, if such has been defined.
     1603 *
     1604 * @uses get_site_favicon_uri();
     1605 *
     1606 * Includes the conditional tag wrapper for an IE (.ico) version.
     1607 */
     1608function generate_site_favicon_html() {
     1609        $ie_favicon_uri = get_site_favicon_uri( 'ico' );
     1610        $favicon_uri = get_site_favicon_uri();
     1611
     1612        $content = "";
     1613        if (! is_wp_error( $ie_favicon_uri ) && ! is_wp_error( $favicon_uri ) ){
     1614
     1615                $content .= <<<FAVICON_HTML
     1616<!--Favicon (via 'wp_head' action) -->
     1617<!--[if IE]>
     1618<link rel="shortcut icon" href="{$ie_favicon_uri}" />
     1619<![endif]-->
     1620<!--[if !IE]>-->
     1621<link href="{$favicon_uri}" rel="icon" type="image/png" />
     1622<!--<![endif]-->
     1623FAVICON_HTML;
     1624    }
     1625        return $content;
     1626}
     1627
     1628/**
     1629 * Get the attachment post object associated with the current site favicon, based on the 'sitefavicon' option
     1630 *
     1631 * @param string $format Default 'png'. Format of the file we're looking for
     1632 * @return object If found, returns the post object; if not, a WP_Error object
     1633 */
     1634function get_site_favicon_attachment( $format = 'png' ){
     1635        $favicon_basename = get_option ( 'sitefavicon' );
     1636       
     1637        if ( ! empty( $favicon_basename ) ) {
     1638                $favicon_fullname = $favicon_basename . '-' . $format;
     1639               
     1640                $posts = get_posts( array( 'name' => $favicon_fullname, 'post_type' => 'attachment' ) );
     1641                if ( $posts[0] ){
     1642                        return $posts[0];
     1643                } else {
     1644                        return new WP_Error( 'attachment_missing', __( "No attachment for '$favicon_fullname' was found." ) );
     1645                }
     1646        } else {
     1647                return new WP_Error( 'not_defined', __( "No favicon file provided." ) );
     1648        }
     1649}
     1650
     1651/**
     1652 * Returns the URI for the site's favicon based on the option set in  Admin > Settings > General.
     1653 *
     1654 * @param string $format png|ico default 'png'. Use 'ico' for serving up an IE-compatible ICO file
     1655 * @return string fully qualified URI
     1656 */
     1657function get_site_favicon_uri( $format = 'png' ){
     1658        /** @TODO provide error checking for validity of $format and $size */
     1659        $favicon_attachment = get_site_favicon_attachment( $format );
     1660       
     1661        /** @TODO provide the ability to define a 'default' favicon that would be distributed with fresh WP installations */
     1662        if ( ! is_wp_error( $favicon_attachment ) ) {
     1663                return wp_get_attachment_url( $favicon_attachment->ID );
     1664        }
     1665       
     1666        // We get here because of an error condition
     1667        /** @TODO default to the theme's favicon **/
     1668        // ATM do nothing (so URI is blank, rather than a WP_Error)
     1669}
     1670
     1671/**
     1672 * Gets the path to the favicon file, or returns a WP_Error
     1673 * @param string $format Default 'png'
     1674 * @return mixed File string or WP_Error object
     1675 */
     1676function get_site_favicon_file( $format = 'png' ){
     1677        $favicon_attachment = get_site_favicon_attachment( $format );
     1678       
     1679        /** @TODO provide the ability to define a 'default' favicon that would be distributed with fresh WP installations */
     1680        if ( ! is_wp_error( $favicon_attachment ) ) {
     1681                return get_attached_file( $favicon_attachment->ID );
     1682        } else {
     1683                return $favicon_attachment; // returns the WP_Error object
     1684        }
     1685}
     1686
     1687/**
     1688 * Returns true or false depending on whether a custom favicon has been defined in Admin
     1689 * @return boolean
     1690 */
     1691function has_custom_favicon(){
     1692        $favicon_basename = get_option ( 'sitefavicon' );
     1693        /** @TODO more robust checking: don't just check that the option has been set: check that the file exists */
     1694        return ( ! empty( $favicon_basename ) );
     1695}
     1696
     1697/**
     1698 * Returns an HTML <img> tag populated with the site favicon, in the format specified (usually PNG)
     1699 * @param string $format Default 'png'. Valid values are 'png', 'bmp' (note 'ico' is NOT valid)
     1700 * @return mixed Returns HTML <img> tag or WP_Error if invalid format given. Returns nothing if the file is missing.
     1701 */
     1702function get_favicon_img( $format = 'png' ){
     1703        if (in_array( strtolower( $format ), array( 'png', 'bmp' ) ) ){
     1704                // Does the file actually exist?
     1705                $file = get_site_favicon_file( $format );
     1706                if (! is_wp_error( $file ) && file_exists( $file ) ){
     1707                        $src = get_site_favicon_uri( $format );
     1708                        if (!is_wp_error( $src ) ){
     1709                                return '<img src="' . $src . '" alt="' . _x( 'Site favicon thumbnail', 'Thumbnail image accessibility text' ) .'" />';
     1710                        }
     1711                }
     1712        } else {
     1713                return new WP_Error( 'invalid_file_format', __( 'Invalid file format. Valid formats are "png", "bmp".' ) );
     1714        }
     1715}
     1716
     1717/**
    15901718 * Display the links to the general feeds.
    15911719 *
    15921720 * @since 2.8.0
  • wp-includes/script-loader.php

     
    8888
    8989        $scripts->add( 'wp-fullscreen', "/wp-admin/js/wp-fullscreen$suffix.js", array('jquery'), false, 1 );
    9090
     91        $scripts->add( 'wp-favicon', "/wp-admin/js/wp-favicon$suffix.js", array('jquery'), false, 1 );
     92
    9193        $scripts->add( 'prototype', '/wp-includes/js/prototype.js', array(), '1.6.1');
    9294
    9395        $scripts->add( 'wp-ajax-response', "/wp-includes/js/wp-ajax-response$suffix.js", array('jquery'), false, 1 );