用GDAL将16位Tiff图像转为8位

关键代码:主要流程是先将16位的像素指针强制转成uint16_t*,方便进行指针运算,因为原始的指针是char*。

注意:指针移动的字节长度等与指针所指类型的字节长度(原来指针类型强制转换这么有用)

然后通过uint16_t获取16位像素的值,再赋值给8位像素值。

通过指针运算进行取值,不同类型的指针移动长度不一样,同时取值时根据指针类型进行取值。

if (eDT ==GDT_UInt16)
    {
        // 申请所有数据所需要的缓存,如果图像太大应该用分块处理
        char *pDataBuff =(char *) malloc(iDstWidth*iDstHeight*iBandCount*eDT);

        int res=pSrcDS->RasterIO(GF_Read, iStartX, iStartY, iDstWidth, iDstHeight, 
            pDataBuff, iDstWidth, iDstHeight, eDT, iBandCount, pBandMap, 0, 0, 0);


        //转化为8位--lj (指针操作真复杂,用会了真方便!)
        char *pDataBuff8 =(char *) malloc(iDstWidth*iDstHeight*iBandCount);
        uint16_t* pDataBuff16=(uint16_t*)pDataBuff;

        for (int w=0;w         {
            for (int h=0;h             {
                for (int b=0;b                 {
                    //此处可以增加灰度拉伸的代码,本程序只是针对在16位图像上像素值是0-255的图像
                    *(pDataBuff8+w*iDstHeight*iBandCount+h*iBandCount+b)=*(pDataBuff16+w*iDstHeight*iBandCount+h*iBandCount+b);
                }
            }
        }

     res=pDstDS->RasterIO(GF_Write, 0, 0, iDstWidth, iDstHeight, 
            pDataBuff8, iDstWidth, iDstHeight, GDT_Byte, iBandCount, pBandMap, 0, 0, 0);

        //delete[] pDataBuff;
        free( pDataBuff);
        free( pDataBuff8);
    }

 

完整代码如下:

void Image18bitTo8bit(const char* pszSrcFile, const char* pszDstFile,const char* pszFormat)
{
    //支持中文路径
    CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");
    GDALAllRegister();
    GDALDataset* pSrcDS=(GDALDataset*)GDALOpen(pszSrcFile, GA_ReadOnly);
    GDALDataType eDT = pSrcDS->GetRasterBand(1)->GetRasterDataType();

    //默认波段为3  
    int iBandCount = pSrcDS->GetRasterCount();
    if (iBandCount>=3)
        iBandCount = 3;

    // 根据裁切范围确定裁切后的图像宽高
    int iDstWidth  = pSrcDS->GetRasterXSize();
    int iDstHeight = pSrcDS->GetRasterYSize();
    int  iStartX=0, iStartY=0;

    double adfGeoTransform[6] = {0};
    pSrcDS->GetGeoTransform(adfGeoTransform);

    // 创建输出文件并设置空间参考和坐标信息
    GDALDriver* poDriver = (GDALDriver *)GDALGetDriverByName(pszFormat);
    GDALDataset *pDstDS = poDriver->Create(pszDstFile, iDstWidth, iDstHeight, iBandCount, GDT_Byte, NULL);
    pDstDS->SetGeoTransform(adfGeoTransform);  
    pDstDS->SetProjection(pSrcDS->GetProjectionRef());
    int *pBandMap = new int[iBandCount];
    for (int i=0; i         pBandMap[i] = i+1;

    if (eDT == GDT_Byte) // 如果是8bit图像
    {
        // 申请所有数据所需要的缓存,如果图像太大应该用分块处理
        //char *pDataBuff =new char[iDstWidth*iDstHeight*iBandCount];
        char *pDataBuff =(char *) malloc(iDstWidth*iDstHeight*iBandCount);

        int res=pSrcDS->RasterIO(GF_Read, iStartX, iStartY, iDstWidth, iDstHeight, 
            pDataBuff, iDstWidth, iDstHeight, eDT, iBandCount, pBandMap, 0, 0, 0);
        res=pDstDS->RasterIO(GF_Write, 0, 0, iDstWidth, iDstHeight, 
            pDataBuff, iDstWidth, iDstHeight, eDT, iBandCount, pBandMap, 0, 0, 0);

        //delete[] pDataBuff;
        free( pDataBuff);
    }
    else if (eDT ==GDT_UInt16)
    {
        // 申请所有数据所需要的缓存,如果图像太大应该用分块处理
        char *pDataBuff =(char *) malloc(iDstWidth*iDstHeight*iBandCount*eDT);

        int res=pSrcDS->RasterIO(GF_Read, iStartX, iStartY, iDstWidth, iDstHeight, 
            pDataBuff, iDstWidth, iDstHeight, eDT, iBandCount, pBandMap, 0, 0, 0);


        //转化为8位--lj (指针操作真复杂,用会了真方便!)
        char *pDataBuff8 =(char *) malloc(iDstWidth*iDstHeight*iBandCount);
        uint16_t* pDataBuff16=(uint16_t*)pDataBuff;

        for (int w=0;w         {
            for (int h=0;h             {
                for (int b=0;b                 {
                    //此处可以增加灰度拉伸的代码,本程序只是针对在16位图像上像素值是0-255的图像
                    *(pDataBuff8+w*iDstHeight*iBandCount+h*iBandCount+b)=*(pDataBuff16+w*iDstHeight*iBandCount+h*iBandCount+b);
                }
                
                
            }
        }

        res=pDstDS->RasterIO(GF_Write, 0, 0, iDstWidth, iDstHeight, 
            pDataBuff8, iDstWidth, iDstHeight, GDT_Byte, iBandCount, pBandMap, 0, 0, 0);

        //delete[] pDataBuff;
        free( pDataBuff);
        free( pDataBuff8);
    }

    delete(pBandMap);
    GDALClose((GDALDatasetH)pSrcDS);
    GDALClose((GDALDatasetH)pDstDS);
    return  ;
}

 

你可能感兴趣的:(C++)