Como aderir 2 jpegs juntos losslessly sem decodificar usando um editor hexadecimal?

StackOverflow https://stackoverflow.com/questions/609586

  •  03-07-2019
  •  | 
  •  

Pergunta

Eu estou tentando escrever um programa (prov em java) para participar de uma série de jpegs juntos losslessly sem decodificação-los primeiro.

Eu pensei que eu ia começar de forma simples e tentar Anexar 2 jpegs do mesmo tamanho compactado com as mesmas configurações de um sobre o outro usando um editor hexadecimal.

Primeiro, extrair os dados de imagem de jpeg B e acrescentá-la à jpeg A. Ao modificar as dimensões especificadas nos cabeçalhos eu obter uma nova imagem reconhecível (jpeg A + B jpeg anexado no eixo y), que pode ser diplayed. No entanto, embora os dados de imagem de jpeg B é claramente reconhecíveis parece ter perdido um monte de informações de cor e é claramente incorreta.

Então, minha pergunta é quais os passos que eu estou perdendo aqui? Eu não acho que existem quaisquer outros valores de cabeçalho dimensão específicas que preciso mudar, talvez por isso eu preciso de decodificação de Huffman os dados de imagem de ambos os jpegs, em seguida, acrescentar-los juntos e, em seguida, reencode o lote?

Eu passei algum tempo lendo sobre especificações de jpeg e cabeçalhos etc, mas para ser honesto eu estou fora da minha profundidade e poderia realmente fazer com um ponteiro ou dois!

Muito obrigado por qualquer ajuda.


Obrigado por todas as sugestões. Sim, este é definitivamente possível, eu deveria ter jpegtran referi na minha pergunta original. Estou basicamente tentando replicar esse aspecto da funcionalidade jpegtran mas usá-lo em meu próprio programa. Acho que eu deveria olhar para a fonte jpegtran mas eu não sei nada sobre C e não muito sobre programação em código fonte de engenharia de modo inverso geral é mais fácil dizer do que fazer!

Foi útil?

Solução 2

Ok eu trabalhei onde eu estava indo errado.

1) os dados de digitalização imagem é guardada em bytes, mas a informação real importante é codificado como seqüências de comprimento de bits variáveis. Isto significa que o fim dos dados de imagem reais não necessariamente caem em um limite de byte. Quando as necessidades codificador JPEG para preencher o número de bits para fazer o byte fronteira ele simplesmente acrescenta uma série de 1s.

2) a forma como o real informações pixel é armazenado é um pouco complicado (pelo menos para mim) para explicar, mas basicamente tudo é codificado dentro MCU, unidades de codificação mínima ou algo assim. Estas variam em tamanho, dependendo tamanhos a subamostragem de crominância, horizontais e verticais, sendo ambos os 8 ou 16 pixels. Para cada MCU, existem DC e AC peças que compõem um único componente de luminância, Y, ou crominância Cb e Cr. O problema era que os componentes DC são armazenados como valores em relação ao valor DC relevante do MCU anterior. Então, quando eu adicionei os novos dados de imagem de jpg B, que tinha armazenado seus valores DC em relação a 0 (porque não havia MCUs anterior), mas é necessário levar em conta os valores finais DC do último MCU a partir jpg A. (esperança de que faz sentido).

A solução:

Você precisa fazer uma decodificação inicial (Huffman + RunLength) dos dados de imagem para descobrir exatamente onde as extremidades de dados de imagem e, em seguida, tira os 1s à direita. Você também precisará alterar os valores iniciais DC no segundo jpg adequadamente. Você precisa então reencode os bits apropriados, adicione 1s para caber para um limite byte, et voila.

Se você deseja anexar no eixo-x, é um pouco mais complicado. Você tem que reorganizar a MCUs para que eles varredura na ordem certa. Jpgs varredura da esquerda para a direita, em seguida, de cima para baixo e, em seguida, ajustar os valores DC de forma adequada.

Até agora eu só testei isso em jpgs MCU individuais, mas, teoricamente, ele deve funcionar com maiores também.

BTW eu só trabalhei isso graças ao proprietário deste excelente relacionados jpg recurso / blog

Outras dicas

Isto é muito factível. Eu fiz isso em um monte de telhas imagem mapa do Google para juntar-se aqueles e formar uma imagem de tamanho de pôster. Há um pacote para Unix chamado Ferramentas JPEG para fazer exatamente isso. O programa é chamado jpegjoin . fonte C pura, com binários do Windows disponível. Quando compilado ele cria um aplicativo de linha de comando que quando executado une duas imagens JPEG loselessly entre muitas outras coisas. Ele não de-comprimir qualquer imagem, apenas funde os dados compactados juntos e fixa o cabeçalho de acordo. Usei-o para fundir 100 imagens para criar 50 tiras e depois fundiu essas tiras novamente para criar uma imagem grande.

Mais informação pode ser encontrada em http://en.wikipedia.org/wiki/Lossy_compression #Lossless_editing

O código-fonte

O código fonte para o subjacente jpegtran biblioteca pode ser encontrada aqui . Um exemplo de script para imitar jpegjoin é aqui .

jpeg é - como mp3 -. Normalmente estável quando você recompress-lo (usando o mesmo algoritmo)

Assim, quando você juntar as imagens e Recompress-los, apenas certifique-se de que a nova taxa de compressão é maior ou igual ao mais elevado dos 2 fotos. Dessa forma, você não vai exatidão realmente perder.

Duas abordagens:

1) decodificar as duas imagens JPEG fonte, mesclar os bitmaps e codificar resultantes novamente como JPEG. Desvantagem aqui é a re-compressão.

2) Certifique-se que a largura da imagem fonte e altura são múltiplos de 16, possivelmente por cortar as imagens. Não decodificar as imagens, mas sim montar o alvo JPEG dos blocos fonte MCU (tamanho 16 x 16 pixles, portanto, o corte).

Eu sugiro que você considerar os marcadores DRI e RSTn, embora isso requer um monte de condições prévias, mas funciona para mim: anexando um PPM (um formato bitmap) a um jpeg que é codificado usando DRI e RSTn, ambos estão em mesma largura, e os dois são em múltiplos de MCU.

Eu só cortar os dados JPEG após o marcador última RSTn (se houver), decodificar isso PPM, e juntar as duas PPMs a uma única linha de MCUs, codificá-lo com as mesmas opções com o JPEG original, reorganizar as RSTs no jpeg resultante de acordo com o original do JPEG, em seguida, adicionando o resultado à original do JPEG. Usando este método, que me impede de decodificar todo o jpeg original e codificação-lo novamente.

Como a codificação e decodificação coisas, eu estou usando libjpeg.

Em vez de anexar imagens horizontalmente, é provavelmente mais fácil de girar cada imagem 90 graus, então se juntar a eles na vertical, em seguida, gire a imagem resultante de volta -90 graus.

operações Lossless JPEG são praticamente um oxímoro. Você pode fazer alguns truques, como girar, mas isso é muito bonito isso.

Eu sugiro que você tenha imagens de origem lossless (TIFF ou PNG vem à mente), ou re-avaliar seus requisitos de qualidade de imagem - resampling um JPEG, mais uma vez, dada arquivos originais decentes, é indistinguível com a grande maioria das pessoas lá fora.

O que você está tentando para é basicamente impossível.
A codificação do arquivo JPEG é um pouco complexo e se você está mudando o conteúdo dos pixels, em seguida, a codificação vai ser alterado. Você pode acabar com uma imagem menor ou maior do que a soma das duas imagens que combinam. As únicas operações que são possíveis sem perdas são aqueles que mantêm correspondência de um-para-um com os pixels da imagem original. Isso basicamente resume-se a rotações de 90 graus.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top