Olá.
Gostaria de saber como faço para inverter uma imagem.
Estou montando uma imagem, e quero transforma-la em bmp. Já tenho o header, só preciso inverter os dados da imagem, pois em bmp a imagem tem que ser invertida, para que seja impressa corretamente na impressora.
Consegui incrementar um algoritmo que me foi sugerido, mas acho que está faltando alguma coisa, talvez tenha que fazer algum cálculo com o bpp.
Com este algoritmo, consigo inverter verticalmente a imagem, mas não consigo inverter horizontalmente. E o resultado da imagem não fica muito bom.
Alguém tem alguma dica?
void ImageMirror( uchar * img, int width, int height, int lenght, int bpp )
{
uchar aux = 0;
uchar * a = img;
uchar * b = &img[ (lenght) - 1 ];;
for( ; a < b; a++, b-- )
{
aux = *a;
*a = *b;
*b = aux;
}
Meu algoritmo está fazendo isso.
Só que ele só consegue inverter verticalmente, não consigo horizontalmente.
Parece simples, mas não é. Manipulação de imagem é mais complexo do que parece.
Tu não entendeste bem minha questão.
O sistema é uma vm. E quando a aplicação envia a imagem para ser impressa, a vm desmembra a imagem, remove o header, separa os dados da imagem. Depois, tem que remontar o cabeçalho e imprimir. Qualquer formato de imagem pode ser enviado. Entretanto, o dispositivo só aceita imagens no formato bmp. Como bem sabemos, o formato bitmap tem suas informações invertidas. O algoritmo do sistema os corrige invertendo os dados da imagem. Entretanto, o firmware do dispositivo quer um bmp autêntico, e não um que foi alterado. Então eu tenho que inverter a imagem para que ela seja impressa de forma correta.
Me foi apresentada essa solução logo abaixo, entretanto, não entendi que regra que foi aplicada para a inversão da imagem, não encontrei material que ensine.
void PrinterImage(WNMEnv *env, Var stack[])
{
//OSL_Debug("TESTE IMPRESSORA - nmt4waba.c - PrinterImage");
uint32 bitmapOffset;
WObject objImg = stack[0].obj;
unsigned int width = WOBJ_ImageWidth(env, objImg);
unsigned int height = WOBJ_ImageHeight(env, objImg);
uint16 bpp = WOBJ_ImageBPP(env, objImg);
if (bpp>1)
env->ThrowException(env, InputOutputException, "bpp deve ser 1");
WObject objRGBArray = WOBJ_ImageRGB(env, objImg);
uchar *rgb = (uchar *)WOBJ_arrayStart(env, objRGBArray);//recebendo dados da imagem
//AQUI NÃO ENTENDI ESSA LÓGICA MALUCA, MAS FUNCIONA - NÃO ENCONTREI MATERIAL QUE EXPLIQUE TAL REGRA
unsigned int bytesPerRow = (width >> 3) + (width & 0x7 ? 1 : 0);
int rgbLen = WOBJ_arrayLen(env, objRGBArray);//tamanho dos dados da imagem
struct BMPColorTable bmpFormat; //Estrutura bmp a ser montada
memset(&bmpFormat, 0, sizeof(bmpFormat));
bitmapOffset= sizeof(bmpFormat); //tamanho da estrutura bmp
unsigned int fileSize= bitmapOffset+ rgbLen;//tamanho total da imagem
//--------------------------------- BMP FILE FORMAT -----------------------------------
//***** File Header ***********
bmpFormat.header.signature = (0x4D << 8) | 0x42; // 0-1 magic chars 'BM' uint16
bmpFormat.header.fileSize = fileSize; // 2-5 uint32 filesize (not reliable) tamanho total em bytes da imagem
bmpFormat.header.filler1 = 0; // 6-9 uint32 0
bmpFormat.header.bitmapOffset = bitmapOffset; // 10-13 uint32 bitmapOffset é a posição onde iniciam os dados
//******************************
//***** Image Header ***********
bmpFormat.header.infoSize = 40; // 14-17 uint32 info size - Tamanho de Image Header
bmpFormat.header.width = width; // 18-21 int32 width tamanho maximo: 384
bmpFormat.header.height = height; // 22-25 int32 height tamanho maximo: 128
bmpFormat.header.nPlanes = 1; // 26-27 uint16 nplanes - sempre sera igual 1
bmpFormat.header.bpp = bpp; // 28-29 uint16 bits per pixel - aqui o bpp deve ser 1, do contrario ocorrerá um exception
bmpFormat.header.compression = 0; // 30-33 uint32 compression flag
bmpFormat.header.imageSize =0; // 34-37 uint32 image size (compressed) in bytes - aqui fica zero se compressão for zero
bmpFormat.header.biXPelsPerMeter = 0; // 38-41 int32 biXPelsPerMeter - valores que servem para ajustar a imagem ao tamanho da tela do dispositivo
bmpFormat.header.biYPelsPerMeter = 0; // 32-45 int32 biYPelsPerMeter - valores que servem para ajustar a imagem ao tamanho da tela do dispositivo
bmpFormat.header.colorsUsed = 0; // 46-49 uint32 colors used
bmpFormat.header.importantColorCount = 0; // 50-53 uint32 important color count
//******************************
//***** Color Table ************
bmpFormat.color1= 0; // 54-57 uint32 color cor preta
bmpFormat.color2= 0x00FFFFFF; // 58-61 uint32 color cor branca
//*******************************
//---------------------------------------------------------------------------------------
uchar *bitmapStream = (uchar *)wabaVm->MemAlloc(fileSize);
memset(bitmapStream,0,fileSize);
memcpy(bitmapStream, &bmpFormat, sizeof(bmpFormat)); //copiando a estrutura bmp para montar a imagem
//Inverte os dados da imagem e armazena-os, finalizando toda a estrutura da imagem
int row;
for (row = height - 1; row >= 0; row--)
memcpy(&(bitmapStream[bitmapOffset + row * bytesPerRow]), &rgb[(height - row - 1) * bytesPerRow], bytesPerRow);
//Imprime imagem
PrintWithGoal(bitmapStream,fileSize,1);
wabaVm->MemFree(bitmapStream);
}
Claro que ta ali comentado, fui eu que descobri como funciona e comentei!
Continuas não entendo minha questão.
A questão é: Da onde vem a regra do bytesPerRow? Porque procurei em toda a internet e não encontrei tal regra. Sem esse ponto chave o algoritmo não funciona!
Dessa vez não vai ter como tu responder sem ser: ta ali comentado, pois não deixei comentado.
Como eu te disse, não é tão simples. O ponto chave é o bytesPerRow. Sem ele, qualquer tentativa de inversão de imagem é inútil!
Acho contraproducente esse tipo de postura já que você não sabe, esta pedindo ajuda, e ainda estou gastando tempo e tendo paciência tentando te ajudar.
Também acho, só que foste tu que começaste, ao me tratar como se eu fosse uma retardada, explicando coisas que eu mesma comentei. Como se eu não tivesse feito toda uma pesquisa, como se não tivesse sido eu que estruturei o código todo e colocado todos os comentários para um melhor entendimento.
A única coisa que não fiz nesse código aí foi o trecho de linha que envolve inverter a imagem e os bytesPerRow, os quais varri toda a web e não encontrei referências. Lembrando que esse trecho de linha que inverte a imagem funciona apenas com imagens monocromáticas.
Obrigada.
Infelizmente não mostra o porquê daquela fórmula:
Apenas explica isso:
bmWidthBytes
The number of bytes in each scan line. This value must be divisible by 2, because the system assumes that the bit values of a bitmap form an array that is word aligned.
Acredito que provavelmente a pessoa que montou esse código, pegou a fórmula em algum google acadêmico pago.