Próbuję utworzyć miniaturę po stronie klienta przy użyciu javascript i elementu canvas, ale kiedy zmniejszam obraz, wygląda to okropnie. Wygląda na to, że został zmniejszony w Photoshopie z ustawieniem ponownego próbkowania na „Nearest Neighbor” zamiast na Bicubic. Wiem, że to możliwe, aby wyglądało to dobrze, ponieważ ta strona może to zrobić dobrze, używając również płótna. Próbowałem użyć tego samego kodu, który robią, jak pokazano w linku „[Źródło]”, ale nadal wygląda okropnie. Czy coś mi brakuje, jakieś ustawienie, które należy ustawić, czy coś?
EDYTOWAĆ:
Próbuję zmienić rozmiar pliku JPG. Próbowałem zmienić rozmiar tego samego pliku JPG na połączonej stronie i w Photoshopie, a po zmniejszeniu rozmiar wygląda dobrze.
Oto odpowiedni kod:
reader.onloadend = function(e)
{
var img = new Image();
var ctx = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");
img.onload = function()
{
var ratio = 1;
if(img.width > maxWidth)
ratio = maxWidth / img.width;
else if(img.height > maxHeight)
ratio = maxHeight / img.height;
canvasCopy.width = img.width;
canvasCopy.height = img.height;
copyContext.drawImage(img, 0, 0);
canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
};
img.src = reader.result;
}
EDYCJA 2:
Wydaje mi się, że się myliłem, połączona witryna nie radziła sobie lepiej z redukcją obrazu. Wypróbowałem inne sugerowane metody i żadna z nich nie wygląda lepiej. Oto, co spowodowały różne metody:
Photoshop:
Brezentowy:
Obraz z renderowaniem obrazu: zoptymalizuj Zestaw jakości i skaluj według szerokości / wysokości:
Obraz z renderowaniem obrazu: zoptymalizuj Zestaw jakości i skaluj za pomocą -moz-transform:
Zmiana rozmiaru płótna na pixastic:
Myślę, że to oznacza, że firefox nie używa bicubic próbkowania, jak powinien. Muszę tylko poczekać, aż faktycznie to dodadzą.
EDYCJA 3:
źródło
Odpowiedzi:
Co więc zrobisz, jeśli wszystkie przeglądarki (właściwie Chrome 5 dał mi całkiem niezłą) nie zapewnią wystarczająco dobrej jakości ponownego próbkowania? Sam je wdrażasz! Och, daj spokój, wkraczamy w nową erę Web 3.0, przeglądarek zgodnych z HTML5, super zoptymalizowanych kompilatorów Jvascript JIT, maszyn wielordzeniowych (†), z mnóstwem pamięci, czego się boisz? Hej, w javascript jest słowo java, więc powinno to gwarantować wydajność, prawda? Oto kod generujący miniaturę:
... dzięki którym możesz uzyskać takie wyniki!
w każdym razie oto „poprawiona” wersja twojego przykładu:
Teraz nadszedł czas, aby udostępnić swoje najlepsze przeglądarki i sprawdzić, która z nich najprawdopodobniej podniesie ciśnienie krwi Twojego klienta!
Umm, gdzie jest mój tag sarkazmu?
(ponieważ wiele części kodu jest opartych na Generatorze Galerii Anrieff, czy jest ono również objęte GPL2? Nie wiem)
† tak naprawdę ze względu na ograniczenie javascript, wielordzeniowy nie jest obsługiwany.
źródło
Algorytm szybkiego zmieniania rozmiaru / ponownego próbkowania obrazu za pomocą filtra Hermite z JavaScript. Obsługuje przezroczystość, daje dobrą jakość. Zapowiedź:
Aktualizacja : wersja 2.0 dodana na GitHub (szybciej, pracownicy sieci + obiekty zbywalne). Wreszcie mam to działa!
Git: https://github.com/viliusle/Hermite-resize
Demo: http://viliusle.github.io/miniPaint/
źródło
Wypróbuj pica - to wysoce zoptymalizowany resizer z wybieranymi algorytmami. Zobacz demo .
Na przykład oryginalny obraz z pierwszego postu jest zmieniany w 120ms z filtrem Lanczos i oknem 3px lub 60ms z filtrem Box i oknem 0,5px. W przypadku ogromnego obrazu 17 MB 5000 x 3000 pikseli zmiana rozmiaru zajmuje około 1 sekundy na komputerze i 3 sekundy na telefonie komórkowym.
Wszystkie zasady zmiany rozmiaru zostały bardzo dobrze opisane w tym wątku, a pica nie dodaje nauki o rakietach. Ale jest bardzo dobrze zoptymalizowany dla nowoczesnych JIT-ów i jest gotowy do użycia po wyjęciu z pudełka (npm lub altana). Korzysta także z pracowników sieci, jeśli są dostępne, aby uniknąć zawieszenia interfejsu.
Planuję również wkrótce dodać obsługę maski wyostrzającej, ponieważ jest to bardzo przydatne po zmniejszeniu skali.
źródło
Wiem, że to stary wątek, ale może być przydatny dla niektórych osób, takich jak ja, że kilka miesięcy później ten problem pojawia się po raz pierwszy.
Oto kod, który zmienia rozmiar obrazu przy każdym ponownym załadowaniu obrazu. Wiem, że to wcale nie jest optymalne, ale zapewniam to jako dowód koncepcji.
Przepraszam również za użycie jQuery dla prostych selektorów, ale po prostu czuję się zbyt swobodnie ze składnią.
Moja funkcja createImage jest wywoływana raz, gdy dokument jest ładowany, a następnie jest wywoływana za każdym razem, gdy okno odbiera zdarzenie zmiany rozmiaru.
Przetestowałem to w Chrome 6 i Firefox 3.6, oba na Macu. Ta „technika” zjada procesor tak, jakby latem był lodem, ale działa.
źródło
Wprowadziłem kilka algorytmów do interpolacji obrazu na tablicach pikseli HTML, które mogą się tu przydać:
https://web.archive.org/web/20170104190425/http://jsperf.com:80/pixel-interpolation/2
Można je kopiować / wklejać i można ich używać wewnątrz robotów internetowych do zmiany rozmiaru obrazów (lub dowolnej innej operacji wymagającej interpolacji - obecnie używam ich do odrzucania obrazów).
Nie dodałem powyższych elementów lanczos, więc możesz dodać je jako porównanie, jeśli chcesz.
źródło
To jest funkcja javascript zaadaptowana z kodu @ Telanor. Przekazując obraz base64 jako pierwszy argument do funkcji, zwraca base64 obrazu o zmienionym rozmiarze. maxWidth i maxHeight są opcjonalne.
źródło
Gorąco polecam sprawdzenie tego linku i upewnienie się, że jest ustawiony na wartość true.
źródło
Jeśli po prostu próbujesz zmienić rozmiar obrazu, zalecam ustawienie
width
iheight
obrazu za pomocą CSS. Oto szybki przykład:Pamiętaj, że
height
iwidth
można również ustawić za pomocą JavaScript. Oto przykładowy kod:Ponadto, aby upewnić się, że obraz o zmienionym rozmiarze wygląda dobrze, dodaj następujące reguły css do selektora obrazu:
-ms-interpolation-mode: bicubic
: wprowadzenie w IE7image-rendering: optimizeQuality
: wprowadzono w FireFox 3.6O ile mi wiadomo, wszystkie przeglądarki oprócz IE używają dwububnego algorytmu do domyślnego zmieniania rozmiaru obrazów, więc obrazy o zmienionym rozmiarze powinny wyglądać dobrze w Firefox i Chrome.
Jeśli ustawienie css
width
iheight
nie działa, możesz chcieć grać z csstransform
:-moz-transform: scale(sx[, sy])
-webkit-transform:scale(sx[, sy])
Jeśli z jakiegokolwiek powodu musisz użyć płótna, pamiętaj, że można zmienić rozmiar obrazu na dwa sposoby: zmieniając rozmiar płótna za pomocą css lub rysując obraz w mniejszym rozmiarze.
Zobacz to pytanie, aby uzyskać więcej informacji.
źródło
Do zmiany rozmiaru do obrazu o szerokości mniejszej niż oryginał używam:
i działa =).
źródło
otrzymałem ten obraz, klikając prawym przyciskiem myszy element canvas w Firefoksie i zapisując jako.
w każdym razie oto „poprawiona” wersja twojego przykładu:
źródło
Problem z niektórymi z tych rozwiązań polega na tym, że uzyskują bezpośredni dostęp do danych pikseli i przechodzą przez nie w celu przeprowadzenia próbkowania w dół. W zależności od rozmiaru obrazu może to być bardzo wymagające pod względem zasobów i lepiej byłoby użyć wewnętrznych algorytmów przeglądarki.
Funkcja drawImage () wykorzystuje metodę próbkowania liniowego z interpolacją najbliższego sąsiada. Że działa dobrze, gdy nie jest zmiana rozmiaru w dół więcej niż połowę pierwotnego rozmiaru .
Jeśli zapętlisz się, aby zmienić rozmiar maksymalnie o połowę na raz, wyniki byłyby całkiem dobre i znacznie szybsze niż dostęp do danych pikseli.
Ta funkcja zmniejsza próbkę do połowy za każdym razem, aż osiągnie pożądany rozmiar:
Podziękowania dla tego postu
źródło
Więc coś interesującego, co znalazłem jakiś czas temu podczas pracy z płótnem, które może być pomocne:
Aby samodzielnie zmienić rozmiar kontrolki obszaru roboczego, musisz użyć atrybutów
height=""
iwidth=""
(lubcanvas.width
/canvas.height
elements). Jeśli użyjesz CSS do zmiany rozmiaru płótna, to faktycznie rozciągnie (tj. Zmieni rozmiar) zawartość płótna, aby dopasować do całego płótna (zamiast po prostu zwiększać lub zmniejszać obszar płótna.Warto spróbować spróbować narysować obraz w kontrolce obszaru roboczego z atrybutami wysokości i szerokości ustawionymi na rozmiar obrazu, a następnie użyć CSS, aby zmienić rozmiar obszaru roboczego do poszukiwanego rozmiaru. Być może wykorzystałoby to inny algorytm zmiany rozmiaru.
Należy również zauważyć, że canvas ma różne efekty w różnych przeglądarkach (a nawet w różnych wersjach różnych przeglądarek). Algorytmy i techniki stosowane w przeglądarkach mogą się z czasem zmieniać (szczególnie w przypadku Firefoxa 4 i Chrome 6, które pojawią się wkrótce, co położy duży nacisk na wydajność renderowania na płótnie).
Ponadto możesz też spróbować SVG, ponieważ prawdopodobnie używa on również innego algorytmu.
Powodzenia!
źródło
Mam wrażenie, że moduł, który napisałem, da podobne wyniki do Photoshopa, ponieważ zachowuje dane kolorów poprzez uśrednienie ich, a nie zastosowanie algorytmu. To trochę powolne, ale dla mnie jest najlepsze, ponieważ zachowuje wszystkie dane kolorów.
https://github.com/danschumann/limby-resize/blob/master/lib/canvas_resize.js
Nie pobiera najbliższego sąsiada i nie upuszcza innych pikseli ani nie próbkuje grupy i nie przyjmuje losowej średniej. Pobiera dokładną proporcję, jaką każdy piksel źródłowy powinien wyprowadzić do piksela docelowego. Średni kolor piksela w źródle będzie średnim kolorem piksela w miejscu docelowym, którym, jak sądzę, nie będą te inne formuły.
przykład użycia znajduje się na dole https://github.com/danschumann/limby-resize
AKTUALIZACJA PAŹDZIERNIKA 2018 : Obecnie mój przykład jest bardziej akademicki niż cokolwiek innego. Webgl jest prawie w 100%, więc lepiej byłoby zmienić jego rozmiar, aby uzyskać podobne wyniki, ale szybciej. Uważam, że PICA.js to robi. -
źródło
Przekształciłem odpowiedź @ syockit oraz podejście stopniowe w usługę Angular wielokrotnego użytku dla wszystkich zainteresowanych: https://gist.github.com/fisch0920/37bac5e741eaec60e983
Dołączyłem oba rozwiązania, ponieważ oba mają swoje zalety / wady. Metoda konwergencji lanczos ma wyższą jakość kosztem bycia wolniejszym, podczas gdy stopniowe zmniejszanie skali daje rozsądnie wyniki antyaliasingu i jest znacznie szybsze.
Przykładowe użycie:
źródło
Szybki i prosty zmieniacz obrazów JavaScript:
https://github.com/calvintwr/blitz-hermite-resize
Historia
To naprawdę jest po wielu rundach badań, czytania i prób.
Algorytm resizera używa skryptu Hermite @ ViliusL (resizer Hermite jest naprawdę najszybszy i daje dość dobrą wydajność). Rozszerzony o potrzebne funkcje.
Widelec 1 pracownika do zmiany rozmiaru, aby nie zamroził przeglądarki podczas zmiany rozmiaru, w przeciwieństwie do wszystkich innych dostępnych tam modyfikatorów JS.
źródło
Dzięki @syockit za świetną odpowiedź. musiałem jednak sformatować trochę w następujący sposób, aby działało. Być może z powodu problemów ze skanowaniem DOM:
źródło
Właśnie uruchomiłem stronę porównań obok siebie i chyba że coś się ostatnio zmieniło, nie widziałem lepszej redukcji (skalowania) przy użyciu canvas względem zwykłego css. Testowałem w FF6 Mac OSX 10.7. Wciąż nieco miękki w porównaniu do oryginału.
Natknąłem się jednak na coś, co zrobiło ogromną różnicę i polegało na użyciu filtrów obrazów w przeglądarkach obsługujących płótno. W rzeczywistości można manipulować obrazami w podobny sposób jak w Photoshopie za pomocą rozmycia, wyostrzenia, nasycenia, tętnienia, skali szarości itp.
Następnie znalazłem niesamowitą wtyczkę jQuery, która sprawia, że zastosowanie tych filtrów jest bardzo proste: http://codecanyon.net/item/jsmanipulate-jquery-image-manipulation-plugin/428234
Po prostu stosuję filtr wyostrzania zaraz po zmianie rozmiaru obrazu, co powinno dać pożądany efekt. Nie musiałem nawet używać elementu canvas.
źródło
Szukasz innego świetnego prostego rozwiązania?
To rozwiązanie wykorzysta algorytm zmiany rozmiaru przeglądarki! :)
źródło