zoombilder

heyho

ich hab ein bild welches die auflösung 12k x 9k besitzt und möchte da jetzt so einen flash oder javascript zoom dafür anbieten, ähnlich wie der für google maps. gibts da irgendwie kostenlose lösungen dafür? wie nennt man diese tools/programme
ich weis auch net so recht nach was ich da googlen soll.
 
Kannste theoretisch mit CSS, notfalls mit javascript realisieren.

http://www.typeer.de/thema/CSS-Bilder-Zoom/

einfach so eine Grundlage, nur dass du, wenn ich dich richtig verstanden habe, den effekt erzielen willst, dass nur eine besimmte region des bildes zu sehen ist =)

also einfach per css alles was über das kleine bild ragt verstecken a la overflow: hidden;

wenn du möchtest, kannst du das ganze ja interaktiv mache, sprich das du wie bei gm das bild sozusagen bewegen kannst und die region des bildes veränderst.
das du sozusagen über das bild navigieren kannst.
sollte mit javascript gehen.
kann dir dafür aber leider nichts sagen, js ist nicht meine stärke =)

lg, hth

PS. ich hoffe du verstehst was ich da rede ^^
 
@ CrAc
Mit CSS lädst du ja das ganze Bild! Da bin ich mal gespannt was die armen User sagen wenn das V90 Modem brüllt :P

Bei einer Auflösung von 12000x9000 Pixel in RGB pro Kanal 8Bit? unkomprimierte Rohdaten haben wir hier:
Code:
12000 Pixel x 9000 Pixel = 108000000 Pixel x 24Bit =2592000000 Bit \ 8 = 324000000 Byte
324000000 Byte \ 1024 = 316406,25 KB =
308,99 MB

Als JPEG 100 oder 2000 wüsste ich gerne die Größe, berechnen lässt sich das ja nicht pauschal, da größere einfarbige Flächen besser komprimiert werden können als ein rosa Rauschen? :).

2
http://de.wikipedia.org/w/index.php?title=Datei:Pink.noise.col.png&filetimestamp=20060704112203
 
hast du auf dem Server PHP5 + gd-lib?

wenn ja, würde ich an deiner Stelle ein PHP-Script schreiben, was das Gesamt-Bild auf eine komplett darstellbare Größe shrinkt und ausgibt.

Dieses Script wird dann in einer anderen Seite im img-Tag geladen.
und je nach Maus-Gesten gibt's per JavaScript ein Reload mit neuen Parametern für das Image.

Wie die Auswahl eines Bild-Bereiches geht, kannst du dir ja von JCrop abgucken.

um Server-Last zu sparen solltest du auch noch ein Caching mit einbauen, damit er nicht jedesmal neu shrinken und croppen muss...


Und um die Bearbeitung und Ausgabe des Bildes zu vereinfachen, kann ich dir meine Image-Klasse anbieten, die ich mir mal geschrieben hab. Da kannst du dann auch gleich Wasserzeichen einfügen, etc.

die Klasse ist noch nicht ganz fertig, solltest du Bugs finden, sag bitte bescheid!
PHP:
<?

/**
 * image-object, where you can edit the image (resize / rotate)
 * works with gdlib!
 * @author Martin Bergann <martin@cs-bergann.de>
 * 
 */
class Image
{
	private $path;
	private $img=null;
	private $infos=null;
	
	private $error=array();

	private $error_msg=array(
	"0"=>"",
	"1"=>"error while loading image",
	"2"=>"error while saving image",
	"3"=>"invalid dimensions",
	"4"=>"no image loaded"
	);


/* Constructor / Destructor */

	public function __construct($path="")
	{
		if(!empty($path))
		$this->loadImage($path);
	}




/* load and save */
	
	public function loadImage($path)
	{
		$this->path = $path;
		if(!$this->infos = @getimagesize($path)){array_push($this->error,1);return false;}
		
	//	var_dump($this->infos);
		
		if($this->infos[2]==1)
		{
			// Bild ist vom Typ gif
			$this->img = @imagecreatefromgif($this->path);
		}
		elseif($this->infos[2]==2)
		{
			// Bild ist vom Typ jpg
			$this->img = @imagecreatefromjpeg($this->path);
		}
		elseif($this->infos[2]==3)
		{
			// Bild ist vom Typ png
			$this->img = @imagecreatefrompng($this->path);
		}
		else
		{
			array_push($this->error,2);
			return false;
		}

		return true;
	}
	
	
	/**
	 * saves images by filename-extension
	 */
	public function saveImage($path)
	{
		switch(strtolower($this->getFilenameExtension($path)))
		{
			case "jpg":
			case "jpeg":
				if(!@imagejpeg($this->img, $path))
				{
					array_push($this->error,2);
					return false;
				}
				break;
			case "gif":
				if(!@imagegif($this->img, $path))
				{
					array_push($this->error,2);
					return false;
				}
				break;
			case "png":
				if(!@imagepng($this->img, $path))
				{
					array_push($this->error,2);
					return false;
				}
				break;
			default:
				break;
		}
		$this->loadImage($path);
		return true;		
	}
	
	public function generateImage($width,$height,$color)
	{
		$this->img = imagecreatetruecolor($width, $height);
		imagefill($this->img, 0, 0, $color);
	}
	
	public function createTextImage($text,$fontfile,$fontsize,$text_color=0xFFFFFF,$background_color=0,$fontangle=0)
	{
		if(!is_numeric($fontsize))
		{
			$fontsize=20;
		}
		if(!is_numeric($fontangle))
		{
			$fontangle = 0;
		}

		//get size of text-field
		$textfield = imagettfbbox($fontsize, $fontangle, $fontfile, $text);
		$text_size_x = (abs($textfield[4] - $textfield[0]) + 10);
		$text_size_y = (abs($textfield[1] - $textfield[7]) + 10);
		$text_pos_x = 3;
		$text_pos_y = $fontsize+5;

		$text_picture = imagecreatetruecolor($text_size_x, $text_size_y);
		
		$t_red=($text_color>>16)&0xFF;
		$t_green=($text_color>>8)&0xFF;
		$t_blue=($text_color)&0xFF;

		$b_red=($background_color>>16)&0xFF;
		$b_green=($background_color>>8)&0xFF;
		$b_blue=($background_color)&0xFF;
		
		$background_color = imagecolorallocate($text_picture, $b_red, $b_green, $b_blue);
		$text_color = imagecolorallocate($text_picture, $t_red, $t_green, $t_blue);

		imagefill($text_picture, 0, 0, $background_color);
		imagettftext($text_picture, $fontsize, $fontangle, $text_pos_x, $text_pos_y, $text_color, $fontfile, $text);
		//if(isset($this->img))imagedestroy($this->img);
		$this->img = $text_picture;
	}
	
	public function getImageRessource()
	{
		return $this->img;
	}
	



/* get infos */

	public function getOrigWidth()
	{
		return $this->infos[0];
	}
	
	public function getOrigHeight()
	{
		return $this->infos[1];
	}
	
	public function getCurrentWidth()
	{
		return (!is_null($this->img))?imagesx($this->img):0;
	}
	
	public function getCurrentHeight()
	{
		return (!is_null($this->img))?imagesy($this->img):0;
	}
	
	public function getOrigMime()
	{
		return $this->infos["mime"];
	}
	
	public function getOrigFilenameExtension()
	{
		return $this->getFilenameExtension($this->path);
	}
	protected function getFilenameExtension($path)
	{
		return preg_replace("/^.*\.([0-9a-z]+)$/i","\\1",$path);
	}
	
/*Errors*/
	public function hasError()
	{
		return (sizeof($this->error)!=0);
	}
	
	public function getErrorMsg()
	{
		$r="";
		foreach($this->error as $errno)
		{
			$r.="Error ".$errno." : ".$this->error_msg[$errno]."   \n";
		}
		return $r;
	}


/* manipulate image */
	public function rotate($degree,$bg=0)
	{			
		try
		{
			$img=imagerotate($this->img,$degree,$bg);
		}
		catch(Exception $e)
		{
			echo $e;
		}

		imagedestroy($this->img);
		$this->img=$img;
	}
	
	/**
	 * mode:
	 * 0 = use long side to scale and override short side
	 * 1 = use short side to scale and override long side
	 * 2 = use width to scale and override height
	 * 3 = use height to scale and override width
	 * --
	 * 4 = use width and height - add a black (or any other color) background to fill
	 * 5 = use width and height - zoom to the center and cut the rest of the image
	 */
	public function resizeProportional($width,$height,$mode=0,$bgcol=0)
	{
		$new_w=0;
		$new_h=0;
		
		if($mode==5)
		{
			$img = imagecreatetruecolor($width,$height);
			imagefill($img,0,0,$bgcol);
			$ratio=$this->getCurrentHeight()/$this->getCurrentWidth();
			$new_ratio=$height/$width;
			if($ratio<$new_ratio)
			{
				//cut left and right
				$new_h=$height;
				$new_w=$height/$ratio;
				$diff=($width-$new_w);
				imagecopyresampled($img,$this->img,$diff/2,0,0,0,$width-$diff,$height,$this->getCurrentWidth(),$this->getCurrentHeight());
			}
			else
			{
				//cut top and bottom
				$new_w=$width;
				$new_h=$width*$ratio;
				$diff=($height-$new_h);
				imagecopyresampled($img,$this->img,0,$diff/2,0,0,$width,$height-$diff,$this->getCurrentWidth(),$this->getCurrentHeight());
			}
			imagedestroy($this->img); /* nötig? */
			$this->img = $img;
		}
		elseif($mode==4)
		{
			$img = imagecreatetruecolor($width,$height);
			imagefill($img,0,0,$bgcol);
			$ratio=$this->getCurrentHeight()/$this->getCurrentWidth();
			$new_ratio=$height/$width;
			if($new_ratio>$ratio)
			{
				//border at top and bottom
				$new_w=$width;
				$new_h=$width*$ratio;
				$diff=($height-$new_h);
				imagecopyresampled($img,$this->img,0,$diff/2,0,0,$width,$height-$diff,$this->getCurrentWidth(),$this->getCurrentHeight());
			}
			else
			{
				//border left and right
				$new_h=$height;
				$new_w=$height/$ratio;
				$diff=($width-$new_w);
				imagecopyresampled($img,$this->img,$diff/2,0,0,0,$width-$diff,$height,$this->getCurrentWidth(),$this->getCurrentHeight());
			}
			imagedestroy($this->img); /* nötig? */
			$this->img = $img;
		}
		elseif($mode==3 || ($mode==0 && $this->getCurrentHeight()>=$this->getCurrentWidth()) || ($mode==1 && $this->getCurrentHeight()<=$this->getCurrentWidth()))
		{
			$ratio=$this->getCurrentWidth()/$this->getCurrentHeight();
			$new_h=$height;
			$new_w=$ratio*$height;
			$this->resize($new_w,$new_h);
		}
		else
		{
			$ratio=$this->getCurrentHeight()/$this->getCurrentWidth();
			$new_w=$width;
			$new_h=$ratio*$width;
			$this->resize($new_w,$new_h);
		}
	}

	
	public function resize($width,$height)
	{
		if(!is_numeric($width)||$width<=0||!is_numeric($height)||$height<=0)
		{
			array_push($this->error,3);
			return false;
		}
        $img = imagecreatetruecolor($width,$height);
		imagecopyresampled($img,$this->img,0,0,0,0,$width,$height,$this->getCurrentWidth(),$this->getCurrentHeight());
		imagedestroy($this->img); /* nötig? */
		$this->img = $img;
	}
	
	public function crop($top,$left,$bottom,$right)
	{
		$nw=($right-$left);
		$nh=($bottom-$top);
        $img = imagecreatetruecolor($nw,$nh);
		imagecopyresampled($img,$this->img,0,0,$left,$top,$nw,$nh,$nw,$nh);
		imagedestroy($this->img);
		$this->img=$img;
	}
	
	public function setTransparentColor($transparentColor,$toleranz=10)
	{
		if(is_null($this->img))
		{
			array_push($this->error,4);
			return false;
		}
		//split index to red green and blue:
		$t_red=($transparentColor>>16)&0xFF;
		$t_green=($transparentColor>>8)&0xFF;
		$t_blue=($transparentColor)&0xFF;
/* info:
 * 	combining the three colors to the color-index:
 * 		$transparentColor=($t_red<<16)|($t_green<<8)|($t_blue);*/

		//fill all pixel within a defined tolerance with the transparentColor
		for ($ix = 0; $ix < $this->getCurrentWidth(); $ix++)
		{
			for ($iy = 0; $iy < $this->getCurrentHeight(); $iy++)
			{
				$farbindex = imagecolorat($this->img, $ix, $iy);
				$p_red=($farbindex>>16)&0xFF;
				$p_green=($farbindex>>8)&0xFF;
				$p_blue=($farbindex)&0xFF;
//				echo " $p_red >= ($t_red-$toleranz) && $p_red <= $t_red + $toleranz ) && ( $p_green >= ( $t_green - $toleranz ) && $p_green <= $t_green + $toleranz ) && ( $p_blue >= ( $t_blue - $toleranz ) && $p_blue <= $t_blue + $toleranz ) ) <br />";
				if(($p_red>=($t_red-$toleranz) && $p_red<=$t_red+$toleranz) && ($p_green>=($t_green-$toleranz) && $p_green<=$t_green+$toleranz) && ($p_blue>=($t_blue-$toleranz) && $p_blue<=$t_blue+$toleranz))
				{
					imagesetpixel ($this->img, $ix, $iy, $transparentColor);
				}
			}
//			echo "<hr>";
		}

		imagecolortransparent($this->img,$transparentColor);
	}
	
	public function addWatermarkImageObject($ImageObject,$opacity=50,$posX=null,$posY=null)
	{
		if(is_null($posX))
			$posX = $this->getCurrentWidth() / 2 - ($ImageObject->getCurrentWidth() / 2);
		if(is_null($posY))
			$posY = $this->getCurrentHeight() / 2 - ($ImageObject->getCurrentHeight() / 2);
		if(is_null($this->img))
		{
			array_push($this->error,4);
			return false;
		}
		imagecopymerge($this->img, $ImageObject->getImageRessource(), $posX, $posY, 0, 0, $ImageObject->getCurrentWidth(), $ImageObject->getCurrentHeight(), $opacity);
	}
	
	public function addWatermarkImageRessource($Image,$opacity=50,$posX=null,$posY=null)
	{
		if(is_null($posX))
			$posX = $this->getCurrentWidth() / 2 - (imagesx($Image) / 2);
		if(is_null($posY))
			$posY = $this->getCurrentHeight() / 2 - (imagesx($Image) / 2);
		if(is_null($this->img))
		{
			array_push($this->error,4);
			return false;
		}
		imagecopymerge($this->img, $Image, $posX, $posY, 0, 0, imagesx($Image), imagesx($Image), $opacity);
	}
	
	public function addWatermark($watermarkFile,$opacity=50,$posX=null,$posY=null,$angle=0,$transparentColor=null,$resizeW=null,$resizeH=null,$resizeMode=null)
	{

		$watermark=new Image($watermarkFile);
//		$watermark->setTransparentColor($transparentColor);
		if(is_null($resizeMode))
		{
			if(!is_null($resizeW) && !is_null($resizeH))
				$watermark->resize($resizeW,$resizeH);
		}
		else
		{
			if(!is_null($resizeW) && !is_null($resizeH))
			$watermark->resizeProportional($resizeW,$resizeH,$resizeMode);
		}
		//im Fehler-Fall beenden
		if($watermark->hasError()) return false;

		$watermark->rotate($angle,$transparentColor);
		$watermark->setTransparentColor($transparentColor);
		$this->addWatermarkImageObject($watermark,$opacity,$posX,$posY);

	}
	
	public function showJPG()
	{
		if(is_null($this->img))
		{
			array_push($this->error,4);
			return false;
		}
		header("Content-type: image/jpeg");
		imagejpeg($this->img);
	}
	
	public function showPNG()
	{
		if(is_null($this->img))
		{
			array_push($this->error,4);
			return false;
		}
		header("Content-type: image/png");
		imagepng($this->img);
	}
}

?>


edit: wenn du natürlich auch noch dich frei durch's Bild durchschieben willst, wie bei Google Maps, dann bleibt dir wohl nix anderes übrig wie das, was lightsaver gerade geschrieben hat: Bild in einzelne Quadrate aufteilen und dann dynamisch nachladen... so macht's selbst Google
 
Da wirst du glaube ich nichts fertiges finden.
Wenn ich mich richtig erinnere, läuft es etwa so, dass du für verschiedene Zoomstufen halt erstmal das ganze als großes Bild vorhältst.
Das jeweilige Bild unterteilst du dann Blöcke, die du dann halt nach Bedarf einzeln überträgst.
So ungefähr läuft das ganz grob ab, so ganz trivial ist das aber wohl nicht.
 
Original von Easyrider
@ CrAc
Mit CSS lädst du ja das ganze Bild! Da bin ich mal gespannt was die armen User sagen wenn das V90 Modem brüllt :P

Bei einer Auflösung von 12000x9000 Pixel in RGB pro Kanal 8Bit? unkomprimierte Rohdaten haben wir hier:
Code:
12000 Pixel x 9000 Pixel = 108000000 Pixel x 24Bit =2592000000 Bit \ 8 = 324000000 Byte
324000000 Byte \ 1024 = 316406,25 KB =
308,99 MB

Als JPEG 100 oder 2000 wüsste ich gerne die Größe, berechnen lässt sich das ja nicht pauschal, da größere einfarbige Flächen besser komprimiert werden können als ein rosa Rauschen? :).

2
http://de.wikipedia.org/w/index.php?title=Datei:Pink.noise.col.png&filetimestamp=20060704112203

da das bild größtenteils nur s/w und große einfarbige flächen ;)
ich habs als png vorliegen und da isses 10mb groß, bereitet aber so vielen browser kopfschmerzen, vorallem wenn der ram knapp wird :D

das mit dem zerstückeln per php und einzeln nachladen klingt eigentlich ganz cool, ist nur die frage ob ich mit php das bild als rohdaten halten kann, weil das dürfte ja nach unten beschriebener rechnung 300mb in anspruch nehmen.

wichtig is mir an sich nur, dass ich im resultat per drag n drop dadrinne rumsurfen kann ;) danke schonmal für eure vielen anregungen, heut muss ich arbeiten, aber wenn ich was schaff, berichte ich!
 
Zurück
Oben