我用的是libtiff库,请问把一个tiff文件切割成四等份?
有一大一小两个tiff,小的放在大的中间,如何把他们合并成一个文件?
谢谢
有一大一小两个tiff,小的放在大的中间,如何把他们合并成一个文件?
谢谢
解决方案 »
- 定义控件变量的奇怪问题
- 利用VC++实现AVI文件分解时出现问题了,请高手帮忙
- 所有键对应该的VK 码
- 请教下在处理WM_TIMER消息还没有结束时会不会有下一个TIMER消息到来?
- 怎样处理WM_CLOSE消息?
- 求助:OnInitstance() 函数是在哪个文件下啊?我怎么找不到啊?谢谢!
- 如何用mci或者waveX函数混音播放2个wave或者midi
- 哪里能找到介绍刻录系统的资料?
- 请教:请问在程序中怎么在Check box 前边的小框上打上对号
- 如何象IE那样,在忙的时候把Mouse指针改成箭头+沙漏,(注意:不是一个大沙漏)
- 在线急等解答。tcp postmessage failur 失败
- propertypage 问题
2. 合并,有两个tiff文件,小的叠加在大的上面,把大图的叠加部分替换成小图。
// 先假设你不管通过libtiff的哪个函数把数据读到pSrc里面了。并且是8位的。
// 接着你就可以通过下面的函数切割图像。 我对libtiff不熟悉,一直在用GDAL
// 一个很牛逼的库。google earth就是用它写的。虽然也通过读取一个区域的
// 函数。RasterIO(pszFilename,regionbeginX, reguionbeginY, regionendX, regionendY, byte*
// Buf,nBufX,nBufY,.... )
// 但是效率都不如自己写的高。建议你还是先读数据出来。在切割,不要通过库提供的函数。
// 下面是切割的程序,如果行的话。再给你提供合并的程序。
int CutImage(byte *pSrc, int width, int height,int nX, int nY )
{
// 注意如果原图的width*height != 原图数据的bytes
// 那么就说明每行有补零,补到4字节整数宽度
int residual = (width%4)%4;
int num = nY * nX; // nY*nX 是要切割的子图像数目。
int subDim= width/nX; // 边角料的宽度
CSize *pSubSize = new CSize[num]; // 存子图的数据 CSize是一个结构体 2个元素 cx 和cy
// CRect *pSubrt = new CRect[num]; // 存子图的尺寸
// 计算每个子图像的长和宽
for ( int i=0; i<nY; i++)
{
for ( int j=0; j<nX; j++)
{
if (i == nY )// 边角料的宽度可能 != subDim
{
pSubSize[i*nX+j].cy = height - subDim * (nY-1);
}
else
{
pSubSize[i*nX+j].cy = subDim;
}
if (j == nX )
{
pSubSize[i*nX+j].cx = width - subDim*(nX-1);
}
else
{
pSubSize[i*nX+j].cx = subDim;
}
}
}
// 存子图像数据的数组
BYTE **pSub = new BYTE * [num];
for (int s=0; s<num; s++)
{
pSub[s] = new BYTE[pSubSize[s].cx * pSubSize[s].cy ] ;
}
// 切割原图,存到各个子图像数组中去。
int nrow=0;
int ncol=0;
for (int k=0; k<num; k++)
{
nrow = ( k/nX ) * subDim;
ncol = ( k%nY ) * subDim;
for ( i=0; i< pSubSize[k].cy; i++ )
{
for (int j=0; j<pSubSize[k].cx; j++ )
{
pSub[k][i* (pSubSize[k].cx) +j] =
pSrc[(nrow +i) *(width+residual) + ncol +j ];
}
}
}}
libtiff读取数据的函数是int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int);
typedef unsigned long uint32; /* sizeof (uint32) must == 4 */,怎么转成byte呢?
第一个问题: 如果数据本身是8位的而你用32位的读取函数读的,就直接转为8位,移位就可以了。
不会丢失数据。如果本身就是32位的,转8位肯定是要丢失数据的,除非32位数据的高24位都是0.
或者数据的值本身就较大,大到低24位可以忽略不计,这样只取高8位。在GDAL里面,读取数据
的函数是RasterIO,在形参里指定buffer数据类型,可以是byte,也可以是int32等等,
如果用8位的buffer存放8位以上的数据,那么大于255的值都会截断为255.第二个问题: 请看GDAL数据模型手册里的一句话:
GDAL datasets have two ways of describing the relationship between raster positions (in pixel/line coordinates) and georeferenced coordinates. The first, and most commonly used is the affine transform (the other is GCPs).栅格坐标到地理坐标之间的转换可以通过两种方式来进行:一种是仿射坐标转换,一种是GCPs。
Affine Transform:
1 Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
2 Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
GCPs:
1 adfGeoTransform[0] /* top left x */
2 adfGeoTransform[1] /* w-e pixel resolution */
3 adfGeoTransform[2] /* rotation, 0 if image is "north up" */
4 adfGeoTransform[3] /* top left y */
5 adfGeoTransform[4] /* rotation, 0 if image is "north up" */
6 adfGeoTransform[5] /* n-s pixel resolution */
和ESRI为GeoTiff定义的tfw文件格式是一个东西。
//这是我用GDAL写的拆分tiff函数,运行后(2行 x 1列)有错误,size设的不对,tif大小为
//2470 x 1933 x 3
//提示: ERROR 5: Access window out of range in RasterIO(). Requested
//(2470,0) of size 2470x966 on range of 2470x1933
//请帮我看下哪不对?谢谢
void SplitTiff(char * fname, int row, int col, char * outfolder)
{
//Open file
GDALDataset * pSrcDS = NULL;
GDALDriver *pDriver = NULL;
pDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
if(!pDriver)
return; pSrcDS = (GDALDataset*)GDALOpen(fname, GA_ReadOnly);
if(!pSrcDS)
return; int XSize,YSize;
XSize = pSrcDS->GetRasterXSize();
YSize = pSrcDS->GetRasterYSize();
if((XSize<=0) || (YSize<=0))
{
delete pSrcDS;
return;
} int i,j;
int width,height;
char destname[256];
GDALDataset * pDestDS;
char **papszOptions = NULL;
GDALRasterBand *pSrcBand,*pDestBand;
width = (int)(XSize/col);
height = (int)(YSize/row);
for (i=0; i<row; ++i)
{
for (j=0; j<col; ++j)
{
//Create file
sprintf(destname, "%s\\%d%d.tif", outfolder, i, j);
pDestDS = pDriver->Create(destname, width, height, 3, GDT_Byte, papszOptions);
if (pDestDS)
{
byte * pBlock = (byte*) CPLMalloc(width*height*sizeof(byte));
for (int band=0; band<3; band++)
{
//Read data
pSrcBand = pSrcDS->GetRasterBand(band+1);
pSrcBand->RasterIO(GF_Read, i*width, j*height, width, height, pBlock, width, height, GDT_Byte, 0, 0);
//Write data
pDestBand = pDestDS->GetRasterBand(band+1);
pDestBand->RasterIO(GF_Write, 0, 0, width, height, pBlock, width, height, GDT_Byte, 0, 0);
} CPLFree(pBlock);
delete pDestDS;
}
}
} //Close
delete pSrcBand;
}
//坐标搞错了,应该是这样
pSrcBand->RasterIO(GF_Read, j*width, i*height, width, height, pBlock, width, height, GDT_Byte, 0, 0);
{
//Read data
pSrcBand = pSrcDS->GetRasterBand(band+1);
pSrcBand->RasterIO(GF_Read, i*width, j*height, width, height, pBlock, width, height, GDT_Byte, 0, 0);// 这里不能是i*weidth 而是0 .你不是切成2行一列吗?
//Write data
pDestBand = pDestDS->GetRasterBand(band+1);
pDestBand->RasterIO(GF_Write, 0, 0, width, height, pBlock, width, height, GDT_Byte, 0, 0);
}