在 c , PNG , JPEG 上打开图像文件

新手上路,请多包涵

我试图打开 bg.png 文件,但没有用。没有错误,但什么也没有出现。帮我!

 int main()
    {
        initwindow(600,600,"GAME");
        ifstream image("bg.png");
        getimage(50, 50 , 450 , 450 , image);
        putimage(50,50,image,COPY_PUT);
        system("pause");
    }

原文由 Bayarjargal Jargalsaikhan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 474
2 个回答

graphics.h 是来自 Borland 的古老 BGI 库,我找到了这个文档:

所以这只是将图像从您的屏幕复制到一些内存缓冲区(以允许后缓冲技术)。你用 ifstream 来调用它,这是错误的。您正在用内存缓冲区或其指针指向的区域覆盖指针(取决于 getimage 行为)。如果您真的想为此使用 BGI ,则将图像解码到内存并使用 putimage 来查看它。但恐怕它不是以 RAW 编码的,更安全的是直接使用像素访问来绘制图像。

正如我写给你的另一个问题一样,你需要使用一些库或编码图像解码你自己。 iostream 这不是一个好方法。

对于 MS-DOS 使用 OS api ( int 21h 如果你没有正确覆盖它的功能) …对于 WindowsBorland 环境使用 FileOpen FileRead FileClose 。对于非 Borland 环境,使用 WinAPI 或来自目标 操作系统(如果不是 windows)的相关 API 。要解码图像,您首先需要选择要解码的文件格式,我建议从 PCX、BMP (仅限于单像素格式)或 TGA 开始。像 JPG、PNG、GIF 这样的文件格式对于新手程序员来说实在是太多了。例如,我在 C++ 中的 GIF 解码器/编码器大约是 36 KByte 的源代码 + 另一个 15 KBytes 用于文件缓存 缓冲多线程 RT 编码调度程序。与具有大约 1.5KByte 的代码来加载/解码它的 PCX 相比。

这是我如何在 Borland/Embarcadero VCL C++ Windows 中将纹理加载到我的 GL 引擎的小例子:

 int picture_load(Graphics::TBitmap *bmp,AnsiString name,int *_alpha)
    {
    if (bmp==NULL)        { _errorlog+="picture_load bmp is NULL\n"; return 0; }
    if (!FileExists(name)){ _errorlog+="picture_load file \""+name+"\" dont exist\n"; return 0; }
    bmp->HandleType=bmDIB;
    bmp->PixelFormat=pf32bit;
    AnsiString ext=ExtractFileExt(name).LowerCase();
    for(;;)
        {
        if (ext==".bmp")
            {
            bmp->LoadFromFile(name);
            break;
            }
        if (ext==".jpg")
            {
            TJPEGImage *jpg=new TJPEGImage;
            #ifdef _mmap_h
            if (jpg) mmap_new('GL',jpg,sizeof(TJPEGImage));
            #endif
            if (jpg==NULL) { _errorlog+="picture_load not enough memory\n"; return 0; }
            jpg->LoadFromFile(name);
            bmp->Assign(jpg);
            #ifdef _mmap_h
            mmap_del('GL',jpg);
            #endif
            delete jpg;
            break;
            }
        if (ext==".png")
            {
            TPNGObject *png=new TPNGObject;
            #ifdef _mmap_h
            if (png) mmap_new('GL',png,sizeof(TJPEGImage));
            #endif
            if (png==NULL) { _errorlog+="picture_load not enough memory\n"; return 0; }
            png->LoadFromFile(name);
            bmp->Assign(png);
            #ifdef _mmap_h
            mmap_del('GL',png);
            #endif
            delete png;
            break;
            }
        if ((ext==".sgi")||(ext==".rgb"))
            {
            sgi sss;
            sss.load(name);
            bmp->Width=sss.rgba->Width;
            bmp->Height=sss.rgba->Height;
            bmp->Canvas->Draw(0,0,sss.rgba);
            break;
            }
        if (ext==".pcx")
            {
            unsigned int *p,c;
            int     x,y,adr;
            int hnd,siz,l,xs,ys;
            unsigned int pal[256],r,g,b;
            Byte *dat;
            for(;;)
                {
                hnd=FileOpen(name,fmOpenRead);
                if (hnd<0) { _errorlog+="picture_load file \""+name+"\" dont exist\n"; return 0; }
                siz=FileSeek(hnd,0,2);
                FileSeek(hnd,0,0);
                dat=new Byte[siz];
                #ifdef _mmap_h
                if (dat) mmap_new('GL',dat,siz*sizeof(BYTE));
                #endif
                if (dat==NULL) { FileClose(hnd); _errorlog+="picture_load not enough memory\n"; return 0; }
                FileRead(hnd,dat,siz);
                FileClose(hnd);
                adr=siz-3*256;
                for (l=0;l<256;l++)
                    {
                    r=dat[adr]; adr++; r&=255;
                    g=dat[adr]; adr++; g&=255;
                    b=dat[adr]; adr++; b&=255;
                    c=(r<<16)|(g<<8)|(b);
                    c&=0x00FFFFFF;
                    pal[l]=c;
                    }
                xs=int(dat[ 8])-int(dat[4])+((int(dat[ 9])-int(dat[5]))<<8)+1;
                ys=int(dat[10])-int(dat[6])+((int(dat[11])-int(dat[7]))<<8)+1;

                bmp->HandleType=bmDIB;
                bmp->PixelFormat=pf32bit;
                bmp->Width=xs;
                bmp->Height=ys;
                xs=bmp->Width;
                ys=bmp->Height;

                adr=128;
                for (y=0;y<ys;y++)
                    {
                    p=(unsigned int*)bmp->ScanLine[y];
                    for (x=0;x<xs;)
                        {
                        c=dat[adr];
                        if (c<192) l=1;
                        else{
                            l=c&63;
                            adr++;
                            c=dat[adr];
                            }
                        adr++;
                        for (;l>0;l--)
                            {
                            if (x>=xs) break;
                            p[x]=pal[c];
                            x++;
                            }
                        }
                    }
                #ifdef _mmap_h
                mmap_del('GL',dat);
                #endif
                delete[] dat;
                break;
                }
            break;
            }
        if (ext==".dds")
            {
            DDS::load(bmp,name);
            _errorlog+=DDS::_errorlog;
            DDS::_errorlog="";
            break;
            }
        _errorlog+="picture_load unsuported file extension \""+ext+"\"\n";
        return 0;
        }
    bmp->HandleType=bmDIB;
    if (_alpha) _alpha[0]=(bmp->PixelFormat==pf32bit);
    bmp->PixelFormat=pf32bit;
    return 1;
    }

由于您的代码看起来像是在 MS-DOS 中,这将不起作用。但您可以提取不使用任何库的 PCX 部分。只需移植代码(替换 AnsiString 并使用您可以使用的功能进行文件访问)

Graphics::TBitmapVCL/GDI 位图,了解其使用请参见:

所以你可以把它移植到你的 BGI 。您也可以忽略所有 #ifdef _mmap_h 与此相关的内存泄漏跟踪/调试剩余的东西:

并在这里查看 PCX 文件格式规范

原文由 Spektre 发布,翻译遵循 CC BY-SA 3.0 许可协议

这个:

 ifstream image("bg.png");

… 以 文本模式 打开文件,在 Windows 和旧 Mac 中,某些表示行尾和文本结束的字节序列在输入和输出时发生更改。

你不想要那个。

指定 二进制模式


也就是说,最接近 C++ 中“标准”图像处理的是 Boost Image 库

原文由 Cheers and hth. - Alf 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题