您的位置:首页 > 其它

TIFF图像数据的排列方式的装换

2017-03-08 22:08 483 查看
  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个空字节

#define KB         1024
#define MB         1024 * KB
#define MAX_MSIZE  128 * MB
extern TIFF_UINT8_T g_big_memory[ MAX_MSIZE ];
extern TIFF_UINT8_T g_line_memory[ 8*MB ];

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 );

int arrangement();//0 - tile  1 - line
bool analysis( char* ret_error );  //分析tiff是否可以进行转换 true - 可以 false - 不可以
int save_to_trans( const char* new_path = NULL );

private:
string new_tiff_name();
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 );

void write_img_data();

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的文件偏移位置
};


2.cpp文件

#include "tifftrans.h"

TIFF_UINT8_T g_big_memory[MAX_MSIZE];
TIFF_UINT8_T g_line_memory[ 8*MB ];

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) );
}

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

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;
}

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++ )
{
_fseeki64( _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 ;
}
}

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 - 4 ];//tile 共4个标签
memset( temp_de_list , 0 , sizeof(deInfo)*( _de_num - 4) );

int j = 0;
for ( int i = 0 ; i < _de_num ; i ++ )
{
if ( ( de_list[i].de.tag != 322 )&&
( de_list[i].de.tag != 323 )&&
( de_list[i].de.tag != 324 )&&
( de_list[i].de.tag != 325 )
)
{
memcpy ( temp_de_list + j , de_list + i , sizeof(deInfo) );
j++;
}
}

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

int tiffTrans::cts_new_tag_list( )
{
de_list = delete_tile_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 ( 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 )//Strip offset
{
_fseeki64( _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 )//文件对应的偏移量
{
_fseeki64( _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对应的数据存放的地址
_fseeki64( _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 )//内存
{
_fseeki64( _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对应的数据存放的地址
_fseeki64( _line_tiff , DE_START + ONE_DE_SIZE * i + 8 , SEEK_SET );
fwrite( &pos , 1 , 4 , _line_tiff );

delete[] de_list[i].mem_data;
}
}
}

TIFF_UINT64_T tiffTrans::file_disk_data( DirectoryEntry de , TIFF_UINT64_T buffer_size )
{
_fseeki64( _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()
{
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*/_fseeki64( _line_tiff , 0 , SEEK_END );
TIFF_UINT64_T cur_size = ftell( _line_tiff );

#if 0

#if 0
for( int i_height = 0 ; i_height < _tiff_src->tif_height ; i_height++ )//按行添加
{
if( i_height % 10000 == 0)
{
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;
}

}
#endif
TIFF_UINT32_T tiff_width_bytes =  _tiff_src->tif_width * _tiff_src->samples_per_pixel ;
TIFF_UINT32_T tile_line_bytes = _tiff_src->tile.tile_width * _tiff_src->samples_per_pixel;
TIFF_UINT8_T* buf = new TIFF_UINT8_T[ tiff_width_bytes ];
memset( buf , 0 , tiff_width_bytes );
TIFF_UINT8_T* temp_buf = buf;
for( int i_height = 0 ; i_height < _tiff_src->tif_height ; i_height++ )//按行添加
{
fseek( _line_tiff , cur_size + i_height * tiff_width_bytes , 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 );

fread( temp_buf , 1 ,tile_line_bytes , _tile_tiff );
temp_buf += tile_line_bytes;
}
fwrite( buf , 1 , tiff_width_bytes , _line_tiff );
memset( buf , 0 , tiff_width_bytes );
temp_buf = buf;
}
delete[] buf;
buf = NULL;
#else
TIFF_UINT32_T table_size = _tiff_src -> tile.tile_width * _tiff_src -> tile.tile_height * _tiff_src -> samples_per_pixel ;
TIFF_UINT32_T tiff_width_bytes =  _tiff_src->tif_width * _tiff_src->samples_per_pixel ;
if( tiff_width_bytes > 8*MB )
{
printf( "图片的行数据 %ld 太大,暂时无法处理!\n" , tiff_width_bytes );
return ;
}
/*TIFF_UINT8_T* buf = new TIFF_UINT8_T[ tiff_width_bytes ];
if ( buf == NULL )
{
printf( "行数据内存分配失败!\n" );
return;
}*/
//TIFF_UINT8_T* buf = ( TIFF_UINT8_T* )malloc( sizeof( TIFF_UINT8_T) * tiff_width_bytes );
TIFF_UINT8_T *buf = g_line_memory ;
memset( buf , 0 , tiff_width_bytes );
TIFF_UINT32_T tile_width_bytes = _tiff_src->tile.tile_width * _tiff_src->samples_per_pixel;

for ( int i_tb_h = 0 ; i_tb_h < table_h ; i_tb_h ++ )
{
TIFF_UINT8_T* pbig = g_big_memory;
for( int i_tb_w = 0 ; i_tb_w < table_w ; i_tb_w ++ )
{
TIFF_UINT32_T table_pos = i_tb_h * table_w + i_tb_w;

TIFF_UINT32_T table_start = _tiff_src->tile.tile_offset_list[ table_pos ] ;
_fseeki64( _tile_tiff , table_start , SEEK_SET );
TIFF_UINT32_T read_bytes = fread( pbig , 1 , table_size , _tile_tiff );
//if ( read_bytes == 0/*table_size*/ )
//{
//  fclose( _line_tiff );
//  return;
//}
pbig += table_size ;
}

for ( int i_h_tile = 0 ; i_h_tile < _tiff_src->tile.tile_height ; i_h_tile ++ )
{
TIFF_UINT8_T* temp_buf = buf ;
for ( int i_tb_w = 0 ; i_tb_w < table_w ; i_tb_w ++  )
{
TIFF_UINT8_T* p = g_big_memory + ( i_tb_w * table_size + tile_width_bytes * i_h_tile );
memcpy( temp_buf , p , tile_width_bytes );
temp_buf += tile_width_bytes;
}
TIFF_UINT32_T write_count = fwrite( buf , 1 , tiff_width_bytes , _line_tiff );
memset( buf , 0 , tiff_width_bytes );
temp_buf = NULL ;
}
pbig = NULL ;

}
//free( buf );
//buf = NULL ;

//delete[] buf;
//buf = NULL;

#endif

}

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_data();

return 0;
}


3.调用

#include <Windows.h>
#include "tifftrans.h"

char parse_cmd( char* sz_cmd );//解析命令
void print_help_info();        //打印帮助信息
int get_all_path_list( const TCHAR* rootDir, vector<wstring>&srcFiles);
bool is_tiff( wstring file_name );
wstring new_dir_path( wstring dir_path );
wstring mbcs_to_unicode(const std::string& str );
string unicode_to_mbcs(const std::wstring& wstr );
string new_name( string tiff_name , string save_dir );

int main( int argc, char* argv[] )
{
for ( int i = 0 ; i < argc ; i++ )
{
printf( "%d): " , i+1 );
printf( argv[i] );
printf( "\n" );
}

if ( argc < 4 )
{
printf("error : 请输入正确的命令和参数!");
return -1;
}

char cmd_symble = parse_cmd( argv[1] );
switch ( cmd_symble )
{
case '?':
case 'h':
case 'H':
{
print_help_info();
}
break;
case 't'://单张图片
{
tiffTrans tiff_trans;
tiff_trans.open( argv[2] );

char error_text[1024] = { 0 };
if ( tiff_trans.analysis( error_text ) )
{
string save_name = new_name( argv[2] , argv[3] );
if( 0 == tiff_trans.save_to_trans( save_name.c_str() ) )
{
printf("处理完成!\n\n");
}
}
else
{
printf( error_text );
}
}
break;
case 'd'://批量处理
{
wstring dir_path = mbcs_to_unicode( argv[2] );
dir_path = new_dir_path( dir_path );
vector<wstring> tiff_list;
get_all_path_list( dir_path.c_str() , tiff_list );

for ( int i = 0 ; i < tiff_list.size() ; i++ )
{
tiffTrans tiff_trans;
tiff_trans.open( unicode_to_mbcs( tiff_list.at( i ) ).c_str() );

char error_text[1024] = { 0 };
if ( tiff_trans.analysis( error_text ) )
{
if( 0 == tiff_trans.save_to_trans( ) )
{
printf("处理完成!\n\n");
}
}
}
}
break;
default:
print_help_info();
break;
}

return 0;
}

char parse_cmd( char* sz_cmd )
{
char ch = 'h';
if ( strlen( sz_cmd ) <= 1 )
{
return ch ;
}

if ( sz_cmd[0]!='-' )
{
return ch;
}

ch = sz_cmd[1];
return ch;
}

void print_help_info()
{
printf( "命令格式:[-x][x:\\xxx.tif][D:\\xxx]\n" );
printf( " -h - H -?    显示帮助信息\n");
printf( " -t           处理单张tiff图片。参数:tiff图片的完整的路径\n");
printf( " -d           批量处理tiff图片。参数:所有tiff图片所在的文件夹目录\n");
}

wstring new_dir_path( wstring dir_path )
{
int len = dir_path.size();
if ( dir_path.at( len - 1 ) == L'\\' )
{
return dir_path.substr( 0 , len - 1 );
}
return dir_path;
}

string new_name( string tiff_name , string save_dir )
{
int pos = tiff_name.rfind('\\');
string name = tiff_name.substr( pos + 1 );
string name2 = "\\line_";
name2 += name ;
wstring new_name2 = new_dir_path( mbcs_to_unicode(save_dir) );
return unicode_to_mbcs( new_name2 ) + name2;
}

int get_all_path_list( const TCHAR* rootDir, vector<wstring>&srcFiles)
{
WIN32_FIND_DATA fd;
ZeroMemory(&fd, sizeof(WIN32_FIND_DATA));

HANDLE hFile;
TCHAR tmpPath[256];
TCHAR subPath[256];
ZeroMemory( tmpPath, 256*sizeof(TCHAR) );
ZeroMemory( subPath, 256*sizeof(TCHAR) );

BOOL bRet = TRUE;
static int nFileSize = 0 ;

//define the format of the basepath
wcscpy(tmpPath, rootDir);
if(tmpPath[wcslen(tmpPath) -1] != L'\\')
{
wcscat(tmpPath, L"\\");
}
wcscat(tmpPath, L"*");

hFile = FindFirstFile(tmpPath, &fd);
while (hFile != INVALID_HANDLE_VALUE && bRet)
{
if (fd.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY &&
wcscmp(fd.cFileName, L".") && wcscmp(fd.cFileName, L".."))
{
wcscpy(subPath, rootDir);
if(subPath[wcslen(subPath) -1] != L'\\')
{
wcscat(subPath, L"\\");
}
wcscat(subPath, fd.cFileName);
get_all_path_list( subPath , srcFiles );
}
else if(!wcscmp(fd.cFileName, L".") || !wcscmp(fd.cFileName, L".."))
{

}
else
{
if ( is_tiff( fd.cFileName ) )
{
nFileSize++;

wstring strdir = rootDir;
strdir += L"\\";
strdir += fd.cFileName;
srcFiles.push_back( strdir );
}
}
bRet = FindNextFile(hFile, &fd);
}
FindClose(hFile);

return nFileSize;
}

bool is_tiff( wstring file_name )
{
int pos = file_name.rfind(L'.');
wstring ext_name = file_name.substr( pos + 1 );
transform(ext_name.begin(), ext_name.end(), ext_name.begin(), ::tolower);
if ( ext_name == L"tif" )
{
return true;
}
return false;
}

wstring mbcs_to_unicode(const std::string& str )
{
int  len = 0;
len = (int)str.length();
int  unicodeLen = ::MultiByteToWideChar( CP_ACP, 0, str.c_str(), -1, NULL, 0 );
wchar_t *  pUnicode;
pUnicode = new  wchar_t[unicodeLen+1];
memset(pUnicode,0,(unicodeLen+1)*sizeof(wchar_t));
::MultiByteToWideChar( CP_ACP, 0, str.c_str(), -1, (LPWSTR)pUnicode, unicodeLen );
wstring wstr = pUnicode;
delete[] pUnicode;
return  wstr;
}

string unicode_to_mbcs(const std::wstring& wstr )
{
int  len = 0;
len = (int)wstr.length();
int  ansiLen = ::WideCharToMultiByte( CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
char*  pAnsi;
pAnsi = new  char[ansiLen+1];
memset(pAnsi,0,(ansiLen+1)*sizeof(char));
::WideCharToMultiByte( CP_ACP, 0, wstr.c_str(), -1, (LPSTR)pAnsi, ansiLen, NULL, NULL);
string str = pAnsi;
delete[] pAnsi;
return  str;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐