为什么我的位图绘制功能在我给它的位置偏移处绘制? (C VGA模式12h)

时间:2016-02-04 14:48:25

标签: c bitmap vga

我正在使用DOSBOX运行程序,在模式12h使用VGA在C上创建位图绘制功能。我在屏幕上显示图像,但是图像的开头是在屏幕中间绘制而不是(0,0)。谁能告诉我为什么我会这样做?

我的plot_pixel函数运行正常。我能够在屏幕上画线和绘制像素而不会得到我现在得到的奇怪偏移。

这显示了问题。

原始图片: enter image description here

结果: enter image description here

这是我的代码:

加载BMP:

/**************************************************************************
 *  load_bmp                                                              *
 *    Loads a bitmap file into memory.                                    *
 **************************************************************************/

void load_bmp(char *file, BITMAP *b){

    FILE *fp;
    long index;
    byte a;
    word num_colors;
    int x;
    //SetGfxMode(0x3);

    /*Opening file */
    if((fp = fopen(file,"rb")) == NULL){

        printf("Error al abrir el archivo %s.\n",file);
        exit(1);
    }

    /*Validating if the image is a valid bitmap*/
    if(fgetc(fp) != 'B' || fgetc(fp) != 'M'){

        fclose(fp);
        printf("%s is not a bitmap file. \n", file);
        exit(1);

    }


    /*Height and width of the image
    */
    fskip(fp,16);
    fread(&b->width, sizeof(word),1 , fp);
    fskip(fp,2);
    fread(&b->height, sizeof(word),1,fp);
    fskip(fp,22);
    fread(&num_colors,sizeof(word),1,fp);
    fskip(fp,6);

    /* We are loading a 16 color image */
    if(num_colors ==0) num_colors = 16;


    /*Intentamos alojar memoria para la data del bitmap*/
    if((b->data = (byte *) malloc((b->width*b->height))) == NULL)
    {
        fclose(fp);
        printf("Error allocating memory for file %s.\n",file);
        exit(1);

    }

    /*Reading pallete info*/
    for(index=0;index<num_colors;index++){
        b->pallete[(int)(index*3+2)] = fgetc(fp) >> 2;
        b->pallete[(int)(index*3+1)] = fgetc(fp) >> 2;
        b->pallete[(int)(index*3+0)] = fgetc(fp) >> 2;
        //fskip(fp,240);
        x = fgetc(fp);

    }


    /* Leyendo el bitmap*/
    for(index=(b->height-1)*b->width;index>=0;index-=b->width){
        for(x=0;x<b->width;x++){
          b->data[index+x]=(byte)fgetc(fp);
        }
    }
    fclose(fp);


}

绘制位图:

/**************************************************************************
 *  draw_transparent_bitmap                                               *
 *    Draws a transparent bitmap.                                         *
 **************************************************************************/

void draw_transparent_bitmap(BITMAP *bmp,int x,int y)
{
  int i,j;
  unsigned long bitmap_offset = 0;
  byte data;
    copyMemory(double_buffer,VGA);

    printf("sum");
    getch();
  for(j=0;j<bmp->height;j++)
  {
    for(i=0;i<bmp->width;i++)
    {
      data = bmp->data[bitmap_offset];
      //if (data) double_buffer[screen_offset+x+i] = data;
      if(data) plot_pixel(x+i,y+j,data);
      bitmap_offset++;
    }
  }
}

设置托盘

void set_pallete(byte *pallete){
    int i;
    outp(PALETTE_INDEX,0);
    for(i=0;i<16*3;i++){
        outp(PALETTE_DATA,pallete[i]);
    }
}

主要

typedef struct

{
    word width;
    word height;
    byte pallete[256*3];
    byte *data;


} BITMAP;
BITMAP fondo_inicio;


load_bmp("home16.bmp",&fondo_inicio);
set_pallete(fondo_inicio.pallete);
draw_transparent_bitmap(&fondo_inicio,0,0); 

1 个答案:

答案 0 :(得分:2)

我没有说服你正确加载BMP。每个维基百科,在你检查过BM&#39;假设fskip之后,有希望设法将这个作为一个罕见的全部但客观的事实,你的代码是正确的。旋转fseek,采取以下步骤:

  • 跳过4个字节,告诉您BMP大小;
  • 跳过4个保留字节;
  • 跳过4个字节,告诉你应该从哪里加载像素数据(你真的应该消费并服从);
  • 假设您正在获取Windows 3.1辅助标头并跳过4个字节告诉您其长度(您不应该);
  • 读取宽度的低两个字节;
  • 跳过宽度的上两个字节;
  • 读取高度的低两个字节;
  • 跳过高度的高两个字节;
  • skip:颜色平面数(+ 2个字节),每像素位数(+ 2个字节),压缩方法(+ 4 = 10),图像大小(+ 4 = 14),水平密度(+ 4 = 18) ,垂直密度(+4 = 22);
  • 读取调色板大小的前两个字节;
  • 跳过接下来两个字母的调色板大小;
  • 跳过重要颜色的数量;
  • 假设标题已经结束(但你应该读取标题大小并在此处跳过相应的标题);
  • 读取RGBA调色板,假设它知道图像为16色,丢弃alpha并从每通道8位映射到VGA样式的6位;
  • 假设图像数据在调色板之后直接显示(你不应该早点读取它的文件偏移量);
  • 读取每像素图像数据一个字节。即使您已经假定每像素有4位用于读取调色板。

如果读取每个像素的整个字节提供正确的图像宽度,那么您的BMP文件可能不是4位。这意味着你对标题大小的假设肯定是错误的。几乎可以肯定,你作为图像数据存储的是一大块标题,然后是图像。首先不跳过告诉您图像数据开始位置的标题条目 - 阅读并使用它。否则,如果您的plot_pixel自动将8位映射到4位,那么如果您正在加载256色图像并假设只使用最低的16种颜色,那么这不是一个大问题,假设持有您的源图像和存储空间无关紧要。