求助C++程序生成bmp文件的问题

erbixxx 2016-04-22 10:26:08
本人尝试使用c++输出一个bmp文件,但是在文件格式上出了问题。
首先是以下代码,能够正常输出一个全部为蓝色的bmp,其中height与width均为500。


void Bmp::fpBin(FILE* out, int num, int len){
for (int i = 0; i<len; ++i){
fputc(num & 255, out);
num >>= 8;
}
}

void Bmp::output(){
FILE* out = fopen(name, "w");
int fill = (4 - ((width * 3) & 3)) & 3;
int size = height*(3*width+fill);

fprintf(out, "BM"); //bfType
fpBin(out, 0, 4); //bfSize
fpBin(out, 0, 2); //bfReserved1
fpBin(out, 0, 2); //bfReserved2
fpBin(out, 54, 4); //bfOffBits

fpBin(out, 40, 4); //biSize
fpBin(out, width, 4); //biWidth
fpBin(out, height, 4); //biHeight
fpBin(out, 1, 2); //biPlanes
fpBin(out, 24, 2); //biBitCount
fpBin(out, 0, 4); //biCompression
fpBin(out, 0, 4); //biSizeImage
fpBin(out, 0, 4); //biXPelsPerMeter
fpBin(out, 0, 4); //biYPelsPerMeter
fpBin(out, 0, 4); //biClrUsed
fpBin(out, 0, 4); //biClrImportant

for (int i = 0; i < height; ++i, fpBin(out, 0, fill))
for (int j = 0; j < width; ++j){
Color color;
fpBin(out, 255 , 1);
fpBin(out, 0 , 1);
fpBin(out, 0 , 1);
}
fclose(out);
}


但是将像素部分修改后,颜色就出现错位了,变成了红蓝绿不断变化的条纹。



for (int i = 0; i < height; ++i, fpBin(out, 0, fill))
for (int j = 0; j < width; ++j){
Color color;
fpBin(out, j&255, 1);
fpBin(out, 0 , 1);
fpBin(out, 0 , 1);
}


求助这究竟是为什么。
...全文
632 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
lqbk1 2016-05-05
  • 打赏
  • 举报
回复
如果不是二进制写入文档,fputc一个\n,可能实际写入了\r\n连续两个字符,这个就跟楼主初衷不一样了 至于出问题的那些斜线…… 楼主只要明白原程序中
int fill = (4 - ((width * 3) & 3)) & 3;
的意义,就自然能够理解斜线为什么出现了
lqbk1 2016-05-05
  • 打赏
  • 举报
回复
直接改成FILE* out = fopen(name, "wb")应该就行了 不过建议将fpBin的实现也改一改,下面是我测试没问题的代码
void fpBin(FILE* out, int num, int len){
	for (int i = 0; i<len; ++i){
		unsigned char buf = num & 255;
		fwrite(&buf,1,1,out);
		num >>= 8;
	}
}

void output(){
	int width = 500;
	int height = 500;
	FILE* out = fopen("d:\\d.bmp", "wb");
	int fill = (4 - ((width * 3) & 3)) & 3;
	int size = height*(3*width+fill);

	fprintf(out, "BM");  //bfType
	fpBin(out, 0, 4);  //bfSize
	fpBin(out, 0, 2);  //bfReserved1
	fpBin(out, 0, 2);  //bfReserved2
	fpBin(out, 54, 4);  //bfOffBits

	fpBin(out, 40, 4);  //biSize
	fpBin(out, width, 4);  //biWidth
	fpBin(out, height, 4);  //biHeight
	fpBin(out, 1, 2);  //biPlanes
	fpBin(out, 24, 2);  //biBitCount
	fpBin(out, 0, 4);  //biCompression
	fpBin(out, 0, 4);  //biSizeImage
	fpBin(out, 0, 4);  //biXPelsPerMeter
	fpBin(out, 0, 4);  //biYPelsPerMeter
	fpBin(out, 0, 4);  //biClrUsed
	fpBin(out, 0, 4);  //biClrImportant

	for (int i = 0; i < height; ++i, fpBin(out, 0, fill))
		for (int j = 0; j < width; ++j){
			
			fpBin(out, j&255 , 1);
			fpBin(out, 0 , 1);
			fpBin(out, 0 , 1);
		}
		fclose(out);
}
int _tmain(int argc, _TCHAR* argv[])
{
	output();
	return 0;
}
lqbk1 2016-05-05
  • 打赏
  • 举报
回复
引用 4 楼 erbixxx 的回复:
[quote=引用 3 楼 lqbk1 的回复:] 不如请楼主先告诉我,你到底期望有怎样的效果呢?
最后一张图应该都是蓝条,但现在出现了红条和绿条。 我会使用其他程序包来生成一个bmp文件,但我想问的是为什么自己根据格式一步一步生成结果就错了。 [/quote] 哦,原来楼主想这样呀? 那你出问题的原因在于这句 FILE* out = fopen(name, "w"); 没有用二进制的方式写入文件,这样搞的话,fputc不一定每次只写入一个字符哟.....
erbixxx 2016-05-04
  • 打赏
  • 举报
回复
引用 3 楼 lqbk1 的回复:
不如请楼主先告诉我,你到底期望有怎样的效果呢?
最后一张图应该都是蓝条,但现在出现了红条和绿条。 我会使用其他程序包来生成一个bmp文件,但我想问的是为什么自己根据格式一步一步生成结果就错了。
lqbk1 2016-05-02
  • 打赏
  • 举报
回复
不如请楼主先告诉我,你到底期望有怎样的效果呢?
赵4老师 2016-04-23
  • 打赏
  • 举报
回复
仅供参考:
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <windows.h>
#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;
wchar_t formats[5][11]={
    L"image/bmp",
    L"image/jpeg",
    L"image/gif",
    L"image/tiff",
    L"image/png",
};
wchar_t exts[5][5]={
    L".bmp",
    L".jpg",
    L".gif",
    L".tif",
    L".png",
};
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) {
   UINT  num = 0;          // number of image encoders
   UINT  size = 0;         // size of the image encoder array in bytes
   ImageCodecInfo* pImageCodecInfo = NULL;
   GetImageEncodersSize(&num, &size);
   if(size == 0) return -1;  // Failure
   pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
   if(pImageCodecInfo == NULL) return -1;  // Failure
   GetImageEncoders(num, size, pImageCodecInfo);
   for (UINT j = 0; j < num; ++j) {
      if ( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 ) {
         *pClsid = pImageCodecInfo[j].Clsid;
         free(pImageCodecInfo);
         return j;  // Success
      }
   }
   free(pImageCodecInfo);
   return -1;  // Failure
}
int wmain(int argc,wchar_t *argv[]) {
    int r=1;
    if (argc<4) {
    USAGE:
        wprintf(L"%s srcimg.{bmp|jpg|gif|tif|png|wmf|emf|ico}  desimg.{bmp|jpg|gif|tif|png}  angle\n",argv[0]);
        return r;
    }
    int i;
    for (i=0;i<5;i++) {
        if (0==_wcsicmp(argv[1]+wcslen(argv[1])-4,exts[i])) break;
    }
    if (i>=5) goto USAGE;
    for (i=0;i<5;i++) {
        if (0==_wcsicmp(argv[2]+wcslen(argv[2])-4,exts[i])) break;
    }
    if (i>=5) goto USAGE;
    GdiplusStartupInput gdiplusstartupinput;
    ULONG_PTR gdiplustoken;
    GdiplusStartup(&gdiplustoken, &gdiplusstartupinput, NULL);
    {
        Image img(argv[1]);
        if (Ok==img.GetLastStatus()) {
            UINT height = img.GetHeight();
            UINT width  = img.GetWidth();
            REAL angle;
            if (1==swscanf_s(argv[3],L"%f",&angle)) {
                REAL size;
                size=(REAL)sqrt(1.0*width*width+1.0*height*height);
                Matrix mat;
                mat.Translate(size / -2.0f, size / -2.0f);
                mat.Rotate(-angle, MatrixOrderAppend);
                mat.Translate(size / 2.0f, size / 2.0f, MatrixOrderAppend);
                PointF pfTL((size-width)/2.0f      ,(size-height)/2.0f       );
                PointF pfTR((size-width)/2.0f+width,(size-height)/2.0f       );
                PointF pfBL((size-width)/2.0f      ,(size-height)/2.0f+height);
                PointF pfBR((size-width)/2.0f+width,(size-height)/2.0f+height);
                Graphics tgp(&img);
                Bitmap bmp((UINT)size,(UINT)size,&tgp);//Let bmp Resolution equal to img Resolution
                Graphics gp(&bmp);
                gp.SetTransform(&mat);
                gp.DrawImage(&img,pfTL);
                REAL xmin,ymin,xmax,ymax,x,y,rw,rh;
                mat.TransformPoints(&pfTL);
                xmin=xmax=pfTL.X;
                ymin=ymax=pfTL.Y;
                mat.TransformPoints(&pfTR);
                if (xmin>pfTR.X) xmin=pfTR.X;
                if (xmax<pfTR.X) xmax=pfTR.X;
                if (ymin>pfTR.Y) ymin=pfTR.Y;
                if (ymax<pfTR.Y) ymax=pfTR.Y;
                mat.TransformPoints(&pfBL);
                if (xmin>pfBL.X) xmin=pfBL.X;
                if (xmax<pfBL.X) xmax=pfBL.X;
                if (ymin>pfBL.Y) ymin=pfBL.Y;
                if (ymax<pfBL.Y) ymax=pfBL.Y;
                mat.TransformPoints(&pfBR);
                if (xmin>pfBR.X) xmin=pfBR.X;
                if (xmax<pfBR.X) xmax=pfBR.X;
                if (ymin>pfBR.Y) ymin=pfBR.Y;
                if (ymax<pfBR.Y) ymax=pfBR.Y;
                x=xmin;
                y=ymin;
                rw=xmax-x;
                rh=ymax-y;
                Bitmap* clone;
                clone = bmp.Clone(x,y,rw,rh,PixelFormat24bppRGB);//bmp.GetPixelFormat()
                CLSID encoderClsid;
                if (0<=GetEncoderClsid(formats[i],&encoderClsid)) {
                    if (Ok==clone->Save(argv[2],&encoderClsid)) {
                        wprintf(L"OK to %s  %s  %s  %s\n",argv[0],argv[1],argv[2],argv[3]);
                        r=0;
                    } else {
                        wprintf(L"Error to save %s\n",argv[2]);
                        r=4;
                    }
                } else {
                    wprintf(L"Error to GetEncoderClsid(%s,...)\n",formats[i]);
                    r=3;
                }
                delete clone;
            } else {
                wprintf(L"Error to get angle %s\n",argv[3]);
                r=2;
            }
        } else {
            wprintf(L"Error to load %s\n",argv[1]);
            r=5;
        }
    }
    GdiplusShutdown(gdiplustoken);
    return r;
}
dustpg 2016-04-22
  • 打赏
  • 举报
回复
WIC组件吧,想保存什么格式就什么格式.

3,882

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧