Como eu faço escalonamento de alta qualidade de uma imagem?

votos
18

Estou a escrever algum código para dimensionar uma imagem RGBA de 32 bits em C / C ++. Eu escrevi algumas tentativas que têm sido pouco sucesso, mas eles são lentos e mais importante a qualidade da imagem de tamanho não é aceitável.

Eu comparei a mesma imagem dimensionada por OpenGL (ou seja, minha placa de vídeo) e minha rotina e é a milhas de distância em qualidade. Eu tenho o Google Code Procurado, percorri árvores de origem de qualquer coisa que eu pensei que iria lançar alguma luz (SDL, Allegro, wxWidgets, CxImage, GD, ImageMagick, etc.), mas geralmente seu código ou é complicado e espalhados por todo o lugar ou crivado montador e pouco ou comentários. Também li vários artigos na Wikipédia e em outros lugares, e eu não estou encontrando uma explicação clara do que eu preciso. I compreender os conceitos básicos de interpolação e amostragem, mas eu estou lutando para obter o direito algoritmo. Eu não quero depender de uma biblioteca externa para uma rotina e tem que converter para o seu formato de imagem e de volta. Além disso, eu gostaria de saber como fazê-lo eu mesmo de qualquer maneira. :)

Eu vi uma pergunta semelhante perguntou sobre estouro de pilha antes, mas não foi realmente respondeu desta maneira, mas eu estou esperando há alguém lá fora que pode ajudar a empurrar-me na direção certa. Talvez me aponte para alguns artigos ou pseudo código ... nada para me ajudar a aprender e fazer.

Aqui está o que eu estou procurando:

  1. Sem assembler (estou escrevendo código muito portátil para vários tipos de processador).
  2. Nenhuma dependência em bibliotecas externas.
  3. Estou principalmente preocupado com dimensionamento para baixo, mas também terá de escrever uma rotina de escala até mais tarde.
  4. Qualidade do resultado e clareza do algoritmo é mais importante (eu posso otimizá-lo mais tarde).

Minha rotina essencialmente toma a seguinte forma:

DrawScaled(uint32 *src, uint32 *dst, 
      src_x, src_y, src_w, src_h, 
      dst_x, dst_y, dst_w, dst_h );

Obrigado!

UPDATE: Para esclarecer, eu preciso de algo mais avançado do que um resample caixa para downscaling que borra a imagem muito. Eu suspeito que eu quero é algum tipo de bicubic (ou outro) de filtro que é um pouco o inverso de um algoritmo de upscaling bicubic (ou seja, cada pixel destino é calculado de todos os pixels de origem contribuem combinados com um algoritmo de ponderação que mantém as coisas afiada.

Exemplo

Aqui está um exemplo do que eu estou começando a partir do algoritmo wxWidgets BoxResample vs. o que eu quero em um 256x256 bitmap redimensionado para 55x55.

  • www.free_image_hosting.net/uploads/1a25434e0b.png

E finalmente:

  • www.free_image_hosting.net/uploads/eec3065e2f.png

a imagem 256x256 originais

Publicado 09/12/2008 em 16:05
fonte usuário
Em outras línguas...                            


11 respostas

votos
2

Agora que eu vejo sua imagem original, eu acho que OpenGL está usando um algoritmo de vizinho mais próximo. Não só é a maneira mais simples possível para redimensionar, mas é também o mais rápido. A única desvantagem é que ele se parece muito áspera se há algum detalhe em sua imagem original.

A idéia é levar amostras uniformemente espaçados de sua imagem original; no seu caso, 55 de 256, ou um em cada 4,6545. Apenas em volta do número para obter o pixel para escolher.

Respondeu 10/12/2008 em 04:20
fonte usuário

votos
2

É possível que OpenGL está fazendo a escala no domínio vector? Se assim for, não há nenhuma maneira que qualquer escala com base em pixel vai ser perto dele em qualidade. Esta é a grande vantagem de imagens baseadas em vetores.

O algoritmo bicubic pode ser sintonizado para nitidez vs. artefatos - Estou tentando encontrar um link, eu vou editá-lo em quando eu faço.

Edit: Foi o trabalho Mitchell-Netravali que eu estava pensando, que é referenciado na parte inferior deste link:

http://www.cg.tuwien.ac.at/~theussl/DA/node11.html

Você também pode olhar para Lanczos resampling como uma alternativa para Bicubic.

Respondeu 09/12/2008 em 19:00
fonte usuário

votos
2

Um algoritmo bastante simples e decente para resample imagens é interpolação Bicubic , wikipedia só tem toda a informação que você precisa para obter este implementado.

Respondeu 09/12/2008 em 16:21
fonte usuário

votos
2

Eu encontrei a implementação wxWidgets bastante simples para modificar conforme necessário. É tudo C ++ assim, não problemas com a portabilidade lá. A única diferença é que a sua implementação trabalha com matrizes de caracteres não assinados (que eu acho ser a maneira mais fácil de lidar com imagens em todo o caso) com uma ordem de byte de RGB eo componente alfa em uma matriz separada.

Se você se referir ao "image.cpp src / common /" arquivo na árvore fonte wxWidgets existe uma função down-amostrador que utiliza um método de amostragem caixa "wxImage :: ResampleBox" e uma função up-scaler chamado "wxImage :: ResampleBicubic".

Respondeu 09/12/2008 em 16:18
fonte usuário

votos
1

Parece que você está realmente tendo dificuldade em compreender é a discreta -> contínua -> fluxo discreto envolvido em reamostragem corretamente uma imagem. Um relatório boa tecnologia que pode ajudar a dar-lhe a visão sobre isso que você precisa é de Alvy Ray Smith Um pixel é Not A Little Square .

Respondeu 09/12/2008 em 20:41
fonte usuário

votos
1

Intel tem bibliotecas IPP que fornecem os algoritmos de interpolação alta velocidade optimizadas para processadores da família Intel. É muito bom, mas não é livre embora. Dê uma olhada no seguinte link:

Intel IPP

Respondeu 09/12/2008 em 17:33
fonte usuário

votos
1

Um artigo genérico de nosso amado host: Melhor redimensionamento da imagem , discutindo as qualidades relativas de vários algoritmos (e links para outro artigo CodeProject).

Respondeu 09/12/2008 em 17:12
fonte usuário

votos
1

Tente usar o Adobe Image Library Genéricos ( http://opensource.adobe.com/wiki/display/gil/Downloads ) se quiser algo pronto e não apenas um algoritmo.


Extrato de: http://www.catenary.com/howto/enlarge.html#c

Ampliar ou reduzir - o código-fonte C requer processamento Biblioteca Victor Imagem para Windows de 32 bits v 5.3 ou superior.


int enlarge_or_reduce(imgdes *image1)
{
   imgdes timage;
   int dx, dy, rcode, pct = 83; // 83% percent of original size

   // Allocate space for the new image
   dx = (int)(((long)(image1->endx - image1->stx + 1)) * pct / 100);
   dy = (int)(((long)(image1->endy - image1->sty + 1)) * pct / 100);
   if((rcode = allocimage(&timage, dx, dy,
      image1->bmh->biBitCount)) == NO_ERROR) {
      // Resize Image into timage
      if((rcode = resizeex(image1, &timage, 1)) == NO_ERROR) {
         // Success, free source image
         freeimage(image1);
         // Assign timage to image1
         copyimgdes(&timage, image1);
         }
      else // Error in resizing image, release timage memory
         freeimage(&timage);
      }
   return(rcode);
}

Este exemplo redimensiona uma área de imagem e substitui a imagem original com a nova imagem.

Respondeu 09/12/2008 em 16:44
fonte usuário

Respondeu 09/12/2008 em 16:37
fonte usuário

votos
0

Como acompanhamento, Jeremy Rudd postou este artigo acima. Implementa filtrado duas redimensionamento passe. As fontes são C #, mas parece clara o suficiente para que eu possa portá-lo para dar-lhe uma tentativa. Eu encontrei código C muito similar ontem que era muito mais difícil de entender (nomes de variáveis muito ruim). Eu tenho que classificar-de-obra, mas foi muito lento e não produzir bons resultados que me levaram a acreditar que havia um erro na minha adaptação. I pode ter melhor sorte escrevê-lo a partir do zero com isso como uma referência, que vou tentar.

Mas, considerando como as duas obras algoritmo passa eu me pergunto se não há uma maneira mais rápida de fazê-lo, talvez até mesmo em uma passagem?

Respondeu 09/12/2008 em 21:07
fonte usuário

votos
0

Dê uma olhada em ImageMagick , que faz todos os tipos de filtros de redimensionamento.

Respondeu 09/12/2008 em 18:57
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more