TIFF添加坐标信息

  处理tiff图片过程中,需要给TIFF图片加上相应的坐标信息,来表示当前图片的坐标范围。下面就给出如何在一张空白的TIFF图片中添加坐标信息。
1.头文件

#pragma once
#include"tiflib.h"
#include<string>
#include <vector>
#include <algorithm>  
using namespace std;

#define TIFF_HEADER_SIZE 8    //文件头字节数
#define DE_START 10           //tiff TAG开始的位置
#define ONE_DE_SIZE 12        //每个TAG的大小
#define IDF_END_FLAG_SIZE 4   //IFD最后结尾的4个空字节
typedef struct
{
    int i_tag;
    const char* text;
}TagText;

typedef struct
{
    TIFF_UINT16_T type;
    char* type_name;
    TIFF_UINT16_T type_size;
}DataType;

typedef struct
{
    TIFF_UINT16_T tag;
    TIFF_UINT16_T type;
    TIFF_UINT32_T count;
    TIFF_UINT32_T offset;
}DirectoryEntry;

typedef struct
{
    DirectoryEntry de;
    int data_source; //0 - offset本身值 1 - offset对应的源文件偏移量 2 - 来自内存
    TIFF_UINT8_T* mem_data; //当 data_soure = 2 时 ,指向内存
}deInfo;

class tiffTrans
{
public:
    tiffTrans();
    tiffTrans( const char* tiff_path );
    ~tiffTrans();

public:
    int open( const char* tiff_path );
    void coord_box( geoRECT geo_rect );
    int save_to_trans( const char* new_path = NULL );
protected:
    int arrangement();//0 - tile  1 - line
    bool analysis( char* ret_error );  //分析tiff是否可以进行转换 true - 可以 false - 不可以  
private:
    string new_tiff_name();
    void write_file_header();

    TIFF_UINT64_T double_to_long( double d_ );
    void cs_pixel_scale( double cx , double cy );
    void cs_tie_point( double x , double y );
    void cs_coord( deInfo* coord_list );

    int get_src_tag_list();
    const char* tag_text( int i_tag );
    deInfo* cts_strip_offsets();  
    deInfo* cts_rows_per_strip();
    deInfo* cts_strip_byte_counts();

    deInfo* cts_line_tag();

    deInfo* delete_coord_tag();

    int cts_new_tag_list();

    void print_tag_info_list();
    void write_tag_list();
    void modify_strip_offset();
    void modify_line_strip();
    void modify_tile_strip();

    void sort_byte_order( TIFF_UINT8_T* buf , TIFF_UINT16_T data_type , TIFF_UINT16_T data_count );
    TIFF_UINT64_T file_disk_data( DirectoryEntry de , TIFF_UINT64_T buffer_size );

    void write_img_data();
    void write_img_data2();
    void write_line_img();
    void write_tile_img();

    void write_data( TIFF_UINT32_T data_start , TIFF_UINT32_T data_size );

private:
    FILE* _tile_tiff;
    FILE* _line_tiff;

    TiffFile* _tiff_src;
    string _src_name;
    TIFF_UINT64_T _current_file_point; //写入当前文件操作的指针

    deInfo* de_list;
    TIFF_UINT16_T _de_num;             //标签的数量
    int _coord_tag_num; //包含坐标信息的TAG的数量


    TIFF_UINT32_T _strip_offset_pos;   //TAG StripOffset or TileOffset 的文件偏移位置
    TIFF_UINT32_T _count_one_offset_pos;

    TIFF_UINT64_T pixel_scale[3];//像元比例
    TIFF_UINT64_T tie_point[6];//控制点坐标对

    geoRECT _geo_rect;
};

2.cpp文件

#include "tifftrans.h"

TagText tag_text_list[] =
{
    { 254 , "NewSubfileType" },
    { 256 , "ImageWidth" },
    { 257 , "ImageLength" },
    { 258 , "BitsPerSample" },
    { 259 , "Compression" },
    { 262 , "PhotometricInterpretation" },
    { 273 , "StripOffsets" },
    { 274 , "相对于图像的行和列的方向" },
    { 277 , "SamplesPerPixel" },
    { 278 , "RowsPerStrip" },
    { 279 , "StripByteCounts" },
    { 282 , "XResolution" },
    { 283 , "YResolution" },
    { 284 , "PlanarConfiguration" },
    { 296 , "ResolutionUnit" },
    { 305 , "Software" },
    { 306 , "DateTime" },
    { 322 , "TileWidth" },
    { 323 , "TileLength" },
    { 324 , "TileOffsets" },
    { 325 , "TileByteCounts" },
    { 339 , "SampleFormat" },
    { 33550 , "ModelPixelScaleTag" },
    { 33922 , "ModelTiepointTag" },
    { 34264 , "ModelTransformationTag" },
    { 34735 , "GeoKeyDirectoryTag" },
    { 34736 , "GeoDoubleParamsTag" },
    { 34737 , "GeoAsciiParamsTag" },
    { -1 , "" }
};

DataType data_type_list[] =
{
    { 0  , "NULL"     , 0 },//NULL
    { 1  , "BYTE"     , 1 },//BYTE 8-bit unsigned integer
    { 2  , "ASCII"    , 1 },//ASCII 8-bit byte that contains a 7-bit ASCII code; the last byte must be NUL (binary zero)
    { 3  , "SHORT"    , 2 },//SHORT 16-bit (2-byte) unsigned integer
    { 4  , "LONG"     , 4 },//LONG 32-bit (4-byte) unsigned integer
    { 5  , "RATIONAL" , 8 },//RATIONAL Two LONGs: the first represents the numerator
    { 6  , "SBYTE"    , 1 },//SBYTE An 8-bit signed (twos-complement) integer.
    { 7  , "UNDEFINED", 1 },//UNDEFINED An 8-bit byte that may contain anything, depending on the definition of the field.
    { 8  , "SSHORT"   , 2 },//SSHORT A 16-bit (2-byte) signed (twos-complement) integer
    { 9  , "SLONG"    , 4 },//SLONG A 32-bit (4-byte) signed (twos-complement) integer
    { 10 , "SRATIONAL", 8 },//SRATIONAL Two SLONG’s: the first represents the numerator of afraction, the second the denominator
    { 11 , "FLOAT"    , 4 },//FLOAT Single precision (4-byte) IEEE format
    { 12 , "DOUBLE"   , 8 } //DOUBLE Double precision (8-byte) IEEE format.

};

tiffTrans::tiffTrans()
{
    _tiff_src = new TiffFile;
    memset( _tiff_src , 0 , sizeof(TiffFile) );
    _coord_tag_num = 0 ;
}

tiffTrans::tiffTrans( const char* tiff_path )
{
    _src_name = tiff_path;
    _tiff_src = new TiffFile;
    memset( _tiff_src , 0 , sizeof(TiffFile) );
    _coord_tag_num = 0 ;
}

tiffTrans::~tiffTrans()
{
    if ( _tiff_src != NULL )
    {
        delete _tiff_src;
        _tiff_src = NULL;
    }
}

int tiffTrans::open( const char* tiff_path )
{
    _src_name = tiff_path;
    int ret = tif_open( tiff_path , _tiff_src );
    _tile_tiff = _tiff_src->pfile;

    return  ret;
}

void tiffTrans::coord_box( geoRECT geo_rect )
{
    _geo_rect = geo_rect;

    double scaleX = ( _geo_rect.right - _geo_rect.left ) / _tiff_src->tif_width;
    double scaleY = ( _geo_rect.top - _geo_rect.botton  ) / _tiff_src->tif_height;

    cs_pixel_scale( scaleX , scaleY );
    cs_tie_point( _geo_rect.left , _geo_rect.top );
}

int tiffTrans::arrangement()
{
    if( _tiff_src->tile.is_tile == true )
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

const char* tiffTrans::tag_text( int i_tag )
{
    int i = 0 ;
    while ( tag_text_list[i].i_tag != -1 )
    {
        if ( tag_text_list[i].i_tag == i_tag )
        {
            return tag_text_list[i].text;
        }
        i++;
    }

    return "";
}

void tiffTrans::write_file_header( )
{
    //字节序   
    fwrite( "II" , 2 , 1 , _line_tiff );

    //版本号
    TIFF_UINT16_T ver = 0x002a;
    fwrite( &ver , 2 , 1 , _line_tiff );

    //Tag偏移量
    TIFF_UINT32_T offset = 0x00000008;
    fwrite( &offset , 4 , 1 , _line_tiff );
}

bool tiffTrans::analysis( char* ret_error )
{
    bool b = true;
    if ( _tiff_src->bit_per_samples == 1 )
    {
        strcpy( ret_error , "错误:这是一张1位图片" );
        b = false;
    }
    else if ( _tiff_src->bit_per_samples == 4 )
    {
        strcpy( ret_error , "错误:这是一张4位图片" );
        b = false;
    }
    else if ( _tiff_src->bit_per_samples == 8 )
    {
        strcpy( ret_error , "错误:这是一张8位图片" );
        b = false;
    }

    if ( _tiff_src->compression != 1 )
    {
        strcpy( ret_error , "错误:这是一张经过压缩的图片" );
        b = false;
    }

    if( _tiff_src->planar_config != 1 )
    {
        strcpy( ret_error , "错误:Planar Config 为 Sperate ,暂时无法处理" );
        b = false;
    }

    if ( _tiff_src->tile.is_tile == false )
    {
        strcpy( ret_error , "错误:TIFF按线性方式排列数据" );
        b = false;
    }
    return b;
}

string tiffTrans::new_tiff_name()
{
    int pos = _src_name.rfind( '\\' );
    string tiff_name = _src_name.substr( pos + 1 );
    string dir = _src_name.substr( 0 , pos + 1 );
    string temp_name = "line_";
    temp_name += tiff_name ;
    return ( dir + temp_name ) ;
}

int tiffTrans::get_src_tag_list()
{
    TIFF_UINT32_T ifd_offset;      //第一个IFD的偏移量
    fseek( _tile_tiff , 0 , SEEK_SET );
    fseek( _tile_tiff ,4 ,SEEK_SET );
    ifd_offset = get4( _tile_tiff , _tiff_src->tiff_byte_order ) ;

    //定位到IFD的位置
    fseek( _tile_tiff , ifd_offset , SEEK_SET );
    //得到IFD的数量
    _de_num = get2( _tile_tiff , _tiff_src->tiff_byte_order );

    de_list = new deInfo[ _de_num ];
    memset( de_list , 0 , _de_num * sizeof( deInfo ) );

    //循环得到DE
    for ( TIFF_UINT16_T i = 0x0000 ; i < _de_num ; i++ )
    {
        fseek( _tile_tiff , ifd_offset + ONE_DE_SIZE * i + 2 , SEEK_SET );//文件指针复原指向

        de_list[i].de.tag = get2( _tile_tiff , _tiff_src->tiff_byte_order );
        de_list[i].de.type = get2( _tile_tiff , _tiff_src->tiff_byte_order );
        de_list[i].de.count = get4( _tile_tiff , _tiff_src->tiff_byte_order );

        //如果是大端字节序并且是short类型,则只会读取四个字节中的前两个字节
        if ( de_list[i].de.type == 3 && _tiff_src->tiff_byte_order == 0x4d4d/*Motor*/ && de_list[i].de.count == 1 )
        {
            de_list[i].de.offset = (TIFF_UINT32_T)get2( _tile_tiff , _tiff_src->tiff_byte_order );
        }
        else
        {
            de_list[i].de.offset = get4( _tile_tiff , _tiff_src->tiff_byte_order );
        }

        //如果是 SHORT 或者 LONG 并且数量为1,则直接存储在Offset中,并不存储地址
        if( ( de_list[i].de.type == 3 || de_list[i].de.type == 4 ) && de_list[i].de.count == 1 )
        {
            de_list[i].data_source = 0 ;
        }
        else
        {
            de_list[i].data_source = 1 ;
        }

        if ( de_list[i].de.tag == 33550 
            || de_list[i].de.tag == 33922
            || de_list[i].de.tag == 34735
            || de_list[i].de.tag == 34736
            || de_list[i].de.tag == 34737)//关于坐标的TAG
        {
            _coord_tag_num ++ ;
        }

    }

    print_tag_info_list();
    return _de_num ;
}

deInfo* tiffTrans::cts_strip_offsets()
{
    deInfo* temp_de = new deInfo;
    temp_de->de.tag = 273;
    temp_de->de.type = 4;//long
    temp_de->de.count = _tiff_src->tif_height;
    temp_de->de.offset = 0;
    temp_de->data_source = 2;
    TIFF_UINT32_T* mem = new TIFF_UINT32_T[_tiff_src->tif_height];
    memset( mem , 0 , sizeof(TIFF_UINT32_T)*_tiff_src->tif_height );
    temp_de->mem_data = (TIFF_UINT8_T*)mem;
    return temp_de;
}

deInfo* tiffTrans::cts_rows_per_strip()
{
    deInfo* temp_de = new deInfo;
    temp_de->de.tag = 278;
    temp_de->de.type = 3;//short
    temp_de->de.count = 1;
    temp_de->de.offset = 1;
    temp_de->data_source = 0;
    temp_de->mem_data = NULL;
    return temp_de;
}

deInfo* tiffTrans::cts_strip_byte_counts()
{
    deInfo* temp_de = new deInfo;
    temp_de->de.tag = 279;
    temp_de->de.type = 4;//short
    temp_de->de.count = _tiff_src->tif_height;
    temp_de->de.offset = 0;
    temp_de->data_source = 2;
    TIFF_UINT32_T* mem = new TIFF_UINT32_T[_tiff_src->tif_height];
    memset( mem , 0 , sizeof(TIFF_UINT32_T)*_tiff_src->tif_height );
    for ( int i = 0 ; i < _tiff_src->tif_height ; i++ )
    {
        mem[i] = _tiff_src->tif_width * _tiff_src->samples_per_pixel;
    }
    temp_de->mem_data = (TIFF_UINT8_T*)mem;
    return temp_de;
}

deInfo* tiffTrans::cts_line_tag()
{
    deInfo* temp_line_tag_list = new deInfo[3];
    memset( temp_line_tag_list , 0 , sizeof(deInfo) * 3 );
    deInfo* temp = cts_strip_offsets();
    memcpy( temp_line_tag_list , temp , sizeof(deInfo) ) ;
    delete temp;
    temp = cts_rows_per_strip();
    memcpy( temp_line_tag_list + 1 , temp , sizeof(deInfo));
    delete temp;
    temp = cts_strip_byte_counts();
    memcpy( temp_line_tag_list + 2 , temp , sizeof(deInfo));
    delete temp;
    temp = NULL;
    return temp_line_tag_list;
}

deInfo* tiffTrans::delete_coord_tag()
{
    deInfo* temp_de_list = new deInfo[ _de_num - _coord_tag_num ];//删除坐标TAG
    memset( temp_de_list , 0 , sizeof(deInfo)*( _de_num - _coord_tag_num ) );

    int j = 0;
    for ( int i = 0 ; i < _de_num ; i ++ )
    {
        if ( ( de_list[i].de.tag != 33550 )&& 
            ( de_list[i].de.tag != 33922 )&& 
            ( de_list[i].de.tag != 34735 )&& 
            ( de_list[i].de.tag != 34736 )&&
            ( de_list[i].de.tag != 34737 )
            )
        {
            memcpy ( temp_de_list + j , de_list + i , sizeof(deInfo) );
            j++;
        }
    }

    delete[] de_list;
    de_list = NULL;
    de_list = temp_de_list;
    _de_num -= _coord_tag_num ;
    return de_list;
}

int tiffTrans::cts_new_tag_list( )
{
    delete_coord_tag( );//删除所有的关于坐标的TAG
    deInfo* temp_line = new deInfo[2];
    memset( temp_line , 0 ,  2 * sizeof( deInfo ) );
    cs_coord( temp_line );

    deInfo* temp_de_list = new deInfo[ _de_num + 2 ];//tile 4个标签 line 只需要3个标签
    memset( temp_de_list , 0 , sizeof(deInfo)*( _de_num + 2 ) );

    int j = 0 , k = 0 ;
    for ( int i = 0 ; i < _de_num ; i++ )
    {
        if ( k < 2 )//只有二个标签
        {
            if ( de_list[i].de.tag < temp_line[k].de.tag )
            {
                memcpy( temp_de_list + j , de_list + i , sizeof( deInfo ) );
                j++;
            }
            else
            {
                memcpy( temp_de_list + j , temp_line + k , sizeof( deInfo ) );
                j++;
                k++;
                i--;
            }
        }
        else
        {
            memcpy( temp_de_list + j , de_list + i , sizeof( deInfo ) );
            j++;
        }
    }

    if ( k < 2 )
    {
        int temp = k;
        for ( int i = temp ; i < 2 ; i++ )
        {
            temp_de_list[ j ] = temp_line[ k ];
            j ++;
            k ++;
        }
    }

    delete[] de_list;
    de_list = NULL;
    de_list = temp_de_list;
    _de_num += 2;

    print_tag_info_list();
    return 0;
}

void tiffTrans::print_tag_info_list()
{
    printf( "\n" );
    for ( int i = 0 ; i < _de_num ; i++ )
    {
        char outStr[1024];
        memset( outStr , 0 , 1024 * sizeof( char ) );
        sprintf( outStr , "0x%04x[ %5d %-26s ] , 0x%02x , 0x%04x( %5d ) , 0x%08x , %d \n" 
            , de_list[i].de.tag 
            , de_list[i].de.tag
            , tag_text( de_list[i].de.tag )
            , de_list[i].de.type 
            , de_list[i].de.count
            , de_list[i].de.count
            , de_list[i].de.offset 
            , de_list[i].data_source ) ;
        printf( outStr );
    }
}

void tiffTrans::write_tag_list()
{
    _strip_offset_pos = 0;
    _count_one_offset_pos = 0;
    for ( int i = 0 ; i < _de_num ; i++ )
    {
        fseek( _line_tiff , DE_START + ONE_DE_SIZE * i , SEEK_SET );
        fwrite( &( de_list[i].de.tag ) , 2 , 1 , _line_tiff );   //TAG 2字节
        fwrite( &( de_list[i].de.type ) , 2 , 1 , _line_tiff );  //数据类型 2字节
        fwrite( &( de_list[i].de.count ) , 4 , 1 , _line_tiff ); //count 4字节    

        if( ( de_list[i].de.tag == 273 || de_list[i].de.tag == 324 ) && de_list[i].de.count > 1 )//Strip offset or TileOffset
        {
            fseek( _line_tiff , 0 , SEEK_END );
            _strip_offset_pos = ftell( _line_tiff );
        }
        else if(  de_list[i].de.tag == 273 && de_list[i].de.count == 1 )//Strip offset or TileOffset值保存在OFFSET中
        {
            fseek( _line_tiff , DE_START + ONE_DE_SIZE * i + 8 , SEEK_SET );
            _count_one_offset_pos = ftell( _line_tiff );
            fseek( _line_tiff , 0 , SEEK_END );
        }

        //写入offset
        if( de_list[i].data_source == 0 )//直接写入值
        {
            fwrite( &( de_list[i].de.offset ) , 4 , 1 , _line_tiff );
        }
        else if ( de_list[i].data_source == 1 )//文件对应的偏移量
        {
            fseek( _line_tiff , 0 , SEEK_END );

            TIFF_UINT32_T pos = ftell( _line_tiff );

            TIFF_UINT64_T buffer_size = data_type_list[de_list[i].de.type].type_size * de_list[i].de.count;
            file_disk_data( de_list[i].de , buffer_size );

            //修改TAG对应的数据存放的地址
            fseek( _line_tiff , DE_START + ONE_DE_SIZE * i + 8 , SEEK_SET );
            fwrite( &pos , 1 , 4 , _line_tiff );
        }
        else if ( de_list[i].data_source == 2 )//内存
        {
            fseek( _line_tiff , 0 , SEEK_END );
            TIFF_UINT32_T pos = ftell( _line_tiff );
            fwrite ( de_list[i].mem_data , 1 ,  data_type_list[de_list[i].de.type].type_size * de_list[i].de.count  , _line_tiff );

            //修改TAG对应的数据存放的地址
            fseek( _line_tiff , DE_START + ONE_DE_SIZE * i + 8 , SEEK_SET );
            fwrite( &pos , 1 , 4 , _line_tiff );

            if ( !( ( de_list[i].de.tag == 33550 ) || ( de_list[i].de.tag == 33922 ) ) )
            {
                delete[] de_list[i].mem_data;
            }

        }
    }
}

TIFF_UINT64_T tiffTrans::file_disk_data( DirectoryEntry de , TIFF_UINT64_T buffer_size )
{
    fseek( _tile_tiff , de.offset , SEEK_SET );

    TIFF_UINT8_T* buf = new TIFF_UINT8_T[1024];
    memset( buf , 0 , 1024 );

    TIFF_UINT64_T fs = 0;
    TIFF_UINT16_T read_size = 0;
    if ( buffer_size <= 1024 )//若小于1024字节,则读取之后直接写入即可
    {
        read_size = fread( buf , 1 , buffer_size , _tile_tiff );

        if( _tiff_src->tiff_byte_order == TIFF_BIGENDIAN && data_type_list[de.type].type_size != 1 )
        {
            sort_byte_order( buf , de.type , de.count );
        }

        fs += fwrite ( buf , 1 , read_size , _line_tiff );
    }
    else//若大于1024字节,则分批写入1024字节,最后写入不足1024的字节
    {
        TIFF_UINT16_T tile_num = ( int )(buffer_size / 1024) ;
        TIFF_UINT16_T last_num = buffer_size % 1024;
        for ( int i = 0 ; i < tile_num ; i++ )
        {
            read_size = fread( buf , 1 , 1024 , _tile_tiff );//注意参数的顺序
            if( _tiff_src->tiff_byte_order == TIFF_BIGENDIAN && data_type_list[de.type].type_size != 1 )
            {
                sort_byte_order( buf , de.type , de.count );
            }
            fs += fwrite ( buf , 1 , read_size , _line_tiff );
        }

        read_size = fread( buf , 1 , last_num , _tile_tiff );
        if( _tiff_src->tiff_byte_order == TIFF_BIGENDIAN && data_type_list[de.type].type_size != 1 )
        {
            sort_byte_order( buf , de.type , de.count );
        }
        fs += fwrite ( buf , 1 , last_num , _line_tiff );
    }
    delete[] buf;
    buf = NULL;
    return fs;
}

void tiffTrans::sort_byte_order( TIFF_UINT8_T* buf , TIFF_UINT16_T data_type , TIFF_UINT16_T data_count )
{
    TIFF_UINT8_T* p = buf;

    for ( TIFF_UINT16_T i = 0 ; i < data_count ; i++ )
    {
        if ( data_type == 3 || data_type == 8 )//SHORT
        {
            TIFF_UINT16_T ret = sget2( p , TIFF_BIGENDIAN );
            memcpy( p , &ret , 2 );
            p += 2;
        }
        else if ( data_type == 4 ||  data_type == 9 ||  data_type == 11 )//LONG
        {
            TIFF_UINT32_T ret = sget4( p , TIFF_BIGENDIAN );
            memcpy( p , &ret , 4 );
            p += 4;
        }
        if ( data_type == 5 || data_type == 10 )
        {
            TIFF_UINT32_T ret = sget4( p , TIFF_BIGENDIAN );
            memcpy( p , &ret , 4 );
            p += 4;

            ret = sget4( p , TIFF_BIGENDIAN );
            memcpy( p , &ret , 4 );
            p += 4;
        }
        else if ( data_type == 12 )//DOUBLE
        {
            TIFF_UINT64_T ret = sget8( p , TIFF_BIGENDIAN );
            memcpy( p , &ret , 8 );
            p += 8;
        }
    }
}

void tiffTrans::modify_line_strip()
{
    fseek( _line_tiff , 0 , SEEK_END );
    TIFF_UINT32_T current_size = ftell( _line_tiff );
    if( _count_one_offset_pos > 0 )//Strip offset or TileOffset值保存在OFFSET中
    {
        fseek( _line_tiff , _count_one_offset_pos , SEEK_SET );
        fwrite( &current_size , 1 , 4 , _line_tiff );
    }
    else if ( _strip_offset_pos > 0 )
    {
        fseek( _line_tiff , _strip_offset_pos , SEEK_SET );
        for ( int i = 0 ; i < _tiff_src->bcount_strip_offset ; i++ )
        {
            TIFF_UINT32_T offset_pos = current_size + i * _tiff_src->strip_byte_counts[i];
            fwrite( &offset_pos , 1 , 4 , _line_tiff );
        }
    }
}

void tiffTrans::modify_tile_strip()
{
    fseek( _line_tiff , 0 , SEEK_END );
    TIFF_UINT32_T current_size = ftell( _line_tiff );
    fseek( _line_tiff , _strip_offset_pos , SEEK_SET );
    TIFF_UINT32_T tile_bytes = _tiff_src->tile.tile_height * _tiff_src->tile.tile_width * _tiff_src->samples_per_pixel ;
    TIFF_UINT32_T tile_satrt = current_size ;
    for ( int i = 0 ; i < _tiff_src->tile.tile_offset_count ; i++ )
    {
        TIFF_UINT32_T tile_satrt = current_size ;
        tile_satrt += i * tile_bytes ;
        fwrite( &tile_satrt , 1 , 4 , _line_tiff );
    }
}

void tiffTrans::modify_strip_offset()
{
    if( _tiff_src->tile.is_tile )
    {
        modify_tile_strip( );
    }
    else
    {
        modify_line_strip( );
    }
}

void tiffTrans::write_img_data()
{
    int table_w = (int)( _tiff_src->tif_width / _tiff_src->tile.tile_width );
    if ( _tiff_src->tif_width % _tiff_src->tile.tile_width > 0 )
    {
        table_w ++ ;
    }
    int table_h = (int)( _tiff_src->tif_height/ _tiff_src->tile.tile_height)+1;

    if (  _tiff_src->tif_height % _tiff_src->tile.tile_height > 0 )
    {
        table_h ++ ;
    }

    fseek( _line_tiff , 0 , SEEK_END );
    TIFF_UINT64_T cur_size = ftell( _line_tiff );

    for( int i_height = 0 ; i_height < _tiff_src->tif_height ; i_height++ )//按行添加
    {
        system("cls");
        printf( "%s\n Tile -> Line %d / %d \n" ,_src_name.c_str(), i_height+1 , _tiff_src->tif_height  );
        fseek( _line_tiff , cur_size + i_height * ( _tiff_src->tif_width * _tiff_src->samples_per_pixel ) , SEEK_SET );
        int temp_table_h = i_height / _tiff_src->tile.tile_height;//确定tile的行高
        int tile_h = i_height % _tiff_src->tile.tile_height;
        for ( int i_w_table = 0 ; i_w_table < table_w ; i_w_table ++ )//按tile的列填充
        {
            TIFF_UINT32_T table_pos = temp_table_h * table_w + i_w_table;

            TIFF_UINT32_T table_start = _tiff_src->tile.tile_offset_list[ table_pos ] + ( _tiff_src->tile.tile_width * _tiff_src->samples_per_pixel) *tile_h ;
            fseek( _tile_tiff , table_start , SEEK_SET );
            TIFF_UINT8_T* buf = new TIFF_UINT8_T[ _tiff_src->tile.tile_width * _tiff_src->samples_per_pixel ];
            fread( buf , 1 , _tiff_src->tile.tile_width * _tiff_src->samples_per_pixel , _tile_tiff );
            fwrite( buf , 1 , _tiff_src->tile.tile_width * _tiff_src->samples_per_pixel , _line_tiff );

            delete[] buf;
            buf = NULL;
        }
    }
}

void tiffTrans::write_img_data2()
{
    if ( _tiff_src->tile.is_tile )
    {
        write_tile_img( );
    }
    else
    {
        write_line_img( );
    }
}

void tiffTrans::write_line_img( )
{
    fseek( _line_tiff , 0 , SEEK_END );
    for ( int i = 0 ; i < _tiff_src->bcount_strip_offset ; i ++ )
    {
        write_data( _tiff_src->strip_line[i] , _tiff_src->strip_byte_counts[i] );
    }

}

void tiffTrans::write_tile_img( )
{
    fseek( _line_tiff , 0 , SEEK_END );

    for ( int i = 0 ; i < _tiff_src->tile.tile_offset_count ; i ++ )
    {
        write_data( _tiff_src->tile.tile_offset_list[i] , _tiff_src->tile.tile_byte_num_list[i] );
    }
}

void tiffTrans::write_data( TIFF_UINT32_T data_start , TIFF_UINT32_T buffer_size )
{
    fseek( _tile_tiff , data_start , SEEK_SET );

    TIFF_UINT8_T* buf = new TIFF_UINT8_T[1024];
    memset( buf , 0 , 1024 );

    TIFF_UINT16_T read_size = 0;
    if ( buffer_size <= 1024 )//若小于1024字节,则读取之后直接写入即可
    {
        read_size = fread( buf , 1 , buffer_size , _tile_tiff );
        fwrite ( buf , 1 , read_size , _line_tiff );
    }
    else//若大于1024字节,则分批写入1024字节,最后写入不足1024的字节
    {
        TIFF_UINT16_T tile_num = ( int )(buffer_size / 1024) ;
        TIFF_UINT16_T last_num = buffer_size % 1024;
        for ( int i = 0 ; i < tile_num ; i++ )
        {
            read_size = fread( buf , 1 , 1024 , _tile_tiff );//注意参数的顺序

            fwrite ( buf , 1 , read_size , _line_tiff );
        }
        read_size = fread( buf , 1 , last_num , _tile_tiff );
        fwrite ( buf , 1 , last_num , _line_tiff );
    }
    delete[] buf;
    buf = NULL;
}

int tiffTrans::save_to_trans( const char* new_path )
{
    string temp_path;
    if (  new_path == NULL )
    {
        temp_path = new_tiff_name() ;
    }
    else
    {
        temp_path = new_path;
    }

    _line_tiff = fopen( temp_path.c_str() , "wb" );
    if ( _line_tiff == NULL )
    {
        return -1 ;
    }

    //1.写入TIFF的文件头
    write_file_header( );

    //读取原来的TIFF中的TAG标签
    get_src_tag_list( );

    //生成新的TAG列表
    cts_new_tag_list( );
    //2.写入tag的数量
    fwrite( &( _de_num ) , 1 , 2 , _line_tiff );
    //3.写入空的DE占位空间
    TIFF_UINT8_T* place_holder = new TIFF_UINT8_T[ _de_num * ONE_DE_SIZE + IDF_END_FLAG_SIZE ];
    memset( place_holder , 0 , _de_num * ONE_DE_SIZE + IDF_END_FLAG_SIZE );
    fwrite( place_holder , 1 , _de_num * ONE_DE_SIZE + IDF_END_FLAG_SIZE , _line_tiff );

    TIFF_UINT64_T write_file_size = ftell( _line_tiff );
    //4.写入具体的TAG内容和对应的偏移量
    write_tag_list();


    //5.修改图像数据的偏移量
    modify_strip_offset();

    //6.写入图像数据
    write_img_data2();

    fclose( _line_tiff );

    delete[] place_holder;
    place_holder = NULL;
    return 0;
}

TIFF_UINT64_T tiffTrans::double_to_long( double d_ )
{
    union { TIFF_UINT64_T i; double f; } u;
    u.f = d_ ;
    return u.i ;
}

void tiffTrans::cs_pixel_scale( double cx , double cy )
{
    pixel_scale[0] = double_to_long ( cx );
    pixel_scale[1] = double_to_long ( cy );
    pixel_scale[2] = 0 ;
}

void tiffTrans::cs_tie_point( double x , double y )
{
    tie_point[0] = 0;
    tie_point[1] = 0;
    tie_point[2] = 0;

    tie_point[3] = double_to_long( x ) ;
    tie_point[4] = double_to_long( y ) ;
    tie_point[5] = 0;
}

void tiffTrans::cs_coord( deInfo* coord_list )
{
    coord_list[0].de.tag = 33550;//GeoTagPixelScale
    coord_list[0].de.type = 12;//double
    coord_list[0].de.count = 3 ;
    coord_list[0].data_source = 2;//内存数据
    coord_list[0].mem_data = ( TIFF_UINT8_T* )pixel_scale;

    coord_list[1].de.tag = 33922;//GeoTagTiePoint
    coord_list[1].de.type = 12;//double
    coord_list[1].de.count = 6 ;
    coord_list[1].data_source = 2;//内存数据
    coord_list[1].mem_data = ( TIFF_UINT8_T* )tie_point;

}

3.使用方法:

#include <stdio.h>
#include <string>
using namespace std;

#include "tifftrans.h"

string save_name( string str_path , string str_save_dir );

int main( int argc, char* argv[] )
{
    if ( argc < 7 )
    {
        printf( "参数输入的不正确!\n[D:\\xxx.tif] [上] [下] [左] [右] 四个方向上的坐标 [D:\\xxx] " );
        return -1;
    }

    string str_path( argv[1] );
    string str_top ( argv[2] );
    string str_botton ( argv[3] );
    string str_left ( argv[4] );
    string str_right ( argv[5] );
    string str_save_dir ( argv[6] );

    tiffTrans tiff_trans;
    tiff_trans.open( str_path.c_str() );
    geoRECT geo_box;
    geo_box.top = atof( str_top.c_str() );
    geo_box.botton = atof( str_botton.c_str() );
    geo_box.left = atof( str_left.c_str() );
    geo_box.right = atof( str_right.c_str() );
    tiff_trans.coord_box( geo_box );
    tiff_trans.save_to_trans( /*"D:\\123.tiff"*/ save_name( str_path , str_save_dir ).c_str() );

    return 0;
}

string save_name( string str_path , string str_save_dir )
{
    int pos = str_path.rfind('\\');
    string tif_name = str_path.substr( pos + 1 );
    string temp = "\\coord_";
    temp += tif_name ;
    return str_save_dir + temp;
}
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
python2.7栅格数据批量转换投影:ProjectRaster_management (in_raster, out_raster, out_coor_system, {resampling_type}, {cell_size}, {geographic_transform}, {Registration_Point}, {in_coor_system}) in_raster 输入栅格数据集。Mosaic Layer; Raster Layer out_raster 要创建的输出栅格数据集。以文件格式存储栅格数据集时,需要指定文件扩展名,具体如下:.bil - Esri BIL, .bip - Esri BIP, .bmp - BMP, .bsq - Esri BSQ, .dat - ENVI DAT,.gif - GIF,.img - ERDAS IMAGINE,.jpg - JPEG,.jp2 - JPEG 2000,.png - PNG,.tif - TIFF,无扩展名 - Esri Grid,以地理数据库形式存储栅格数据集时,不应向栅格数据集的名称添加文件扩展名。 将栅格数据集存储到 JPEG 文件、JPEG 2000 文件、TIFF 文件或地理数据库时,可以指定压缩类型和压缩质量。 Raster Dataset out_coor_system 输入栅格待投影到的目标坐标系。默认值将基于“输出坐标系”环境设置进行设定。该参数的有效值是扩展名为 .prj 的文件。现有要素类、要素数据集、栅格目录(基本上包含了与坐标系相关的所有内容)。坐标系的字符串表示。要生成此类较长的字符串,可向模型构建器添加一个坐标系变量,并根据需要设置该变量的值,然后将模型导出到 Python 脚本。 Coordinate System resampling_type (可选) 要使用的重采样算法。默认设置为 NEAREST。 NEAREST —最邻近分配法 BILINEAR —双线性插值法 CUBIC —三次卷积插值法 MAJORITY —众数重采样法 NEAREST 和 MAJORITY 选项用于分类数据,如土地利用分类。NEAREST 选项是默认设置,因为它是最快的插值法,同时也因为它不会更改像元值。请勿对连续数据(如高程表面)使用 NEAREST 或 MAJORITY。BILINEAR 选项和 CUBIC 选项最适用于连续数据。不推荐对分类数据使用 BILINEAR 或者 CUBIC,因为像元值可能被更改。 cell_size (可选) 新栅格数据集的像元大小。默认像元大小为所选栅格数据集的像元大小。 Cell Size XY geographic_transform (可选) 在两个地理坐标系或基准面之间实现变换的方法。当输入和输出坐标系的基准面相同时,地理(坐标)变换为可选参数。如果输入和输出基准面不同,则必须指定地理(坐标)变换。 有关各个受支持的地理(基准面)变换的详细信息,请参阅位于 ArcGIS 安装目录的 \Documentation 文件夹下的 geographic_transformations.pdf 文件。 Registration_Point(可选)用于对齐像素的 x 和 y 坐标(位于输出空间中)。配准的工作原理与捕捉栅格的概念类似。通过配准可指定用于定位输出像元的原,而不是仅将输出捕捉到现有栅格像元。所有输出像元与该之间必须间隔一个像元。该坐标不必位于一角,也不必落入栅格数据集中。捕捉栅格环境设置参数将优先于 Registration_Point 参数。因此,如果您要设置配准,请确保尚未设置捕捉栅格。 in_coor_system (可选) 输入栅格数据集的坐标系。Coordinate System
### 回答1: 要将tiff图片的原坐标导入CAD插件,首先需要找到一个支持tiff格式并具备此功能的插件。一种常见的选择是AutoCAD软件本身,它具有强大的CAD绘图功能,并支持多种图片格式的导入。 在AutoCAD中,我们可以通过以下步骤实现该功能。首先,打开AutoCAD软件并创建一个新的绘图文件。然后,选择“插入”选项卡中的“图像”命令,在弹出的对话框中选择要导入的tiff图片。 在导入图片后,AutoCAD会将其默认放置在绘图区域的左下角,并使用自身的坐标系统进行定位。为了保持tiff图片的原始坐标,我们可以将其移动到合适的位置。 首先,选择“修改”选项卡中的“移动”命令,然后选择要移动的图片对象。接下来,输入参考的原始坐标和目标坐标,这样AutoCAD就会按照我们输入的坐标图片移动到指定位置。 当完成上述步骤后,我们就成功将tiff图片的原坐标导入CAD插件中了。通过这种方法,我们可以在CAD软件中使用tiff图片,并按照原始坐标进行进一步绘图、编辑和处理。 ### 回答2: tiff图片坐标导入CAD的插件,是一种类型的软件工具,旨在帮助用户将基于TIFF格式的图片以保持其原始坐标的方式导入到计算机辅助设计(CAD)软件中。 通常情况下,CAD软件并不直接支持TIFF图片的导入,因为TIFF是一种图像格式,其中包含了图像的像素信息,而不是坐标信息。因此,使用插件可以帮助用户在CAD软件中导入和处理TIFF图片,而不会丢失图像的原始坐标信息。 这些插件通常包括一系列功能,可以通过选择、缩放和旋转等操作,精确地将TIFF图片定位在CAD软件的坐标系统中。插件可能还提供一些额外的功能,例如自动校准图像、调整图像亮度和对比度等。 TIFF图片坐标导入CAD的插件可以广泛应用于多个领域。例如,在土地测量、建筑设计和工程绘图等方面,工程师和设计师可以使用这些插件,将现场采集的地理信息系统(GIS)数据以TIFF格式导入CAD软件,以便在CAD中进行进一步的设计和分析。 总之,TIFF图片坐标导入CAD的插件是一种有用的工具,可以帮助用户在CAD软件中有效处理TIFF图像,并确保图像的原始坐标信息得以保留,使得用户能够更准确地进行设计和分析工作。 ### 回答3: Tiff图片坐标导入CAD插件是一种可用于将Tiff格式的图片以其原始坐标导入到CAD软件中的扩展工具。这种插件可以极大地简化CAD设计过程中的图像导入操作,提高工作效率。 使用该插件,用户可以直接选择要导入的Tiff图片并将其添加到CAD软件中。插件会自动将Tiff图片的原始坐标信息与CAD中的坐标系统进行匹配,确保图像的准确导入。这意味着无需手动调整图像位置或重新定位,因为插件能够自动将其放置在正确的位置上。 此外,该插件还具有一些额外功能,例如根据用户的需要进行图像缩放、旋转或倾斜。通过使用这些功能,用户可以根据实际情况对导入的Tiff图片进行调整,以满足具体设计要求。 总的来说,Tiff图片坐标导入CAD的插件是一款功能强大且易于使用的工具,可以帮助用户更高效地将Tiff格式的图片导入到CAD软件中,并保持其原始坐标。它大大简化了设计过程中的图像导入操作,并提供了额外的调整功能,使用户能够更好地适应各种设计需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wb175208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值