function wppa_create_thumbnail($id, $use_source = true)
{
    // Find file to make thumbnail from
    $source_path = wppa_fix_poster_ext(wppa_get_source_path($id), $id);
    // Use source if requested and available
    if ($use_source) {
        if (!wppa_switch('watermark_thumbs') && is_file($source_path)) {
            $file = $source_path;
            // Use sourcefile
        } else {
            $file = wppa_fix_poster_ext(wppa_get_photo_path($id), $id);
            // Use photofile
        }
        // Non standard orientation files: never use source
        $orient = wppa_get_exif_orientation($file);
        if ($orient > '1') {
            $file = wppa_fix_poster_ext(wppa_get_photo_path($id), $id);
            // Use photofile
        }
    } else {
        $file = wppa_fix_poster_ext(wppa_get_photo_path($id), $id);
        // Use photofile
    }
    // Max side
    $max_side = wppa_get_minisize();
    // Check file
    if (!file_exists($file)) {
        return false;
    }
    // No file, fail
    $img_attr = getimagesize($file);
    if (!$img_attr) {
        return false;
    }
    // Not an image, fail
    // Retrieve aspect
    $asp_attr = explode(':', wppa_opt('thumb_aspect'));
    // Get output path
    $thumbpath = wppa_get_thumb_path($id);
    if (wppa_get_ext($thumbpath) == 'xxx') {
        // Video poster
        $thumbpath = wppa_strip_ext($thumbpath) . '.jpg';
    }
    // Source size
    $src_size_w = $img_attr[0];
    $src_size_h = $img_attr[1];
    // Temp convert width if stereo
    if (wppa_get_photo_item($id, 'stereo')) {
        $src_size_w /= 2;
    }
    // Mime type and thumb type
    $mime = $img_attr[2];
    $type = $asp_attr[2];
    // Source native aspect
    $src_asp = $src_size_h / $src_size_w;
    // Required aspect
    if ($type == 'none') {
        $dst_asp = $src_asp;
    } else {
        $dst_asp = $asp_attr[0] / $asp_attr[1];
    }
    // Convert back width if stereo
    if (wppa_get_photo_item($id, 'stereo')) {
        $src_size_w *= 2;
    }
    // Create the source image
    switch ($mime) {
        // mime type
        case 1:
            // gif
            $temp = @imagecreatefromgif($file);
            if ($temp) {
                $src = imagecreatetruecolor($src_size_w, $src_size_h);
                imagecopy($src, $temp, 0, 0, 0, 0, $src_size_w, $src_size_h);
                imagedestroy($temp);
            } else {
                $src = false;
            }
            break;
        case 2:
            // jpeg
            if (!function_exists('wppa_imagecreatefromjpeg')) {
                wppa_log('Error', 'Function wppa_imagecreatefromjpeg does not exist.');
            }
            $src = @wppa_imagecreatefromjpeg($file);
            break;
        case 3:
            // png
            $src = @imagecreatefrompng($file);
            break;
    }
    if (!$src) {
        wppa_log('Error', 'Image file ' . $file . ' is corrupt while creating thmbnail');
        return true;
    }
    // Compute the destination image size
    if ($dst_asp < 1.0) {
        // Landscape
        $dst_size_w = $max_side;
        $dst_size_h = round($max_side * $dst_asp);
    } else {
        // Portrait
        $dst_size_w = round($max_side / $dst_asp);
        $dst_size_h = $max_side;
    }
    // Create the ( empty ) destination image
    $dst = imagecreatetruecolor($dst_size_w, $dst_size_h);
    if ($mime == 3) {
        // Png, save transparancy
        imagealphablending($dst, false);
        imagesavealpha($dst, true);
    }
    // Fill with the required color
    $c = trim(strtolower(wppa_opt('bgcolor_thumbnail')));
    if ($c != '#000000') {
        $r = hexdec(substr($c, 1, 2));
        $g = hexdec(substr($c, 3, 2));
        $b = hexdec(substr($c, 5, 2));
        $color = imagecolorallocate($dst, $r, $g, $b);
        if ($color === false) {
            wppa_log('Err', 'Unable to set background color to: ' . $r . ', ' . $g . ', ' . $b . ' in wppa_create_thumbnail');
        } else {
            imagefilledrectangle($dst, 0, 0, $dst_size_w, $dst_size_h, $color);
        }
    }
    // Switch on what we have to do
    switch ($type) {
        case 'none':
            // Use aspect from fullsize image
            $src_x = 0;
            $src_y = 0;
            $src_w = $src_size_w;
            $src_h = $src_size_h;
            $dst_x = 0;
            $dst_y = 0;
            $dst_w = $dst_size_w;
            $dst_h = $dst_size_h;
            break;
        case 'clip':
            // Clip image to given aspect ratio
            if ($src_asp < $dst_asp) {
                // Source image more landscape than destination
                $dst_x = 0;
                $dst_y = 0;
                $dst_w = $dst_size_w;
                $dst_h = $dst_size_h;
                $src_x = round(($src_size_w - $src_size_h / $dst_asp) / 2);
                $src_y = 0;
                $src_w = round($src_size_h / $dst_asp);
                $src_h = $src_size_h;
            } else {
                $dst_x = 0;
                $dst_y = 0;
                $dst_w = $dst_size_w;
                $dst_h = $dst_size_h;
                $src_x = 0;
                $src_y = round(($src_size_h - $src_size_w * $dst_asp) / 2);
                $src_w = $src_size_w;
                $src_h = round($src_size_w * $dst_asp);
            }
            break;
        case 'padd':
            // Padd image to given aspect ratio
            if ($src_asp < $dst_asp) {
                // Source image more landscape than destination
                $dst_x = 0;
                $dst_y = round(($dst_size_h - $dst_size_w * $src_asp) / 2);
                $dst_w = $dst_size_w;
                $dst_h = round($dst_size_w * $src_asp);
                $src_x = 0;
                $src_y = 0;
                $src_w = $src_size_w;
                $src_h = $src_size_h;
            } else {
                $dst_x = round(($dst_size_w - $dst_size_h / $src_asp) / 2);
                $dst_y = 0;
                $dst_w = round($dst_size_h / $src_asp);
                $dst_h = $dst_size_h;
                $src_x = 0;
                $src_y = 0;
                $src_w = $src_size_w;
                $src_h = $src_size_h;
            }
            break;
        default:
            // Not implemented
            return false;
    }
    // Copy left half if stereo
    if (wppa_get_photo_item($id, 'stereo')) {
        $src_w /= 2;
    }
    // Do the copy
    imagecopyresampled($dst, $src, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
    // Save the thumb
    $thumbpath = wppa_strip_ext($thumbpath);
    switch ($mime) {
        // mime type
        case 1:
            $full_thumbpath = $thumbpath . '.gif';
            imagegif($dst, $full_thumbpath);
            break;
        case 2:
            $full_thumbpath = $thumbpath . '.jpg';
            imagejpeg($dst, $full_thumbpath, wppa_opt('jpeg_quality'));
            break;
        case 3:
            $full_thumbpath = $thumbpath . '.png';
            imagepng($dst, $full_thumbpath, 6);
            break;
    }
    // Cleanup
    imagedestroy($src);
    imagedestroy($dst);
    // Make sure file is accessable
    wppa_chmod($full_thumbpath);
    // Optimize
    wppa_optimize_image_file($full_thumbpath);
    // Compute and save sizes
    wppa_get_thumbx($id, 'force');
    // forces recalc x and y
    return true;
}
function wppa_rotate($id, $ang)
{
    global $wpdb;
    // Check args
    $err = '1';
    if (!is_numeric($id) || !is_numeric($ang)) {
        return $err;
    }
    // Get the ext
    $err = '2';
    $ext = $wpdb->get_var($wpdb->prepare('SELECT ext FROM ' . WPPA_PHOTOS . ' WHERE id = %s', $id));
    if (!$ext) {
        return $err;
    }
    // Get the image
    $err = '3';
    $file = wppa_fix_poster_ext(wppa_get_photo_path($id), $id);
    if (!is_file($file)) {
        return $err;
    }
    // Get the imgdetails
    $err = '4';
    $img = getimagesize($file);
    if (!$img) {
        return $err;
    }
    // Get the image
    switch ($img[2]) {
        case 1:
            // gif
            $err = '5';
            $source = imagecreatefromgif($file);
            break;
        case 2:
            // jpg
            $err = '6';
            $source = wppa_imagecreatefromjpeg($file);
            break;
        case 3:
            // png
            $err = '7';
            $source = imagecreatefrompng($file);
            break;
        default:
            // unsupported mimetype
            $err = '10';
            $source = false;
    }
    if (!$source) {
        return $err;
    }
    // Rotate the image
    $err = '11';
    if ($ang == '360') {
        if (!imageflip($source, IMG_FLIP_HORIZONTAL)) {
            return $err;
        }
        $rotate = $source;
    } else {
        $rotate = imagerotate($source, $ang, 0);
        if (!$rotate) {
            return $err;
        }
    }
    // Save the image
    switch ($img[2]) {
        case 1:
            $err = '15';
            $bret = imagegif($rotate, $file, 95);
            break;
        case 2:
            $err = '16';
            $bret = imagejpeg($rotate, $file);
            break;
        case 3:
            $err = '17';
            $bret = imagepng($rotate, $file);
            break;
        default:
            $err = '20';
            $bret = false;
    }
    if (!$bret) {
        return $err;
    }
    // Destroy the source
    imagedestroy($source);
    // Destroy the result
    imagedestroy($rotate);
    // accessable
    wppa_chmod($file);
    // Optimized
    wppa_optimize_image_file($file);
    // Clear stored dimensions
    wppa_update_photo(array('id' => $id, 'thumbx' => '0', 'thumby' => '0', 'photox' => '0', 'photoy' => '0'));
    $err = '30';
    // Recreate the thumbnail, do NOT use source: source can not be rotated
    $bret = wppa_create_thumbnail($id, false);
    if (!$bret) {
        return $err;
    }
    // Return success
    return false;
}
function wppa_add_watermark($id)
{
    // Init
    if (!wppa_switch('watermark_on')) {
        return false;
    }
    // Watermarks off
    //	if ( wppa_is_video( $id ) ) return false;					// Can not on a video
    // Find the watermark file and location
    $temp = wppa_get_water_file_and_pos($id);
    $waterfile = $temp['file'];
    if (!$waterfile) {
        return false;
    }
    // an error has occurred
    $waterpos = $temp['pos'];
    // default
    if (basename($waterfile) == '--- none ---') {
        return false;
        // No watermark this time
    }
    // Open the watermark file
    $watersize = @getimagesize($waterfile);
    if (!is_array($watersize)) {
        return false;
    }
    // Not a valid picture file
    $waterimage = imagecreatefrompng($waterfile);
    if (empty($waterimage) or !$waterimage) {
        wppa_dbg_msg('Watermark file ' . $waterfile . ' not found or corrupt');
        return false;
        // No image
    }
    imagealphablending($waterimage, false);
    imagesavealpha($waterimage, true);
    // Open the photo file
    $file = wppa_get_photo_path($id);
    if (wppa_is_video($id)) {
        $file = wppa_fix_poster_ext($file, $id);
    }
    if (!is_file($file)) {
        return false;
    }
    // File gone
    $photosize = getimagesize($file);
    if (!is_array($photosize)) {
        return false;
        // Not a valid photo
    }
    switch ($photosize[2]) {
        case 1:
            $tempimage = imagecreatefromgif($file);
            $photoimage = imagecreatetruecolor($photosize[0], $photosize[1]);
            imagecopy($photoimage, $tempimage, 0, 0, 0, 0, $photosize[0], $photosize[1]);
            break;
        case 2:
            $photoimage = wppa_imagecreatefromjpeg($file);
            break;
        case 3:
            $photoimage = imagecreatefrompng($file);
            break;
    }
    if (empty($photoimage) or !$photoimage) {
        return false;
    }
    // No image
    $ps_x = $photosize[0];
    $ps_y = $photosize[1];
    $ws_x = $watersize[0];
    $ws_y = $watersize[1];
    $src_x = 0;
    $src_y = 0;
    if ($ws_x > $ps_x) {
        $src_x = ($ws_x - $ps_x) / 2;
        $ws_x = $ps_x;
    }
    if ($ws_y > $ps_y) {
        $src_y = ($ws_y - $ps_y) / 2;
        $ws_y = $ps_y;
    }
    $loy = substr($waterpos, 0, 3);
    switch ($loy) {
        case 'top':
            $dest_y = 0;
            break;
        case 'cen':
            $dest_y = ($ps_y - $ws_y) / 2;
            break;
        case 'bot':
            $dest_y = $ps_y - $ws_y;
            break;
        default:
            $dest_y = 0;
            // should never get here
    }
    $lox = substr($waterpos, 3);
    switch ($lox) {
        case 'lft':
            $dest_x = 0;
            break;
        case 'cen':
            $dest_x = ($ps_x - $ws_x) / 2;
            break;
        case 'rht':
            $dest_x = $ps_x - $ws_x;
            break;
        default:
            $dest_x = 0;
            // should never get here
    }
    $opacity = strpos($waterfile, '/temp/') === false ? intval(wppa_opt('watermark_opacity')) : intval(wppa_opt('watermark_opacity_text'));
    wppa_imagecopymerge_alpha($photoimage, $waterimage, $dest_x, $dest_y, $src_x, $src_y, $ws_x, $ws_y, $opacity);
    // Save the result
    switch ($photosize[2]) {
        case 1:
            imagegif($photoimage, $file);
            break;
        case 2:
            imagejpeg($photoimage, $file, wppa_opt('jpeg_quality'));
            break;
        case 3:
            imagepng($photoimage, $file, 7);
            break;
    }
    // accessable
    wppa_chmod($file);
    // Optimized
    wppa_optimize_image_file($file);
    // Cleanup
    imagedestroy($photoimage);
    imagedestroy($waterimage);
    return true;
}
function wppa_create_stereo_image($id, $type, $glass)
{
    static $f299;
    static $f587;
    static $f114;
    // Init
    if ($glass == 'rc') {
        $glass = 'redcyan';
    }
    if (!is_array($f299)) {
        $i = 0;
        while ($i < 256) {
            $f299[$i] = floor(0.299 * $i + 0.5);
            $f587[$i] = floor(0.587 * $i + 0.5);
            $f114[$i] = floor(0.114 * $i + 0.5);
            $i++;
        }
    }
    // Feature enabled?
    if (!wppa_switch('enable_stereo')) {
        return;
    }
    // Init.
    $is_stereo = wppa_is_stereo($id);
    if (!$is_stereo) {
        return;
    }
    $stereodir = WPPA_UPLOAD_PATH . '/stereo';
    if (!is_dir($stereodir)) {
        wppa_mkdir($stereodir);
    }
    $fromfile = wppa_get_photo_path($id);
    $tofile = wppa_get_stereo_path($id, $type, $glass);
    $sizes = getimagesize($fromfile);
    $width = $sizes['0'] / 2;
    $height = $sizes['1'];
    $fromimage = wppa_imagecreatefromjpeg($fromfile);
    $toimage = imagecreatetruecolor($width, $height);
    if ($is_stereo == 1) {
        $offset1 = 0;
        $offset2 = $width;
    } else {
        $offset1 = $width;
        $offset2 = 0;
    }
    // Do the dirty work
    switch ($type) {
        case 'color':
            for ($y = 0; $y < $height; $y++) {
                for ($x = 0; $x < $width; $x++) {
                    $rgb1 = imagecolorat($fromimage, $x + $offset1, $y);
                    $r1 = $rgb1 >> 16 & 0xff;
                    $g1 = $rgb1 >> 8 & 0xff;
                    $b1 = $rgb1 & 0xff;
                    $rgb2 = imagecolorat($fromimage, $x + $offset2, $y);
                    $r2 = $rgb2 >> 16 & 0xff;
                    $g2 = $rgb2 >> 8 & 0xff;
                    $b2 = $rgb2 & 0xff;
                    // Red - Cyan glass
                    if ($glass == 'redcyan') {
                        $newpix = $r2 << 16 | $g1 << 8 | $b1;
                    } else {
                        $newpix = $r1 << 16 | $g2 << 8 | $b1;
                    }
                    imagesetpixel($toimage, $x, $y, $newpix);
                }
            }
            imagejpeg($toimage, $tofile, wppa_opt('jpeg_quality'));
            break;
        case 'gray':
            for ($y = 0; $y < $height; $y++) {
                for ($x = 0; $x < $width; $x++) {
                    $rgb1 = imagecolorat($fromimage, $x + $offset1, $y);
                    $r1 = $rgb1 >> 16 & 0xff;
                    $g1 = $rgb1 >> 8 & 0xff;
                    $b1 = $rgb1 & 0xff;
                    $rgb2 = imagecolorat($fromimage, $x + $offset2, $y);
                    $r2 = $rgb2 >> 16 & 0xff;
                    $g2 = $rgb2 >> 8 & 0xff;
                    $b2 = $rgb2 & 0xff;
                    // Red - Cyan glass
                    if ($glass == 'redcyan') {
                        $r = $f299[$r2] + $f587[$g2] + $f114[$b2];
                        $g = $f299[$r1] + $f587[$g1] + $f114[$b1];
                        $b = $f299[$r1] + $f587[$g1] + $f114[$b1];
                        $newpix = $r << 16 | $g << 8 | $b;
                    } else {
                        $r = $f299[$r1] + $f587[$g1] + $f114[$b1];
                        $g = $f299[$r2] + $f587[$g2] + $f114[$b2];
                        $b = $f299[$r1] + $f587[$g1] + $f114[$b1];
                        $newpix = $r << 16 | $g << 8 | $b;
                    }
                    imagesetpixel($toimage, $x, $y, $newpix);
                }
            }
            imagejpeg($toimage, $tofile, wppa_opt('jpeg_quality'));
            break;
        case 'true':
            for ($y = 0; $y < $height; $y++) {
                for ($x = 0; $x < $width; $x++) {
                    $rgb1 = imagecolorat($fromimage, $x + $offset1, $y);
                    $r1 = $rgb1 >> 16 & 0xff;
                    $g1 = $rgb1 >> 8 & 0xff;
                    $b1 = $rgb1 & 0xff;
                    $rgb2 = imagecolorat($fromimage, $x + $offset2, $y);
                    $r2 = $rgb2 >> 16 & 0xff;
                    $g2 = $rgb2 >> 8 & 0xff;
                    $b2 = $rgb2 & 0xff;
                    // Red - Cyan glass
                    if ($glass == 'redcyan') {
                        $r = $f299[$r1] + $f587[$g1] + $f114[$b1];
                        $g = 0;
                        $b = $f299[$r2] + $f587[$g2] + $f114[$b2];
                        $newpix = $r << 16 | $g << 8 | $b;
                    } else {
                        $r = $f299[$r2] + $f587[$g2] + $f114[$b2];
                        $g = $f299[$r1] + $f587[$g1] + $f114[$b1];
                        $b = 0;
                        $newpix = $r << 16 | $g << 8 | $b;
                    }
                    imagesetpixel($toimage, $x, $y, $newpix);
                }
            }
            imagejpeg($toimage, $tofile, wppa_opt('jpeg_quality'));
            break;
        case 'halfcolor':
            for ($y = 0; $y < $height; $y++) {
                for ($x = 0; $x < $width; $x++) {
                    $rgb1 = imagecolorat($fromimage, $x + $offset1, $y);
                    $r1 = $rgb1 >> 16 & 0xff;
                    $g1 = $rgb1 >> 8 & 0xff;
                    $b1 = $rgb1 & 0xff;
                    $rgb2 = imagecolorat($fromimage, $x + $offset2, $y);
                    $r2 = $rgb2 >> 16 & 0xff;
                    $g2 = $rgb2 >> 8 & 0xff;
                    $b2 = $rgb2 & 0xff;
                    // Red - Cyan glass
                    if ($glass == 'redcyan') {
                        $r = $f299[$r1] + $f587[$g1] + $f114[$b1];
                        //	$g = $g2;
                        //	$b = $b2;
                        $newpix = $r << 16 | $g2 << 8 | $b2;
                    } else {
                        $r = $f299[$r2] + $f587[$g2] + $f114[$b2];
                        //						$g = $g1;
                        //						$b = $b2;
                        $r = ceil(min($r, 255));
                        $newpix = $r << 16 | $g1 << 8 | $b2;
                    }
                    imagesetpixel($toimage, $x, $y, $newpix);
                }
            }
            imagejpeg($toimage, $tofile, wppa_opt('jpeg_quality'));
            break;
        case 'optimized':
            for ($y = 0; $y < $height; $y++) {
                for ($x = 0; $x < $width; $x++) {
                    $rgb1 = imagecolorat($fromimage, $x + $offset1, $y);
                    $r1 = $rgb1 >> 16 & 0xff;
                    $g1 = $rgb1 >> 8 & 0xff;
                    $b1 = $rgb1 & 0xff;
                    $rgb2 = imagecolorat($fromimage, $x + $offset2, $y);
                    $r2 = $rgb2 >> 16 & 0xff;
                    $g2 = $rgb2 >> 8 & 0xff;
                    $b2 = $rgb2 & 0xff;
                    // Red - Cyan glass
                    if ($glass == 'redcyan') {
                        $r = 0.7 * $g1 + 0.3 * $b1;
                        $g = $g2;
                        $b = $b2;
                        $r = ceil(min($r, 255));
                        $newpix = $r << 16 | $g << 8 | $b;
                    } else {
                        $r = 0.7 * $g2 + 0.3 * $b2;
                        $g = $g1;
                        $b = $b2;
                        $r = ceil(min($r, 255));
                        $newpix = $r << 16 | $g << 8 | $b;
                    }
                    imagesetpixel($toimage, $x, $y, $newpix);
                }
            }
            imagejpeg($toimage, $tofile, wppa_opt('jpeg_quality'));
            break;
        case '_flat':
            imagecopy($toimage, $fromimage, 0, 0, 0, 0, $width, $height);
            imagejpeg($toimage, $tofile, wppa_opt('jpeg_quality'));
            break;
        default:
            break;
    }
    // accessable
    wppa_chmod($tofile);
    // Optimized
    wppa_optimize_image_file($tofile);
    // Bump version
    wppa_bump_photo_rev();
}