• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Najszybsza metoda na sprawdzenie czy obraz posiada więcej niż jeden kolor

Cloud VPS
0 głosów
390 wizyt
pytanie zadane 25 czerwca 2019 w JavaScript przez BT101 Stary wyjadacz (12,540 p.)

Natknąłem się na ciekawy problem - musiałem sprawdzić czy dany obraz posiada więcej niż 1 kolor. Użyłem funkcji getPixels która zwraca ndarray (wielowymiarowa tablica w js) pikseli. W tej tablicy piksele były ułożone we wzorze [ r, g, b, a, r, g, b, a ... ] czyli każde 4 elementy stanowiły opis jednego piksela. Przekonwertowałem to na zwykłą tablicę tablic we wzorze [ [r, g, b, a], [r, g, b, a] ... ].

Następnie w pętli przeiterowałem po tej tablicy i porównwałem kolejno obecną zagnieżdżoną tablicę z następną zamieniając je na JSON stringa.

Jeżeli którakolwiek z tablic się nie zgadza to ustawiam boolean na false i przerywałem działanie pętli.

const getPixels = require("get-pixels");

//1px only black https://i.imgur.com/dStJ1Og.png
//2px only black https://i.imgur.com/5z46WVp.png
//88x62px only black https://i.imgur.com/ZtGMUh9.png
//88x62px black and red https://i.imgur.com/67IZCaD.png
//220x297px black and red https://i.imgur.com/KTNnJGF.jpg

getPixels("https://i.imgur.com/JiHtQuR.jpg", function(err, ndarray) {
    if(err) {
        console.log("Bad image path!");
        return;
    }

    const uintArr = new Uint8Array(ndarray.data);
    const regularArr = [];
    let oneColor = true;

    for(let i = 0, l = uintArr.length / 4; i < l; i++) {
        regularArr.push([uintArr[4*i], uintArr[4*i+1], uintArr[4*i+2], uintArr[4*i+3]])
    }
    for(let i = 0, l = regularArr.length; i < l; i++) {
        if(regularArr[i + 1]) {
            let currentValString = JSON.stringify(regularArr[i]);
            let nextValString = JSON.stringify(regularArr[i + 1]);

            if(currentValString !== nextValString) {
                oneColor = false;
                break;
            }
        }
    }

    console.log('Is image one color? ', oneColor);
});

Wygląda na to, że kod działa poprawnie. Problemem jest wydajność. Dla obrazu 3000x4000px (12 mln pikseli) operacja trwa 8 sekund (co prawda specjalnie stworzyłem cały czarny obraz z 1 px czerwonym gdzieś w prawym dolnym rogu). To o 90% za dużo. Czy mam jakieś opcje poza zmianą języka?

komentarz 25 czerwca 2019 przez niezalogowany
Jakie formaty plików chcesz obsługiwać?
komentarz 25 czerwca 2019 przez BT101 Stary wyjadacz (12,540 p.)
gif, png

1 odpowiedź

+1 głos
odpowiedź 25 czerwca 2019 przez adrian17 Mentor (354,720 p.)
wybrane 25 czerwca 2019 przez BT101
 
Najlepsza

Coś takiego?

let r = uintArr[0], g = uintArr[1], b = uintArr[2], a = uintArr[3];
for (let i = 0; i < uintArr.length; i += 4) {
	if (
		r != uintArr[i] ||
		g != uintArr[i+1] ||
		b != uintArr[i+2] ||
		a != uintArr[i+3]
	) {
		return false;
	}
}
return true;

 

komentarz 25 czerwca 2019 przez BT101 Stary wyjadacz (12,540 p.)
i porównać Uint32Array z ...?
komentarz 25 czerwca 2019 przez adrian17 Mentor (354,720 p.)
no, porównać jego elementy.
komentarz 25 czerwca 2019 przez BT101 Stary wyjadacz (12,540 p.)
aaa, dobra spróbuje
komentarz 25 czerwca 2019 przez Comandeer Guru (607,100 p.)

żeby nie sprawdzać długości przy każdym "obrocie" pętli

Polecam poczytać: https://mrale.ph/blog/2014/12/24/array-length-caching.html 

komentarz 25 czerwca 2019 przez BT101 Stary wyjadacz (12,540 p.)
a spoko czyli v8 robi to za mnie

Podobne pytania

+3 głosów
2 odpowiedzi 797 wizyt
+2 głosów
1 odpowiedź 5,336 wizyt
0 głosów
1 odpowiedź 948 wizyt

93,487 zapytań

142,421 odpowiedzi

322,772 komentarzy

62,906 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...