La lettura di pixeldata dalle immagini in JavaScript restituisce risultati inaspettati per i pixel semitrasparenti

Sto leggendo i dati RGBA da un file png in JavaScript. Per fare questo traiamo l'image su una canvas e usiamo .getImageData . I dati sono diversi da quello che prevedo:

Immagine di prova: https://raw.githubusercontent.com/FlorianLudwig/imghash/master/test/transparent.png

Il terzo pixel di RGBA in JS è: [9, 0, 0, 54] (testato in cromo e firefox), ma dovrebbe essere [12, 0, 0, 54] (alless è quello che chiedono gimp e python cuscino).

Le mie ipotesi che cosa potrebbe essere sbagliato

  1. drawImage fa qualche compositing (impostazione ctx.globalCompositeOperation per copy non fa alcuna differenza)
  2. esiste un certo errore di colore durante il carico di tempo dell'image

Codice di esempio

  1. http://codepen.io/anon/pen/EaemZw
  2. Selezionare l'image di prova
  3. controllare l'output della consolle

1) Composizione

Le operazioni di prelievo più applicate si verificano nel corso del tempo. Tuttavia, con un pareggio iniziale questo non import.

copy modalità di copy non influenza come si è scoperto. Questo solo ignora i dati di background esistenti. source-over utilizzano il valore alfa di background, ma poiché nessuno inizialmente avrà lo stesso effetto.

Il problema principale con questo è però che ci sono problemi generali con gli alfa e gli errori di arrotondamento dovuti ai valori alfa pre-moltiplicati che devono essere convertiti internamente.

2) Gestione del colore

I browser supportno diversi livelli di gestione dei colors. Questo include i seguenti dati dal file PNG:

  • sRGB che indica come il PNG è conforms allo standard sRGB (relativo, assoluto ecc.)
  • il pezzo iCCP che contiene un profilo ICC compreso gamma, che se il browser support ICC e anche questa versione di ICC (versioni tipiche sono versione 2 e 4).
  • Se non vengono trovati profili sRGB o iCCP, cercherà il pezzo gAMA che contiene un numero che rappresenta la gamma.

Quando questi dati vengono applicati, verrà modificata la bitmap originale. Gamma non influisce sui valori più bassi né sui valori più alti, ma il mid-range avrà una notevole modifica. I valori ancora modificati verranno modificati a causa degli errori di gestione dei colors e di conversione (1.).

Ad esempio, anche se il file non ha un pezzo gamma (o un "file gamma"), che è il caso del file di prova o il suo valore è 1, verrà applicata una gamma di visualizzazione (ad exception di IE). Per le windows questo sarebbe 2.2 e per Mac tipicamente 1.8.

E questo accade prima che l'image venga restituita per essere utilizzata nel codice con la canvas.

In alternativa, vorrei suggerire di dare un'occhiata alla mia versione (MIT) che ho creato per questo tipo di scenario, per consentire agli sviluppatori di get un bitmap inalterato raw da un PNG (basta vedere le note / lo stato in quanto attualmente ancora in alpha ). Ho fornito un esempio di codice al di sotto che legge anche il terzo pixel che dà 12 per il canale rosso come previsto.

Prova con pngtoy

In questo modo verrà mostrato il valore bitmap inalterato.

 var out = document.querySelector("output"), png = new PngToy(); png.fetch("https://i.imgur.com/oX1kom7.png").then( function() {png.decode().then(show)} ); function show(bmp) { var data = bmp.bitmap; out.innerHTML += data[8] + "," + data[9] + "," + data[10] + "," + data[11]; } 
 <script src="https://rawgit.com/epistemex/pngtoy/master/tests/Promise.js"></script> <script src="https://rawgit.com/epistemex/pngtoy/master/pngtoy.min.js"></script> <output>Loading external scripts (pngtoy.min.js + Promise polyfill for IE...)<br></output> 

La tua ipotesi # 2 è corretta.

I browser vengono rilasciati liberamente dalla specifica per fare le regolazioni Alpha & Gamma alle immagini in entrata.