我用的是libtiff库,请问把一个tiff文件切割成四等份?
有一大一小两个tiff,小的放在大的中间,如何把他们合并成一个文件?
谢谢

解决方案 »

  1.   

    1. 切割,把一大tiff按网格切割成多个小块。
    2. 合并,有两个tiff文件,小的叠加在大的上面,把大图的叠加部分替换成小图。
      

  2.   


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

  3.   

    非常感谢the_eagles的回复,我用的GeoTiff库,它可以读取tfw里的坐标,它也是调用libtiff的。
    libtiff读取数据的函数是int TIFFReadRGBAImage(TIFF*, uint32, uint32, uint32*, int);
    typedef unsigned long uint32; /* sizeof (uint32) must == 4 */,怎么转成byte呢?
      

  4.   

    我正在看GDAL,能直接用它最好,不知道他能不能读取tfw的坐标
      

  5.   


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

  6.   


    //这是我用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;
    }
      

  7.   


    //坐标搞错了,应该是这样
    pSrcBand->RasterIO(GF_Read, j*width, i*height, width, height, pBlock, width, height, GDT_Byte, 0, 0);
      

  8.   

                 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);
                    }