#!/usr/bin/php
<?php
#######################################################
# this script create missing screenhot thumbnails     #
# before to run, please empty the whole appdata queue #
#######################################################

# configuration: please put the connection infos here
$hAppdbLink = mysql_connect("localhost", "root", "");
mysql_select_db("apidb");
define("DOCUMENTROOT", "/var/www/localhost/htdocs");
define("WATERMARK", "/images/winehq_top_logo.png");
define("APPDB_THUMBNAIL_WIDTH","128"); // to be copied from the config file
define("APPDB_THUMBNAIL_HEIGHT","128"); // to be copied from the config file
define("APPDB_SCREENSHOT_MAXWIDTH","800"); // to be copied from the config file
define("APPDB_SCREENSHOT_MAXHEIGHT","600"); // to be copied from the config file

#the following lines don't need to be changed
$sql = "SELECT id,url FROM appData";
$result = mysql_query($sql);
echo "\nStarting job...\n\n";
while($row=mysql_fetch_array($result)) {
    echo "Working on screenshot #$row[id]\n";

    $screenshot = new screenshot($row['id']);
    // first we will create the thumbnail
    // load the screenshot
    $screenshot->oScreenshotImage->make_thumb(0,0,1,'#000000');
    // store the image
    $screenshot->oScreenshotImage->output_to_file(DOCUMENTROOT."/data/screenshots/thumbnails/".$screenshot->iScreenshotId);
    $screenshot->free();

    // now we'll process the screenshot image for watermarking
    // load the screenshot
    $screenshot = new screenshot($row['id']);
    // resize the image
    $screenshot->oScreenshotImage->make_full();
    // store the resized image
    $screenshot->oScreenshotImage->output_to_file(DOCUMENTROOT."/data/screenshots/".$screenshot->iScreenshotId);
    $screenshot->free();
    // delete the old screenshot and update the table
    $sql2 = "UPDATE appData SET url = '".$screenshot->iScreenshotId."' WHERE id = '".$screenshot->iScreenshotId."'";
    $result2 = mysql_query($sql2);
    if($row['url']!=$screenshot->iScreenshotId)
        unlink(DOCUMENTROOT."/data/screenshots/".$row['url']);

    // reload the resized screenshot
    $screenshot = new screenshot($row['id']);
    // load the watermark
    $watermark = new image(WATERMARK);
    // add the watermark to the screenshot
    $screenshot->oScreenshotImage->add_watermark($watermark->get_image_resource());
    // clean up the memory
    $watermark->destroy();
    // store the watermarked image
    $screenshot->oScreenshotImage->output_to_file();
    $screenshot->free();
}

    echo "Work done\n\n";


/******************************************/
/* screenshot class and related functions */
/******************************************/

/**
 * Screenshot class for handling screenshots and thumbnails
 */
class Screenshot {
    var $iScreenshotId;
    var $sDescription;
    var $oScreenshotImage;
    var $oThumbnailImage;
    var $sTable;
    var $sTableId;
    var $userId;
    var $bQueued;
    var $iVersionId;
    var $iAppId;
    var $sDirectory;

    /**    
     * constructor, fetches the description and creates the Image objects and files if needed.
     */
    function Screenshot($iScreenshotId,$bQueued = false,$iUserId = null,$iAppId = null,$iVersionId = null,$sDescription = null,$hFile = null)
    {
        $this->sTable = appData;          
        $this->sTableId = id;
        $this->sDirectory = "screenshots";
 
        // we are working on an existing screenshot
        $this->iScreenshotId = $iScreenshotId;
        $sQuery = "SELECT * FROM ".$this->sTable." WHERE ".$this->sTableId." = ".$this->iScreenshotId." AND type = 'image'";
        if($hResult = mysql_query($sQuery))
        {
            $oRow = mysql_fetch_object($hResult);
            $this->iScreenshotId = $oRow->id;
            $this->sDescription = $oRow->description;
            $this->oScreenshotImage = new Image("/data/".$this->sDirectory."/".$oRow->url);
            $this->oThumbnailImage = new Image("/data/".$this->sDirectory."/thumbnails/".$oRow->url);
            $this->sSubmitTime = $oRow->submitTime;
            $this->iAppId = $oRow->appId;
            $this->iVersionId = $oRow->versionId;
        }
    }

    /**
     * clean up the memory
     */
    function free() 
    {
        $this->oScreenshotImage->destroy();
        $this->oThumbnailImage->destroy();
    }

    /**
     * sets the screenshot description.
     */
    function setDescription($sDescription)
    {
        $sQuery = "UPDATE ".$this->sTableId." SET description = '".$sDescription."' WHERE ".$this->sTableId." = ".$this->iScreenshotId." AND type = 'image'";   
        if($hResult = mysql_query($sQuery))
            $this->sDescription = $sDescription;
    }

}


/*************************************/
/* image and image_resource classes  */
/*************************************/

/**
 * Image class for handling screenshot and thumbnail image files.
 */
class Image {
    var $file; // absolute path from the docroot
    var $debug_log;
    var $image;
    var $width;
    var $height;
    var $type;
    
    /**
     * Constructor:
     * $file is the full path to the image. $this->is_loaded()
     * should really be checked after making a new object.
     */
    function Image($sRelativePath)
    {
        $this->file = DOCUMENTROOT.$sRelativePath;
       
        $info = @getimagesize($this->file);       
        
        if( empty($info) )
        {
            $this->set_debuglog("Failed to load file ".$this->file);
            return;
        }
        
        switch( $info[2] )
        {
            case 2:
                $data = imagecreatefromjpeg($this->file);
            break;
        
            case 3:
                $data = imagecreatefrompng($this->file);
            break;
        
            default;
                $this->set_debuglog("Image type ({$info[2]}) unkown");
                return;
            return;
        }
        
        $this->image = $data;
        $this->width = $info[0];
        $this->height = $info[1];
        $this->type = $info[2];
        
        $this->set_debuglog("New image class created with as $file as"
                          ." file and {$info[2]} as type. Dimensions"
                          ." {$info[0]}x{$info[1]}");
    }
    
    /**
     * is_loaded()
     * This function should always be checked after loading a file
     * with the constructor. Rteturns true if the image has been
     * succesfully loaded.
     */ 
    function is_loaded()
    {
        if($this->width > 0 AND $this->height > 0)
            return true;
        else
            return false;
    }
    
    /**
     * Returns the latest debug log made for the last function. If $full is
     * set it will return the full log as array of the object.
     */
    function get_debuglog($full = 0)
    {
        if($full)
            return $this->debug_log;
        else
            return end($this->debug_log);
    }
    
    function get_width()
    {
        return $this->width;
    }
    
    function get_height()
    {
        return $this->height;
    }
    
    /**
     * Returns the image resource identifier.
     */
    function get_image_resource()
    {
        return $this->image;
    }
    
    /**
     * make_thumb()
     *
     * Calculates resize based on one parameter and calculates the other
     * with the right aspect ratio. If you want to use $new_height set
     * $new_width to 0.
     *
     * If none are set APPDB_THUMBNAIL_WIDTH is used. If both are set
     * $new_width is used.
     *
     * If you want to make a border, look at resize_image_border() comment
     * and set $border_width and $border_color as appropriate.
     *
     */
    function make_thumb($new_width, $new_height, $border_width = 0, $border_color = '')
    {
        
        if($new_width == 0 AND $new_height == 0)
        {
            $new_width = APPDB_THUMBNAIL_WIDTH;
            $new_height = $this->calculate_proportions($this->width, $this->height,$new_width);
        }
        else if($new_width > 0)
        {
            $new_height = $this->calculate_proportions($this->width, $this->height,$new_width);
        }
        else if($new_height > 0)
        {
            $new_width = $this->calculate_proportions($this->width, $this->height, 0, $new_height);
        }
                    
        $this->set_debuglog("Resizing image to $new_width x $new_height");
        
        if(!empty($border_color) and $border_width > 0)
            $this->resize_image_border($border_color,$border_width,$new_height,$new_width);
        else
            $this->resize_image( $new_height, $new_width);        
    }
    
    /**
     * make_full() 
     *
     * Function will make sure your image is as big or smaller than the sizes
     * set here with $max_width and $max_height. Aspect ratio will be mantained.
     *
     * If none are set APPDB_SCREENSHOT_MAXWIDTH and APPDB_SCREENSHOT_MAXHEIGHT
     * are used.
     */    
    function make_full($max_width = 0, $max_height = 0)
    {
        if(!$max_width > 0)
            $max_width = APPDB_SCREENSHOT_MAXWIDTH;
        
        if(!$max_height > 0)
            $max_height = APPDB_SCREENSHOT_MAXHEIGHT;
            
        if($this->width > $max_width)
        {
            /* The width is too much */
            $new_width = $max_width;
            $new_height = $this->calculate_proportions($this->width,$this->height,$new_width);
            
            /* Check if the height is also within the limits */
            if($new_height > $max_height )
            {
                $new_width = $this->calculate_proportions($new_width,$new_height,0,$max_height);
                $new_height = $max_height;
            }
        }
        else if($this->height > $max_height)
        {
            /* Width was ok, height not */
            $new_width = $this->calculate_proportions($this->width,$this->height,0,$max_height);
            $new_height = $max_height;
        }
        else
        {
            /* All ok */
            $new_width = $this->width;
            $new_height = $this->height;
        }
        
        $this->set_debuglog("Resizing image to $new_width x $new_height");
        
        $this->resize_image($new_height, $new_width);
    }
    
    /**
     * resize_image()
     *
     * Resizes the image with the width and height specified with
     * $new_height and $new_width.
     */
    function resize_image($new_height, $new_width)
    {
        // GD 2.x
        // $new = imagecreatetruecolor($new_width, $new_height);
        // GD 1.x
        $new = imagecreate($new_width, $new_height);
        
        // GD 2.x
        // imagecopyresampled($new,$this->image,0,0,0,0,$new_width,$new_height,$this->width,$this->height);
        // GD 1.x
        imagecopyresized($new,$this->image,0,0,0,0,$new_width,$new_height,$this->width,$this->height);
        
        $this->set_debuglog("imagecopyresized($new,$this->image,0,0,0,0,$new_width,$new_height,$this->width,$this->height);");
        
        $this->image = $new;
    }
    
    /**
     * resize_image_border()
     *
     * Resizes the image. With the $new_width + $border_width*2
     * and $new_height + $border_width*2 as size. $border_color is a
     * HTML hexadecimal color (like #0000FF)
     */
    function resize_image_border($border_color, $border_width, $new_height, $new_width)
    {
        
        $r = hexdec(substr($border_color, 1, 2));
        $g = hexdec(substr($border_color, 3, 2));
        $b = hexdec(substr($border_color, 5, 2));
        
        /* We multiply the border width by two because there are are borders
        at both sides */
        // GD 2.x
        // $new = imagecreatetruecolor($new_width + ($border_width*2), $new_height + ($border_width*2));
        // GD 1.x
        $new = imagecreate($new_width + ($border_width*2), $new_height + ($border_width*2));
        
        /* Make the border by filling it completely,
        later on we will overwrite everything except the border */
        $color = ImageColorAllocate( $new, $r, $g, $b );
        imagefill($new,0,0,$color);
        
        // GD 2.x
        // imagecopyresampled($new,$this->image,$border_width,$border_width,0,0,
        //                 $new_width,$new_height,$this->width,$this->height);
        // GD 1.x
        imagecopyresized($new,$this->image,$border_width,$border_width,0,0,
                         $new_width,$new_height,$this->width,$this->height);
        
        $this->set_debuglog("imagecopyresized($new,$this->image,$border_width,$border_width,0,0,"
                           ." $new_width,$new_height,$this->width,$this->height); with a $border_width px border"
                           ." in $border_color");
        $this->image = $new;
    }
    
    /**
     * add_watermark()
     *
     * $watermark is a image resource identifier to any image resource.
     *
     * $min_mark_wwidth and $min_mark_height are the minimum sizes of the
     * destination image before the watermark is added. If none are set
     * both will be 0.
     *
     * A warning for transparency. If you resize an image down with make_thumb()
     * you loose the transparency on png images.
     */
    function add_watermark($watermark,$min_mark_width = 0,$min_mark_height = 0)
    {
        
        $watermark_width = imagesx($watermark);
        $watermark_height = imagesy($watermark);
        
        if( $watermark_width > $min_mark_width AND $watermark_height > $min_mark_height)
        {
            $watermark_x = $this->width - $watermark_width;
            $watermark_y = $this->height - $watermark_height;
            
            imagecopy($this->image, $watermark, $watermark_x, $watermark_y, 0, 0, $watermark_width, $watermark_height);
        }
    }
    
    /**
     * Output the image to a file set with $store.
     *
     * $type is optional and is set like the second index of getimagesize().
     * If none (or 0) is set the orginal type of the file is used.
     * If $store is not give, the current file name will be used.
     * $quality is the jpeg output quality (100 best, 0 worst). Default is 75
     */
    function output_to_file($store=null, $type = 0, $quality = 75)
    {
        if(!$store)
            $store = $this->file;
        if($type == 0)
            $type = $this->type;
        
        switch($type)
        {
            case 2:
            imagejpeg($this->image,$store,$quality);
            $this->set_debuglog("Outputed file as jpeg to $store");
            break;
            
            case 3:
            imagepng($this->image,$store);
            $this->set_debuglog("Outputed file as png to $store");
            break;
            
            default:
            $this->set_debuglog("Unkown output type");
            return;
        }
        
        return true;
    }
    
    /**
     * Destroys the image resource. Be sure to do this at the end of your
     * actions with this object.
     */
    function destroy()
    {
        if(is_resource($this->image))
            imagedestroy($this->image);
    }

    
    /***********************
    * PRIVATE FUNCTIONS
    ************************/
    
    function set_debuglog( $log ) {
        $this->debug_log[] = $log;
    }
    
    function calculate_proportions($width, $height, $new_width, $new_height = '0')
    {
        if($new_width > 0)
            // we want to calculate the new height
            return ($height * $new_width) / $width;
        else if( $new_height > 0 )
            return ($width * $new_height) / $height;
        else
            return 0;
    }

}
?>
