webForumDet fria alternativet

Ändra storlek på bilder vid upload

24 svar · 1 032 visningar · startad av Steady

SteadyMedlem sedan dec. 2004225 inlägg
#1

Hejsan!

Denna fråga har säkert varit upp en jäkla massa gånger innan men har inte hittat riktigt vad jag söker efter.
Det är så att jag vill att när jag laddar upp en bild, som oftast är från kameran, vilka är på 1.5mb så vill jag att den ska ändra storlek på denna bild så den blir ett visst antal pixlar i bredd, och sedan räknas höjden ut procentiuellt. Detta ska ske när man laddar upp bilden och när det är klart ska den gamla tas bort, och den nya bilden finnas kvar. Detta skulle förenkla enormt mycket, eftersom man då slipper göra om bildernas storlek i Photoshop varje gång man ska ladda upp bilderna. Samt, att många som laddar upp bilder (eftersom det ska vara en site för bl.a. fotoalbum till vårat "kompisgäng") inte har den möjligheten att ändra storlek på bilderna.

Hoppas någon har tips på hur jag ska gå till väga!

Gott nytt! :)

kjellMedlem sedan dec. 1999757 inlägg
#2

Här har du ett exempel. Nu finns det inga kontroller om vad som laddas upp eller hur stora bilderna är etc. etc.
Modifieras efter eget behov.

<?php
// ###################################### Vars
$img_dir = 'C:/mappen/img';// Sökväg till mappen dör bilden ska sparas
$new_img_width = '400';// Bredd som bilden ska ha
$img_compress = 75;// Vilken komprimering (100=ingen)
$uploaded_img_name = $_FILES['foto']['name'];// foto är namnet på fältet
$uploaded_img_location = $_FILES['foto']['tmp_name'];
// ######################################

if (isset($_POST['action']) AND $_POST['action'] == 'upload') {
	$img_x_y_size =  getimagesize($uploaded_img_location);
	// Ändra storleken om bilden är större än $new_img_width
	if ($new_img_width < $img_x_y_size[0]) {
		$new_img_height = ceil(($new_img_width / $img_x_y_size[0]) * $img_x_y_size[1]);
		// Gör om bildens storlek
		$new_image = imagecreatetruecolor($new_img_width, $new_img_height);
		// Kontrollera vilken bildtyp det är (1=gif , 2=jpg , 3=png)
		switch($img_x_y_size[2]) {
			case 1:
				$image = imagecreatefromgif($uploaded_img_location);
			break;
			case 2:
				$image = imagecreatefromjpeg($uploaded_img_location);
			break;
			case 3:
				$image = imagecreatefrompng($uploaded_img_location);
			break;
		}
		imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_img_width, $new_img_height, $img_x_y_size[0], $img_x_y_size[1]);
		// Kopiera bilden till sin mapp
		$save_img = $img_dir . '/' . $uploaded_img_name;
		imagejpeg($new_image, $save_img, $img_compress);
		// Frigör minne som associerats med bilderna
		imagedestroy($image);
		imagedestroy($new_image);
	} else {
		copy($uploaded_img_location, $img_dir . '/' . $uploaded_img_name);
	}
}
?>
<form method="post" enctype="multipart/form-data" name="form" action="">
<table border="0" cellspacing="0" cellpadding="2">
  <tr>
    <td align="right" valign="top"><b>Bilden</b></td>
    <td valign="top"><input type="file" name="foto"></td>
  </tr>
  <tr>
    <td align="right"><input type="hidden" name="action" value="upload"></td>
    <td><input type="submit" name="Submit" value="Ladda upp bilden"></td>
  </tr>
</table>
</form>

[r]
Ok, la till en kontroll om bilden är mindre än värdet man anger.

SteadyMedlem sedan dec. 2004225 inlägg
#3

Du anar inte hur tacksam jag är! Hoppas du får ett extremt bra år och för formalitetens skull: Gott nytt år! ;)

SteadyMedlem sedan dec. 2004225 inlägg
#4

En liten följdfråga. Jag vill att bilden ska heta ett nummer.jpg/png/gif. Det som vore smidigast är att använda mysql_insert_id(); eftersom jag sparar namnet i databasen samtidigt som jag laddar upp bilden. Hur ska jag gå till väga för att byta namn på bilden när den laddas upp?

Senaste ID:et ligger i en variabel som heter $InsertID.

SteadyMedlem sedan dec. 2004225 inlägg
#5

Ni får ursäkta min snabba fråga utan att egentligen ha undersökt saken själv. Jag löste det såhär enkelt:

$uploaded_img_end = explode(".", $uploaded_img_name);
$save_img = $img_dir . '/' . $InsertID . '.' . $uploaded_img_end[1];
SteadyMedlem sedan dec. 2004225 inlägg
#6

Hehe, nu är jag tillbaka! :) Märkt att koden, även om bilden är under ex. 400px bred så ändrar den storlek på den. Vet hur getimagesize fungerar men vet dock inte riktigt hur jag ska lyckas lösa det genom den koden du gav mig kjell.

kjellMedlem sedan dec. 1999757 inlägg
#7

Jo, som jag nämnde så gjordes inga som helst kontroller.
Vill man inte att mindre bilder ska bli bredare än angivet så är det bara att kontrollera det med exempelvis

if ($new_img_width < $img_x_y_size[0]) {

Är detta sant görs bilden mindre, annars behåller man storleken.
Ok, det var inte komplett lösning men det är ju bara nyttigt att fundera lite :)

SteadyMedlem sedan dec. 2004225 inlägg
#8

Okej :) Jag försökte med det här men det gick inge vidare, den tar bara ut en del av bilden, eller hur man ska förklara det.

if ($new_img_width < $img_x_y_size[0]) {
	// Gör om bildens storlek
	$new_image = imagecreatetruecolor($new_img_width, $new_img_height);
} else {
	// Behåller gamla storleken
	$new_image = imagecreatetruecolor($img_x_y_size[0], $img_x_y_size[1]);
}
kjellMedlem sedan dec. 1999757 inlägg
#9

Nja, jag vill nog inte att man ö.h.t. kör några image-funktioner eftersom det inte behövs när bilden inte ska ändras.

Det räcker ju att köra en vanlig copy i det läget.
Jag uppdaterade skriptet ovanför så nu har du kontrollen i den.

SteadyMedlem sedan dec. 2004225 inlägg
#10

Kanon, jag återkommer om jag har några fler frågor.
Tack!

SteadyMedlem sedan dec. 2004225 inlägg
#11

Upptäckt en sak till! Har tänkt att lägga in en if(file_exists($fil)) { någonstans, men får inte riktigt grepp på hur jag ska lägga upp det. Såhär ser det ut nu:

<?
// ###################################### Vars
$img_dir = '/bortasidan/bilder'; // Sökväg till mappen där bilden ska sparas
$new_img_width = '600'; // Bredd som bilden ska ha
$img_compress = 75; // Vilken komprimering (100=ingen)
$uploaded_img_name = $_FILES['foto']['name']; // foto är namnet på fältet
$uploaded_img_location = $_FILES['foto']['tmp_name'];
// ######################################

if (isset($_POST['action']) AND $_POST['action'] == 'upload') {

    $img_x_y_size =  getimagesize($uploaded_img_location);
	// Ändra storleken om bilden är större än $new_img_width

	$uploaded_img_end = explode(".", $uploaded_img_name);
	$uploaded_file_end = strtolower($uploaded_img_end[1]);

	//  Godkänn filändelsen
	if ($uploaded_file_end != "jpg" && $uploaded_file_end != "gif" && $uploaded_file_end != "jpeg" && $uploaded_file_end != "png") {
		$upload_error = 1;
	} else {
		mysql_query("INSERT INTO photo (Photo) VALUES ('$uploaded_img_name')") or die(mysql_error());
		$InsertID = mysql_insert_id();
	}

	if ($new_img_width < $img_x_y_size[0]) {

		$new_img_height = ceil(($new_img_width / $img_x_y_size[0]) * $img_x_y_size[1]);

		// Gör om bildens storlek
		$new_image = imagecreatetruecolor($new_img_width, $new_img_height);

		// Kontrollera vilken bildtyp det är (1=gif , 2=jpg , 3=png)
		switch($img_x_y_size[2]) {
			case 1:
				$image = imagecreatefromgif($uploaded_img_location);
			break;
			case 2:
				$image = imagecreatefromjpeg($uploaded_img_location);
			break;
			case 3:
				$image = imagecreatefrompng($uploaded_img_location);
			break;
		}

		imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_img_width, $new_img_height, $img_x_y_size[0], $img_x_y_size[1]);

		// Kopiera bilden till sin mapp
		$save_img = $img_dir . '/' . $InsertID . '.' . $uploaded_img_end[1];

	} else {

		copy($uploaded_img_location, $img_dir . '/' . $InsertID . '.' . $uploaded_img_end[1]);

	}

    imagejpeg($new_image, $save_img, $img_compress);
    // Frigör minne som associerats med bilderna
    imagedestroy($image);
    imagedestroy($new_image);

    if(isset($upload_error)) {
    	echo "Det är fel filändelse på bilden du försökte ladda upp, det måste vara gif, jpg eller png.";
    }

}
?>

Tack på förhand

kjellMedlem sedan dec. 1999757 inlägg
#12

Menar du om man glömt välja filen när man klickar på submitknappen?
Byt bara ut

if (isset($_POST['action']) AND $_POST['action'] == 'upload') {

mot

if (isset($_POST['action']) AND $_POST['action'] == 'upload' AND !empty($_FILES['foto']['name'])) {

En annan sak är att du egentligen inte kontrollera vilken filändelse filen har. Nu får du bara fram vad som existerar efter första punkten så filen min.fina.bild.jpg kommer inte fungera eftersom jpg nu ligger i $uploaded_img_end[3].
(tänker på raderna:)
$uploaded_img_end = explode(".", $uploaded_img_name);
$uploaded_file_end = strtolower($uploaded_img_end[1]);

Koden

$uploaded_file_end = strtolower(substr($uploaded_img_name, (strrpos($uploaded_img_name, '.'))));

väljer allt efter sista punkten (punkten inkluderad) och använder du det istället så tänk på att lägga till en punkt när du verifierar filnamnet och att du inte behöver lägga till punkten i filnamnet när du skriver till databasen och disken ($uploaded_file_end kommer exempelvis att innehålla .jpg istället för bara jpg). Sen är väl inte det heller såvärst säkert om du låter andra ladda upp. En jpg kan ju mycket väl vara något helt annat och då får du istället kontrollera formatet.

SteadyMedlem sedan dec. 2004225 inlägg
#13

kjell skrev:

Menar du om man glömt välja filen när man klickar på submitknappen?

Nej, menar att den ska kolla om befintlig fil redan har laddats upp en gång. Det kan ju vara så att man råkat dubbelklicka på uploadknappen, då sparas den två gånger i databasen men filen läggs bara upp en gång, eftersom den alltid heter $InsertID.filändelse

kjell skrev:

En annan sak är att du egentligen inte kontrollera vilken filändelse filen har. Nu får du bara fram vad som existerar efter första punkten så filen min.fina.bild.jpg kommer inte fungera eftersom jpg nu ligger i $uploaded_img_end[3].
(tänker på raderna:)
$uploaded_img_end = explode(".", $uploaded_img_name);
$uploaded_file_end = strtolower($uploaded_img_end[1]);

Koden

$uploaded_file_end = strtolower(substr($uploaded_img_name, (strrpos($uploaded_img_name, '.'))));

väljer allt efter sista punkten (punkten inkluderad) och använder du det istället så tänk på att lägga till en punkt när du verifierar filnamnet och att du inte behöver lägga till punkten i filnamnet när du skriver till databasen och disken ($uploaded_file_end kommer exempelvis att innehålla .jpg istället för bara jpg). Sen är väl inte det heller såvärst säkert om du låter andra ladda upp. En jpg kan ju mycket väl vara något helt annat och då får du istället kontrollera formatet.

Kanon, det visste jag inte. Funkar finfint. :) Såhär blev det:

$uploaded_img_type = $_FILES['foto']['type']; // vilken typ filen är

...

if ($uploaded_img_type == "image/pjpeg" || $uploaded_img_type == "image/gif" || $uploaded_img_type == "image/jpeg" || $uploaded_img_type == "image/png") {

	Laddar upp bilden

} else {

	echo "Fel filändelse.";

}

Kan meddela att ditt ursprungliga inlägg var på 1337 tecken. ;)

K@llenMedlem sedan mars 20032 667 inlägg
#14

kjell skrev:

Det räcker ju att köra en vanlig copy i det läget.
Jag uppdaterade skriptet ovanför så nu har du kontrollen i den.

Använd move_uploaded_file() istället för copy(). copy() fungerar tex inte om safe-mode är satt till on.

http://se2.php.net/move_uploaded_file

kjellMedlem sedan dec. 1999757 inlägg
#15

Steady skrev:

Nej, menar att den ska kolla om befintlig fil redan har laddats upp en gång.

Problemet är att du döper om filen och då försvinner den möjligheten. Det går naturligtvis att skapa ett nytt fält i tabellen där du anger orginalnamnet som du sedan jämför med eller alternativt en timestamp som du kontrollera mot och inte godkänner en uppladdning inom viss tid. För att hindra dubbelklick på knappen så tror jag javaskript är den enklaste lösningen.
http://www.webforum.nu/showthread.php?forumid=24&threadid=41514

SteadyMedlem sedan dec. 2004225 inlägg
#16

kjell skrev:

Det går naturligtvis att skapa ett nytt fält i tabellen där du anger orginalnamnet som du sedan jämför med eller alternativt en timestamp som du kontrollera mot och inte godkänner en uppladdning inom viss tid.

Det låter som en klyftig idée. Så, jag skapar två nya fält i tabellen där ett heter PhotoOrginal (varchar) och det andra PhotoUploaded (datetime).

Hur gör jag för att jämföra två datum, om jag vill ha en mellanskillnad på två timmar?

kjellMedlem sedan dec. 1999757 inlägg
#17

Jag gillar personligen inte DATETIME utan vill hellre använda timestamp som är enklare när man ska räkna ut något.
Lägg till en ny variabel uppe i skriptet:
$time_between_uploads = '7200';// Sekunder mellan uppladdning

Fältet för timestampen bör vara INT.
Du lägger till timestamp i tabellen samtidigt som bildnamnet, t.ex.

mysql_query("INSERT INTO photo (Photo,Uploadtime) VALUES ('$uploaded_img_name','" . time() . "')") or die(mysql_error());

När du kontrollera så söker du bara upp senaste timestamp och jämför med det

$sql = mysql_query("SELECT Uploadtime FROM photo ORDER BY Uploadtime DESC LIMIT 0,1", DB);
$result = mysql_fetch_array($sql);
if ($result['Uploadtime'] < (time()-$time_between_uploads)) {
	// Uppladdning ok
} else {
	// Ingen uppladdning ännu
}

Nu är ju allt otestat men du ser säkert hur det ska vara...

[r]
Vände visst på skiljetecknet, ska vara < istället

SteadyMedlem sedan dec. 2004225 inlägg
#18

Medans jag väntade på svar kollade jag upp lite saker själv. Vad är det för skillnad på om man skriver

$datediff = date("Y-m-d H:i:s", time("U") - 120);
$S_PHOTO = mysql_query("SELECT * FROM photo") or die (mysql_error());
while($row = mysql_fetch_array($S_PHOTO)) {

	if($uploaded_img_name == $row['PhotoOrginal'] && $row['PhotoUploaded'] > $datediff) {
		Header("Location: photo.php?file_exists");
		exit;
	}

}

Och det du skrev? :)

SteadyMedlem sedan dec. 2004225 inlägg
#19

Jo, ovanstående kod funkar utmärkt, förutom att all kod körs efter att Headern skickat iväg till en annan adress.

// ###################################### Vars
$img_dir = 'bilder'; // Sökväg till mappen där bilden ska sparas
$new_img_width = '600'; // Bredd som bilden ska ha
$img_compress = 60; // Vilken komprimering (100=ingen)
$uploaded_img_name = $_FILES['foto']['name']; // foto är namnet på fältet
$uploaded_img_location = $_FILES['foto']['tmp_name'];
$uploaded_img_type = $_FILES['foto']['type']; // vilken typ filen är
$uploaded_img_end = strtolower(substr($uploaded_img_name, (strrpos($uploaded_img_name, '.')))); // filändelsen på bilden
// ######################################

if (isset($_POST['action']) && $_POST['action'] == 'upload' && !empty($_FILES['foto']['name'])) {

	$datediff = date("Y-m-d H:i:s", time("U") - 120);
	$S_PHOTO = mysql_query("SELECT * FROM photo ORDER BY PhotoUploaded DESC Limit 0,1") or die (mysql_error());
	while($row = mysql_fetch_array($S_PHOTO)) {

		if($row['PhotoUploaded'] > $datediff && $row['PhotoOrginal'] == $uploaded_img_name) {
			Header("Location: photo.php?file_exists=1");
			exit;
		}

	}

	//  Godkänn filändelsen
	if ($uploaded_img_type == "image/pjpeg" || $uploaded_img_type == "image/gif" || $uploaded_img_type == "image/jpeg" || $uploaded_img_type == "image/png") {

	$PhotoUploaded = date("Y-m-d H:i:s");
	mysql_query("INSERT INTO photo (Photo, PhotoOrginal, PhotoUploaded, PlaceID) VALUES ('$uploaded_img_end','$uploaded_img_name','$PhotoUploaded','$_POST[place]')") or die(mysql_error());
	$InsertID = mysql_insert_id();

	$img_x_y_size =  getimagesize($uploaded_img_location);
	// Ändra storleken om bilden är större än $new_img_width

	$uploaded_img_end = strtolower(substr($uploaded_img_name, (strrpos($uploaded_img_name, '.'))));

		if ($new_img_width < $img_x_y_size[0]) {

			$new_img_height = ceil(($new_img_width / $img_x_y_size[0]) * $img_x_y_size[1]);

			// Gör om bildens storlek
			$new_image = imagecreatetruecolor($new_img_width, $new_img_height);

			// Kontrollera vilken bildtyp det är (1=gif , 2=jpg , 3=png)
			switch($img_x_y_size[2]) {
				case 1:
					$image = imagecreatefromgif($uploaded_img_location);
				break;
				case 2:
					$image = imagecreatefromjpeg($uploaded_img_location);
				break;
				case 3:
					$image = imagecreatefrompng($uploaded_img_location);
				break;
			}

			imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_img_width, $new_img_height, $img_x_y_size[0], $img_x_y_size[1]);

			// Kopiera bilden till sin mapp
			$save_img = $img_dir . '/' . $InsertID . $uploaded_img_end;

		} else {

			move_uploaded_file($uploaded_img_location, $img_dir . '/' . $InsertID . $uploaded_img_end);

		}

		imagejpeg($new_image, $save_img, $img_compress);
		// Frigör minne som associerats med bilderna
		imagedestroy($image);
		imagedestroy($new_image);

	} else {
		Header("Location: photo.php?wrong_file_end=1");
		exit;
	}

	Header("Location: photo.php?");
	exit;

}

Den laddar alltså upp bilden och det läggs till i databasen, även om man skickat besökaren till ?file_exists. Varför då? Jag vill ju att den ska avbryta koden där eftersom filen redan finns och den laddades upp inom en tidsram på två timmar.

kjellMedlem sedan dec. 1999757 inlägg
#20

Det går alltid att koda saker på olika sätt i PHP och man gör det som faller en bäst. Jag tycker det är enklare att räkna med unixformatet av timestamp men det väljer var och en själv :)

Lägg till en exit; efter din header så borde skriptet inte köras vidare.

[r]
En sak skiljer sig en hel del ser jag nu.
Du väljer alla poster i tabellen och sedan loopar ut dessa för att hitta det du letar efter. I mitt exempel hämtas endast den post jag vill ha.
En prestandafråga alltså men så länge tabellen inte är av storlek så har det förmodligen ingen större betydelse men många bäckar små...

139 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
136 ms — hämta tråd, inlägg och bilagor (db)