Zobrazení obrázku po uploadu bez uložení na server

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
kovarik.t
Člen | 18
+
0
-

Ahoj, chtěl bych udělat upload pomocí nette a oříznutí obrázku pomocí javascriptu Až sem nejlépe bez nutnosti uložit ho na serveru. K tomu potřebuji zobrazit obrázek po uploadu ale nějak se mi nedaří.
Zkusí mě někdo nasměrovat?

public $img

    protected function createComponentUploadForm($name)
    {
        $uploadForm = new Form($this, $name);
        $uploadForm->addUpload('img', 'Obrázek')
                ->addRule(Form::IMAGE, 'Avatar musí být JPEG, PNG nebo GIF.')
                ->addRule(Form::MAX_FILE_SIZE, 'Maximální velikost souboru je 500 kB.', 500 * 1024 /* v bytech */);
        $uploadForm->addSubmit('upload', 'Nahraj')
                        ->setAttribute('class', 'btn btn-primary')
                ->onClick[] = callback($this, 'upload');
        return $uploadForm;
    }

 public function upload($button)
    {
        $values = $button->getForm()->getValues(TRUE);

        $this->img = $values['img']->toImage()->toString(IMAGETYPE_JPEG, NULL);
    }
	<img src="{$img}"> //zkoušel jsem i helper |dataStream

Editoval kovarik.t (18. 1. 2014 11:31)

Majkl578
Moderator | 1364
+
0
-

Datastream by měl fungovat, akorát v IE<=8 je omezen na 32kB. Předáváš proměnnou do šablony? V uvedeném kódu to neděláš. (Mělo by se tak dít buď v té metodě upload nebo někde v render fázi, v action by se předalo NULL).
Jinak obrázek můžeš zobrazit i před uploadem pomocí FileReaderu, který je součástí HTML5 File API.

kovarik.t
Člen | 18
+
0
-

Majkl578 napsal(a):
Jinak obrázek můžeš zobrazit i před uploadem pomocí FileReaderu, který je součástí HTML5 File API.

Díky za tip, HTML5 File API zafungovalo skvěle. Přikládám komponentu kdyby to někoho zajímalo. Ořez je provedenej pomocí imgAreaSelect

class AvatarControl extends Control
{
    public function render()
    {
        $template = $this->template;
        $template->setFile(__DIR__ . '/AvatarControl.latte');
        //$template->form = $this->getComponent('uploadForm');
        $template->render();
    }

    protected function createComponentUploadForm($name)
    {
        $uploadForm = new Form($this, $name);
        $uploadForm->addUpload('img', 'Obrázek')
                ->setAttribute('onchange', 'PreviewImage();')
                ->addRule(Form::IMAGE, 'Avatar musí být JPEG, PNG nebo GIF.');
        $uploadForm->addHidden('left', '');
        $uploadForm->addHidden('top', '');
        $uploadForm->addHidden('selectionWidth', '');
        $uploadForm->addHidden('selectionHeight', '');
        $uploadForm->addHidden('imgWidth', '');
        $uploadForm->addHidden('imgHeight', '');
        $uploadForm->addSubmit('upload', 'Nahraj')
                        ->setAttribute('class', 'btn btn-primary')
                ->onClick[] = callback($this, 'upload');
        return $uploadForm;
    }

    public function upload($button)
    {
        $values = $button->getForm()->getValues(TRUE);
        dump($values);

        if ($values['img']->isOk())
        {
            $image = Image::fromFile($values["img"]);


            if($values['imgWidth'])
            {
            $z = $image->getWidth() / $values['imgWidth']; // koeficient zmenšení
            $left = $values['left'] * $z;
            $top = $values['top'] * $z;
            $width = $values['selectionWidth'] * $z;
            $height = $values['selectionHeight'] * $z;
            }
            else
            {
                if($image->getWidth() > $image->getHeight()) //obrázek na šířku
                {
                    $left = ($image->getWidth() - $image->getHeight()) /2;
                    $top = 0;
                    $width = $image->getHeight(); //aspect ratio 1:1
                    $height = $image->getHeight();
                }
                else //obrázek na výšku nebo 1:1
                {
                    $left = 0;
                    $top = ($image->getHeight() - $image->getWidth()) /2;
                    $width = $image->getWidth();
                    $height = $image->getWidth(); //aspect ratio 1:1
                }

            }

            $path = "c:/xampp/htdocs/avatar-component-nette/www/userfiles/images/";
            $name = uniqid();

            $image->crop($left, $top, $width, $height);
            //$image->sharpen();
            $image->resize(150, 150);
            $image->save($path . $name.".jpg", 80, Image::JPEG); // JPEG, kvalita 80%

            $this->flashMessage('Profilový obrázek byl úspěšně nahrán.', 'success');
        }
        else
        {
            $this->flashMessage('Nepovedlo se nahrát profilový obrázek.', 'warning');
        }
    }

}
<style>
    #uploadPreview {
        max-height: 500px;
        max-width: 100%;
    }
</style>

<img id="uploadPreview" />
{form uploadForm}
    {input  img}{input upload}
{/form}

<script type="text/javascript">
    function PreviewImage() {
        var oFReader = new FileReader();
        oFReader.readAsDataURL(document.getElementById("frm-avatar-uploadForm-img").files[0]);

        oFReader.onload = function (oFREvent) {
            document.getElementById("uploadPreview").src = oFREvent.target.result;
        };
    };

    $(document).ready(function () {
        $('#uploadPreview').imgAreaSelect({
           aspectRatio: '1:1',
            handles: true,
            onSelectEnd: function (img, selection) {
                $('input[name="left"]').val(selection.x1); // koordináty zleva
                $('input[name="top"]').val(selection.y1); //koordynáty shora
                $('input[name="selectionWidth"]').val(selection.width); //šířka výběru
                $('input[name="selectionHeight"]').val(selection.height); //výška výběru
                $('input[name="imgWidth"]').val(img.width); //šířka obrázku v prohlížeči
                $('input[name="imgHeight"]').val(img.height); //výška obrázku v prohlížeči
            }
        });
    });
</script>

Editoval kovarik.t (18. 1. 2014 22:49)

mpis
Člen | 65
+
0
-

To je přesně to, co hledám. Ale nemůžu to rozchodit.
Předpokládám, že ten script má zobrazit obrázek na stránce ještě před odesláním.
A to se mi právě nezobrazí.
Nevím, kde bych mohl dělat chybu. Opsal jsem to odtud přesně.
Mně by stačilo jen pouhé zobrazení načteného obrázku bez ořezávání.

honos
Člen | 109
+
0
-

mpis napsal(a):

prohlizec nepodporuje html5?

EDIT:
clanek v eng ale srozumitelny a obsirny a pisecek – pohraj si

Editoval honos (31. 1. 2014 0:27)

Majkl578
Moderator | 1364
+
0
-

V kódu od @kovarik.t by bylo určitě žádoucí přidat kontrolu, zda prohlížeč File API vůbec podporuje. Tedy řekněme obalit podmínkou if (window.FileReader) { ... }.
Přidám kousíček kódu, který jsem použil před pár dny, kdy jsem dělal právě client-side náhled obrázku, spíš jako inspiraci:

	// file upload image preview before submit
	if (window.FileReader) {
		$body.on('change', FORM_SELECTOR + ' .upload-picture input[type=file]', function () {
			var $this = $(this);
			var $previewContainer = $this.parents('.some-form-wrapper').find('.upload-picture-preview');

			var reader = new FileReader();
			reader.onloadend = function () {
				var $img = $previewContainer.children('img');

				if (!$img.length) {
					$img = $('<img>');
					$img.appendTo($previewContainer);
				}

				$img.prop('src', reader.result);
			};

			reader.readAsDataURL(this.files[0]);
		});
	}
mpis
Člen | 65
+
0
-

Velké díky honos a Majkl578.
Použil jsem kód z „písečku“ a funguje na první drc.
Teď to musím ještě zamontovat do mé aplikace,
aby se mi obrázek kreslil na místo, které potřebuji.