📄 geotrans.cpp
字号:
/************************************************************************** * 文件名:GeoTrans.cpp * * 图像几何变换API函数库: * * TranslationDIB1() - 图像平移 * TranslationDIB() - 图像平移 * MirrorDIB() - 图像镜像 * TransposeDIB() - 图像转置 * ZoomDIB() - 图像缩放 * RotateDIB() - 图像旋转 * *************************************************************************/#include "stdafx.h"#include "geotrans.h"#include "DIBAPI.h"#include <math.h>#include <direct.h>/************************************************************************* * * 函数名称: * TranslationDIB1() * * 参数: * LPSTR lpDIBBits - 指向源DIB图像指针 * LONG lWidth - 源图像宽度(象素数) * LONG lHeight - 源图像高度(象素数) * LONG lXOffset - X轴平移量(象素数) * LONG lYOffset - Y轴平移量(象素数) * * 返回值: * BOOL - 平移成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数用来水平移动DIB图像。函数不会改变图像的大小,移出的部分图像 * 将截去,空白部分用白色填充。 * ************************************************************************/BOOL WINAPI TranslationDIB1(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, LONG lXOffset, LONG lYOffset){ // 指向源图像的指针 LPSTR lpSrc; // 指向要复制区域的指针 LPSTR lpDst; // 指向复制图像的指针 LPSTR lpNewDIBBits; HLOCAL hNewDIBBits; // 象素在新DIB中的坐标 LONG i; LONG j; // 象素在源DIB中的坐标 LONG i0; LONG j0; // 图像每行的字节数 LONG lLineBytes; // 计算图像每行的字节数 lLineBytes = WIDTHBYTES(lWidth * 8); // 暂时分配内存,以保存新图像 hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); if (hNewDIBBits == NULL) { // 分配内存失败 return FALSE; } // 锁定内存 lpNewDIBBits = (char * )LocalLock(hNewDIBBits); // 每行 for(i = 0; i < lHeight; i++) { // 每列 for(j = 0; j < lWidth; j++) { // 指向新DIB第i行,第j个象素的指针 // 注意由于DIB中图像第一行其实保存在最后一行的位置,因此lpDst // 值不是(char *)lpNewDIBBits + lLineBytes * i + j,而是 // (char *)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j lpDst = (char *)lpNewDIBBits + lLineBytes * (lHeight - 1 - i) + j; // 计算该象素在源DIB中的坐标 i0 = i - lXOffset; j0 = j - lYOffset; // 判断是否在源图范围内 if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight)) { // 指向源DIB第i0行,第j0个象素的指针 // 同样要注意DIB上下倒置的问题 lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0; // 复制象素 *lpDst = *lpSrc; } else { // 对于源图中没有的象素,直接赋值为255 * ((unsigned char*)lpDst) = 255; } } } // 复制平移后的图像 memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight); // 释放内存 LocalUnlock(hNewDIBBits); LocalFree(hNewDIBBits); // 返回 return TRUE;}/************************************************************************* * * 函数名称: * TranslationDIB() * * 参数: * LPSTR lpDIBBits - 指向源DIB图像指针 * LONG lWidth - 源图像宽度(象素数) * LONG lHeight - 源图像高度(象素数) * LONG lXOffset - X轴平移量(象素数) * LONG lYOffset - Y轴平移量(象素数) * * 返回值: * BOOL - 平移成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数用来水平移动DIB图像。函数不会改变图像的大小,移出的部分图像 * 将截去,空白部分用白色填充。 * ************************************************************************/BOOL WINAPI TranslationDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, LONG lXOffset, LONG lYOffset){ // 平移后剩余图像在源图像中的位置(矩形区域) CRect rectSrc; // 平移后剩余图像在新图像中的位置(矩形区域) CRect rectDst; // 指向源图像的指针 LPSTR lpSrc; // 指向要复制区域的指针 LPSTR lpDst; // 指向复制图像的指针 LPSTR lpNewDIBBits; HLOCAL hNewDIBBits; // 指明图像是否全部移去可视区间 BOOL bVisible; // 循环变量 LONG i; // 图像每行的字节数 LONG lLineBytes; // 计算图像每行的字节数 lLineBytes = WIDTHBYTES(lWidth * 8); // 赋初值 bVisible = TRUE; // 计算rectSrc和rectDst的X坐标 if (lXOffset <= -lWidth) { // X轴方向全部移出可视区域 bVisible = FALSE; } else if (lXOffset <= 0) { // 移动后,有图区域左上角X坐标为0 rectDst.left = 0; // 移动后,有图区域右下角X坐标为lWidth - |lXOffset| = lWidth + lXOffset rectDst.right = lWidth + lXOffset; } else if (lXOffset < lWidth) { // 移动后,有图区域左上角X坐标为lXOffset rectDst.left = lXOffset; // 移动后,有图区域右下角X坐标为lWidth rectDst.right = lWidth; } else { // X轴方向全部移出可视区域 bVisible = FALSE; } // 平移后剩余图像在源图像中的X坐标 rectSrc.left = rectDst.left - lXOffset; rectSrc.right = rectDst.right - lXOffset; // 计算rectSrc和rectDst的Y坐标 if (lYOffset <= -lHeight) { // Y轴方向全部移出可视区域 bVisible = FALSE; } else if (lYOffset <= 0) { // 移动后,有图区域左上角Y坐标为0 rectDst.top = 0; // 移动后,有图区域右下角Y坐标为lHeight - |lYOffset| = lHeight + lYOffset rectDst.bottom = lHeight + lYOffset; } else if (lYOffset < lHeight) { // 移动后,有图区域左上角Y坐标为lYOffset rectDst.top = lYOffset; // 移动后,有图区域右下角Y坐标为lHeight rectDst.bottom = lHeight; } else { // X轴方向全部移出可视区域 bVisible = FALSE; } // 平移后剩余图像在源图像中的Y坐标 rectSrc.top = rectDst.top - lYOffset; rectSrc.bottom = rectDst.bottom - lYOffset; // 暂时分配内存,以保存新图像 hNewDIBBits = LocalAlloc(LHND, lLineBytes * lHeight); if (hNewDIBBits == NULL) { // 分配内存失败 return FALSE; } // 锁定内存 lpNewDIBBits = (char * )LocalLock(hNewDIBBits); // 初始化新分配的内存,设定初始值为255 lpDst = (char *)lpNewDIBBits; memset(lpDst, (BYTE)255, lLineBytes * lHeight); // 如果有部分图像可见 if (bVisible) { // 平移图像 for(i = 0; i < (rectSrc.bottom - rectSrc.top); i++) { // 要复制区域的起点,注意由于DIB图像内容是上下倒置的,第一行内容是保存在最后 // 一行,因此复制区域的起点不是lpDIBBits + lLineBytes * (i + rectSrc.top) + // rectSrc.left,而是 lpDIBBits + lLineBytes * (lHeight - i - rectSrc.top - 1) + // rectSrc.left。 lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - i - rectSrc.top - 1) + rectSrc.left; // 要目标区域的起点 // 同样注意上下倒置的问题。 lpDst = (char *)lpNewDIBBits + lLineBytes * (lHeight - i - rectDst.top - 1) + rectDst.left; // 拷贝每一行,宽度为rectSrc.right - rectSrc.left memcpy(lpDst, lpSrc, rectSrc.right - rectSrc.left); } } // 复制平移后的图像 memcpy(lpDIBBits, lpNewDIBBits, lLineBytes * lHeight); // 释放内存 LocalUnlock(hNewDIBBits); LocalFree(hNewDIBBits); // 返回 return TRUE;}/************************************************************************* * * 函数名称: * MirrorDIB() * * 参数: * LPSTR lpDIBBits - 指向源DIB图像指针 * LONG lWidth - 源图像宽度(象素数) * LONG lHeight - 源图像高度(象素数) * BOOL bDirection - 镜像的方向,TRUE表示水平镜像,FALSE表示垂直镜像 * * 返回值: * BOOL - 镜像成功返回TRUE,否则返回FALSE。 * * 说明: * 该函数用来镜像DIB图像。可以指定镜像的方式是水平还是垂直。 * ************************************************************************/BOOL WINAPI MirrorDIB(LPSTR lpDIBBits, LONG lWidth, LONG lHeight, BOOL bDirection){ // 指向源图像的指针 LPSTR lpSrc; // 指向要复制区域的指针 LPSTR lpDst; // 指向复制图像的指针 LPSTR lpBits; HLOCAL hBits; // 循环变量 LONG i; LONG j; // 图像每行的字节数 LONG lLineBytes; // 计算图像每行的字节数 lLineBytes = WIDTHBYTES(lWidth * 8); // 暂时分配内存,以保存一行图像 hBits = LocalAlloc(LHND, lLineBytes); if (hBits == NULL) { // 分配内存失败 return FALSE; } // 锁定内存 lpBits = (char * )LocalLock(hBits); // 判断镜像方式 if (bDirection) { // 水平镜像 // 针对图像每行进行操作 for(i = 0; i < lHeight; i++) { // 针对每行图像左半部分进行操作 for(j = 0; j < lWidth / 2; j++) { // 指向倒数第i行,第j个象素的指针 lpSrc = (char *)lpDIBBits + lLineBytes * i + j; // 指向倒数第i行,倒数第j个象素的指针 lpDst = (char *)lpDIBBits + lLineBytes * (i + 1) - j; // 备份一个象素 *lpBits = *lpDst; // 将倒数第i行,第j个象素复制到倒数第i行,倒数第j个象素 *lpDst = *lpSrc; // 将倒数第i行,倒数第j个象素复制到倒数第i行,第j个象素 *lpSrc = *lpBits; } } } else { // 垂直镜像 // 针对上半图像进行操作 for(i = 0; i < lHeight / 2; i++) { // 指向倒数第i行象素起点的指针 lpSrc = (char *)lpDIBBits + lLineBytes * i; // 指向第i行象素起点的指针 lpDst = (char *)lpDIBBits + lLineBytes * (lHeight - i - 1); // 备份一行,宽度为lWidth memcpy(lpBits, lpDst, lLineBytes); // 将倒数第i行象素复制到第i行 memcpy(lpDst, lpSrc, lLineBytes); // 将第i行象素复制到倒数第i行 memcpy(lpSrc, lpBits, lLineBytes); } } // 释放内存 LocalUnlock(hBits);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -