有时TIFF图片都是很大的,但是我们又不是需要那么大的图片,只是需要其中的某一部分,这就需要我们裁剪其中的一块,同时还要把相应的坐标信息也要保存下来。
1.头文件
#pragma once
#include <Windows.h>
#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 set_cut_rect( int x1 , int y1 , int x2 , int y2 );
int arrangement();//0 - tile 1 - line
bool analysis( char* ret_error ); //分析tiff是否可以进行转换 true - 可以 false - 不可以
int save_to_trans( const char* new_path = NULL , const char* new_name = NULL );
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 );
void coord_box( geoRECT geo_rect );
private:
string new_tiff_name( string save_dir );
void write_file_header();
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_tile_tag();
int cts_new_tag_list();
void print_tag_info_list();
void write_tag_list();
void modify_strip_offset();
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 );
deInfo* delete_coord_tag( );
void write_img_data();
void write_img_data2();
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; //标签的数量
TIFF_UINT32_T _strip_offset_pos; //TAG StripOffset的文件偏移位置
int _tiff_w_src , _tiff_h_src ;
int _tiff_start_x;
int _tiff_start_y;
int _tiff_end_x;
int _tiff_end_y;
int _coord_tag_num; //包含坐标信息的TAG的数量
TIFF_UINT64_T pixel_scale[3];//像元比例
TIFF_UINT64_T tie_point[6];//控制点坐标对
geoRECT _geo_rect;
deInfo _new_tie_tag ;
};
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;
_tiff_w_src = _tiff_src->tif_width;
_tiff_h_src = _tiff_src->tif_height;
_coord_tag_num = 0 ;
return ret;
}
void tiffTrans::set_cut_rect( int x1 , int y1 , int x2 , int y2 )
{
_tiff_start_x = x1;
_tiff_start_y = y1;
_tiff_end_x = x2;
_tiff_end_y = y2;
_tiff_src->tif_width = _tiff_end_x - _tiff_start_x;
_tiff_src->tif_height = _tiff_end_y - _tiff_start_y;
geoRECT pixel_rect ;
pixel_rect.left = 0 ;
pixel_rect.top = 0 ;
pixel_rect.right = _tiff_w_src;
pixel_rect.botton = _tiff_h_src;
geo_coord( _tiff_src , pixel_rect , _geo_rect );
//cs_pixel_scale( scaleX , scaleY );
double new_start_x = _geo_rect.left + _tiff_src->geo_tiff.pixel_scale.scaleX * _tiff_start_x;
double new_start_y = _geo_rect.top - _tiff_src->geo_tiff.pixel_scale.scaleY * _tiff_start_y ;
cs_tie_point( new_start_x , new_start_y );
_new_tie_tag.de.tag = 33922;//GeoTagTiePoint
_new_tie_tag.de.type = 12;//double
_new_tie_tag.de.count = 6 ;
_new_tie_tag.de.offset = 0 ;
_new_tie_tag.data_source = 2;//内存数据
_new_tie_tag.mem_data = ( TIFF_UINT8_T* )tie_point;
}
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( string save_dir )
{
int pos = _src_name.rfind( '\\' );
string tiff_name = _src_name.substr( pos + 1 );
string dir = save_dir/*_src_name.substr( 0 , pos + 1 )*/;
string temp_name = "\\cut_";
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 );
}
if ( de_list[i].de.tag == 256 )
{
de_list[i].de.offset = _tiff_end_x - _tiff_start_x;
}
if ( de_list[i].de.tag == 257 )
{
de_list[i].de.offset = _tiff_end_y - _tiff_start_y;
}
//如果是 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_tile_tag()
{
deInfo* temp_de_list = new deInfo[ _de_num - 3 ];//tile 共4个标签
memset( temp_de_list , 0 , sizeof(deInfo)*( _de_num - 3) );
int j = 0;
for ( int i = 0 ; i < _de_num ; i ++ )
{
if ( ( de_list[i].de.tag != 273 )&& //StripOffsets
( de_list[i].de.tag != 278 )&& //RowsPerStrip
( de_list[i].de.tag != 279 )//StripByteCounts
)
{
memcpy ( temp_de_list + j , de_list + i , sizeof(deInfo) );
j++;
}
}
delete[] de_list;
de_list = NULL;
de_list = temp_de_list;
_de_num -= 3 ;
return de_list;
}
int tiffTrans::cts_new_tag_list( )
{
de_list = delete_tile_tag();
//de_list = delete_coord_tag();
deInfo* temp_line = cts_line_tag();
deInfo* temp_de_list = new deInfo[ _de_num + 3 ];//tile 4个标签 line 只需要3个标签
memset( temp_de_list , 0 , sizeof(deInfo)*( _de_num + 3 ) );
int j = 0 , k = 0 ;
for ( int i = 0 ; i < _de_num ; i++ )
{
if ( de_list[i].de.tag == 33922 )//ModelTiepointTag
{
memcpy ( &de_list[i] , &_new_tie_tag , sizeof( deInfo ));
}
if ( k < 3 )//line只有三个标签
{
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++;
}
}
delete[] de_list;
de_list = NULL;
de_list = temp_de_list;
_de_num += 3;
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()
{
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.count > 1 )//Strip offset
{
fseek( _line_tiff , 0 , SEEK_END );
_strip_offset_pos = ftell( _line_tiff );
}
//写入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_strip_offset()
{
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 width_bytes = _tiff_src->tif_width * _tiff_src->samples_per_pixel ;
for ( int i = 0 ; i < _tiff_src->tif_height ; i++ )
{
TIFF_UINT32_T height_start = current_size + i * width_bytes;
fwrite( &height_start , 1 , 4 , _line_tiff );
}
}
void tiffTrans::write_img_data()
{
fseek( _line_tiff , 0 , SEEK_END );
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()
{
fseek( _line_tiff , 0 , SEEK_END );
long theight = _tiff_h_src/*_tiff_src->tif_height */;
TIFF_UINT32_T* height_start = (TIFF_UINT32_T*) VirtualAlloc ( NULL , theight*sizeof(TIFF_UINT32_T) , MEM_COMMIT , PAGE_READWRITE );
_tiff_src->tif_width = _tiff_w_src;
_tiff_src->tif_height = _tiff_h_src ;
int bits = _tiff_src->bit_per_samples ;
if ( bits >= 24 )
{
if ( !_tiff_src->tile.is_tile )//瓦片数据
{
fresh_line_start( _tiff_src , height_start );
}
}
int len = ( _tiff_end_x - _tiff_start_x )* _tiff_src->samples_per_pixel ;
TIFF_UINT8_T* buf = new TIFF_UINT8_T[ len ];
memset( buf , 0 , len );
for ( int i = _tiff_start_y ; i < _tiff_end_y ; i++ )
{
/*fseek*/_fseeki64( _tile_tiff , ( height_start[i] + _tiff_start_x * _tiff_src->samples_per_pixel ) , SEEK_SET );
fread( buf ,1 , len , _tile_tiff );
fwrite( buf , 1 , len , _line_tiff );
}
delete[] buf;
buf = NULL ;
if ( height_start != NULL )
{
VirtualFree( height_start , 0 , MEM_RELEASE );
height_start = NULL;
}
}
int tiffTrans::save_to_trans( const char* new_path , const char* new_name )
{
string temp_path;
if ( strlen( new_path )!= 0 && strlen( new_name ) == 0 )
{
temp_path = new_tiff_name( new_path ) ;
}
else
{
temp_path = new_path ;
temp_path += "\\";
temp_path += new_name;
}
_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 );
return 0;
}
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;
}
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 );
}
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 "tifftrans.h"
int main( int argc, char* argv[] )
{
if ( argc < 8 )
{
printf("error : 请输入正确的命令和参数!\n");
printf("D:\\xxx.tif 左:100 上:100 右:300 下:300 D:\\yyy new_name.tif\n");
return -1;
}
tiffTrans _tiff_trans;
_tiff_trans.open( argv[1] );
_tiff_trans.set_cut_rect( atoi(argv[2]) , atoi(argv[3]) , atoi(argv[4]) , atoi(argv[5]) );
_tiff_trans.save_to_trans( argv[6] , argv[7] );
return 0;
}