El proyecto de marco de foto digital muestra una imagen que se puede ampliar, reducir y arrastrar

He trabajado en un proyecto de marco de fotos electrónico antes, y las principales dificultades involucradas son: acercamiento, alejamiento e imágenes en movimiento en la pantalla LCD.

En primer lugar, tenemos que entender que si se amplía o reduce la imagen original, la imagen original se reduce en proporciones iguales y luego se muestra en la pantalla LCD, pero el grado de reducción es diferente (sobre cómo extraer los datos de la imagen original y luego Reducido al tamaño que necesitamos, puede ver mi otro blog: https://blog.csdn.net/qq_37659294/article/details/104382032 ).

Después del algoritmo de zoom introducido en el blog anterior, hemos obtenido una imagen que es reducida y proporcional a la imagen original y almacenada en el búfer, pero esta es solo una imagen que no se ha mostrado en la pantalla LCD, entonces, ¿cómo podemos ¿Esta imagen se ampliará, reducirá y moverá dinámicamente en la pantalla LCD?

 

Primero, echemos un vistazo a una función muy crítica, la función ShowZoomedPictureInLayout . Esta función muestra una imagen ampliada y movida en la pantalla LCD, porque el tamaño de la imagen puede ser mayor que el área de visualización, puede ser pequeña o puede moverse. En el borde del marco de la foto, solo se puede mostrar una parte de la imagen, por lo que debemos confirmar dónde comenzar a buscar datos de la imagen (iStartXofNewPic, iStartYofNewPic), y dónde mostrar en el área de visualización (iStartXofOldPic, iStartYofOldPic), qué tan grande mostrar (iWidthPicturePicture Area.

La idea de realización de la función ShowZoomedPictureInLayout es:

① Calcule iStartXofNewPic, iStartYofNewPic, determine dónde comenzar a buscar datos de la imagen

②Use the g_iXofZoomedPicShowInCenter-iStartXofNewPic = iDeltaX = X coordenada del punto central del área de visualización (g_tManualPictureLayout.iTopLeftX + iPictureLayoutWi / ItartX de la imagen de la pantalla Comienza a mostrar imágenes

③ Calcule el ancho real iWidthPictureInPlay y la altura iHeightPictureInPlay

RAgregue los datos de la imagen en el framebuffer LCD según los parámetros calculados arriba


/ ************************************************* *********************
 * Nombre de la función: ShowZoomedPictureInLayout
 * Descripción de la función: Muestra la imagen ampliada en la "página del manual"
 * Parámetro de entrada: ptZoomedPicPixelDatas-contiene ya Datos de píxeles de la imagen ampliada
 * ptVideoMem-mostrado en este VideoMem
 * Parámetro de salida: Ninguno
 * Valor de retorno: Ninguno
 *************************** ********************************************** /

vacío estático ShowZoomedPictureInLayout (PT_PixelDatas ptZoomedPicPixelDatas, PT_VideoMem ptVideoMem)
{

    / * Las dos variables




iStartXofNewPic e iStartYofNewPic no significan las coordenadas xy de la nueva imagen en el área de visualización (o el área de la pantalla completa)      * sino de las coordenadas de la imagen ampliada (iStartXofNewPic, iStartYofNewPic), muestran esta imagen      * coordenadas (x, y ) El área anterior, es decir, cualquier lugar donde la coordenada horizontal es menor que x y la coordenada vertical es menor que y, no se muestra      * porque la imagen ampliada puede no mostrarse completamente en la pantalla, y solo se puede mostrar una parte de ella      * Calcular dónde comenzar a mostrar la imagen , Y agregue un largo y ancho, entonces la parte que se muestra en la pantalla se puede representar      * /
    int iStartXofNewPic, iStartYofNewPic;

    / * Las dos variables




iStartXofOldPic e iStartYofOldPic no son la posición de visualización de la imagen anterior, sino las coordenadas iniciales de la nueva imagen que se muestra en la pantalla.      * Estas seis variables están conectadas para pensar en:      * De la imagen después del zoom (iStartXofNewPic , iStartYofNewPic) Este lugar comienza      * Tome un área grande como iWidthPictureInPlay, iHeightPictureInPlay      * Visualice en la memoria (iStartXofOldPic, iStartYofOldPic) este lugar      * /
    int iStartXofOldPic, iStartYofOldPic;
    int; iPight;


    int iPictureLayoutWidth, iPictureLayoutHeight;
    int iDeltaX, iDeltaY; // Variables intermedias en el proceso de cálculo

 

    / * iPictureLayoutWidth ancho del área de visualización
     * iPictureLayoutHeight altura del área de visualización
     * /

    = G_tManualPictureLayout.iBotRightX iPictureLayoutWidth - g_tManualPictureLayout.iTopLeftX + 1;.
    IPictureLayoutHeight = g_tManualPictureLayout.iBotRightY - g_tManualPictureLayout.iTopLeftY + 1;.
    
    / * G_iXofZoomedPicShowInCenter imagen es a la izquierda desde el centro del área de visualización, g_iXofZoomedPicShowInCenter = media anchura de la ajustada a escala compensado movimiento + Cantidad (positiva cuando se mueve hacia la izquierda, negativa cuando se mueve hacia la derecha (moverse demasiado puede volverse negativa))
     * La primera asignación de esta variable está en ShowPictureInManualPage (la primera visualización de la imagen (visualización centrada), en este momento la imagen El tamaño es menor que el área de visualización de la imagen LCD) En esta función, el valor es la mitad del ancho de la imagen mostrada, lo que también representa la distancia desde el extremo izquierdo al centro
     * Cuando no se mueve, el valor de g_iXofZoomedPicShowInCenter es el mismo múltiplo de acercamiento y alejamiento
     * Al moverse En ese momento, en la lógica de procesamiento de "imágenes en movimiento" en la función ManualPageRun, el desplazamiento a la izquierda aumenta y el desplazamiento a la derecha disminuye.
     * Del mismo modo, g_iYofZoomedPicShowInCenter es la distancia desde la parte superior de la posición de visualización de la imagen hasta el centro del área de visualización
     * /

    iStartXofNewP ic = g_iXofZoomedPicShowInCenter-iPictureLayoutWidth / 2;// Calcule iStartXofNewPic usando g_iXofZoomedPicShowInCenter, y luego sepa dónde tomar los datos de la imagen para mostrar, correspondiente al primer paso de la idea anterior
    si (iStartXofNewPic <0) // Es decir, g_iXofZoomedPicShowInCenter <iPictureLayoutW de la mitad / ancho de la mitad , Indicando que el lado izquierdo de la imagen está en el área de visualización
    {
        iStartXofNewPic = 0; // Si el lado izquierdo de la imagen está en el área de visualización, los datos se tomarán del lado izquierdo de la imagen
    }

    / * Existe otra situación intermedia, es decir,
     cuando (iStartXofNewPic> 0) && (iStartXofNewPic <ptZoomedPicPixelDatas-> iWidth)
     * significa que el lado izquierdo de la imagen se ha movido fuera del área de visualización (el lado derecho todavía está en el área de visualización) y solo se puede mostrar Parte de
     esto * iStartXofNewPic = g_iXofZoomedPicShowInCenter-iPictureLayoutWidth / 2;
     * significa comenzar a mostrar desde este lugar de la imagen
     * /

    if (iStartXofNewPic> ptZoomedPicPixelDatas-> iWidth) // que es G_iXPP (La mitad del ancho del área de visualización), lo que indica que la imagen se ha         movido completamente a la izquierda
    {
iStartXofNewPic = ptZoomedPicPixelDatas-> iWidth; // Toda la imagen se ha movido fuera del área de visualización a la izquierda, no es necesario mostrarla
    }

     / * IDeltaX posición de inicio de visualización es la distancia real al punto central de la imagen representada por g_iXofZoomedPicShowInCenter iStartXofNewPic obtiene restando solamente un iStartXofOldPic para el cálculo de las variables intermedias
     * porque la amplificación se puede mover a la izquierda o a no rayar, Este es el caso de 0 <iStartXofNewPic <ptZoomedPicPixelDatas-> iWidth
     * Esta fórmula calcula la distancia desde el
borde izquierdo de la imagen real al centro del área de visualización      * iDeltaX puede ser un número negativo (cuando la imagen se mueve a la derecha de la línea central, Entonces iDeltaX es un número negativo), pero debido a que estamos usando ecuaciones matemáticas para calcular iStartXofOldPic, el negativo final y el negativo serán positivos
     * /
    iDeltaX = g_iXofZoomedPicShowInCenter-iStartXofNewPic;

     / * G_iXofZoomedPicShowInCenter - iStartXofNewPic
     * = iDeltaX
     * = X de coordenadas del punto central de la región de visualización (g_tManualPictureLayout.iTopLeftX + iPictureLayoutWidth / 2) - iStartXofOldPic ( imagen de la pantalla de inicio de coordenadas en la pantalla LCD)
     * de acuerdo con la ecuación anterior podemos calcular iStartXofOldPic

     * /
    iStartXofOldPic = (g_tManualPictureLayout.iTopLeftX + iPictureLayoutWidth / 2) -iDeltaX;


     / * Cuando iStartXofNewPic = ptZoomedPicPixelDatas-> iWidth, toda la imagen ha sido descrito desde la izquierda para dibujar un
     * = g_iXofZoomedPicShowInCenter iDeltaX - ptZoomedPicPixelDatas-> iWidth> = iPictureLayoutWidth / 2
     * iStartXofOldPic por lo que en este caso puede ser inferior a g_tManualPictureLayout.iTopLeftX, Por lo tanto, debe juzgar
     * /

    if (iStartXofOldPic <g_tManualPictureLayout.iTopLeftX)
    {
        iStartXofOldPic = g_tManualPictureLayout.iTopLeftX;
    }

     / *
    Marcado a la derecha * / if (iStartXofOldPic> g_tManualPictureLayout.iBotRightX)
    {
        iStartXofOldPic = g_tManualPictureLayout.iBotRightX + 1;
    }
     

     / * ptZoomedPicPixelDatas-> iWidth-iStartXofNewPic es la imagen, excepto por el lado izquierdo que puede no mostrarse, el resto debe mostrarse
     * g_tManualPictureLayout.iBotRightX-iStartXofOldPic + 1 es desde la posición de visualización hasta el final del área donde se puede ver la imagen.
     * la dos seleccionados de una pequeña, como la anchura de la pantalla real
     * /

    IF ((ptZoomedPicPixelDatas-> iWidth - iStartXofNewPic)> (g_tManualPictureLayout.iBotRightX - iStartXofOldPic + 1).)
        iWidthPictureInPlay = (g_tManualPictureLayout.iBotRightX - iStartXofOldPic + 1.);
    el otro
        iWidthPictureInPlay = (ptZoomedPicPixelDatas-> iWidth-iStartXofNewPic);
    

     / * Lo anterior es para calcular la coordenada X, la dirección Y se calcula siguiendo el principio, los mismos principios * /
    iStartYofNewPic = g_iYofZoomedPicShowInCenter - iPictureLayoutHeight / 2;
    IF (iStartYofNewPic <0)
    {
        iStartYofNewPic = 0;
    }
    IF (iStartYofNewPic> ptZoomedPicPixelDatas-> IHEIGHT)
    {
        iStartYofNewPic = ptZoomedPicPixelDatas-> iHeight;
    }
    iDeltaY = g_iYofZoomedPicShowInCenter-iStartYofNewPic;
    iStartYofOldPic = (g_tManualPictureLayout.iTopLeftYiTopLeftYi iPopLeftY-iPicture-Ii )

    if (iStartYofOldPic <g_tManualPictureLayout.iTopLeftY)
    {
        iStartYofOldPic = g_tManualPictureLayout.iTopLeftY;
    }
    if (iStartYofOldPic> g_tManualPictureLayout.iBotRightY)
    {
        iStartYofOldPic = g_tManualPictureLayout.iBotRightY + 1;
    }
    
    if ((ptZoomedPicPixelDatas-> iHeight - iStartYofNewPic)> (g_tManualPictureLayout.iBotRightY - iStartYofOldPic + 1))
    {
        iHeightPictureInPlay = (g_tManualPictureLayout.ITot;
    }
    else
    {
        iHeightPictureInPlay = (ptZoomedPicPixelDatas-> iHeight - iStartYofNewPic);
    }
   

     / * Rellene toda el área de visualización de la imagen con un color de fondo * /    
    ClearVideoMemRegion (ptVideoMem, & g_tManualPictureLayout, COLOR_BACKGROUND);

     / *
     Pase los parámetros previamente calculados y muestre la imagen ampliada y movida * iStartXofNewPic, iStartYofNewPic: desde qué posición de la imagen comenzar a tomar datos
     * iStartXofOldPic, iStartYofOldPic: dónde comenzar a mostrar la imagen en la pantalla LCD
     * iWidthPictureInPlay, iHeightPicture, iHeightPicture, iHeightPicture, iHeight ancho de la imagen de visualización y altura
     * ptZoomedPicPixelDatas, y ptVideoMem-> tPixelDatas: origen y el destino
     * /

    PicMergeRegion (iStartXofNewPic, iStartYofNewPic, iStartXofOldPic, iStartYofOldPic, iWidthPictureInPlay, iHeightPictureInPlay, ptZoomedPicPixelDatas, y ptVideoMem-> tPixelDatas);
}

 

La función PicMergeRegion se define de la siguiente manera:



/**********************************************************************
 * 函数名称: PicMergeRegion
 * 功能描述: 把新图片的某部分, 合并入老图片的指定区域
 * 输入参数: iStartXofNewPic, iStartYofNewPic : 从新图片的(iStartXofNewPic, iStartYofNewPic)座标处开始读出数据用于合并
 *            iStartXofOldPic, iStartYofOldPic : 合并到老图片的(iStartXofOldPic, iStartYofOldPic)座标去
 *            iWidth, iHeight                  : 合并区域的大小
 *            ptNewPic                         : 新图片
 *            ptOldPic                         : 老图片
 * 输出参数: 无
 * 返 回 值: 0 - 成功, 其他值 - 失败
 ***********************************************************************/
int PicMergeRegion(int iStartXofNewPic, int iStartYofNewPic, int iStartXofOldPic, int iStartYofOldPic, int iWidth, int iHeight, PT_PixelDatas ptNewPic, PT_PixelDatas ptOldPic)
{
	int i;
	unsigned char *pucSrc;
	unsigned char *pucDst;
    int iLineBytesCpy = iWidth * ptNewPic->iBpp / 8;

    if ((iStartXofNewPic < 0 || iStartXofNewPic >= ptNewPic->iWidth) || \
        (iStartYofNewPic < 0 || iStartYofNewPic >= ptNewPic->iHeight) || \
        (iStartXofOldPic < 0 || iStartXofOldPic >= ptOldPic->iWidth) || \
        (iStartYofOldPic < 0 || iStartYofOldPic >= ptOldPic->iHeight))
    {
        return -1;
    }
	
	pucSrc = ptNewPic->aucPixelDatas + iStartYofNewPic * ptNewPic->iLineBytes + iStartXofNewPic * ptNewPic->iBpp / 8;
	pucDst = ptOldPic->aucPixelDatas + iStartYofOldPic * ptOldPic->iLineBytes + iStartXofOldPic * ptOldPic->iBpp / 8;
	for (i = 0; i < iHeight; i++)
	{
		memcpy(pucDst, pucSrc, iLineBytesCpy);
		pucSrc += ptNewPic->iLineBytes;
		pucDst += ptOldPic->iLineBytes;
	}
	return 0;
}

 

 

El siguiente es el proceso completo de acercamiento:

static int g_iXofZoomedPicShowInCenter;  
static int g_iYofZoomedPicShowInCenter;
/* 放大/缩小系数 */
#define ZOOM_RATIO (0.9)
case 2: /* 放大按钮 */
{
     /* 获得放大后的数据 */
     iZoomedWidth  = (float)g_tZoomedPicPixelDatas.iWidth / ZOOM_RATIO;
     iZoomedHeight = (float)g_tZoomedPicPixelDatas.iHeight / ZOOM_RATIO;
     ptZoomedPicPixelDatas = GetZoomedPicPixelDatas(&g_tOriginPicPixelDatas, iZoomedWidth, iZoomedHeight);

     /* 重新计算中心点 */
     g_iXofZoomedPicShowInCenter = (float)g_iXofZoomedPicShowInCenter / ZOOM_RATIO;
     g_iYofZoomedPicShowInCenter = (float)g_iYofZoomedPicShowInCenter / ZOOM_RATIO;

     /* 显示新数据 */
     ShowZoomedPictureInLayout(ptZoomedPicPixelDatas, ptDevVideoMem);

     break;
}

Alejar:

/* 放大/缩小系数 */
#define ZOOM_RATIO (0.9)
case 1: /* 缩小按钮 */
{
    /* 获得缩小后的数据 */
    iZoomedWidth  = (float)g_tZoomedPicPixelDatas.iWidth * ZOOM_RATIO;
    iZoomedHeight = (float)g_tZoomedPicPixelDatas.iHeight * ZOOM_RATIO;
    ptZoomedPicPixelDatas = GetZoomedPicPixelDatas(&g_tOriginPicPixelDatas, iZoomedWidth, iZoomedHeight);

    /* 重新计算中心点 */
    g_iXofZoomedPicShowInCenter = (float)g_iXofZoomedPicShowInCenter * ZOOM_RATIO;
    g_iYofZoomedPicShowInCenter = (float)g_iYofZoomedPicShowInCenter * ZOOM_RATIO;

    /* 显示新数据 */
    ShowZoomedPictureInLayout(ptZoomedPicPixelDatas, ptDevVideoMem);

    break;
}

Arrastrar y soltar:

/* 如果触点滑动距离大于规定值, 则挪动图片 */
if (DistanceBetweenTwoPoint(&tInputEvent, &tPreInputEvent) > SLIP_MIN_DISTANCE)
{                            
    /* 重新计算中心点 */
    g_iXofZoomedPicShowInCenter -= (tInputEvent.iX - tPreInputEvent.iX);
    g_iYofZoomedPicShowInCenter -= (tInputEvent.iY - tPreInputEvent.iY);
                            
    /* 显示新数据 */
    ShowZoomedPictureInLayout(ptZoomedPicPixelDatas, ptDevVideoMem);
                            
    /* 记录上次滑动点 */
    tPreInputEvent = tInputEvent;                            
}

Efecto experimental:

La pantalla inicial está centrada

Arrastrar 

Acercar 

Artículo de referencia: https://blog.csdn.net/qq_22655017/article/details/97627382

 

42 artículos originales publicados · Me gusta 10 · Visitantes más de 10,000

Supongo que te gusta

Origin blog.csdn.net/qq_37659294/article/details/104518692
Recomendado
Clasificación