处理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( ¤t_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;
}