Come configurare smartphone e PC. Portale informativo
  • Casa
  • Windows 7, XP
  • JPEG, JPEG2000, JPEG-LS. Compressione delle immagini con e senza perdita di dati

JPEG, JPEG2000, JPEG-LS. Compressione delle immagini con e senza perdita di dati

Fotografie e immagini differiscono l'una dall'altra non solo nel contenuto, ma anche in altre caratteristiche "informatiche". Ad esempio, per dimensione.

Succede che sembrano esserci due disegni identici, ma uno è tre volte più grande dell'altro.

Le immagini differiscono anche in termini di qualità. Penso che tu abbia visto foto di qualità estremamente scadente più di una volta. Questo è visibile ad occhio nudo. Ad esempio, due foto identiche, ma uno è di qualità migliore e l'altro è di qualità peggiore.

E succede che il disegno sembra privo di colori. Ecco un esempio.

E il formato o il tipo di file è responsabile di tutto questo.

In effetti, le immagini sono disponibili in una varietà di formati. E ce ne sono moltissimi. Non li considereremo tutti, ma parleremo di quelli più comuni. Questi sono formati come bmp, gif, jpg, png, tiff.

Differiscono l'uno dall'altro, prima di tutto, per la qualità. E la qualità differisce nel numero (saturazione) dei colori.

Ad esempio, dipingo un'immagine utilizzando colori diversi. E poi all'improvviso alcuni finiscono e devi finire di dipingere con quello che hai. Naturalmente, cercherò di fare tutto il possibile in modo che ciò non influisca molto sul risultato, ma l'immagine non risulterà comunque come vorrei: più sbiadita, sfocata.

Con i formati immagine è così. Alcuni lasciano tutti i colori, mentre altri ne tagliano alcuni. E a volte questo fa sì che l'immagine si deteriori.

Questo è un esempio piuttosto approssimativo. In effetti, tutto è un po' più complicato, ma penso che tu abbia capito il punto principale.

Formati di immagine comuni

BMP è un formato per i disegni realizzati nel programma Paint. Può essere utilizzato per memorizzare immagini disegnate sul tuo computer. Ma questo tipo di file non viene utilizzato su Internet a causa delle sue grandi dimensioni. Quindi, se desideri pubblicare un'immagine disegnata con Paint su un blog o un social network, deve essere di tipo diverso: gif, jpg o png.

GIF è un formato immagine popolare su Internet. Puoi salvarli senza perdere la qualità, ma con un numero limitato di colori - 256. La GIF ha guadagnato particolare popolarità grazie al fatto che può creare piccole immagini animate (in movimento).

JPG è un formato per fotografie e dipinti con un gran numero di colori. Puoi salvare un'immagine al suo interno sia senza perdita di qualità che con perdita.

PNG è un formato immagine moderno. Si ottiene questo tipo di immagine piccola dimensione e senza perdita di qualità. Molto comodo: il file è piccolo e la qualità è buona. Supporta anche la trasparenza.

TIFF: le immagini sono molto buona qualità, senza compressione Di conseguenza, la dimensione di tali file è enorme. TIFF viene utilizzato quando la qualità è di grande importanza. Ad esempio, quando si creano biglietti da visita, opuscoli, copertine di riviste.

Quale formato scegliere

  • BMP: se si tratta di un disegno realizzato in Paint e lo manterrai solo sul computer.
  • GIF - se un'animazione o un disegno con un numero limitato di colori per la pubblicazione su Internet.
  • PNG - se si tratta di un'immagine con molti colori o alcune parti trasparenti.
  • JPG (jpeg) - se una fotografia.
  • TIFF - immagine per la stampa (biglietti da visita, opuscoli, poster, ecc.).

Ciao, cari amici. Oggi parleremo di quale formato immagine è meglio utilizzare sul sito, quali formati di file grafici sono disponibili oggi per il sito e se è necessario perseguire nuovi formati grafici.

Ricevo molte domande come questa; molti dei miei studenti mi chiedono se possono utilizzare i nuovi formati SVG e WebP e qual è il posto migliore per utilizzare queste immagini. Certo, puoi usare nuovi formati, devi solo capire quale formato è più adatto a cosa.

Oggi le immagini su un sito web ne sono parte integrante. A partire da graphic design e il caricamento di immagini negli articoli, la grafica accompagna la maggior parte dei siti della rete. Ma la bellezza ha un prezzo

Le immagini non ottimizzate sono uno dei fattori che rallentano un sito web, come indicato dai servizi di verifica.

Pertanto, dovrai sempre decidere quale formato scegliere per l'immagine. Le sue dimensioni e qualità dipenderanno da questo. E usare le immagini dimensione più piccola e senza perdere qualità, dovresti sapere alcune cose.

Quali immagini per i siti web utilizzo oggi?

Tutte le immagini per i siti web sono suddivise in:

  • raster (esempio: JPG, JPEG, GIF, PNG),
  • vettore (esempio - SVG).

Raster Le immagini sono costituite da pixel che memorizzano valori di colore e trasparenza. Questi formati includono immagini in articoli, pulsanti, icone ed elementi di design. Queste immagini sono popolari tra gli sviluppatori e i proprietari di siti web. Lo svantaggio principale delle immagini raster è che non si adattano bene.

Cioè, quando la dimensione dell'immagine aumenta, si verifica una perdita di qualità.

Vettore le immagini sono costituite da linee e punti di passaggio. Le informazioni sull'immagine vengono memorizzate in istruzioni di rendering matematico, che consentono di ridimensionare tali immagini quanto desiderato senza perdita di qualità.

Tutte queste immagini possono e vengono utilizzate sui siti Web moderni. Devi solo capirlo prima di caricarlo sul sito!

Descrizione dei formati di immagine più diffusi per il sito

Dalla descrizione di questi formati capirai dove e quale formato è meglio utilizzare nel sito.

JPEG

JPEG o JPG è uno dei formati di immagine più popolari per i siti Web. Il formato supporta milioni di colori, il che gli conferisce una posizione di leadership nella presentazione di fotografie e immagini sul sito.

Le immagini in questo formato sono ottimizzate abbastanza bene praticamente senza perdita di qualità, il che consente di ottenere un file più piccolo senza perdita visiva di qualità. Va ricordato che ogni ottimizzazione successiva riduce la qualità.

I file di questo formato sono supportati da tutti i dispositivi e browser, il che conferma ancora una volta la sua popolarità e ti consente di non preoccuparti di problemi di visualizzazione sui siti.

Il grande svantaggio di questo formato è la mancanza di trasparenza. Cioè, non sarà possibile combinare immagini in questo formato. Per tali compiti è meglio utilizzare il seguente formato.

PNG

Questo formato utilizza un algoritmo di compressione senza perdita di dati. In termini di numero di colori e livello di trasparenza, è disponibile in due tipi: 8 e 24 bit. Entrambi sostengono la trasparenza.

La tecnologia a 8 bit non è molto popolare, ma la versione a 24 bit è ampiamente utilizzata varie immagini sul sito web. Grazie alla trasparenza, ti consente di creare immagini combinate. Spesso utilizzato per creare pulsanti e icone animati in cui è necessario un effetto di trasparenza.

Le immagini in formato PNG possono essere ottimizzate e modificate più volte: manterranno la qualità originale.

Il formato è inoltre supportato da tutti i browser e dispositivi, garantendone la visualizzazione su qualsiasi schermo.

La qualità delle immagini sembra migliore di JPG, ma il peso del file sarà maggiore. Questo deve essere preso in considerazione quando si inseriscono file sul sito.

GIF

È un formato a 8 bit che supporta 256 colori, trasparenza e animazione. Grazie al supporto di un numero limitato di colori, anche il peso del file è minimo.

Il formato non è adatto per fotografie e immagini con ampia gamma fiori.

Ma è ampiamente utilizzato nella creazione di banner, pulsanti, icone e così via.

Nei siti web moderni questo formato viene utilizzato sempre meno.

Parliamo poi dei formati relativamente recenti SVG e WebP, che non sono così popolari, ma stanno guadagnando popolarità e supporto e sono perfettamente adatti ai requisiti di velocità di caricamento e adattabilità del sito web.

SVG

È un formato di file vettoriale basato su XML. Il formato ha iniziato a guadagnare popolarità abbastanza recentemente, poiché in precedenza era scarsamente supportato nei browser. E a causa di problemi di visualizzazione, nessuno aveva fretta di usarlo.

Oggi SVG è supportato da tutti i browser moderni. Ma si verificano ancora problemi con il display.

Questo formato viene spesso utilizzato per immagini semplici, come loghi, elementi di design e così via. Non adatto per fotografie.

Il formato SVG è leggero, altamente scalabile, fornisce immagini nitide su qualsiasi risoluzione dello schermo, supporta l'animazione, può essere controllato tramite CSS e inserito in HTML, riducendo il numero di richieste.

WebP

Un formato open source sviluppato da Google appositamente per Internet. Oggi YouTube utilizza la conversione delle miniature dei video in WebP.

Il formato fornisce una compressione superiore e supporta la trasparenza. Combina i vantaggi dei formati JPG e PNG senza aumentare le dimensioni del file.

Ma, nonostante i vantaggi del formato, non è supportato da tutti i browser, ad esempio IE, Edge, Firefox e Safari.

Esistono modi per aggirare queste restrizioni, ma impediscono l'utilizzo del formato ovunque.

Conclusione

Amici, spero di aver spiegato tutto chiaramente e che ora sappiate quale formato di immagine è meglio utilizzare sul sito e perché non insisto sull'utilizzo di un formato particolare, ma consiglio un approccio integrato.

Forse quando WebP otterrà un supporto diffuso, passeremo tutti ad esso e sostituiremo jpg e png sui nostri siti.

Discutiamo nei commenti quali formati utilizzate sui vostri siti, cosa vi piace e cosa non vi piace.

Per oggi è tutto, aspetto i vostri commenti.

Cordiali saluti, Maxim Zaitsev.

    CON I tre formati di file più popolari sono JPEG, RAW, TIFF. A volte puoi sentire disaccordi tra i fotografi: quale formato di file è migliore per la fotografia, in quale formato è meglio scattare foto, perché le fotocamere moderne ti consentono di scattare fotografietografia in uno qualsiasi di questi formati e talvolta in più formati contemporaneamente!

    Il formato file in cui viene archiviata un'immagine è essenzialmente un compromesso tra la qualità dell'immagine e la dimensione del file.

    Probabilmente lo sai già immagine rasterè costituito da pixel. Il modo in cui è organizzato un file raster e in quale forma sono archiviate le informazioni sui pixel determina il formato del file. La qualità dell'immagine di un file raster è determinata da due parametri principali: la dimensione dei pixel (ovvero il numero totale di pixel) e la precisione del colore del pixel nel rappresentare il colore reale.Con la dimensione dei pixel è chiaro: maggiore è il numero di pixel (o “più piccolo” il pixel), meglio è.E la precisione della riproduzione del colore dipende dal numero di colori per pixel o dalla profondità del colore.

    Profondità colore (qualità della resa cromatica, profondità in bit dell'immagine): la quantità di memoria nel numero di bit utilizzata per archiviare e rappresentare il colore durante la codifica di un pixel grafica raster o immagini video. Il numero di bit indica il numero di gradazioni (passi di tono) in ciascuna componente di colore o, semplicemente, il numero di colori. Aggiungere 1 bit significa aggiungere un altro bit al codice colore binario.

    • Colore a 1 bit (21 = 2 colori) colore binario, spesso rappresentato da bianco e nero (o nero e verde)
    • Colore a 2 bit (22 = 4 colori) CGA, gradazione grigio Nextstation
    • Colore a 3 bit (23 = 8 colori) molti personal computer legacy con uscita TV
    • Il colore a 4 bit (24 = 16 colori) è noto come EGA e, in misura minore, come standard VGA ad alta risoluzione
    • Colore a 5 bit (25 = 32 colori) Chipset originale Amiga
    • Colore a 6 bit (26 = 64 colori) Chipset Amiga originale
    • Colore a 8 bit (28 = 256 colori) Workstation Unix legacy, VGA a bassa risoluzione, Super VGA, AGA
    • Colore a 12 bit (212 = 4.096 colori) su alcuni sistemi Silicon Graphics, sistemi NeXTstation e sistemi in modalità Amiga HAM.

    Ad esempio, lavoriamo nello spazio colore RGB. Ciò significa che ci sono tre canali da cui si forma il colore finale del pixel: il canale rosso (Rad), il canale verde (Green) e il canale blu (Blue). Supponiamo che i canali siano a quattro bit. Ciò significa che ciascun canale ha la capacità di visualizzare 16 colori. Di conseguenza, tutto l'RGB sarà a 12 bit e sarà in grado di essere visualizzato

    C=16x16x16=4096 colori

    La profondità del colore in questo caso è di 12 bit.

    Quando si parla di RGB a 24 bit, si intendono canali a 8 bit (256 colori ciascuno) con un numero totale di opzioni colore per pixel

    C=256x256x256=16777216 colori.

    La cifra è impressionante. Questo numero di colori per ciascun pixel soddisfa i requisiti del fotografo più esigente.

    Un po' sui formati stessi.

    Formato TIFF

    TIFF sta per Tagged Image File Format ed è uno standard per il settore della stampa e della stampa.

    Di conseguenza, questo è ciò che accade:

    1. Se la tua fotocamera è così semplice da scattare solo JPEG e desideri ottenerla massima qualità, imposta la dimensione massima e la compressione minima e non tormentarti con il fatto di non avere altri formati. Nella maggior parte dei casi, un'immagine RAW resa manualmente scrupolosamente corrisponde al JPEG catturato automaticamente dalla fotocamera.

    2. Probabilmente non dovresti scattare fotografie in TIFF. La registrazione in questo formato è più difficile, ma non vi è alcuna differenza evidente rispetto al JPEG di alta qualità.

    3. Se hai l'opportunità di scattare foto, lavora con esso. Sentirai tu stesso se è giusto per te. In alcuni casi, solo RAW rende possibile la realizzazione foto unica per un ingrandimento elevato durante la stampa.

    Resta ancora una soluzione, si potrebbe dire universale. Esiste una modalità che ti consente di scattare fotogrammi in due formati contemporaneamente: RAW+ JPEG. Riprendi scene importanti in questa modalità. La moderna memorizzazione delle informazioni digitali, sia schede di memoria che dischi rigidi, rende possibile ciò. In questo caso riceverai un JPEG per utilizzare immediatamente la foto, senza perdere tempo nella revisione. E, se ne hai bisogno, affida il file RAW a uno specialista per l'elaborazione.

    Foto. Formati di file.

    È facile calcolare che un'immagine a colori non compressa con una dimensione di 2000 * 1000 pixel avrà una dimensione di circa 6 megabyte. Se parliamo di immagini ottenute da fotocamere professionali o scanner ad alta risoluzione, le loro dimensioni possono essere ancora maggiori. Nonostante la rapida crescita della capacità dei dispositivi di memorizzazione, diversi algoritmi di compressione delle immagini sono ancora molto rilevanti.
    Tutti gli algoritmi esistenti possono essere suddivisi in due grandi classi:

    • Algoritmi di compressione senza perdite;
    • Algoritmi di compressione con perdita.
    Quando parliamo di compressione senza perdita di dati, intendiamo che esiste un algoritmo inverso all'algoritmo di compressione che consente di ripristinare con precisione l'immagine originale. Per algoritmi di compressione con perdita algoritmo inverso non esiste. Esiste un algoritmo che ripristina un'immagine che non necessariamente corrisponde esattamente a quella originale. Gli algoritmi di compressione e recupero sono selezionati per ottenere un rapporto di compressione elevato mantenendo la qualità visiva dell'immagine.

    Algoritmi di compressione senza perdite

    Algoritmo RLE
    Tutti gli algoritmi Serie RLE si basano su un'idea molto semplice: i gruppi ripetuti di elementi vengono sostituiti da una coppia (numero di ripetizioni, elemento ripetuto). Consideriamo questo algoritmo usando l'esempio di una sequenza di bit. Questa sequenza alternerà gruppi di zeri e uno. Inoltre, i gruppi avranno spesso più di un elemento. Quindi la sequenza 11111 000000 11111111 00 corrisponderà al seguente insieme di numeri 5 6 8 2. Questi numeri indicano il numero di ripetizioni (il conteggio inizia da uno), ma anche questi numeri devono essere codificati. Assumeremo che il numero di ripetizioni sia compreso tra 0 e 7 (ovvero, 3 bit sono sufficienti per codificare il numero di ripetizioni). Quindi la sequenza considerata sopra viene codificata dalla seguente sequenza di numeri 5 6 7 0 1 2. È facile calcolare che sono necessari 21 bit per codificare la sequenza originale, e nella compressa Metodo RLE Nella forma, questa sequenza richiede 18 bit.
    Sebbene questo algoritmo sia molto semplice, la sua efficienza è relativamente bassa. Inoltre, in alcuni casi, l'utilizzo di questo algoritmo non porta ad una diminuzione, ma ad un aumento della lunghezza della sequenza. Ad esempio, considera la seguente sequenza 111 0000 11111111 00. La sequenza RL corrispondente è simile a questa: 3 4 7 0 1 2. La lunghezza della sequenza originale è 17 bit, la lunghezza della sequenza compressa è 18 bit.
    Questo algoritmo è più efficace per le immagini in bianco e nero. Viene spesso utilizzato anche come uno degli stadi intermedi di compressione di algoritmi più complessi.

    Algoritmi del dizionario

    L'idea alla base degli algoritmi del dizionario è che vengono codificate catene di elementi della sequenza originale. Questa codifica utilizza un dizionario speciale, ottenuto in base alla sequenza originale.
    Esiste un'intera famiglia di algoritmi di dizionario, ma esamineremo l'algoritmo più comune LZW, che prende il nome dai suoi sviluppatori Lepel, Ziv e Welch.
    Il dizionario in questo algoritmo è una tabella che viene riempita con catene di codifica durante l'esecuzione dell'algoritmo. Quando il codice compresso viene decodificato, il dizionario viene ripristinato automaticamente, quindi non è necessario trasmettere il dizionario insieme al codice compresso.
    Il dizionario viene inizializzato con tutte le stringhe singleton, ad es. le prime righe del dizionario rappresentano l'alfabeto in cui codifichiamo. Durante la compressione viene ricercata la catena più lunga già registrata nel dizionario. Ogni volta che si incontra una catena che non è stata ancora scritta nel dizionario, questa viene aggiunta lì e viene emesso un codice compresso corrispondente alla catena già scritta nel dizionario. In teoria non vengono imposte restrizioni alla dimensione del dizionario, ma in pratica ha senso limitare questa dimensione, poiché nel tempo iniziano ad apparire catene che non si trovano più nel testo. Inoltre, quando raddoppiamo la dimensione della tabella, dobbiamo allocare un bit in più per memorizzare i codici compressi. Al fine di prevenire tali situazioni, viene introdotto codice speciale, che simboleggia l'inizializzazione della tabella con tutte le catene singleton.
    Consideriamo un esempio di algoritmo di compressione. Comprimeremo la linea cuckoocuckoocuckoohood. Supponiamo che il dizionario contenga 32 posizioni, il che significa che ciascuno dei suoi codici occuperà 5 bit. Inizialmente, il dizionario è compilato come segue:

    Questa tabella esiste sia dalla parte di chi comprime l'informazione, sia dalla parte di chi la decomprime. Ora esamineremo il processo di compressione.


    La tabella mostra il processo di compilazione del dizionario. È facile calcolare che il codice compresso risultante richiede 105 bit e il testo originale (assumendo di impiegare 4 bit per codificare un carattere) richiede 116 bit.
    In sostanza, il processo di decodifica si riduce alla decodifica diretta dei codici ed è importante che la tabella venga inizializzata allo stesso modo della codifica. Ora diamo un'occhiata all'algoritmo di decodifica.



    Possiamo definire completamente la stringa aggiunta al dizionario al passo i-esimo solo a i+1. Ovviamente la riga i-esima deve terminare con il primo carattere della riga i+1. Quello. Abbiamo appena scoperto come ripristinare un dizionario. Di un certo interesse è la situazione in cui viene codificata una sequenza della forma cScSc, dove c è un carattere e S è una stringa, e la parola cS è già nel dizionario. A prima vista può sembrare che il decoder non riesca a risolvere questa situazione, ma in realtà tutte le righe di questo tipo devono terminare sempre con lo stesso carattere con cui iniziano.

    Algoritmi di codifica statistica
    Gli algoritmi di questa serie assegnano il codice compresso più breve agli elementi più frequenti delle sequenze. Quelli. sequenze della stessa lunghezza sono codificate con codici compressi di diversa lunghezza. Inoltre, quanto più spesso si verifica una sequenza, tanto più corto è il corrispondente codice compresso.
    Algoritmo di Huffman
    L'algoritmo di Huffman consente di costruire codici prefisso. Possiamo pensare ai codici prefisso come percorsi in un albero binario: un passaggio da un nodo al suo figlio sinistro corrisponde a uno 0 nel codice, e al suo figlio destro corrisponde a un 1. Se etichettiamo le foglie dell'albero con il simboli da codificare, otteniamo la rappresentazione codice prefisso sotto forma di albero binario.
    Descriviamo l'algoritmo per costruire un albero di Huffman e ottenere i codici di Huffman.
  1. I caratteri dell'alfabeto in input formano un elenco di nodi liberi. Ogni foglio ha un peso pari alla frequenza di occorrenza del simbolo
  2. Vengono selezionati due nodi dell'albero liberi con i pesi più piccoli
  3. Il loro genitore viene creato con un peso pari al peso totale
  4. Il genitore viene aggiunto all'elenco dei nodi liberi e i suoi due figli vengono rimossi da questo elenco
  5. A un arco che lascia l'arco principale viene assegnato il bit 1, all'altro viene assegnato il bit 0
  6. I passaggi a partire dal secondo vengono ripetuti finché nell'elenco dei nodi liberi rimane un solo nodo libero. Questa sarà considerata la radice dell'albero.
Usando questo algoritmo, possiamo ottenere i codici Huffman per un dato alfabeto, tenendo conto della frequenza di occorrenza dei caratteri.
Codifica aritmetica
Gli algoritmi di codifica aritmetica codificano stringhe di elementi in una frazione. In questo caso, viene presa in considerazione la distribuzione di frequenza degli elementi. Al momento gli algoritmi di codifica aritmetica sono protetti da brevetti, quindi esamineremo solo l'idea di base.

È facile calcolare che un'immagine a colori non compressa con una dimensione di 2000 * 1000 pixel avrà una dimensione di circa 6 megabyte. Se parliamo di immagini ottenute da fotocamere professionali o scanner ad alta risoluzione, le loro dimensioni possono essere ancora maggiori. Nonostante la rapida crescita della capacità dei dispositivi di memorizzazione, diversi algoritmi di compressione delle immagini sono ancora molto rilevanti.
Tutti gli algoritmi esistenti possono essere suddivisi in due grandi classi:

  • Algoritmi di compressione senza perdite;
  • Algoritmi di compressione con perdita.
Quando parliamo di compressione senza perdita di dati, intendiamo che esiste un algoritmo inverso all'algoritmo di compressione che consente di ripristinare con precisione l'immagine originale. Non esiste un algoritmo inverso per gli algoritmi di compressione con perdita. Esiste un algoritmo che ripristina un'immagine che non necessariamente corrisponde esattamente a quella originale. Gli algoritmi di compressione e recupero sono selezionati per ottenere un rapporto di compressione elevato mantenendo la qualità visiva dell'immagine.

Algoritmi di compressione senza perdite

Algoritmo RLE
Tutti gli algoritmi della serie RLE si basano su un'idea molto semplice: i gruppi ripetuti di elementi vengono sostituiti da una coppia (numero di ripetizioni, elemento ripetuto). Consideriamo questo algoritmo usando l'esempio di una sequenza di bit. Questa sequenza alternerà gruppi di zeri e uno. Inoltre, i gruppi avranno spesso più di un elemento. Quindi la sequenza 11111 000000 11111111 00 corrisponderà al seguente insieme di numeri 5 6 8 2. Questi numeri indicano il numero di ripetizioni (il conteggio inizia da uno), ma anche questi numeri devono essere codificati. Assumeremo che il numero di ripetizioni sia compreso tra 0 e 7 (ovvero, 3 bit sono sufficienti per codificare il numero di ripetizioni). Quindi la sequenza discussa sopra viene codificata dalla seguente sequenza di numeri 5 6 7 0 1 2. È facile calcolare che la codifica della sequenza originale richiede 21 bit e nella forma compressa RLE questa sequenza richiede 18 bit.
Sebbene questo algoritmo sia molto semplice, la sua efficienza è relativamente bassa. Inoltre, in alcuni casi, l'utilizzo di questo algoritmo non porta ad una diminuzione, ma ad un aumento della lunghezza della sequenza. Ad esempio, considera la seguente sequenza 111 0000 11111111 00. La sequenza RL corrispondente è simile a questa: 3 4 7 0 1 2. La lunghezza della sequenza originale è 17 bit, la lunghezza della sequenza compressa è 18 bit.
Questo algoritmo è più efficace per le immagini in bianco e nero. Viene spesso utilizzato anche come uno degli stadi intermedi di compressione di algoritmi più complessi.

Algoritmi del dizionario

L'idea alla base degli algoritmi del dizionario è che vengono codificate catene di elementi della sequenza originale. Questa codifica utilizza un dizionario speciale, ottenuto in base alla sequenza originale.
Esiste un'intera famiglia di algoritmi di dizionario, ma esamineremo l'algoritmo più comune LZW, che prende il nome dai suoi sviluppatori Lepel, Ziv e Welch.
Il dizionario in questo algoritmo è una tabella che viene riempita con catene di codifica durante l'esecuzione dell'algoritmo. Quando il codice compresso viene decodificato, il dizionario viene ripristinato automaticamente, quindi non è necessario trasmettere il dizionario insieme al codice compresso.
Il dizionario viene inizializzato con tutte le stringhe singleton, ad es. le prime righe del dizionario rappresentano l'alfabeto in cui codifichiamo. Durante la compressione viene ricercata la catena più lunga già registrata nel dizionario. Ogni volta che si incontra una catena che non è stata ancora scritta nel dizionario, questa viene aggiunta lì e viene emesso un codice compresso corrispondente alla catena già scritta nel dizionario. In teoria non vengono imposte restrizioni alla dimensione del dizionario, ma in pratica ha senso limitare questa dimensione, poiché nel tempo iniziano ad apparire catene che non si trovano più nel testo. Inoltre, quando raddoppiamo la dimensione della tabella, dobbiamo allocare un bit in più per memorizzare i codici compressi. Per prevenire tali situazioni, viene introdotto un codice speciale, che simboleggia l'inizializzazione della tabella con tutte le catene a elemento singolo.
Consideriamo un esempio di algoritmo di compressione. Comprimeremo la linea cuckoocuckoocuckoohood. Supponiamo che il dizionario contenga 32 posizioni, il che significa che ciascuno dei suoi codici occuperà 5 bit. Inizialmente, il dizionario è compilato come segue:

Questa tabella esiste sia dalla parte di chi comprime l'informazione, sia dalla parte di chi la decomprime. Ora esamineremo il processo di compressione.

La tabella mostra il processo di compilazione del dizionario. È facile calcolare che il codice compresso risultante richiede 105 bit e il testo originale (assumendo di impiegare 4 bit per codificare un carattere) richiede 116 bit.
In sostanza, il processo di decodifica si riduce alla decodifica diretta dei codici ed è importante che la tabella venga inizializzata allo stesso modo della codifica. Ora diamo un'occhiata all'algoritmo di decodifica.


Possiamo definire completamente la stringa aggiunta al dizionario al passo i-esimo solo a i+1. Ovviamente la riga i-esima deve terminare con il primo carattere della riga i+1. Quello. Abbiamo appena scoperto come ripristinare un dizionario. Di un certo interesse è la situazione in cui viene codificata una sequenza della forma cScSc, dove c è un carattere e S è una stringa, e la parola cS è già nel dizionario. A prima vista può sembrare che il decoder non riesca a risolvere questa situazione, ma in realtà tutte le righe di questo tipo devono terminare sempre con lo stesso carattere con cui iniziano.

Algoritmi di codifica statistica
Gli algoritmi di questa serie assegnano il codice compresso più breve agli elementi più frequenti delle sequenze. Quelli. sequenze della stessa lunghezza sono codificate con codici compressi di diversa lunghezza. Inoltre, quanto più spesso si verifica una sequenza, tanto più corto è il corrispondente codice compresso.
Algoritmo di Huffman
L'algoritmo di Huffman consente di costruire codici prefisso. Possiamo pensare ai codici prefisso come percorsi in un albero binario: andare da un nodo al suo figlio sinistro corrisponde a uno 0 nel codice, e al suo figlio destro corrisponde a un 1. Se etichettiamo le foglie dell'albero con i simboli da codificare, otteniamo una rappresentazione ad albero binario del codice del prefisso.
Descriviamo l'algoritmo per costruire un albero di Huffman e ottenere i codici di Huffman.
  1. I caratteri dell'alfabeto in input formano un elenco di nodi liberi. Ogni foglio ha un peso pari alla frequenza di occorrenza del simbolo
  2. Vengono selezionati due nodi dell'albero liberi con i pesi più piccoli
  3. Il loro genitore viene creato con un peso pari al peso totale
  4. Il genitore viene aggiunto all'elenco dei nodi liberi e i suoi due figli vengono rimossi da questo elenco
  5. A un arco che lascia l'arco principale viene assegnato il bit 1, all'altro viene assegnato il bit 0
  6. I passaggi a partire dal secondo vengono ripetuti finché nell'elenco dei nodi liberi rimane un solo nodo libero. Questa sarà considerata la radice dell'albero.
Usando questo algoritmo, possiamo ottenere i codici Huffman per un dato alfabeto, tenendo conto della frequenza di occorrenza dei caratteri.
Codifica aritmetica
Gli algoritmi di codifica aritmetica codificano stringhe di elementi in una frazione. In questo caso, viene presa in considerazione la distribuzione di frequenza degli elementi. Al momento gli algoritmi di codifica aritmetica sono protetti da brevetti, quindi esamineremo solo l'idea di base.
Supponiamo che il nostro alfabeto sia costituito rispettivamente da N simboli a1,...,aN e dalle loro frequenze di occorrenza p1,...,pN. Dividiamo la metà dell'intervallo. Questi passaggi sono importanti affinché il programmatore possa lavorare in modo efficace nel passaggio successivo.

1.2. PreEP

Come passaggio chiave dell'algoritmo di compressione, la trasformata discreta del coseno (di seguito denominata DCT) è un tipo di trasformata di Fourier e, come quest'ultima, ha una trasformata inversa (DCCT). Se consideriamo un'immagine come un insieme di onde spaziali, dove gli assi X e Y corrispondono alla larghezza e all'altezza dell'immagine, e l'asse Z visualizza i valori cromatici dei pixel corrispondenti, allora possiamo muoverci dalla dimensione spaziale rappresentazione dell'immagine al suo rappresentazione spettrale e ritorno. DCT converte una matrice N x N di pixel in una matrice di coefficienti di frequenza della dimensione appropriata.



Riso. 4.

Nella matrice risultante, i componenti a bassa frequenza si trovano più vicini all'angolo in alto a sinistra e i componenti a frequenza più alta vengono spostati in basso a destra. Dato che la maggior parte delle immagini grafiche sullo schermo è costituita da informazioni a bassa frequenza, utilizzando la matrice risultante è possibile scartare in modo differenziale il minimo informazioni importanti con una perdita visiva minima. Pertanto, DCT consente di selezionare informazioni che possono essere scartate in modo sicuro senza introdurre gravi distorsioni nell'immagine. È difficile immaginare come questo compito possa essere eseguito sull'immagine originale.

Dalle formule (Fig. 4) è chiaro che il calcolo di un elemento della matrice risultante richiede tempo O(N 2), quindi è quasi impossibile trasformare l'intera matrice. Il team di sviluppo JPEG ha proposto la migliore soluzione a questo problema: dividere la matrice originale in quadrati dimensione standard 8x8 e trasforma ciascuno di essi. L'uso di blocchi più grandi migliorerà la qualità della compressione, ma non indefinitamente, poiché la probabilità che punti molto distanti siano simili tra loro è troppo piccola.

Vale la pena notare che durante i calcoli vengono utilizzati solo 32 valori del coseno precalcolati, il che consente di aumentare significativamente la velocità di conversione. Ciò porta indubbiamente ad una perdita parziale di informazioni, ma i suoi volumi sono relativamente insignificanti.

Un leggero aumento delle prestazioni può essere ottenuto se nei calcoli viene utilizzata solo l'aritmetica dei numeri interi, che però è rilevante solo per i vecchi computer, poiché nei computer moderni il costo delle operazioni sui numeri in virgola mobile non è diverso dalle operazioni sugli interi. Inoltre, l'uso dell'aritmetica dei numeri interi influisce negativamente sulla qualità dell'immagine compressa, il che rende questo metodo inaccettabile per computer moderni. Poiché DCT è un tipo di trasformata di Fourier, qui è possibile utilizzare tutti i metodi per aumentare la prestazione della trasformata di Fourier.

1.3. Arrotondamento

La fase successiva, in cui si verifica la principale perdita di informazioni, è l'arrotondamento o quantizzazione. Come puoi vedere, DCT non esegue alcuna compressione o codifica. Il suo compito principale è trasformare l'immagine originale in una forma comoda per le successive operazioni su di essa.

L'arrotondamento è il processo di riduzione della quantità di informazioni richieste per memorizzare la matrice DCT, con una parziale perdita di precisione. Secondo lo standard JPEG a questo scopo viene utilizzata una matrice di arrotondamento (RO). Ogni elemento della matrice DCT originale corrisponde a un elemento MO. La matrice risultante si ottiene dividendo la matrice originale per il MO. In questo caso, i valori a bassa frequenza nella matrice DCT corrispondono a coefficienti MO più piccoli, il che consente di conservare informazioni più significative a bassa frequenza e scartare informazioni ad alta frequenza meno importanti. A causa del fatto che i componenti a bassa frequenza sono concentrati a sinistra angolo superiore Matrici DCT, i valori MO crescono da sinistra a destra e dall'alto verso il basso.


3 5 7 9 11 13 15 17
5 7 9 11 13 15 17 19
7 9 11 13 15 17 19 21
9 11 13 15 17 19 21 23
11 13 15 17 19 21 23 25
13 15 17 19 21 23 25 27
15 17 19 21 23 25 27 29
17 19 21 23 25 27 29 31

Un esempio di matrice di arrotondamento con un fattore di qualità pari a 2.

I risultati dell'arrotondamento e la qualità dell'immagine ricostruita dipendono direttamente dalla matrice di arrotondamento selezionata. Lo standard JPEG consente l'utilizzo di qualsiasi MO, ma ISO, attraverso approfonditi test sperimentali, ha sviluppato una serie di matrici che consentono di ottenere risultati ottimali.

1.4. Compressione

L'ultima fase dell'algoritmo di codifica JPEG è la compressione. Dopo aver elaborato la matrice DCT utilizzando MO, nella matrice risultante appare un gran numero di zeri, specialmente nella regione delle alte frequenze (angolo inferiore destro).

Il primo passo è sostituire il valore nell'angolo in alto a sinistra della matrice risultante con uno relativo. Poiché i blocchi immagine adiacenti sono simili tra loro, codificare l'elemento successivo (0,0) attraverso la differenza con quello precedente sarà più efficiente. Il secondo passaggio consiste nell'applicare direttamente l'algoritmo di codifica di ripetizione (LZW) all'elaborazione grande quantità zeri consecutivi. Test sperimentali hanno dimostrato che i risultati migliori si possono ottenere se si gira intorno alla matrice a zigzag, come mostrato nella figura seguente.

Riso. 5.

Infine, nella terza e ultima fase, il risultato risultante viene compresso come normali dati utilizzando l'algoritmo di Huffman o la codifica aritmetica a seconda dell'implementazione. Questa fase è chiamata “codifica entropica” (nella terminologia JPEG).

1.5. Decodifica

Poiché la DCT è una trasformata di Fourier, esiste una trasformata coseno discreta inversa (IDCT). L'algoritmo di decodifica ripete l'algoritmo di codifica in ordine inverso.

2.JPEG2000

Inizialmente, il nuovo standard è stato sviluppato come base per il futuro standard di compressione senza perdita JPEG-LS, ma è stato successivamente rifiutato a causa dell'avvento di algoritmi più efficienti. A causa dello sviluppo della tecnologia, lo standard JPEG ha gradualmente perso la sua rilevanza. Gli sviluppatori di JPEG2000 speravano di creare uno standard che correggesse molti degli errori degli standard esistenti. Tra i loro compiti c'erano:

  • L'eliminazione non lo è compressione efficace nella regione delle basse frequenze. Gli algoritmi esistenti hanno fatto un buon lavoro nel comprimere le regioni a media e alta frequenza, ma hanno mostrato scarsi risultati nella regione a bassa frequenza.
  • Compressione con e senza perdite. Al momento dello sviluppo, non esisteva uno standard che consentisse la compressione con e senza perdite in un unico flusso di compressione.
  • Elaborazione di immagini di grandi dimensioni. Gli algoritmi esistenti non consentivano una compressione efficiente di immagini superiori a 64Kx64K senza affiancamento.
  • Struttura dell'algoritmo di compressione unificata. L'attuale implementazione JPEG supportava 44 modifiche, la maggior parte delle quali erano specifiche dell'applicazione e non supportate dalla maggior parte dei decoder.
  • Immunità al rumore. Al momento dello sviluppo di JPEG, le tecnologie di rete non erano ancora sufficientemente sviluppate e i progettisti JPEG non pensavano all'immunità al rumore durante la trasmissione di immagini su canali non sicuri o alla capacità di ripristinare l'immagine se veniva danneggiata a causa della trasmissione.
  • Immagini generate dal computer. Gli algoritmi originali funzionavano bene su fotografie digitali e immagini ottenute utilizzando una fotocamera digitale o uno scanner, ma non elaboravano in modo efficace le immagini create su un computer, ad esempio utilizzando editor di immagini.
  • Documenti complessi. JPEG ha funzionato molto male durante l'elaborazione di immagini 2D complesse (immagini di testo in particolare).

Il diagramma seguente mostra i passaggi fondamentali di un codificatore JPEG2000.


Riso. 6.


Riso. 7.

A differenza del JPEG, il codificatore JPEG2000 non richiede la divisione dell'immagine in piccoli blocchi quadrati, poiché la DWT (trasformata wavelet discreta) utilizzata durante il funzionamento dell'algoritmo funziona su frammenti di qualsiasi dimensione. D'altra parte, a volte, se la quantità di memoria disponibile per il codificatore con cui lavorare è inferiore alla quantità di memoria richiesta per codificare l'intera immagine, l'immagine viene divisa in tessere quadrate, codificate indipendentemente l'una dall'altra. Successivamente, prenderemo in considerazione la codifica di una tessera.

I passaggi rimanenti sono simili a JPEG.

Riso. 8.

2.2. Fibra di legno JPEG2000 utilizza la trasformazione wavelet discreta per dividere l'immagine in regioni ad alta e bassa frequenza. Il DWP elabora ogni riga e colonna dell'immagine sorgente utilizzando.

filtro di frequenza

Riso. 9.

  • A causa del fatto che ogni passaggio utilizzando un filtro di frequenza in uscita raddoppia la quantità di informazioni, dopo l'elaborazione la dimensione dell'immagine viene ridotta della metà. Dopo una fase di lavorazione del pannello rigido, il frammento lavorato viene diviso in quattro segmenti: LL - basse frequenze
  • per righe e colonne
  • HL – alte frequenze in righe e basse frequenze in colonne
  • LH – frequenze basse in righe e frequenze alte in colonne

HH – alte frequenze in righe e colonne


Secondo lo standard, il numero di fasi può variare da 0 a 32. Per un'immagine normale vengono utilizzate da 4 a 8 fasi. In ogni fase successiva viene elaborata solo la regione a bassa frequenza (LL), poiché le regioni ad alta frequenza di solito non contengono informazioni importanti.

Riso. 10.

Riso. 11.

2.3. Arrotondamento Per arrotondare i coefficienti DWT viene utilizzato un quantizzatore costante con una zona morta. (Fig. 14) Per ciascun frammento, viene utilizzato un valore costante del passo di arrotondamento per tutti i coefficienti di questo frammento. La formula per il calcolo dei valori arrotondati è presentata nella Figura 12. Qui y è il valore iniziale del coefficiente, sign(y) determina il segno del coefficiente e Δb è il valore del passo di arrotondamento. Zona morta

il quantizzatore è un intervallo con un intervallo di 2Δb attorno allo zero, fornisce un numero maggiore di zeri in uscita.

La codifica dei coefficienti arrotondati risultanti viene eseguita blocco per blocco. Secondo lo standard JPEG2000, immediatamente prima della codifica, i frammenti vengono divisi in blocchi sufficientemente piccoli (ad esempio, 32x32 o 64x64) in modo che tutti i blocchi di un frammento abbiano la stessa dimensione. La partizione in blocchi viene eseguita al fine di implementare un'organizzazione più flessibile delle informazioni compresse per aumentare l'immunità al rumore e così via.


Riso. 16.

In JPEG2000, ogni blocco è codificato separatamente. L'algoritmo di codifica attraversa la matrice dei coefficienti di arrotondamento di ciascun blocco in strisce, come mostrato nella Figura 17. I blocchi vengono divisi in blocchi con un'altezza nominale pari a 4. Le strisce vengono quindi scansionate dall'alto verso il basso e le colonne di ciascuna striscia vengono attraversato da sinistra a destra.


Riso. 17.

Durante il processo di codifica, i coefficienti di un blocco vengono virtualmente rappresentati come piani di bit. Uno di questi piani è formato dai segni dei coefficienti;

i restanti piani corrispondono a diverse cifre dei valori dei coefficienti (la posizione del bit nel piano corrisponde alla posizione del coefficiente nel blocco).

Per ogni bit del piano, se il coefficiente corrispondente non è ancora significativo, e se almeno un coefficiente vicino è già significativo, viene codificato il fatto di significatività per il coefficiente corrente, cioè il valore di questo bit della corrente codificata aereo è effettivamente codificato. Se il bit codificato risulta diverso da zero, subito dopo averlo elaborato, viene codificato il bit corrispondente del piano di bit dei segni dei coefficienti (codifica del segno).

Durante il secondo passaggio vengono codificati i bit dei coefficienti attualmente significativi, non toccati nel primo passaggio. A differenza del passaggio precedente, quando la decisione di codifica veniva presa sulla base delle informazioni sul significato dei coefficienti vicini, durante questo passaggio i bit vengono codificati senza errori.

Il terzo e ultimo passaggio elabora i bit che non sono stati elaborati durante il primo e il secondo passaggio. Durante questo fase finale codifica aritmetica utilizzato insieme alla codifica di gruppo.

Una caratteristica essenziale fornita dallo standard è la possibilità di saltare i passaggi di codice, che è un'altra fonte di guadagni di efficienza dovuti alla perdita di informazioni (la prima, più ovvia, è la quantizzazione). Questa funzionalità viene utilizzata attivamente per controllare la velocità di generazione del codice.

2.5. Organizzazione dei dati

Un vantaggio importante dello standard in esame è la possibilità di accedere ai singoli elementi dell'immagine senza decodificarne completamente la rappresentazione. Questa possibilità è assicurata, da un lato, dividendo l'immagine originale in aree (tiles) non sovrapposte, che vengono codificate come immagini separate, e, dall'altro, rappresentando il codice di una singola tessera sotto forma di parti (livelli), ciascuno dei quali che è un codice totale di coefficienti corrispondente a una certa area (piastrella). Gli strati, a loro volta, sono suddivisi nei cosiddetti pacchetti contenenti il ​​codice dei blocchi di coefficienti diversi livelli decomposizione. Per decodificare qualsiasi area dell'immagine



, è sufficiente determinare a quali piastrelle appartiene e quali strati relativi a queste piastrelle contengono il codice dei blocchi di coefficienti necessari per ripristinare l'area richiesta.

Naturalmente, una rappresentazione dell'immagine “conveniente” potrebbe non essere vantaggiosa in termini di efficienza di compressione. Infatti, con una diminuzione delle dimensioni degli elementi strutturali (tegole, aree di piastrelle che formano strati, ecc.), l'efficienza di compressione diminuisce leggermente. Lo standard in questo caso ci lascia una scelta: da un lato abbiamo la possibilità di ottenere rappresentazioni di informazioni che ci permettono di estrarre e modificare velocemente parti dell'immagine, dall'altro lo standard non impedisce la creazione di rappresentazioni dell’informazione efficienti in termini di volume.

Per garantire l'immunità al rumore e la facilità di accesso alle informazioni, lo standard JPEG2000 fornisce un sistema di marcatori e segmenti di marcatori. I segmenti dei marcatori contengono parametri di informazioni limitate dai marcatori. I dati che iniziano con un contrassegno possono essere interpretati correttamente senza alcuna informazione aggiuntiva (questo non significa che il tutto possa essere ricostruito da frammenti), il che rende possibile ripristinare parzialmente un'immagine la cui rappresentazione è stata danneggiata.

L'introduzione di elementi di immunità al rumore dà il via libera all'uso dello standard in tutti i tipi di applicazioni di telecomunicazione.

Ottenere una compressione di alta qualità è stato, ovviamente, uno dei compiti principali durante la creazione dello standard, e qui gli sviluppatori hanno fatto evidenti progressi.

Lo standard JPEG2000 è circa 2 volte più efficiente dello standard JPEG se compresso con perdita e del 5-20% se compresso senza perdita. Naturalmente, l'efficienza della compressione senza perdita in questo caso non è così elevata come, ad esempio, lo standard JPEG-LS, ma è abbastanza accettabile. Per quanto riguarda l'efficienza della compressione con perdita, qui lo standard consente di ottenere risultati vicini ai migliori risultati odierni per questo tipo di metodi. 3.JPEG-LS Formato JPEG-LS era basato sul formato

LOCO-I

  • (Compressione senza perdita di qualità a bassa complessità per le immagini). L'algoritmo di compressione senza perdita LOCO-I, adottato come base per lo sviluppo dello standard JPEG-LS, per la prima volta ha fornito non solo la modalità senza perdita, ma anche quasi senza perdita (compressione con perdite limitate, definite dall'utente). A differenza della modalità lossless JPEG2000, JPEG-LS si è rivelato un vero successo: con una maggiore efficienza di compressione, il nuovo standard fornisce un'elevata velocità di compressione/decompressione e non richiede troppo risorse del computer.
  • non utilizza né la DCT né la codifica aritmetica;
  • utilizza la quantizzazione debole solo in modalità "quasi senza perdite".

3.1. Introduzione dei concetti base e dei principi di funzionamento

La compressione dei dati senza perdita è costituita da due parti indipendenti separate: modellazione e codifica. Definiamo alcuni termini che utilizzeremo attivamente in futuro:

L'Encoder è “responsabile” del processo di codifica, ovvero: riceve in input l'immagine originale in formato digitale e tutti i parametri necessari definiti dallo standard, e utilizzando un insieme speciale di procedure crea un insieme di dati contenenti l'immagine compressa. Il Decoder “risponde” al processo di decodifica e conversione dei frammenti, ovvero: ricevendo i dati con un'immagine compressa e tutti i parametri necessari in input, restituisce in output l'immagine ricostruita

Il decoder JPEG-LS differisce poco dal codificatore, quindi questo algoritmo di compressione può essere definito quasi simmetrico. Ecco un diagramma semplificato che mostra i principi della codifica:



Riso. 21.

Alcune informazioni su immagine originale: come mostrato nello schema sottostante (Fig. 22), l'immagine originale può essere costituita da componenti Nf. Ciascun componente Ci contiene una matrice bidimensionale di pixel (campioni) di xi colonne e y i righe. Le dimensioni dei componenti dipendono da due parametri: X e Y, dove X è il massimo tra i valori x i, e Y è il massimo tra i valori y i di tutti i componenti. (Lo standard JPEG-LS ha un intero capitolo dedicato alle differenze nel lavorare con immagini a più componenti rispetto a immagini a componente singolo, ma in questo articolo ci concentreremo solo sul lavoro con immagini a componente singolo).



Riso. 22.

La figura mostra l'orientamento di ciascun componente: superiore, inferiore, sinistra e destra. L'ordine in cui i pixel vengono sottoposti alle procedure di codifica è determinato come segue: da sinistra a destra (da sinistra a destra) e dall'alto in basso (dall'alto in basso) per componente.

I pixel di contesto a, b, c, d vengono utilizzati per prevedere il pixel x corrente. A seconda del contesto, l'encoder sceglie una modalità: seriale (modalità di esecuzione) O modalità regolare. La moda seriale viene scelto se è probabile che y e z coincidano, regolare- Altrimenti. Facciamo qui una nota relativa alla presenza dell'opzione "quasi nessuna perdita": Quando questa opzione è abilitata, la modalità seriale verrà selezionata se yez sono quasi identici secondo il parametro di tolleranza NEAR.

Nel caso di utilizzo della moda seriale, iniziamo la navigazione linea corrente dal pixel x e trova la lunghezza maggiore di una serie di pixel coincidenti con il pixel contestuale a. Pertanto, all'interno della riga corrente otteniamo una serie di pixel identici che coincidono in valore con il noto pixel a.

Tutto ciò che resta da fare è codificare la lunghezza della serie. (Questo viene fatto utilizzando un array di 32 elementi J.) Potresti aver già intuito che con l'opzione “quasi senza perdita” abilitata, una serie di pixel vicini a a vengono selezionati utilizzando il parametro NEAR.


Ora diamo un'occhiata alle nostre azioni nel caso di utilizzo della modalità normale. I valori dei pixel a, b e c vengono utilizzati per calcolare la previsione del pixel x (Px).

Successivamente viene calcolato il cosiddetto errore di previsione (Errval). Il suo valore è pari alla differenza tra i valori di x e Px. Errval viene regolato da un termine dipendente dal contesto e quindi codificato utilizzando i codici Golomb. Il codice Golomb dipende da a, b, c, d ed Errval degli stessi pixel, che sono memorizzati in speciali array A e N. Quando l'opzione “quasi senza perdita” è abilitata, l'errore di previsione viene ulteriormente quantizzato prima della codifica.

Riso. 23.

3.2. Codificatore

  • JPEG-LS viene utilizzato principalmente come metodo di compressione delle informazioni senza perdita di dati, quindi il file immagine recuperato è solitamente identico al file originale. Quasi senza perdite, l'immagine originale e l'immagine ricostruita potrebbero differire. Indicheremo il pixel ricostruito con Rp e il pixel originale con p.
  • In fase di inizializzazione l’encoder esegue le seguenti operazioni:
  • I parametri sono calcolati RANGE = floor((MAXVAL + 2 * NEAR) / (2 * NEAR + 1)) + 1, qbpp = ceil(log RANGE), bpp = max(2, ceil(log(MAXVAL + 1)) ), LIMITE = 2 * (bpp + max(8, bpp)) . (Nel caso della codifica lossless, NEAR = 0, RANGE = MAXVAL + 1. Se è abilitata la modalità "quasi lossless", NEAR > 0). MAXVAL e NEAR sono parametri impostati dall'applicazione che implementa l'algoritmo.
  • Gli array di indici N, A, B e C vengono inizializzati. Spieghiamo il loro scopo: N viene utilizzato per memorizzare la frequenza di occorrenza di ciascun contesto, A - per accumulare il valore dell'errore di previsione, B - per calcolare la deviazione sistematica, C - per memorizzare i valori della correzione di l'errore di previsione.

Le variabili per la modalità di esecuzione vengono inizializzate RUNindex=0 e J = (0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5 , 5, 6, 6, 7, 7, 8, 9,10,11,12,13,14,15) .

Funzione GetNextSample(): riceve informazioni sul pixel successivo dell'immagine sorgente e imposta i valori corrispondenti delle variabili x, a, b, c, d, Ix, Ra, Rb, Rc, Rd. Se il pixel letto è alla fine della riga, GetNextSample() imposta EOLine = 1 . In tutti gli altri casi, EOLine = 0. I valori Ra, Rb, Rc, Rd ereditano i loro valori dal valore Rx precedentemente calcolato. EOLine Variabile globale: impostata dalla funzione GetNextSample(): uguale a 1 se il pixel corrente è l'ultimo della riga, uguale a 0 altrimenti. AppendToBitStream(a,b) Funzione: aggiunge un numero non negativo in formato binario al flusso di bit codificato utilizzando b bit. I bit più significativi vengono aggiunti per primi. Funzione Quantize(a): utilizzata per quantizzare l'errore di previsione in modalità "quasi senza perdita". ComputeRx() Funzione: restituisce il valore Rx ricostruito per il pixel corrente (utilizza l'"errore di previsione" quantizzato).

Dall'immagine sopra (Fig. 23) è chiaro che i pixel a, b, c e d svolgono un ruolo significativo nella codifica del pixel x. Proviamo a capire cosa succede quando mancano questi pixel. Pertanto, quando si codifica la riga superiore, mancano i pixel di contesto c, b e d, quindi i loro valori sono considerati zero. Se il pixel corrente si trova all'inizio o alla fine della riga, i pixel a, c o d non sono definiti.

In questo caso, a e d utilizzano il valore Rb ricostruito del pixel b (o zero per la riga superiore) e c utilizza il valore ricostruito di a durante la codifica del primo carattere della riga precedente. Pertanto, il codificatore deve svolgere parte del lavoro del decodificatore ricostruendo alcuni pixel.

L'encoder inizia con i seguenti tre passaggi:

Dopo aver stabilito il contesto Q, il codificatore prevede il pixel x. Innanzitutto, la previsione Px viene calcolata utilizzando il cosiddetto “predittore di rilevamento dei bordi”:
se (Rc > = max(Ra, Rb)) Px = min(Ra, Rb);
altro(<= min(Ra, Rb))
se (Rc
Px=max(Ra, Rb);
altro
}

Px = Ra + Rb - Rc;< а. При этом условии «правило края» выбирает b в качестве прогноза х во многих случаях, когда вертикальный край изображения находится непосредственно слева от х. Аналогично, пиксель а выбирается в качестве прогноза х во многих случаях, когда горизонтальный край находится непосредственно над х. Если край не обнаруживается, то «правило края» вычисляет прогноз в виде а + b - с, что имеет простую геометрическую интерпретацию. Если каждый пиксель является точкой трехмерного пространства, то прогноз а + b - с помещает Рх на ту же плоскость, что и точки а, b и с.

Spieghiamo l'essenza della "regola del margine". Per fare ciò, consideriamo il caso b

Il passo successivo è la correzione della previsione dal bias utilizzando il numero SIGN (a seconda dei tre numeri di zona Qi), i valori di correzione C(Q) (derivati ​​da bias sistematici e non discussi qui) e il parametro MAXVAL.
se (SEGNO == +1)
Px=max(Ra, Rb);
Px = Px + C(Q);

Px = Px - C(Q);
Se (Px > MAXVAL)
Px = VAL.MASSIMO;< 0)
altrimenti se (Px

Dopo aver trovato la previsione Px, il codificatore calcola l'errore di previsione Errval come differenza x - Px, ma cambia segno se SIGN è negativo.

In modo quasi senza perdite, l'errore viene quantizzato e il codificatore utilizza questo valore Rx ricostruito del pixel x allo stesso modo di un decodificatore.

Il passo di quantizzazione di base è il seguente:
se (Errval > 0)
Px=max(Ra, Rb);
Errval = (Errval + NEAR) / (2 * NEAR + 1);

Errval = - (Errval - NEAR) / (2 * NEAR + 1);

Utilizza il parametro NEAR, ma ci sono alcuni dettagli che non vengono mostrati qui. Il passaggio principale della ricostruzione è trovare Rx = Px + SIGN * Errval * (2 * NEAR + 1) .

L'errore di previsione (dopo eventuale quantizzazione) subisce una riduzione del modulo. (Dopodiché è pronto per la fase principale di codifica).< 0)
se (Errval
Errval = Errval + RANGE;
if (Errval >= ((RANGE + 1) / 2))

Errval = Errval - RANGE; Codici Golomb (il parametro principale era indicato con b). In JPEG-LS questo parametro è designato m. Se il numero m è già stato scelto, allora il codice Golomb di un intero non negativo n è costituito da due parti: il codice unario della parte intera del numero n/m e rappresentazione binaria< r < 1) . Для каждого геометрического распределения найдется такое число m, что код Голомба, построенный по m, имеет наименьшую возможную среднюю длину. n mod m. Questo codice è ideale per gli interi che hanno una distribuzione geometrica (cioè quando la probabilità del numero n è (1 - r) * r n , 0 Il caso più semplice

, quando m è una potenza di 2 (m = 2 k), porta a semplici operazioni di codifica/decodifica. Il codice del numero n in questo caso è costituito dalle k cifre di ordine basso del numero n, precedute dal codice unario del numero composto dalle restanti cifre di ordine alto del numero n. Questo speciale codice Golomb è indicato con G(k) .

Ad esempio, calcoliamo il codice G(2) del numero n = 19 = 10011 2 . Poiché k = 2, allora m = 4. Cominciamo con le due cifre meno significative, 11 2, del numero n. Sono uguali a 3, che equivale a n mod m (3 = 19 mod 4). Le restanti cifre più significative, 100 2, daranno il numero 4, che è uguale alla parte intera n/m (19/4 = 4,75). Il codice unario di 4 è 00001, quindi il codice G(2) di n = 19 è 00001|11.< glimit- - 1 , то код LG(k, glimit) совпадает с кодом LG(k]. В противном случае, приготавливается унарный код числа glimit - ceil(log I) - 1 (то есть, glimit - ceil(log I) - 1 нулей, за которыми стоит единственная 1). Это действует как код esc, после которого стоит двоичный код n - 1 из ceil(log I) бит.

Gli errori di previsione non sono necessariamente numeri positivi. Sono uguali ad alcune differenze, che possono essere zero o negative. Tuttavia, i codici Golomb sono stati creati per numeri positivi. Pertanto, prima della codifica, i valori di errore negativi dovrebbero riflettersi in un insieme di numeri non negativi. Per fare ciò, utilizzare la seguente mappatura:
MErrval =
2 * Errval se Errval >= 0,
2 * |Errval| se Errval< 0.

Questa visualizzazione alterna valori negativi e positivi nella sequenza 0, -1, +1, -2, +2, -3,... .

La tabella seguente elenca alcuni errori di previsione, i valori visualizzati e i relativi codici LG(2, 32), presupponendo che l'alfabeto abbia dimensione 256 (ovvero I = 255 e ceil(log I) = 8).

Tabella: errori di previsione, visualizzazioni e codici LG(2, 32)

Errore di previsione Valore visualizzato Codice
0 0 1 00
-1 1 1 01
1 2 1 10
-2 3 1 11
2 4 01 00
-3 5 01 01
3 6 01 10
-4 7 01 11
4 8 001 00
-5 9 001 01
5 10 001 10
-6 11 001 11
6 12 0001 00
...
50 100 000000000000
000000000001
01100011

Dobbiamo ora discutere la scelta del parametro k per i codici di Golomb. Questo viene fatto in modo adattivo. Il parametro k dipende dal contesto e il suo valore viene aggiornato ogni volta che viene trovato un pixel con quel contesto. Il calcolo di k può essere espresso in una semplice riga:
per (k=0; (N[Q]<dove A e N sono matrici di indici da 0 a 364. Questa formula utilizza il contesto Q come indice delle due matrici. All'inizio k viene inizializzato a zero e quindi viene eseguito il ciclo. Ad ogni iterazione del ciclo, un elemento dell'array N[Q] viene spostato a sinistra di k bit e confrontato con A[Q]. Se il valore spostato N[Q] è maggiore o uguale a A[Q], viene selezionato il valore corrente k. Altrimenti k viene aumentato di 1 e il test viene ripetuto.

Dopo aver trovato il numero k, l'errore di previsione Errval viene convertito utilizzando il numero MErrval, che è codificato utilizzando il codice LG(k, LIMIT). Il numero LIMIT è un parametro. L'aggiornamento degli array A e N (insieme all'array ausiliario B) è illustrato dal seguente frammento di codice (il parametro RESET è impostato dall'applicazione):

B[Q] = B[Q] + Errval * (2 * NEAR + 1);
A[Q] = A[Q] + abs(Errval);
se (N[Q] == RESET) (
A[Q] = A[Q]>>1;
B[Q] = B[Q]>>1;
N[Q] = N[Q]>>1;
}
N[Q] = N[Q] + 1;

Parliamo ora del calcolo della deviazione sistematica della previsione. Il valore di correzione della previsione C[Q] deve essere aggiornato alla fine della codifica del pixel x. Ciò richiede due variabili: B[Q] e N[Q]. N[Q] è il numero di occorrenze del contesto Q dall'inizializzazione. B[Q] è una deviazione sistematica che consente di aggiornare il valore di C[Q] al massimo una volta per iterazione.

Pertanto, il valore del predittore C[Q] viene calcolato secondo il seguente codice:<= -N[Q]) {
B[Q] = B[Q] + N[Q];
se (C[Q] > MIN_C)
DO[Q] = DO[Q] - 1;
se (B[Q]<= -N[Q])
B[Q] = -N[Q] + 1;
}
altrimenti se (B[Q] > 0) (
B[Q] = B[Q] - N[Q];
se (C[Q]< MAX_C)
C[Q] = C[Q] + 1;
se (B[Q] > 0)
B[Q] = 0;
}

Le costanti MIN_C e MAX_C sono il minimo e il massimo possibile significato array di indici C, pari rispettivamente a -128 e 127.

La codifica in modalità seriale viene eseguita diversamente. Ricordiamo che l'encoder seleziona questa modalità quando rileva successivi pixel x i cui valori Ix corrispondono e sono uguali al valore Ra ricostruito del pixel di contesto a. Per l'opzione "quasi senza perdita", i pixel della serie devono avere valori Ix che soddisfino la disuguaglianza |Ix - Ra|<= NEAR . Серия не должна выходить за пределы текущей строки. Длина серии кодируется (сам пиксель кодировать не нужно, поскольку он равен Ra), и если конец серии находится раньше конца строки, то после ее закодированной длины будет сразу записан код следующего пикселя (который прерывает серию). Две основные задачи кодера в этой моде состоят

  1. nel tracciare una serie e codificarne la lunghezza;
  2. nella codifica del pixel che ha interrotto la serie.

La serie può essere monitorata come segue:

CORSAval = Ra;
RUNcnt = 0;
mentre (abs(Ix - RUNval)<= NEAR) {
CORSAcnt = CORSAcnt + 1;
Rx = RUNval;
se (EOLine == 1)
rottura;
Px=max(Ra, Rb);
Ottieniesempiosuccessivo();
}

Spieghiamo alcuni dei valori introdotti: RUNcnt è il conteggio dei pixel ripetuti (per la modalità seriale) e RUNval è il valore corrente del pixel ripetuto ricostruito.

Descriviamo il processo di codifica delle serie. Il primo frammento di codice descrive la codifica per i segmenti di esecuzione di lunghezza rm:

mentre (RUNcnt >= (1<AggiungiABitStream(1, 1);
RUNcnt = RUNcnt - (1<se (RUNindice< 31))
indice CORSA = indice CORSA + 1;
}

Il codice seguente illustra la codifica per segmenti di esecuzione di lunghezza inferiore a rm:

se (EOLinea == 0) (
AggiungiABitStream(0, 1);
AggiungiABitStream(RUNcnt, J);
if (indiceRUN > 0)) (
indice CORSA = indice CORSA - 1;
}
altrimenti se (RUNcnt > 0)
AggiungiABitStream(1, 1);

Qui il codificatore utilizza la tabella J, che consiste di 32 voci, indicate con rk.
0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15 .

J è inizializzato con valori

Può succedere che la lunghezza della serie RUNlen non sia uguale alla somma intera dei numeri rm. Ad esempio, RUNlen = 7 . In questo caso, come codice vengono scritti cinque bit pari a 1, seguiti da un bit di prefisso e dal resto di RUNlen (nel nostro esempio è 1), che viene scritto nel file come un numero di bit rk (il valore corrente di rk nel nostro esempio è 2). Quest'ultima operazione viene eseguita chiamando la procedura AppendToBitStream(RUNcnt, J). Il bit del prefisso è 0 se la serie è interrotta da un altro pixel nella riga. Se la serie arriva alla fine della riga, il bit del prefisso è 1.

Il secondo compito principale del codificatore, ovvero codificare il pixel burst, viene eseguito in modo simile alla codifica del pixel corrente. Discutiamo i dettagli della sua implementazione.

Consideriamo una situazione in cui l'avanzamento della codifica viene interrotto dalla fine di una stringa di pixel: come verrà codificato il nuovo pixel che causa l'interruzione? Questo problema viene risolto codificando la differenza tra il valore di Ix nella posizione corrente x e il valore ricostruito dei pixel aob (ricordiamo che questi sono pixel vicini rispetto a x - vedere Fig. 23). In questo caso si considerano due diverse situazioni: la prima, quando abs(Ra - Rb)<= NEAR , вторая - в противном случае. По сути кодирование пикселя прерывания серии происходит теми же методами, что и кодирование нового пикселя в регулярной моде с тем лишь дополнением, что Ix должно отличаться от Ra на величину большую NEAR, иначе ход кодирования будет продолжен. Опишем операции, которые должны быть выполнены:

se (abs(Ra - Rb)<= NEAR)
tipo RI = 1;
altro
tipo RI = 0;
if (tipo RI == 1)
Px = Ra;
Px=max(Ra, Rb);
Px = Rb;
Errval = Ix - Rb;

Lo snippet di codice riportato sopra definisce l'indice RItype e l'errore di previsione per il pixel x. Poi, se necessario, cambia il segno di Errval, e per l’opzione “quasi senza perdita”, quantizza anche l’errore di previsione:

if ((RItipo == 0) && (Ra > Rb)) (
Valore Err = -Val Err;
SEGNO = -1;
altro
SEGNO = 1;
se (VICINO > 0) (
Errval = Quantizza(Errval);
Rx = ComputeRx();
}
Px=max(Ra, Rb);
Rx = Ix;
Valore Err = ModRange(Val Err, RANGE);

Calcoliamo ora la variabile ausiliaria TEMP, che servirà per calcolare il parametro k nei codici Golomb.

if (tipo RI == 0)
TEMP = A;
altro
TEMP = A + (N>>1);

Impostiamo Q = RItipo + 365. Calcoleremo il parametro k per i codici Golomb come segue: for (k=0; (N[Q]<

L'errore di previsione (dopo eventuale quantizzazione) subisce una riduzione del modulo. (Dopodiché è pronto per la fase principale di codifica).< 0) {
Nn[Q] = Nn[Q] + 1;
A[Q] = A[Q] + ((EMERrval + 1 -RItipo)>>1);
se (N[Q] == RESET) (
A[Q] = A[Q]>>1;
N[Q] = N[Q]>>1;
Nn[Q] = Nn[Q]>>1;
}
N[Q] = N[Q] + 1;

Con questo si conclude la descrizione del codificatore JPEG-LS. Tieni presente che è certamente incompleto, ma non ci siamo posti l'obiettivo di copiare lo standard di questo metodo. Tutti i dettagli omessi possono essere trovati nella norma. Passiamo ora ad una breve descrizione dei principi di funzionamento del decoder.

3.3. Decodificatore

Come accennato in precedenza, il metodo JPEG-LS è quasi simmetrico, quindi non copieremo la descrizione del codificatore con piccole modifiche: queste informazioni possono essere lette nello standard. Soffermiamoci solo su come avviene la decodifica in modalità seriale. Dopo che tutti i valori per il pixel corrente sono stati calcolati, leggi nuova parte R dal flusso di bit. Se è uguale a 1, allora:

  1. L'immagine è completata da 2 J|RUNindex| pixel con valore Ra.
  2. Se nel passaggio precedente l'immagine era già stata completata con 2 J|RUNindex|< 31, то RUNindex увеличивается на 1. Если последний пиксель в строке ещё не декодирован, то мы снова считываем биты, в противном случае переходим к вычислению всех требуемых величин.

pixel e RUNindex

  1. Se il bit è 0, allora:
  2. Leggi J|RUNindex| bit dal flusso di bit e viene convertito in un numero e l'immagine viene integrata con pixel con valori Ra in una quantità corrispondente al numero calcolato.
  3. Se RUNindex > 0, RUNindex viene diminuito di 1.

Il pixel di interruzione della serie viene decodificato e il calcolo di tutte le quantità necessarie ricomincia.

3.4. Formato file File compresso

  • è costituito da:
  • da segmenti di dati contenenti codici Golomb e lunghezze di corsa;
  • dai segmenti marker (informazioni necessarie al decoder);

dal segmento dei marcatori "resto" (alcuni marcatori JPEG riservati).

Qui chiamiamo marcatore un byte di unità, seguito da un codice speciale che segnala l'inizio di un nuovo segmento. Se un token è seguito da un byte il cui bit più significativo è 1, quel byte sarà l'inizio del segmento del token.

Altrimenti inizia il segmento dati.

  • 3.5. Codici Golomb
    Abbiamo già menzionato più volte i codici Golomb. Cos'è questo? Il codice Golomb di un intero non negativo "può essere un codice Huffman efficiente". Dipende dalla scelta di qualche parametro b. Il principio di codifica è il seguente:
    vengono calcolate due quantità
  • q = pavimento((n - 1) / b) e

r = n - qb - 1 ;<= p <= 1) , то коды Голомба будут оптимальными кодами для этого потока данных, если выбрать параметр b следующим образом:
il codice è costruito in due parti: la prima parte è q in codice unario, la seconda parte è un'espressione binaria per r, composta da bit floor(log 2 b) per resti piccoli e bit ceil(log 2 b) per resti grandi .<= 1 <= (1 - p) b - 1 + (1 - p) b .

Non forniamo una giustificazione matematica per l'uso dei codici Golomb in JPEG-LS, notiamo solo che se il flusso di dati in input è costituito da numeri interi, e la probabilità del numero n è pari a P(n) = (1 - p ) n - 1p (0

Il formato JPEG-LS è stato sviluppato principalmente per la memorizzazione di immagini per scopi medici, cioè per quei casi in cui è importante avere un'immagine di grandi dimensioni senza la minima perdita di qualità. Come già accennato, come base è stato preso il formato LOCO-I, sviluppato all'interno delle mura di HP Labs. È stato poi ulteriormente sviluppato grazie agli sforzi congiunti di HP e Mitsubishi.

Entrambe le società hanno consentito l'utilizzo dei loro brevetti su questo formato senza pagare una licenza, quindi JPEG-LS può essere trovato anche nei normali programmi per PC.

Lasciatemi spiegare con il mio esempio. Forse puoi aiutarmi a capire alcune cose. Il compito che mi è stato assegnato da solo è il seguente. Trasferimento di un fotogramma (tramite comando) dalla WEB camera alla memoria di un cellulare con successivo trasferimento su un altro cellulare. Dal tuo articolo non è chiaro su quale formato dovrebbe basarsi, la disponibilità dell'algoritmo. Successivamente - la trasformazione del coseno - solo un'interpretazione superficiale, e dove posso guardare un algoritmo dettagliato con un esempio specifico (ad esempio, studiare l'analisi matematica, ma anche lì non ci sono quasi esempi specifici e, se ci sono, allora intere sezioni di mancano i calcoli. Forse c'è un manuale specifico, quindi fai riferimento. Hanno completamente eliminato la struttura dell'organizzazione dei file e non hanno nemmeno indicato i collegamenti. “Nella matrice risultante, i componenti a bassa frequenza si trovano più in alto a sinistra angolo, e quelli con la frequenza più alta vengono spostati in basso a destra”, mi sembra che sia così, ma non funziona (forse mi sbaglio!).

Domanda: come catturare, ad esempio, solo le informazioni necessarie da un frame JPG per un'ulteriore decodifica nella risoluzione dello schermo del telefono, senza utilizzare un PC, utilizzando un MK. È sufficiente una versione della cornice in bianco e nero. A quale FFxx dovresti prestare attenzione e registrare solo quelle informazioni. Dove posso trovare la struttura del telaio della telecamera WEB? Capisco che la questione sia complessa e sfaccettata. Ad esempio, su MK è impossibile decriptare il fotogramma e poi comprimerlo con la risoluzione richiesta, ma probabilmente è possibile ritagliare almeno l'angolo superiore con il formato richiesto.

Sarei grato per l'informazione.

Cosa posso fare = programma in VB, MK. Sviluppo interattivo e operativo indipendente del controllo tramite telefono cellulare con più relè, controllo audio tramite telefono cellulare.

>>Il secondo passo è applicare direttamente >>l'algoritmo di codifica di ripetizione (LZW)

forse RLE?

Naturalmente, in questo passaggio JPEG (vedi contesto) è RLE. Grazie per aver identificato l'errore.