使用gdal对图像重采样再按指定格式输出

本文介绍了一种使用GDAL库实现图像重采样的方法,包括如何读取图像、进行重采样处理,并最终输出为指定格式的图像文件。
/*使用gdal将图像进行重采样,然后按照指定的格式输出
 * 运行此程序需要安装gdal,目前知道可以处理.tif、.img。生成.jpeg图像
 * 生成.so命令:g++ -fpic -shared -o libxxx.so main.cpp -lgdal
 * main.cpp
 *
 *  Created on: 2013-1-15
 *      Author: he_fa
 */
#include "gdal_priv.h"
#include "cpl_conv.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**
 *将Dataset转换成图像
 *@param    szPath        目标文件
 *@param    poDataset    源Dataset
 *@param    pszFormat    目标文件的格式,必须得和目标文件的后缀名一样
 *@return    1:成功        0:失败
 */
int MEM_to_File(const char *szPath, GDALDataset *poDataset, char *pszFormat = "JPEG")
{
    if(NULL == szPath)
    {
        printf("输出路径不能为空!\n");
        return 0;
    }
    GDALAllRegister();
    CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");   //设置支持中文路径
    GDALDriver *pJPGDriver;
    pJPGDriver = GetGDALDriverManager()->GetDriverByName("JPEG");
    if(NULL == pJPGDriver)
    {
        printf("不能创建指定类型的文件,请检查该文件类型GDAL是否支持创建 \n");
        return 0;
    }
    GDALDataset *pJPGDataset;
    pJPGDataset = pJPGDriver->CreateCopy(szPath, poDataset, FALSE, NULL, NULL, NULL);
    GDALClose((GDALDatasetH)pJPGDataset);
    return 1;
}
/**
 * 将图像转换成指定大小的MEM的Dataset,
 * @param    file_path    图像的路径
 * @param    MEM_Xsize    MEM图像的宽
 * @param    MEM_Ysize    MEM图像的高
 * @parma    pDataset    用于保存结果
 * @return    1:成功        0:失败
 */
int file_to_MEM(const char *file_path, int MEM_Xsize, int MEM_Ysize, GDALDataset **pDataset)
{
    GDALAllRegister();
    CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");   //设置支持中文路径
    GDALDataset *poDataset= (GDALDataset *)GDALOpen(file_path, GA_ReadOnly);
    if(NULL == poDataset)
    {
        printf("图像打开失败,路径可能有误!\n");
        return 0;
    }

    //获取输入图像的基本信息
    int band_count = poDataset->GetRasterCount();
    int nXSize = poDataset->GetRasterXSize();
    int nYSize = poDataset->GetRasterYSize();

    //获取MEM的驱动和数据集
    GDALDriver *pMEMDriver = GetGDALDriverManager()->GetDriverByName("MEM");
    if(NULL == pMEMDriver)
    {
        printf("MEMDriver创建失败!\n");
        GDALClose((GDALDatasetH)poDataset);
        return 0;
    }

    //gdal无法处理GDT_Float32,只能处理8位或12位,所以写成GDT_Byte
    GDALDataset *MEMDataset = pMEMDriver->Create("", MEM_Xsize, MEM_Ysize, band_count, GDT_Byte, NULL);
    if(NULL == MEMDataset)
    {
        printf("MEM的Dataset创建失败!\n");
        return 0;
    }

    //两个辅助数组,用于读取File的数据和写入MEM的Dataset的数据
    float *pafScanline = (float *)CPLMalloc(sizeof(float *) * MEM_Xsize);
    unsigned char *array = (unsigned char*)CPLMalloc(sizeof(unsigned char*) * MEM_Xsize);
    if(NULL == pafScanline || NULL == array)
    {
        printf("辅助数组内存分配失败!\n");
        return 0;
    }

    //用于重采样,控制读取原图像的哪一行
    float Ysteps = 1.0f * nYSize / MEM_Ysize;

    int i_count;
    for(i_count = 1; i_count <= band_count; ++ i_count)
    {
        GDALRasterBand *psrcBand = poDataset->GetRasterBand(i_count);
        GDALRasterBand *pdstBand = MEMDataset->GetRasterBand(i_count);

        //用于获取图像像素的最值
        float max = -999999, min = 999999;

        float file_line;
        int MEM_line;    //用于控制将数组的值写入MEM的Dataset
        for(file_line = 0, MEM_line = 0;
                file_line < nYSize && MEM_line < MEM_Ysize;
                file_line += Ysteps, ++ MEM_line)
        {
            psrcBand->RasterIO(GF_Read, 0, (int)file_line, nXSize, 1,
                    pafScanline, MEM_Xsize, 1, GDT_Float32, 0, 0);

            //对采样得到的数组求最值
            int i;
            for(i = 0; i < MEM_Xsize; ++ i)
            {
                max = max > pafScanline[i] ? max : pafScanline[i];
                min = min < pafScanline[i] ? min : pafScanline[i];
            }

            //将float数组中的数值转换成unsigned char, 将图像的像素值进行拉伸成0~255
            for(i = 0; i < MEM_Xsize; ++ i)
            {
                array[i] = (unsigned char)((pafScanline[i] - min) * 255 / (max - min + 1));
            }

            //将数组中的数据写入MEM的Dataset
            pdstBand->RasterIO(GF_Write, 0, MEM_line, MEM_Xsize, 1,
                    array, MEM_Xsize, 1, GDT_Byte, 0, 0);
        }

    }
    *pDataset = MEMDataset;    //MEMDataset不能关闭
    GDALClose((GDALDatasetH)poDataset);
    free(pafScanline);
    free(array);
    return 1;
}

int main(void)
{
    GDALAllRegister();
    CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");   //设置支持中文路径
    GDALDataset *pDataset;
    if(0 == file_to_MEM("/home/he_fa/project/test.img", 1000, 1000, &pDataset) )
    {
        return 0;
    }
    if(0 == MEM_to_File("/home/he_fa/project/result.jpg", pDataset, "jpg") )
    {
        return 0;
    }
    GDALClose((GDALDatasetH)pDataset);
    return 1;
}
//extern "C" int run(char *inpath, char *outpath)
//{
//    GDALAllRegister();
//    CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");   //设置支持中文路径
//    GDALDataset *pDataset;
//    if(0 == file_to_MEM(inpath, 1000, 1000, &pDataset))
//    {
//        return 0;
//    }
//    if(0 == MEM_to_File(outpath, pDataset, "jpg"))
//    {
//        return 0;
//    }
//    GDALClose((GDALDatasetH)pDataset);
//    return 1;
//}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值