TIFF文件合并与切割

xiongyouyi 2008-11-14 05:38:01
我用的是libtiff库,请问把一个tiff文件切割成四等份?
有一大一小两个tiff,小的放在大的中间,如何把他们合并成一个文件?
谢谢
...全文
1105 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiongyouyi 2008-11-17
  • 打赏
  • 举报
回复

//坐标搞错了,应该是这样
pSrcBand->RasterIO(GF_Read, j*width, i*height, width, height, pBlock, width, height, GDT_Byte, 0, 0);
xiongyouyi 2008-11-17
  • 打赏
  • 举报
回复

//这是我用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;
}
The_eagles 2008-11-17
  • 打赏
  • 举报
回复

第一个问题: 如果数据本身是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文件格式是一个东西。


xiongyouyi 2008-11-17
  • 打赏
  • 举报
回复
我正在看GDAL,能直接用它最好,不知道他能不能读取tfw的坐标
xiongyouyi 2008-11-17
  • 打赏
  • 举报
回复
非常感谢the_eagles的回复,我用的GeoTiff库,它可以读取tfw里的坐标,它也是调用libtiff的。
libtiff读取数据的函数是int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int);
typedef unsigned long uint32; /* sizeof (uint32) must == 4 */,

怎么转成byte呢?
xiongyouyi 2008-11-17
  • 打赏
  • 举报
回复
GDAL确实挺牛X的
The_eagles 2008-11-17
  • 打赏
  • 举报
回复


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);// 这里不能是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);
}



xiongyouyi 2008-11-15
  • 打赏
  • 举报
回复
1. 切割,把一大tiff按网格切割成多个小块。
2. 合并,有两个tiff文件,小的叠加在大的上面,把大图的叠加部分替换成小图。
The_eagles 2008-11-15
  • 打赏
  • 举报
回复
6楼9楼说的我好惭愧啊~
这个可是图像处理里面最基本的东西哦。
sept80 2008-11-15
  • 打赏
  • 举报
回复
3楼牛人
dadalan 2008-11-15
  • 打赏
  • 举报
回复
记住每个文件包的偏移量
dadalan 2008-11-15
  • 打赏
  • 举报
回复
记住每个文件包的偏移量
leer168 2008-11-15
  • 打赏
  • 举报
回复
3楼的牛人太牛了
fjwyshan 2008-11-15
  • 打赏
  • 举报
回复
oo
android2008 2008-11-15
  • 打赏
  • 举报
回复
oo
The_eagles 2008-11-15
  • 打赏
  • 举报
回复

// 先假设你不管通过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 ];
}
}
}

}



The_eagles 2008-11-14
  • 打赏
  • 举报
回复

问题没有描述清楚~说详细点吧。

19,464

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧