将1bpp的bmp图像存储为1bpp或者2bpp的tiff格式



// 将1bpp的位图转换为 1bit/2bit tiff
/**
参数:
	BYTE *src  二值图像的像素数据,不包含头部信息, 1bpp, 
	int src_width  原图的宽度, in pixles,
	int src_height  原图的高度, in pixles
	int bpp   转换tiff指定的bpp
*/
static BYTE *
	BW2Tif(BYTE *src, int src_width, int src_height, int bpp, DWORD& totalSize)
{
	int dst_width  = (bpp == 1) ? src_width : src_width/2;
	int dst_height = src_height;


	// get src and dst scan width
	int src_pitch = (src_width + 7)/8 + 3 & ~3; 
	int dst_pitch = (dst_width * bpp + 31)/32*4;

	// get src and dst size
	unsigned int tif_size, bmp_size;
	if(0x80000000 & dst_height)
	{
		bmp_size= src_pitch*(0 - src_height);
		tif_size = dst_pitch*(0 - dst_height);
	}
	else{
		bmp_size = src_pitch*src_height;
		tif_size = dst_pitch*dst_height;
	}

	// Image File Header
	const unsigned char tif_ifh[10]={
		'I','I',					//intel顺序
		0x2a,0x00,					//tiff版本号
		0x08,0x00,0x00,0x00,		//IFD(图形文卷目录 Image File Diretory)偏移, 8个字节
		0x0F,0x00,					// 这两个字节属于IFD了,指定有多少个Directory Entry
	};

	// Directory Entry ,每个都是12个字节的 , TIFF 6.0规定,标签要以升序的方式排列
	unsigned long tif_ifd[0x0f*3+4]={
		0x000400FE, 0x01,	0x000,		// NewSubfileType,   
		0x00030100, 0x01,	0x018,		// ImageWidth,The number of columns in the image, i.e., the number of pixels per scanline
		0x00030101, 0x01,	0x018,		// ImageLength, The number of rows (sometimes described as scanlines) in the image.

		0x00030102, 0x01,	bpp,		// BitPerSample  258
		0x00030103, 0x01,	0x001,		// Compression, 1无压缩
		0x00030106, 0x01,	0x000,		// PhotometricInterpretation,  对于bilevel图像,值0=WhiteIsZero,1=BlackIsZero

		0x00040111, 0x01,	0x0CE,		// StripOffsets,For each strip, the byte offset of that strip, 
										// N = StripsPerImage for PlanarConfiguration equal to 1; 
										// N = SamplesPerPixel * StripsPerImage for PlanarConfiguration equal to 2
										// 从字面上看来, StripOffsets是个数组,小于64kb,  这里是0xce, 就是头部的206个字节了
		0x00030112, 0x01,	0x001,		// Orientation
		0x00030115, 0x01,	0x001,		// SamplesPerPixel
		0x00030116, 0x01,	0xffff,		// RowsPerStrip, The number of rows in each strip (except possibly the last strip.)
		// RowsPerStrip and ImageLength together tell us the number of strips in the entire image. default is 2^32-1, 推荐每个strip是8k数据
		// image. The equation is:     StripsPerImage= floor ((ImageLength + RowsPerStrip - 1) / RowsPerStrip).
		0x00040117, 0x01,	0x07F,		// StripByteCounts

		0x0005011A, 0x01,	0x0BE,		// XResolution
		0x0005011B, 0x01,	0x0C6,		// YResolution
		0x0003011C, 0x01,	0x001,		// PlanarConfiguration , 1是单平面格式, 2多平面格式
		0x00030128, 0x01,	0x002,		// ResolutionUnit, 0x002 = inch

		0x60031280, 0x01000000,			// X分辨率ofset=164
		0x60031280, 0x01000000,			// Y分辨率ofset=16C
	};

	//
	tif_ifd[ 5] = dst_width;
	tif_ifd[ 8] = dst_height;
	tif_ifd[29] = (tif_size + 0x0f) & 0xfffffff0;  // 简单的做成一个strip
	tif_ifd[32] = tif_size;


	// allocate dst image  hpgl
	unsigned int total_size = sizeof(tif_ifh) + sizeof(tif_ifd) + tif_size;

	TRACE1("tiff size=0x%x\n", sizeof(tif_ifh) + sizeof(tif_ifd));

	BYTE *dst =  new BYTE[total_size];
	if(NULL == dst) return FALSE;

	BYTE *curr = dst;

	totalSize = total_size;

	// 
	memcpy(curr, tif_ifh, sizeof(tif_ifh));
	curr += sizeof(tif_ifh);

	memcpy(curr, tif_ifd, sizeof(tif_ifd));
	curr += sizeof(tif_ifd);

	// 当src图像的宽度是整数个字节的时候,可以直接复制数据,如果多出几个bit,就不好搞了
	//memcpy(curr, src, tif_size);
	
	// gray2bmp_to_tif.c 中程序,是把每个像素用一个字节来存储了,而这里不是的
	// 所以不能照着写程序了
	
	int width_align = src_width & 0xffffFFF8;
	int nBytes = width_align/8;
	if (src_width - width_align)   // 有边角bit位
		nBytes += 1;

	LPBYTE src2 = src;  
	LPBYTE dst2 = curr;

	int x,y;
	for (y = 0; y < src_height; y++)
	{
		src2 = src + y * src_pitch;
		dst2 = curr + y * nBytes;    //写入tiff的数据流,不要自己补充空白数据

		memcpy(dst2, src2, nBytes);
		src2 += nBytes;
		dst2 += nBytes;
	}

	return dst;
}


// 这个是测试代码
void CPagePt::OnBnClickedButtonCv()
{

	CFileDialog fd(TRUE, _T("bmp"), NULL,  NULL,  _T("All files(*.*)|*.*|Wibdows Bitmap(*.bmp)|*.bmp||"));
	if(fd.DoModal() != IDOK)
		return;

	CString filename = fd.GetPathName();

	HBITMAP hImage = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP,
		0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_DEFAULTSIZE);

	//CBitmap* m_Bitmap = CBitmap::FromHandle(hImage);

	BITMAP bm;				//获取位图信息 
	GetObject(hImage, sizeof(BITMAP), &bm); 

	// Sumit: memory allocation is still 1800x1800 in your code..
	BYTE* bmpBuffer=(BYTE*)bm.bmBits;    // GlobalAlloc(GPTR, bm.bmWidthBytes * bm.bmHeight);      //allocate memory


	DWORD tifSize;
	BYTE *tif = BW2Tif(bmpBuffer, bm.bmWidth, bm.bmHeight, 2, tifSize);

	CFile cf("C:\\bw2tif_out.tif", CFile::modeCreate | CFile::modeWrite);

	cf.Write(tif, tifSize);

	cf.Close();

	delete tif;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值