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

Los amigos que ven televisión con frecuencia no saben si lo han notado. En los dramas televisivos recientes, algunas escenas con efectos especiales se muestran al principio o al final de cada episodio, como "La Larga Marcha", que se transmitió en el primer episodio de CCTV hace un tiempo, y "Dinastía Kangxi", que se está transmitiendo actualmente. transmitido en el primer episodio de CCTV. Estos efectos especiales se denominan "efectos de relieve de imagen" y "efectos de grabado de imagen". Las imágenes procesadas por estos efectos especiales mejoran el efecto visual de la audiencia y parecen haber sido producidas con tecnología 3D. De hecho, podemos utilizar algunos algoritmos simples de procesamiento de imágenes digitales para lograr estos efectos de visualización aparentemente complejos y profundos. La mayor parte de la información que tenemos sobre el uso de VC para desarrollar imágenes digitales trata sobre cómo controlar el tiempo de visualización o el orden de los píxeles en cada fila o columna de una imagen para lograr algunos efectos simples de visualización de imágenes. Hay pocos artículos sobre algoritmos de imágenes. Este artículo se centra en las dos tecnologías de procesamiento de efectos especiales de imágenes anteriores, las amplía y explica algunos algoritmos para lograr efectos especiales de imágenes. Tomando una imagen estándar en escala de grises de Lena como imagen original, se proporciona la representación procesada y parte del código fuente para implementar efectos especiales de imagen en la plataforma de desarrollo VC.

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" es el proceso de expresar la diferencia entre un píxel en la imagen del dibujo y el píxel en la esquina superior izquierda. Para mantener la imagen brillante y gris, agregué un valor constante de 128 a esta diferencia durante el procesamiento. Los lectores deben tener en cuenta que al establecer un valor de píxel, se utilizará este y el píxel de la esquina superior izquierda. Para evitar utilizar píxeles ya configurados, debemos comenzar con los píxeles de la esquina inferior derecha de la imagen. El siguiente es el código fuente:

Void CDibView::OnFDImage() //La función genera una representación de "relieve"

{

Manejar datos 1 mango ;

p>

LPBITMAPINFOHEADER lpBi

CDibDoc * pDoc = get document();

HDIB hdib

Caracteres sin firmar * hData

Carácter sin firmar*datos;

hdib = pDoc-& gt;GetHDIB();

//¿Cómo abrir un archivo de imagen y obtener datos de imagen? Por favor consulte a amigos interesados.

//Mis artículos relacionados sobre Tianji.com se analizan en detalle allí, por lo que no entraré en detalles aquí.

BeginWaitCursor();

lpBi =(LPBITMAPINFOHEADER)bloqueo global((h global)hdib);

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

pDoc->SetModifiedFlag(TRUE);

identificador de datos 1 = global alloc(GMEM_shared, ancho byte(lpBi->biWidth * 8)* lpBi ->BIH height);

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

datos=(carácter sin firmar *)bloqueo global((h global)datos 1 identificador);

AfxGetApp()-& gt;BeginWaitCursor();

int i, j, buf

for(I = lpBi->BIH altura;I>=2;I-)

for(j = lpBi-& gt; doble ancho ; j & gt=2;j -)

{

//Procesamiento de "alivio"

buf = *(hData+(lpBi- >altura BIH) -I)* ancho bytes(lpBi->biWidth * 8)+j)-*(hData+(lpBi->BIH altura-I+1)* ancho bytes(lpBi-> biWidth * 8)+j-1 )+128;

if(buf & gt;255)buf = 255;

if(buf <0)buf = 0

*( data+(lpBi-& gt;BIH altura-I)* ancho bytes(lpBi-& gt;biWidth * 8)+j)=(BYTE)buf;

}

para (j = 0; jbiHeightj++)

for(I = 0; ibiWidthi++)

// Vuelve a escribir el búfer de datos de la imagen original.

*(hData+I * ancho bytes(lpBi-& gt;biWidth * 8)+j)= *(datos+I * ancho bytes(lpBi-& gt;biWidth * 8)+j) ;

AfxGetApp()-& gt;EndWaitCursor();

desbloqueo global((h global)hdib);

desbloqueo global(datos 1 identificador) ;

EndWaitCursor();

Invalidate(true); //Mostrar imagen

}

2. /p>

La imagen en escala de grises con el efecto de "relieve" descrito anteriormente se genera encontrando la diferencia entre un píxel y su píxel superior izquierdo y agregando una constante. En cambio, se genera una imagen de "escultura" tomando la diferencia entre un píxel y su píxel inferior derecho y agregando una constante. Aquí también tomo 128. Después de dicho procesamiento, se puede obtener una imagen "escultural", en la que el primer plano de la imagen está empotrado en el fondo. Otro punto que los lectores deben tener en cuenta es que para evitar la reutilización de los píxeles de la imagen procesada, la imagen debe procesarse comenzando desde el píxel superior izquierdo de la imagen.

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

void CDibView::OnDKImage()

{

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

Manejar datos 1 identificador;

LPBITMAPINFOHEADER lpBi

CDibDoc * pDoc = get document();

HDIB hdib

Caracteres sin firmar * hData

Carácter sin firmar *data;

hdib = pDoc-& gt;GetHDIB();

BeginWaitCursor();

lpBi =(LPBITMAPINFOHEADER)bloqueo global((h global)hdib);

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

pDoc-& gt; (VERDADERO);

datos 1 identificador = global alloc(GMEM_share, ancho bytes (lpBi->biWidth * 8)* lpBi->BIH alto);

datos=( char unsigned *)bloqueo global((h global)data 1 handle);

AfxGetApp()-& gt;BeginWaitCursor();

int i, j, buf

//Procesamiento de "tallado" de imágenes

for(I = 0; I<= lpBi->; BIH altura-2; i++)

for(j = 0; j & lt= lpBi->; doble-ancho-2; j++)

{

buf = *(hData+(lpBi-& gt; BIH alto-I)* ancho bytes (lpBi-& gt; biWidth * 8)+j)-*(hData+(lpBi-& gt; BIH altura-I-1)* ancho bytes(lpBi-& gt; biWidth * 8 )+j+1)+128 ;

if(buf & gt; 255)buf = 255;

if(buf & lt; 0)buf = 0;

*(datos+( lpBi-& gt;BIH altura-I)* ancho bytes(lpBi-& gt;biWidth * 8)+j)=(BYTE)buf;

}

for(j = 0; jbiHeightj++)

for(I = 0; ibiWidthi++)

//Escribe los datos de la imagen procesada en el búfer de imagen original nuevamente.

*(hData+I * ancho bytes(lpBi-& gt;biWidth * 8)+j)= *(datos+I * ancho bytes(lpBi-& gt;biWidth * 8)+j) ;

AfxGetApp()-& gt;EndWaitCursor();

desbloqueo global((h global)hdib);

desbloqueo global(datos 1 identificador) ;

EndWaitCursor();

Invalidar(true);

}

Imagen original de Lena

" Representaciones de "grabado"

Representaciones de "relieve"

Desarrollar un pequeño sistema de gráficos vectoriales usando VC

Después de aprender algunos conocimientos básicos del MFC de VC, si puedo Usar VC para desarrollar un software relativamente práctico es muy útil para estar familiarizado con todos los aspectos de la programación de VC y el diseño y desarrollo de software orientado a objetos.

Este artículo tiene como objetivo proporcionar 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 de resolver un pequeño software desde el diseño hasta la implementación. Al mismo tiempo, las funciones de los sistemas MFC y Windows también se analizan 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 tiene muchas discusiones útiles sobre algoritmos e implementación de gráficos.

1. Diseño de funciones y de interfaz

Primero, que todos comprendan las funciones de este software. Cuando comienzas a desarrollar un software, lo primero que debes resolver es, por supuesto, la función del software (la ingeniería de software a menudo se denomina instancias funcionales y puedes consultar materiales relevantes para conceptos específicos, por lo que puede entenderse simplemente como lo que los usuarios puede lograr con ello). Porque al momento de escribir este artículo, este software ya cuenta con un prototipo relativamente completo. Podemos utilizar su interfaz para introducir el proceso de diseño de software (Figura 1).

Como puedes ver, este software es un subconjunto de la funcionalidad de dibujo. Inicialmente se determina que el entorno de desarrollo es VC6.0 y la interfaz es estilo IE. Para brindar a los usuarios la mayor comodidad, se utilizan 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 una barra de herramientas de dibujo con botones grandes con descripciones de texto. Flotante o posición en cualquier muelle-Dock).

Durante la operación, haga clic en el botón izquierdo para establecer el punto de inicio del objeto gráfico, mueva y ajuste dinámicamente el tamaño y la posición del gráfico (arrastre con el botón izquierdo, haga clic en el botón izquierdo nuevamente para confirmar la posición, 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). En términos de diseño funcional, básicamente se ajusta a las convenciones del software de gráficos general, pero para comodidad del autor y protección del mouse, toda la función refleja la idea de básicamente no mantener presionado el botón izquierdo y arrastrar. Esto también es muy aceptable, porque incluso los usuarios que están acostumbrados a arrastrar tendrán un ajuste de posición al arrastrar, pero aún estarán en el estado de arrastre después de soltarlo, y aún se confirmarán haciendo clic nuevamente o haciendo doble clic.

Se seleccionan las funciones de dibujar líneas, marcos, círculos, polígonos, sólidos, caracteres, curvas, rellenar y eliminar, y se añaden varias categorías según si se debe rellenar y iluminar. El método de llenado proporciona dos métodos basados ​​en el concepto de gráficos (que se describe más adelante). De acuerdo con los atributos gráficos, el autor tomó varios atributos, como el ancho de línea y el tipo de línea (el tipo de línea simple es fácil de implementar porque quiero agregar más funciones, pero el autor no lo implementó primero. El autor mencionará su implementación más adelante Los lectores pueden intentar implementarlo si están interesados), color de borde, color de relleno y fuente. Por supuesto, estas funciones se amplían fácilmente en métodos orientados a objetos (como dibujar una elipse, seleccionar un objeto, mover y rotar objetos, seleccionar el mismo color según 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 la función existente para dibujar con un color de fondo).

En la implementación interna, los atributos clave de cada gráfico deben registrarse por separado (como posición, color, etc., estas son las características de los gráficos vectoriales que son diferentes de los mapas de bits).

Debido a que cada objeto puede formar una lista vinculada de objetos, también es necesario implementar funciones de deshacer y rehacer de varios pasos, que es lo que los usuarios suelen esperar (el propio programa de actualización de archivos adjuntos de Windows es muy deficiente a este respecto).

Dos. Diseño de objetos

Los métodos de programación orientada a objetos admiten tres actividades básicas: identificar objetos y clases, describir las relaciones entre objetos y clases y definir el comportamiento de los objetos describiendo la funcionalidad de cada clase.

Primero, se introduce la diferencia entre objetos y clases. Una clase es una clase definida por la palabra clave Class en los datos convexos δφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφφ.

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