【问题标题】:Delphi DIB with DIB Header into TBitmapDelphi DIB 与 DIB 标头到 TBitmap
【发布时间】:2010-01-29 17:51:41
【问题描述】:

请您帮我解决这个问题:

有一个字节数组 (data: PByte) 包含 DIB 数据和 DIBHeader:

TDibHeader = record size: Cardinal; width: Integer; height: Integer; planes: Word; bits: Word; compression: Cardinal; image_size: Cardinal; x_res: Integer; y_res: Integer; n_colors: Cardinal; important_colors: Cardinal; end;

如何在保持低CPU使用率的同时将DIB转换为TBitmap?

我试过http://files.codes-sources.com/fichier.aspx?id=43989&f=GdipApi.pas 没有成功。

我已将 DIB 分配给内存流:

DibMemStream.Clear; DibMemStream.SetSize(header.image_size); MoveMemory(DibMemStream.Memory,DibBuffer,header.image_size);

我想在 Bitmap.LoadFromMemoryStream(DibMemStream) 之前的某个地方应该有 DIB 标头。不知道在哪里。

有什么想法吗?

谢谢!

【问题讨论】:

    标签: delphi bitmap dib


    【解决方案1】:

    我使用以下方案将内存中的图像转换为 TBitmap:

    1) 填充TBMPHeader结构

      TBMPHeader = packed record
        bmfHeader: TBitmapFileHeader;
        bmiHeader: TBitmapInfoHeader;
        bmiColors: {depends on image format, may be absent};
      end;
    

    2) 将 BMPHeader + 图像数据写入 MemoryStream

    3) 使用 TBitmap.LoadFromStream 从 MemoryStream 加载 TBitmap

    您似乎已经填充了 bmiHeader 结构。添加 bmfHeader 和(也许)bmiColors。

    这是我用来将 256 色灰度内存图像转换为 TBitmap 的代码(很多年前,抱歉,所以没有详细信息):

    procedure TksImage.CopyToBitmap(Bitmap: TBitmap);
    var
      Stream: TStream;
    
    begin
      Stream:= TMemoryStream.Create;
      try
        SaveToStream(Stream);
        Stream.Position:= 0;
        Bitmap.LoadFromStream(Stream);
      finally
        Stream.Free;
      end;
    end;
    
    procedure TksImage.SaveToStream(Stream: TStream);
    type
      TBMPHeader = packed record
        bmfHeader: TBitmapFileHeader;
        bmiHeader: TBitmapInfoHeader;
        bmiColors: array[0..255] of TRGBQuad;
      end;
    
    var
      BMPHeader: TBMPHeader;
      N: LongWord;
      I: Integer;
    
    begin
      FillChar(BMPHeader, SizeOf(BMPHeader), 0);
      with BMPHeader.bmfHeader do begin
        bfType:= $4D42; {'BM'}
        bfOffBits:= SizeOf(BMPHeader);
        if FChannels = 4 then Dec(bfOffBits, SizeOf(BMPHeader.bmiColors));
        bfSize:= bfOffBits + LongWord(FImageSize);
      end;
      with BMPHeader.bmiHeader do begin
        biSize:= SizeOf(BMPHeader.bmiHeader);
        biWidth:= FWidth;
        biHeight:= FHeight;
        biPlanes:= 1;
        biBitCount:= 8 * FChannels;
        biCompression:= BI_RGB;
        biSizeImage:= FImageSize;
        {((((biWidth * biBitCount) + 31) and not 31) shr 3) * biHeight;}
      end;
      N:= 0;
      for I:= 0 to 255 do begin
        LongWord(bmpHeader.bmiColors[I]):= N;
        Inc(N, $010101);
      end;
      Stream.Write(BMPHeader, BMPHeader.bmfHeader.bfOffBits);
      Stream.Write(FImageData^, FImageSize);
    end;
    

    【讨论】:

    • Serg,当 bmiColors 从记录中删除时,它就像一个魅力 :) 谢谢!
    【解决方案2】:

    自从我进行任何 Delphi 编码以来已经很长时间了,我还无法对此进行测试,但是如果您可以提供 DIB 的句柄,那么有一个函数 - hDIBToTBitmap1() - 应该可以解决问题这个链接:

    http://www.efg2.com/Lab/Library/Delphi/Graphics/LeadToolsConversions.TXT

    【讨论】:

    • 如何将 PByte 数组作为 THandle 传递(需要 hDIB)。 THandle() 铸造不会成功,但类似的事情?
    • PByteTHandle 是两个非常不同的东西,所以你不能投射。
    猜你喜欢
    • 2012-01-07
    • 2013-10-16
    • 2020-08-05
    • 2012-03-20
    • 2012-08-23
    • 2010-09-15
    • 1970-01-01
    • 2017-10-10
    • 1970-01-01
    相关资源
    最近更新 更多