From 7cc8c369cb6a01cffb58215966844b53794f32f4 Mon Sep 17 00:00:00 2001 From: Fabio Comuni Date: Thu, 7 Jun 2012 17:42:13 +0200 Subject: [PATCH 1/2] Add support for PNG images with alpha --- boot.php | 7 ++- include/Photo.php | 127 ++++++++++++++++++++++++++++++++++++------ include/items.php | 12 ++-- include/network.php | 5 +- include/user.php | 8 ++- mod/parse_url.php | 5 +- mod/photo.php | 18 ++++-- mod/photos.php | 51 ++++++++++------- mod/profile_photo.php | 10 ++-- mod/wall_upload.php | 34 +++++------ update.php | 8 ++- 11 files changed, 215 insertions(+), 70 deletions(-) diff --git a/boot.php b/boot.php index 7961efc4..0e8f017f 100644 --- a/boot.php +++ b/boot.php @@ -11,7 +11,7 @@ require_once('include/cache.php'); define ( 'FRIENDICA_PLATFORM', 'Friendica'); define ( 'FRIENDICA_VERSION', '3.0.1366' ); define ( 'DFRN_PROTOCOL_VERSION', '2.23' ); -define ( 'DB_UPDATE_VERSION', 1148 ); +define ( 'DB_UPDATE_VERSION', 1149 ); define ( 'EOL', "
\r\n" ); define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' ); @@ -28,6 +28,11 @@ define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' ); */ define ( 'JPEG_QUALITY', 100 ); +/** + * $a->config['system']['png_quality'] from 0 (uncompressed) to 9 + */ +define ( 'PNG_QUALITY', 8 ); + /** * Not yet used diff --git a/include/Photo.php b/include/Photo.php index fce55999..ffefc37e 100644 --- a/include/Photo.php +++ b/include/Photo.php @@ -7,14 +7,34 @@ class Photo { private $width; private $height; private $valid; + private $type; + private $types; - public function __construct($data) { + /** + * supported mimetypes and corresponding file extensions + */ + static function supportedTypes() { + $t = array(); + $t['image/jpeg'] ='jpg'; + if (imagetypes() & IMG_PNG) $t['image/png'] = 'png'; + return $t; + } + + public function __construct($data, $type="image/jpeg") { + + $this->types = $this->supportedTypes(); + if (!array_key_exists($type,$this->types)){ + $type='image/jpeg'; + } $this->valid = false; + $this->type = $type; $this->image = @imagecreatefromstring($data); if($this->image !== FALSE) { $this->width = imagesx($this->image); $this->height = imagesy($this->image); $this->valid = true; + imagealphablending($this->image, false); + imagesavealpha($this->image, true); } } @@ -38,6 +58,13 @@ class Photo { public function getImage() { return $this->image; } + + public function getType() { + return $this->type; + } + public function getExt() { + return $this->types[$this->type]; + } public function scaleImage($max) { @@ -78,6 +105,9 @@ class Photo { $dest = imagecreatetruecolor( $dest_width, $dest_height ); + imagealphablending($dest->image, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127));; // fill with alpha imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); if($this->image) imagedestroy($this->image); @@ -134,6 +164,9 @@ class Photo { $dest = imagecreatetruecolor( $dest_width, $dest_height ); + imagealphablending($dest->image, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127));; // fill with alpha imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); if($this->image) imagedestroy($this->image); @@ -148,6 +181,9 @@ class Photo { public function scaleImageSquare($dim) { $dest = imagecreatetruecolor( $dim, $dim ); + imagealphablending($dest->image, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127));; // fill with alpha imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dim, $dim, $this->width, $this->height); if($this->image) imagedestroy($this->image); @@ -159,6 +195,9 @@ class Photo { public function cropImage($max,$x,$y,$w,$h) { $dest = imagecreatetruecolor( $max, $max ); + imagealphablending($dest->image, false); + imagesavealpha($dest, true); + if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127));; // fill with alpha imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $max, $max, $w, $h); if($this->image) imagedestroy($this->image); @@ -168,20 +207,38 @@ class Photo { } public function saveImage($path) { - $quality = get_config('system','jpeg_quality'); - if((! $quality) || ($quality > 100)) - $quality = JPEG_QUALITY; - imagejpeg($this->image,$path,$quality); + switch($this->type){ + case "image/png": + $quality = get_config('system','png_quality'); + if((! $quality) || ($quality > 9)) + $quality = PNG_QUALITY; + imagepng($this->image, $path, $quality); + break; + default: + $quality = get_config('system','jpeg_quality'); + if((! $quality) || ($quality > 100)) + $quality = JPEG_QUALITY; + imagejpeg($this->image,$path,$quality); + } + } public function imageString() { ob_start(); + switch($this->type){ + case "image/png": + $quality = get_config('system','png_quality'); + if((! $quality) || ($quality > 9)) + $quality = PNG_QUALITY; + imagepng($this->image,NULL, $quality); + break; + default: + $quality = get_config('system','jpeg_quality'); + if((! $quality) || ($quality > 100)) + $quality = JPEG_QUALITY; - $quality = get_config('system','jpeg_quality'); - if((! $quality) || ($quality > 100)) - $quality = JPEG_QUALITY; - - imagejpeg($this->image,NULL,$quality); + imagejpeg($this->image,NULL,$quality); + } $s = ob_get_contents(); ob_end_clean(); return $s; @@ -200,8 +257,8 @@ class Photo { $guid = get_guid(); $r = q("INSERT INTO `photo` - ( `uid`, `contact-id`, `guid`, `resource-id`, `created`, `edited`, `filename`, `album`, `height`, `width`, `data`, `scale`, `profile`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid` ) - VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, '%s', '%s', '%s', '%s' )", + ( `uid`, `contact-id`, `guid`, `resource-id`, `created`, `edited`, `filename`, type, `album`, `height`, `width`, `data`, `scale`, `profile`, `allow_cid`, `allow_gid`, `deny_cid`, `deny_gid` ) + VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, '%s', '%s', '%s', '%s' )", intval($uid), intval($cid), dbesc($guid), @@ -209,6 +266,7 @@ class Photo { dbesc(datetime_convert()), dbesc(datetime_convert()), dbesc(basename($filename)), + dbesc($this->type), dbesc($album), intval($this->height), intval($this->width), @@ -230,6 +288,38 @@ class Photo { }} +/** + * Guess image mimetype from filename or from Content-Type header + * + * @arg $filename string Image filename + * @arg $fromcurl boolean Check Content-Type header from curl request + */ +function guess_image_type($filename, $fromcurl=false) { + $type = null; + if ($fromcurl) { + $a = get_app(); + $headers=array(); + $h = explode("\n",$a->get_curl_headers()); + foreach ($h as $l) { + list($k,$v) = array_map("trim", explode(":", trim($l), 2)); + $headers[$k] = $v; + } + if (array_key_exists('Content-Type', $headers)) + $type = $headers['Content-Type']; + } + if (is_null($type)){ + $ext = pathinfo($filename, PATHINFO_EXTENSION); + $types = Photo::supportedTypes(); + foreach ($types as $m=>$e){ + if ($ext==$e) return $m; + } + $type = "image/jpeg"; + } + + return $type; + +} + function import_profile_photo($photo,$uid,$cid) { $a = get_app(); @@ -238,7 +328,12 @@ function import_profile_photo($photo,$uid,$cid) { $filename = basename($photo); $img_str = fetch_url($photo,true); - $img = new Photo($img_str); + + // guess mimetype from headers or filename + $type = guess_image_type($photo,true); + + + $img = new Photo($img_str, $type); if($img->is_valid()) { $img->scaleImageSquare(175); @@ -266,9 +361,9 @@ function import_profile_photo($photo,$uid,$cid) { - $photo = $a->get_baseurl() . '/photo/' . $hash . '-4.jpg'; - $thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.jpg'; - $micro = $a->get_baseurl() . '/photo/' . $hash . '-6.jpg'; + $photo = $a->get_baseurl() . '/photo/' . $hash . '-4.' . $img->getExt(); + $thumb = $a->get_baseurl() . '/photo/' . $hash . '-5.' . $img->getExt(); + $micro = $a->get_baseurl() . '/photo/' . $hash . '-6.' . $img->getExt(); } else $photo_failure = true; diff --git a/include/items.php b/include/items.php index 66e219dd..15c043e9 100755 --- a/include/items.php +++ b/include/items.php @@ -1346,7 +1346,11 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) } $img_str = fetch_url($photo_url,true); - $img = new Photo($img_str); + // guess mimetype from headers or filename + $type = guess_image_type($photo_url,true); + + + $img = new Photo($img_str, $type); if($img->is_valid()) { if($have_photo) { q("DELETE FROM `photo` WHERE `resource-id` = '%s' AND `contact-id` = %d AND `uid` = %d", @@ -1372,9 +1376,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) q("UPDATE `contact` SET `avatar-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s' WHERE `uid` = %d AND `id` = %d LIMIT 1", dbesc(datetime_convert()), - dbesc($a->get_baseurl() . '/photo/' . $hash . '-4.jpg'), - dbesc($a->get_baseurl() . '/photo/' . $hash . '-5.jpg'), - dbesc($a->get_baseurl() . '/photo/' . $hash . '-6.jpg'), + dbesc($a->get_baseurl() . '/photo/' . $hash . '-4.'.$img->getExt()), + dbesc($a->get_baseurl() . '/photo/' . $hash . '-5.'.$img->getExt()), + dbesc($a->get_baseurl() . '/photo/' . $hash . '-6.'.$img->getExt()), intval($contact['uid']), intval($contact['id']) ); diff --git a/include/network.php b/include/network.php index eeb2460d..446413cd 100644 --- a/include/network.php +++ b/include/network.php @@ -807,8 +807,11 @@ function scale_external_images($s,$include_link = true) { if(stristr($mtch[1],$hostname)) continue; $i = fetch_url($mtch[1]); + // guess mimetype from headers or filename + $type = guess_image_type($mtch[1],true); + if($i) { - $ph = new Photo($i); + $ph = new Photo($i, $type); if($ph->is_valid()) { $orig_width = $ph->getWidth(); $orig_height = $ph->getHeight(); diff --git a/include/user.php b/include/user.php index af43a2b5..2477438b 100644 --- a/include/user.php +++ b/include/user.php @@ -284,7 +284,11 @@ function create_user($arr) { $filename = basename($photo); $img_str = fetch_url($photo,true); - $img = new Photo($img_str); + // guess mimetype from headers or filename + $type = guess_image_type($photo,true); + + + $img = new Photo($img_str, $type); if($img->is_valid()) { $img->scaleImageSquare(175); @@ -324,4 +328,4 @@ function create_user($arr) { $result['user'] = $u; return $result; -} \ No newline at end of file +} diff --git a/mod/parse_url.php b/mod/parse_url.php index 27dac4d5..cdf2223a 100644 --- a/mod/parse_url.php +++ b/mod/parse_url.php @@ -215,8 +215,11 @@ function parse_url_content(&$a) { $i = fetch_url($image); if($i) { + // guess mimetype from headers or filename + $type = guess_image_type($image,true); + require_once('include/Photo.php'); - $ph = new Photo($i); + $ph = new Photo($i, $type); if($ph->is_valid()) { if($ph->getWidth() > 300 || $ph->getHeight() > 300) { $ph->scaleImage(300); diff --git a/mod/photo.php b/mod/photo.php index 3cd8250a..e8e74cfd 100644 --- a/mod/photo.php +++ b/mod/photo.php @@ -1,6 +1,7 @@ $e){ + $photo = str_replace(".$e",'',$photo); + } if(substr($photo,-2,1) == '-') { $resolution = intval(substr($photo,-1,1)); @@ -119,6 +124,7 @@ function photo_init(&$a) { if(count($r)) { $data = $r[0]['data']; + $mimetype = $r[0]['type']; } else { @@ -136,6 +142,7 @@ function photo_init(&$a) { ); if(count($r)) { $data = file_get_contents('images/nosign.jpg'); + $mimetype = 'image/jpeg'; $prvcachecontrol = true; } } @@ -148,12 +155,15 @@ function photo_init(&$a) { case 4: $data = file_get_contents('images/person-175.jpg'); + $mimetype = 'image/jpeg'; break; case 5: $data = file_get_contents('images/person-80.jpg'); + $mimetype = 'image/jpeg'; break; case 6: $data = file_get_contents('images/person-48.jpg'); + $mimetype = 'image/jpeg'; break; default: killme(); @@ -164,11 +174,11 @@ function photo_init(&$a) { } if(isset($customres) && $customres > 0 && $customres < 500) { - require_once('include/Photo.php'); - $ph = new Photo($data); + $ph = new Photo($data, $mimetype); if($ph->is_valid()) { $ph->scaleImageSquare($customres); $data = $ph->imageString(); + $mimetype = $ph->getType(); } } @@ -181,7 +191,7 @@ function photo_init(&$a) { header_remove('pragma'); } - header("Content-type: image/jpeg"); + header("Content-type: ".$mimetype); if($prvcachecontrol) { diff --git a/mod/photos.php b/mod/photos.php index 3ce6f993..07235358 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -5,6 +5,7 @@ require_once('include/acl_selectors.php'); require_once('include/bbcode.php'); require_once('include/security.php'); + function photos_init(&$a) { @@ -105,6 +106,8 @@ function photos_post(&$a) { logger('mod_photos: REQUEST ' . print_r($_REQUEST,true), LOGGER_DATA); logger('mod_photos: FILES ' . print_r($_FILES,true), LOGGER_DATA); + $phototypes = Photo::supportedTypes(); + $can_post = false; $visitor = 0; @@ -311,7 +314,7 @@ function photos_post(&$a) { intval($page_owner_uid) ); if(count($r)) { - $ph = new Photo($r[0]['data']); + $ph = new Photo($r[0]['data'], $r[0]['type']); if($ph->is_valid()) { $ph->rotate(270); @@ -362,6 +365,7 @@ function photos_post(&$a) { intval($page_owner_uid) ); if(count($p)) { + $ext = $phototypes[$p[0]['type']]; $r = q("UPDATE `photo` SET `desc` = '%s', `album` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s' WHERE `resource-id` = '%s' AND `uid` = %d", dbesc($desc), dbesc($albname), @@ -386,7 +390,7 @@ function photos_post(&$a) { $title = ''; $uri = item_new_uri($a->get_hostname(),$page_owner_uid); - + $arr = array(); $arr['uid'] = $page_owner_uid; @@ -412,7 +416,7 @@ function photos_post(&$a) { $arr['origin'] = 1; $arr['body'] = '[url=' . $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $p[0]['resource-id'] . ']' - . '[img]' . $a->get_baseurl() . '/photo/' . $p[0]['resource-id'] . '-' . $p[0]['scale'] . '.jpg' . '[/img]' + . '[img]' . $a->get_baseurl() . '/photo/' . $p[0]['resource-id'] . '-' . $p[0]['scale'] . '.'. $ext . '[/img]' . '[/url]'; $item_id = item_store($arr); @@ -581,17 +585,17 @@ function photos_post(&$a) { $arr['inform'] = $tagged[2]; $arr['origin'] = 1; $arr['body'] = '[url=' . $tagged[1] . ']' . $tagged[0] . '[/url]' . ' ' . t('was tagged in a') . ' ' . '[url=' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . ']' . t('photo') . '[/url]' . ' ' . t('by') . ' ' . '[url=' . $owner_record['url'] . ']' . $owner_record['name'] . '[/url]' ; - $arr['body'] .= "\n\n" . '[url=' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . ']' . '[img]' . $a->get_baseurl() . "/photo/" . $p[0]['resource-id'] . '-' . $best . '.jpg' . '[/img][/url]' . "\n" ; + $arr['body'] .= "\n\n" . '[url=' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . ']' . '[img]' . $a->get_baseurl() . "/photo/" . $p[0]['resource-id'] . '-' . $best . '.' . $ext . '[/img][/url]' . "\n" ; $arr['object'] = '' . ACTIVITY_OBJ_PERSON . '' . $tagged[0] . '' . $tagged[1] . '/' . $tagged[0] . ''; $arr['object'] .= '' . xmlify('' . "\n"); if($tagged[3]) - $arr['object'] .= xmlify('' . "\n"); + $arr['object'] .= xmlify('' . "\n"); $arr['object'] .= '' . "\n"; $arr['target'] = '' . ACTIVITY_OBJ_PHOTO . '' . $p[0]['desc'] . '' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . ''; - $arr['target'] .= '' . xmlify('' . "\n" . '') . ''; + $arr['target'] .= '' . xmlify('' . "\n" . '') . ''; $item_id = item_store($arr); if($item_id) { @@ -662,7 +666,7 @@ function photos_post(&$a) { $str_group_deny = perms2str(((is_array($_REQUEST['group_deny'])) ? $_REQUEST['group_deny'] : explode(',',$_REQUEST['group_deny']))); $str_contact_deny = perms2str(((is_array($_REQUEST['contact_deny'])) ? $_REQUEST['contact_deny'] : explode(',',$_REQUEST['contact_deny']))); - $ret = array('src' => '', 'filename' => '', 'filesize' => 0); + $ret = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => ''); call_hooks('photo_post_file',$ret); @@ -670,15 +674,17 @@ function photos_post(&$a) { $src = $ret['src']; $filename = $ret['filename']; $filesize = $ret['filesize']; + $type = $ret['type']; } else { $src = $_FILES['userfile']['tmp_name']; $filename = basename($_FILES['userfile']['name']); $filesize = intval($_FILES['userfile']['size']); + $type = $_FILES['userfile']['type']; } + - - logger('photos: upload: received file: ' . $filename . ' as ' . $src . ' ' . $filesize . ' bytes', LOGGER_DEBUG); + logger('photos: upload: received file: ' . $filename . ' as ' . $src . ' '. $type . ' ' . $filesize . ' bytes', LOGGER_DEBUG); $maximagesize = get_config('system','maximagesize'); @@ -701,7 +707,7 @@ function photos_post(&$a) { logger('mod/photos.php: photos_post(): loading the contents of ' . $src , LOGGER_DEBUG); $imagedata = @file_get_contents($src); - $ph = new Photo($imagedata); + $ph = new Photo($imagedata, $type); if(! $ph->is_valid()) { logger('mod/photos.php: photos_post(): unable to process image' , LOGGER_DEBUG); @@ -771,7 +777,7 @@ function photos_post(&$a) { $arr['origin'] = 1; $arr['body'] = '[url=' . $a->get_baseurl() . '/photos/' . $owner_record['nickname'] . '/image/' . $photo_hash . ']' - . '[img]' . $a->get_baseurl() . "/photo/{$photo_hash}-{$smallest}.jpg" . '[/img]' + . '[img]' . $a->get_baseurl() . "/photo/{$photo_hash}-{$smallest}.".$ph->getExt() . '[/img]' . '[/url]'; $item_id = item_store($arr); @@ -814,8 +820,8 @@ function photos_content(&$a) { notice( t('Public access denied.') . EOL); return; } - - + + require_once('include/bbcode.php'); require_once('include/security.php'); require_once('include/conversation.php'); @@ -825,6 +831,8 @@ function photos_content(&$a) { return; } + $phototypes = Photo::supportedTypes(); + $_SESSION['photo_return'] = $a->cmd; // @@ -991,7 +999,7 @@ function photos_content(&$a) { $a->set_pager_itemspage(20); } - $r = q("SELECT `resource-id`, `id`, `filename`, max(`scale`) AS `scale`, `desc` FROM `photo` WHERE `uid` = %d AND `album` = '%s' + $r = q("SELECT `resource-id`, `id`, `filename`, type, max(`scale`) AS `scale`, `desc` FROM `photo` WHERE `uid` = %d AND `album` = '%s' AND `scale` <= 4 $sql_extra GROUP BY `resource-id` ORDER BY `created` DESC LIMIT %d , %d", intval($owner_uid), dbesc($album), @@ -1038,13 +1046,15 @@ function photos_content(&$a) { $twist = 'rotleft'; else $twist = 'rotright'; + + $ext = $phototypes[$rr['type']]; $o .= replace_macros($tpl,array( '$id' => $rr['id'], '$twist' => ' ' . $twist . rand(2,4), '$photolink' => $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $rr['resource-id'], '$phototitle' => t('View Photo'), - '$imgsrc' => $a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['scale'] . '.jpg', + '$imgsrc' => $a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['scale'] . '.' .$ext, '$imgalt' => template_escape($rr['filename']), '$desc'=> template_escape($rr['desc']) )); @@ -1158,9 +1168,9 @@ function photos_content(&$a) { $prevlink = array($prevlink, '') ; $photo = array( - 'href' => $a->get_baseurl() . '/photo/' . $hires['resource-id'] . '-' . $hires['scale'] . '.jpg', + 'href' => $a->get_baseurl() . '/photo/' . $hires['resource-id'] . '-' . $hires['scale'] . '.' . $phototypes[$hires['type']], 'title'=> t('View Full Size'), - 'src' => $a->get_baseurl() . '/photo/' . $lores['resource-id'] . '-' . $lores['scale'] . '.jpg' . '?f=&_u=' . datetime_convert('','','','ymdhis') + 'src' => $a->get_baseurl() . '/photo/' . $lores['resource-id'] . '-' . $lores['scale'] . '.' . $phototypes[$lores['type']] . '?f=&_u=' . datetime_convert('','','','ymdhis') ); if($nextlink) @@ -1449,7 +1459,7 @@ function photos_content(&$a) { $a->set_pager_itemspage(20); } - $r = q("SELECT `resource-id`, `id`, `filename`, `album`, max(`scale`) AS `scale` FROM `photo` + $r = q("SELECT `resource-id`, `id`, `filename`, type, `album`, max(`scale`) AS `scale` FROM `photo` WHERE `uid` = %d AND `album` != '%s' AND `album` != '%s' $sql_extra GROUP BY `resource-id` ORDER BY `created` DESC LIMIT %d , %d", intval($a->data['user']['uid']), @@ -1469,13 +1479,14 @@ function photos_content(&$a) { $twist = 'rotleft'; else $twist = 'rotright'; - + $ext = $phototypes[$rr['type']]; + $photos[] = array( 'id' => $rr['id'], 'twist' => ' ' . $twist . rand(2,4), 'link' => $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $rr['resource-id'], 'title' => t('View Photo'), - 'src' => $a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . ((($rr['scale']) == 6) ? 4 : $rr['scale']) . '.jpg', + 'src' => $a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . ((($rr['scale']) == 6) ? 4 : $rr['scale']) . '.' . $ext, 'alt' => template_escape($rr['filename']), 'album' => array( 'link' => $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($rr['album']), diff --git a/mod/profile_photo.php b/mod/profile_photo.php index ace8dadd..2817f394 100644 --- a/mod/profile_photo.php +++ b/mod/profile_photo.php @@ -53,7 +53,7 @@ function profile_photo_post(&$a) { $base_image = $r[0]; - $im = new Photo($base_image['data']); + $im = new Photo($base_image['data'], $base_image['type']); if($im->is_valid()) { $im->cropImage(175,$srcX,$srcY,$srcW,$srcH); @@ -108,6 +108,7 @@ function profile_photo_post(&$a) { $src = $_FILES['userfile']['tmp_name']; $filename = basename($_FILES['userfile']['name']); $filesize = intval($_FILES['userfile']['size']); + $filetype = $_FILES['userfile']['type']; $maximagesize = get_config('system','maximagesize'); @@ -118,7 +119,7 @@ function profile_photo_post(&$a) { } $imagedata = @file_get_contents($src); - $ph = new Photo($imagedata); + $ph = new Photo($imagedata, $filetype); if(! $ph->is_valid()) { notice( t('Unable to process image.') . EOL ); @@ -193,7 +194,7 @@ function profile_photo_content(&$a) { goaway($a->get_baseurl() . '/profiles'); return; // NOTREACHED } - $ph = new Photo($r[0]['data']); + $ph = new Photo($r[0]['data'], $r[0]['type']); profile_photo_crop_ui_head($a, $ph); // go ahead as we have jus uploaded a new photo to crop } @@ -214,7 +215,7 @@ function profile_photo_content(&$a) { return $o; } else { - $filename = $a->config['imagecrop'] . '-' . $a->config['imagecrop_resolution'] . '.jpg'; + $filename = $a->config['imagecrop'] . '-' . $a->config['imagecrop_resolution'] . '.'.$a->config['imagecrop_ext']; $resolution = $a->config['imagecrop_resolution']; $tpl = get_markup_template("cropbody.tpl"); $o .= replace_macros($tpl,array( @@ -268,6 +269,7 @@ function profile_photo_crop_ui_head(&$a, $ph){ $a->config['imagecrop'] = $hash; $a->config['imagecrop_resolution'] = $smallest; + $a->config['imagecrop_ext'] = $ph->getExt(); $a->page['htmlhead'] .= get_markup_template("crophead.tpl"); return; }} diff --git a/mod/wall_upload.php b/mod/wall_upload.php index fa66561e..20666e0e 100644 --- a/mod/wall_upload.php +++ b/mod/wall_upload.php @@ -57,16 +57,18 @@ function wall_upload_post(&$a) { if(! x($_FILES,'userfile') && ! x($_FILES,'media')) killme(); - if(x($_FILES,'userfile')) { - $src = $_FILES['userfile']['tmp_name']; - $filename = basename($_FILES['userfile']['name']); - $filesize = intval($_FILES['userfile']['size']); - } - elseif(x($_FILES,'media')) { - $src = $_FILES['media']['tmp_name']; - $filename = basename($_FILES['media']['name']); - $filesize = intval($_FILES['media']['size']); - } + if(x($_FILES,'userfile')) { + $src = $_FILES['userfile']['tmp_name']; + $filename = basename($_FILES['userfile']['name']); + $filesize = intval($_FILES['userfile']['size']); + $filetype = $_FILES['userfile']['type']; + } + elseif(x($_FILES,'media')) { + $src = $_FILES['media']['tmp_name']; + $filename = basename($_FILES['media']['name']); + $filesize = intval($_FILES['media']['size']); + $filetype = $_FILES['media']['type']; + } $maximagesize = get_config('system','maximagesize'); @@ -77,7 +79,7 @@ function wall_upload_post(&$a) { } $imagedata = @file_get_contents($src); - $ph = new Photo($imagedata); + $ph = new Photo($imagedata, $filetype); if(! $ph->is_valid()) { echo ( t('Unable to process image.') . EOL); @@ -123,19 +125,19 @@ function wall_upload_post(&$a) { /* mod Waitman Gobble NO WARRANTY */ //if we get the signal then return the image url info in BBCODE, otherwise this outputs the info and bails (for the ajax image uploader on wall post) - if ($_REQUEST['hush']!='yeah') { + if ($_REQUEST['hush']!='yeah') { /*existing code*/ if(local_user() && intval(get_pconfig(local_user(),'system','plaintext'))) - echo "\n\n" . '[url=' . $a->get_baseurl() . '/photos/' . $page_owner_nick . '/image/' . $hash . '][img]' . $a->get_baseurl() . "/photo/{$hash}-{$smallest}.jpg[/img][/url]\n\n"; + echo "\n\n" . '[url=' . $a->get_baseurl() . '/photos/' . $page_owner_nick . '/image/' . $hash . '][img]' . $a->get_baseurl() . "/photo/{$hash}-{$smallest}.".$ph->getExt()."[/img][/url]\n\n"; else - echo '

\"$basename\"

"; + echo '

getExt()."\" alt=\"$basename\" />

"; /*existing code*/ } else { - $m = '[url=' . $a->get_baseurl() . '/photos/' . $page_owner_nick . '/image/' . $hash . '][img]' . $a->get_baseurl() . "/photo/{$hash}-{$smallest}.jpg[/img][/url]"; + $m = '[url=' . $a->get_baseurl() . '/photos/' . $page_owner_nick . '/image/' . $hash . '][img]' . $a->get_baseurl() . "/photo/{$hash}-{$smallest}.".$ph->getExt()."[/img][/url]"; return($m); - } + } /* mod Waitman Gobble NO WARRANTY */ killme(); diff --git a/update.php b/update.php index 35a6771b..0f7bf664 100644 --- a/update.php +++ b/update.php @@ -1,6 +1,6 @@ Date: Thu, 7 Jun 2012 20:17:31 +0200 Subject: [PATCH 2/2] png support: update database.sql, fix some typos, fix tinymce image browser --- database.sql | 1 + include/Photo.php | 26 ++++++++++++++------------ mod/fbrowser.php | 18 ++++++++++++++---- mod/photos.php | 4 ++-- mod/profile_photo.php | 3 ++- mod/wall_upload.php | 3 ++- 6 files changed, 35 insertions(+), 20 deletions(-) diff --git a/database.sql b/database.sql index c1d1b27e..53dc0c5b 100644 --- a/database.sql +++ b/database.sql @@ -745,6 +745,7 @@ CREATE TABLE IF NOT EXISTS `photo` ( `desc` text NOT NULL, `album` char(255) NOT NULL, `filename` char(255) NOT NULL, + `type` CHAR(128) NOT NULL DEFAULT 'image/jpeg', `height` smallint(6) NOT NULL, `width` smallint(6) NOT NULL, `data` mediumblob NOT NULL, diff --git a/include/Photo.php b/include/Photo.php index ffefc37e..f769a70a 100644 --- a/include/Photo.php +++ b/include/Photo.php @@ -105,9 +105,9 @@ class Photo { $dest = imagecreatetruecolor( $dest_width, $dest_height ); - imagealphablending($dest->image, false); + imagealphablending($dest, false); imagesavealpha($dest, true); - if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127));; // fill with alpha + if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); if($this->image) imagedestroy($this->image); @@ -164,9 +164,9 @@ class Photo { $dest = imagecreatetruecolor( $dest_width, $dest_height ); - imagealphablending($dest->image, false); + imagealphablending($dest, false); imagesavealpha($dest, true); - if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127));; // fill with alpha + if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dest_width, $dest_height, $width, $height); if($this->image) imagedestroy($this->image); @@ -181,9 +181,9 @@ class Photo { public function scaleImageSquare($dim) { $dest = imagecreatetruecolor( $dim, $dim ); - imagealphablending($dest->image, false); + imagealphablending($dest, false); imagesavealpha($dest, true); - if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127));; // fill with alpha + if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha imagecopyresampled($dest, $this->image, 0, 0, 0, 0, $dim, $dim, $this->width, $this->height); if($this->image) imagedestroy($this->image); @@ -195,9 +195,9 @@ class Photo { public function cropImage($max,$x,$y,$w,$h) { $dest = imagecreatetruecolor( $max, $max ); - imagealphablending($dest->image, false); + imagealphablending($dest, false); imagesavealpha($dest, true); - if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127));; // fill with alpha + if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $max, $max, $w, $h); if($this->image) imagedestroy($this->image); @@ -295,6 +295,7 @@ class Photo { * @arg $fromcurl boolean Check Content-Type header from curl request */ function guess_image_type($filename, $fromcurl=false) { + logger('Photo: guess_image_type: '.$filename . ($fromcurl?' from curl headers':''), LOGGER_DEBUG); $type = null; if ($fromcurl) { $a = get_app(); @@ -310,12 +311,13 @@ function guess_image_type($filename, $fromcurl=false) { if (is_null($type)){ $ext = pathinfo($filename, PATHINFO_EXTENSION); $types = Photo::supportedTypes(); - foreach ($types as $m=>$e){ - if ($ext==$e) return $m; - } $type = "image/jpeg"; - } + foreach ($types as $m=>$e){ + if ($ext==$e) $type = $m; + } + } + logger('Photo: guess_image_type: type='.$type, LOGGER_DEBUG); return $type; } diff --git a/mod/fbrowser.php b/mod/fbrowser.php index 66ff9252..3f034226 100644 --- a/mod/fbrowser.php +++ b/mod/fbrowser.php @@ -4,7 +4,9 @@ * @subpackage FileBrowser * @author Fabio Comuni */ - + +require_once('include/Photo.php'); + /** * @param App $a */ @@ -43,14 +45,22 @@ function fbrowser_content($a){ $path[]=array($a->get_baseurl()."/fbrowser/image/".$a->argv[2]."/", $album); } - $r = q("SELECT `resource-id`, `id`, `filename`, min(`scale`) AS `hiq`,max(`scale`) AS `loq`, `desc` + $r = q("SELECT `resource-id`, `id`, `filename`, type, min(`scale`) AS `hiq`,max(`scale`) AS `loq`, `desc` FROM `photo` WHERE `uid` = %d $sql_extra GROUP BY `resource-id` $sql_extra2", intval(local_user()) ); - - function files1($rr){ global $a; return array( $a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['hiq'] . '.jpg', template_escape($rr['filename']), $a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['loq'] . '.jpg'); } + function files1($rr){ + global $a; + $types = Photo::supportedTypes(); + $ext = $types[$rr['type']]; + return array( + $a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['hiq'] . '.' .$ext, + template_escape($rr['filename']), + $a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['loq'] . '.'. $ext + ); + } $files = array_map("files1", $r); $tpl = get_markup_template("filebrowser.tpl"); diff --git a/mod/photos.php b/mod/photos.php index 07235358..efeab8fa 100644 --- a/mod/photos.php +++ b/mod/photos.php @@ -682,9 +682,9 @@ function photos_post(&$a) { $filesize = intval($_FILES['userfile']['size']); $type = $_FILES['userfile']['type']; } - + if ($type=="") $type=guess_image_type($filename); - logger('photos: upload: received file: ' . $filename . ' as ' . $src . ' '. $type . ' ' . $filesize . ' bytes', LOGGER_DEBUG); + logger('photos: upload: received file: ' . $filename . ' as ' . $src . ' ('. $type . ') ' . $filesize . ' bytes', LOGGER_DEBUG); $maximagesize = get_config('system','maximagesize'); diff --git a/mod/profile_photo.php b/mod/profile_photo.php index 2817f394..e44707f9 100644 --- a/mod/profile_photo.php +++ b/mod/profile_photo.php @@ -109,7 +109,8 @@ function profile_photo_post(&$a) { $filename = basename($_FILES['userfile']['name']); $filesize = intval($_FILES['userfile']['size']); $filetype = $_FILES['userfile']['type']; - + if ($filetype=="") $filetype=guess_image_type($filename); + $maximagesize = get_config('system','maximagesize'); if(($maximagesize) && ($filesize > $maximagesize)) { diff --git a/mod/wall_upload.php b/mod/wall_upload.php index 20666e0e..4b81f8d1 100644 --- a/mod/wall_upload.php +++ b/mod/wall_upload.php @@ -69,7 +69,8 @@ function wall_upload_post(&$a) { $filesize = intval($_FILES['media']['size']); $filetype = $_FILES['media']['type']; } - + + if ($filetype=="") $filetype=guess_image_type($filename); $maximagesize = get_config('system','maximagesize'); if(($maximagesize) && ($filesize > $maximagesize)) {