Red de conocimiento informático - Conocimiento informático - Cómo lograr varios efectos en imágenes mbp a través de la programación vc

Cómo lograr varios efectos en imágenes mbp a través de la programación vc

Para aquellos de ustedes que ven televisión con frecuencia, me pregunto si habrán notado que las series de televisión recientes tienen algunas imágenes de efectos especiales al principio o al final de cada episodio, como "La Larga Marcha" que se mostró. En la estación de televisión central hace un tiempo, "Dinastía Kangxi" se transmite actualmente en los ocho platós centrales. Estos efectos especiales se denominan "efecto de relieve de imagen" y "efecto de tallado de imagen". efecto visual de la audiencia, y parece que está hecho con tecnología 3D, razón por la cual esta tecnología es tan popular. De hecho, podemos utilizar algunos algoritmos simples de procesamiento de imágenes digitales para lograr estos efectos de visualización aparentemente complejos y avanzados. La mayoría de los materiales que tenemos a mano sobre el uso de VC para desarrollar imágenes digitales explican cómo controlar el tiempo de visualización o el orden de los píxeles en cada fila o columna de la imagen para lograr algunos efectos simples de visualización de imágenes. Hay muy pocos artículos que involucren algoritmos de imágenes. Este artículo se centra en Las dos tecnologías de procesamiento de efectos especiales de imágenes anteriores se amplían para explicar algunos algoritmos para realizar efectos especiales de imágenes. Utilizando una imagen estándar en escala de grises de Lena como imagen original, se proporcionan las representaciones procesadas y, al mismo tiempo, el VC. Se proporciona la plataforma de desarrollo. Parte del código fuente de implementación.

1. Imagen en "relieve"

El efecto de imagen en "relieve" significa que el primer plano de la imagen sobresale del fondo. El concepto llamado "relieve" se refiere a un proceso de procesamiento que se refiere a la diferencia entre un píxel en la imagen del dibujo y el píxel en la parte superior izquierda de la misma para mantener la imagen con un cierto brillo y aparecer gris. Agregué esta diferencia durante el procesamiento. Se agrega al valor una constante con un valor de 128. Los lectores deben tener en cuenta que al configurar un valor de píxel, se utilizarán tanto este como los píxeles en la parte superior izquierda. Para evitar el uso de píxeles que ya se han configurado, el procesamiento debe comenzar desde los píxeles en la parte inferior derecha de la imagen. A continuación se muestra el código fuente implementado:

void CDibView::OnFDImage() //Generar función de renderizado de "alivio"

{

HANDLE data1handle;

LPBITMAPINFOHEADER lpBi;

CDibDoc *pDoc=GetDocument();

HDIB hdib;

carácter sin firmar *hData;

unsigned char *data;

hdib=pDoc->GetHDIB();

// ¿Cómo abro el archivo de imagen y obtengo los datos de la imagen? Consúltelo si lo desea. interesado

//Mis artículos relacionados en Tianji.com tienen discusiones detalladas allí, así que no las repetiré aquí.

BeginWaitCursor();

lpBi=(LPBITMAPINFOHEADER)GlobalLock((HGLOBAL)hdib);

hData=(unsigned char*)FindDIBBits((LPSTR) lpBi);

pDoc->SetModifiedFlag(TRUE);

data1handle=GlobalAlloc(GMEM_SHARE,WIDTHBYTES(lpBi->biWidth*8)*lpBi->biHeight);

//Declarar un búfer para almacenar temporalmente los datos de la imagen procesada

data=(unsigned char*)GlobalLock((HGLOBAL)data1handle);

AfxGetApp( )-> BeginWaitCursor();

int i,j,buf;

for( i=lpBi->biHeight; i>=2; i--)

for( j=lpBi->biWidth; j>=2; j--)

{

//procesamiento de "alivio"

buf =*( hData+(lpBi->biHeight-i)*WIDTHBYTES(lpBi->biWidth*8)+j)-*(hData+(lpBi->biHeight-i+1)*WIDTHBYTES(lpBi->biWidth*8)+ j-1 )+128;

if(buf>255) buf=255;

if(buf<0)buf=0;

*( datos+(lpBi ->biHeight-i)*WIDTHBYTES(lpBi->biWidth*8)+j)=(BYTE)buf;

}

for( j=0; jbiHeight ; j++)

for( i=0; ibiWidth; i++)

//Reescribe el búfer de datos de la imagen original

*(hData+i *WIDTHBYTES( lpBi->biWidth*8)+j)=*(data+i*WIDTHBYTES(lpBi->biWidth*8)+j);

AfxGetApp()->EndWaitCursor();

GlobalUnlock((HGLOBAL)hdib);

GlobalUnlock(data1handle);

EndWaitCursor();

Invalidate(TRUE);/ /Mostrar imagen

}

2. Imagen "grabada"

Lo anterior describe cómo generar una imagen en escala de grises con un efecto de "relieve" encontrando la diferencia entre un píxel y su píxel superior izquierdo y agregando una constante. La imagen "grabada" es similar. Por el contrario, toma la diferencia entre un píxel y el píxel en la parte inferior derecha y agrega una constante. Aquí también tomo 128. Después de este procesamiento, puede obtener una imagen "tallada". el primer plano de la imagen está hundido en el fondo. Los lectores también deben tener en cuenta que para evitar la reutilización de píxeles de la imagen procesada, el procesamiento de la imagen debe comenzar desde el píxel superior izquierdo de la imagen.

El código de implementación es el siguiente:

void CDibView::OnDKImage()

{

// TODO: agregue aquí el código del controlador de comandos

HANDLE data1handle;

LPBITMAPINFOHEADER lpBi;

CDibDoc *pDoc=GetDocument();

HDIB hdib;

carácter sin firmar *hData;

carácter sin firmar *data;

hdib=pDoc->GetHDIB();

BeginWaitCursor();

lpBi =(LPBITMAPINFOHEADER )GlobalLock((HGLOBAL)hdib);

hData=(unsigned char*)FindDIBBits((LPSTR)lpBi);

pDoc->SetModifiedFlag(TRUE);

data1handle=GlobalAlloc(GMEM_SHARE,WIDTHBYTES(lpBi->biWidth*8)*lpBi->biHeight);

data=(unsigned char*)GlobalLock((HGLOBAL)data1handle);

AfxGetApp()->BeginWaitCursor();

int i,j,buf;

//Procesamiento de "tallado" de imágenes

for ( i=0;i<=lpBi->biHeight-2; i++)

for( j=0;j<=lpBi->biWidth-2; j++)

{

buf=*(hData+(lpBi->biHeight-i)*WIDTHBYTES(lpBi->biWidth*8)+j)-*(hData+(lpBi->biHeight-i-1)* WIDTHBYTES( lpBi->biWidth*8)+j+1)+128;

if(buf>255) buf=255;

if(buf<0)buf=0 ;

*(datos+(lpBi->biHeight-i)*WIDTHBYTES(lpBi->biWidth*8)+j)=(BYTE)buf;

}

for( j=0; jbiHeight; j++)

for( i=0; ibiWidth; i++)

// Vuelva a escribir los datos de la imagen procesada en la imagen original buffer Dentro del área

*(hData+i*WIDTHBYTES(lpBi->biWidth*8)+j)=*(data+i*WIDTHBYTES(lpBi->biWidth*8)+j);

AfxGetApp()->EndWaitCursor();

GlobalUnlock((HGLOBAL)hdib);

GlobalUnlock(data1handle);

EndWaitCursor () ;

Invalidar(TRUE);

 }

Imagen original de Lena

Representación de "grabado"

Representación en "relieve"

Uso de VC para desarrollar un pequeño sistema de gráficos vectoriales

Después de que todos hayan aprendido algunos conocimientos básicos del MFC de VC, si pueden usar VC desarrolla un software relativamente práctico, que es muy útil para familiarizarse con todos los aspectos de la programación VC y el diseño y desarrollo de software orientado a objetos.

El propósito de este artículo es brindar a los lectores una descripción completa de un pequeño sistema de gráficos vectoriales desarrollado por el propio autor para que los lectores puedan comprender los problemas resueltos desde las etapas de diseño hasta la implementación de un pequeño software. Al mismo tiempo, también explora las funciones de los sistemas MFC y Windows desde la interfaz y las funciones. De manera similar, los lectores que estudian gráficos por computadora también pueden ver que este artículo contiene muchas discusiones útiles sobre algoritmos e implementación de gráficos.

1. Diseño de funciones e interfaces

En primer lugar, que todos tengan una comprensión general de las funciones de este software. Cuando comienza a desarrollar un software, lo primero que debe resolver es, por supuesto, la función del software (la ingeniería de software a menudo se denomina casos de uso. Puede consultar materiales relevantes para conceptos específicos. Puede entenderse simplemente como lo que los usuarios pueden lograr). al usarlo). En el momento de escribir este artículo, este software ya cuenta con un prototipo relativamente completo. Podemos introducir el proceso de diseño de software combinando su interfaz (Figura 1).

 

Como puedes ver, este software implementa un subconjunto de funciones de dibujo. Inicialmente, se determinó que el entorno de desarrollo era VC6.0 y la interfaz adoptó el estilo IE. Para brindar a los usuarios la mayor comodidad de uso, se adoptan tres barras de herramientas (herramientas estándar como archivos comunes y operaciones de impresión, un cuadro de diálogo estilo barra de herramientas para configurar las propiedades de los objetos gráficos y un tipo de botón grande con descripción de texto). que puede flotar o acoplarse en cualquier ubicación (barra de herramientas de dibujo ubicada en el muelle).

En funcionamiento, se utiliza el clic izquierdo para establecer el punto de inicio del objeto gráfico, y el tamaño y la posición del gráfico se ajustan dinámicamente al moverlo (para dibujar a mano alzada, mantenga presionado el botón izquierdo y arrastre , haga clic en el botón izquierdo nuevamente para confirmar la posición y haga clic derecho para cancelar la operación. Haga doble clic para confirmar (finalizar) el dibujo de objetos gráficos de varios pasos (como polígonos). Se ajusta a las convenciones del software de gráficos general. Sin embargo, para comodidad del autor y protección del mouse, toda la función básicamente no requiere mantener presionado el botón izquierdo. Esto también es muy fácil de hacer. Aceptar, porque incluso los usuarios que están acostumbrados a arrastrar harán ajustes de posición, pero seguirán en el estado de arrastre después de soltarlos y se finalizarán haciendo clic o haciendo doble clic nuevamente.

Funcionalmente, se seleccionan las funciones de dibujar líneas, cuadros, círculos, polígonos, sólidos, texto, curvas, relleno y eliminación según si se rellena y se ilumina. El método de relleno se proporciona según el concepto de gráficos. Dos métodos (presentados más adelante) de acuerdo con los atributos gráficos, se seleccionan el ancho de línea y el tipo de línea (es fácil implementar un tipo de línea simple. Como quiero agregar más funciones, el autor no lo ha implementado específicamente. Lo haré). Los lectores interesados ​​​​pueden intentar implementarlo), color de borde, color de relleno y atributos de fuente. Por supuesto, estas funciones se pueden ampliar fácilmente en el método orientado a objetos (como dibujar elipses, seleccionar objetos y objetos). selección). Las operaciones de desplazamiento y rotación se pueden utilizar para seleccionar el mismo color de acuerdo con el algoritmo de relleno, es decir, la función de varita mágica de software como Photoshop, etc.). Para la función de borrador, es muy sencillo implementar una. herramienta específica o decirle al usuario cómo implementar esta función (es decir, usar el color de fondo para utilizar las funciones existentes.

En términos de implementación interna, es necesario registrar los atributos clave de cada uno). gráfico por separado (como posición, color, etc., estas son las características que distinguen los gráficos vectoriales de los mapas de bits. Dado que cada objeto puede formar una lista vinculada de objetos, también requiere la implementación de funciones de deshacer y rehacer de varios pasos). son a menudo características que los usuarios esperan con ansias (el programa de accesorio de pincel que viene con Windows es muy deficiente a este respecto)

2. Diseño de objetos

Todos los métodos de programación orientados a objetos son compatibles. tres actividades básicas: identificar objetos y clases, describir la relación entre objetos y clases y definir las funciones de cada clase describiendo

Primero que nada, introduzcamos la diferencia entre objeto (Objeto) y clase (Clase ). La clase son los datos del objeto del mismo tipo. Se define mediante la palabra clave Clase en ++), el objeto es la forma específica de la clase en la memoria (las variables del objeto se declaran con el nombre de la clase o se generan por el. nueva operación), y el objeto generalmente se denomina instancia de la clase.

El diseño de objetos gráficos se menciona a menudo en muchos libros de programación orientada a objetos debido a su fuerte correlación, por lo que creo que no será difícil para los lectores identificar objetos y clases. Sin embargo, para aprovechar al máximo las características de herencia y polimorfismo para describir la relación entre objetos y clases, y para describir la definición funcional de cada clase, es necesario analizar en detalle cuestiones específicas.