AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi Direct2D.Canvas in einer Bitmap speichern
Thema durchsuchen
Ansicht
Themen-Optionen

Direct2D.Canvas in einer Bitmap speichern

Ein Thema von cocsy · begonnen am 15. Mär 2023 · letzter Beitrag vom 19. Apr 2023
Antwort Antwort
cocsy

Registriert seit: 12. Jul 2011
31 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Direct2D.Canvas in einer Bitmap speichern

  Alt 31. Mär 2023, 09:10
ich arbeite auf einem richtigen Rechner,
- Prozessor Intel(R) Core(TM) i7-8550U CPU @ 1.80GHz, 1992 MHz, 4 Kern(e), 8 logische(r) Prozessor(en)
- System-SKU LENOVO_MT_20L7_BU_Think_FM_ThinkPad T480s



Delphi-Quellcode:
Debug-Ausgabe: VCLBitmap.Canvas.Handle: 0000000022010EB5 Prozess _Test.exe (16108)
Debug-Ausgabe: VCLBitmap.Handle: 0000000001053574 Prozess _Test.exe (16108)
Debug-Ausgabe: VCLBitmap.Height: 424 Prozess _Test.exe (16108)
Debug-Ausgabe: MappedRect.bits: 000002422D6E0000 Prozess _Test.exe (16108)
Debug-Ausgabe: BitmapInfo.bmiHeader.biSize: 40 Prozess _Test.exe (16108)
Debug-Ausgabe: BitmapInfo.bmiHeader.biHeight: -424 Prozess _Test.exe (16108)
Debug-Ausgabe: BitmapInfo.bmiHeader.biWidth: 624 Prozess _Test.exe (16108)
Debug-Ausgabe: BitmapInfo.bmiHeader.biPlanes: 1 Prozess _Test.exe (16108)
Debug-Ausgabe: BitmapInfo.biBitCount.biSize: 32 Prozess _Test.exe (16108)
Jan

Geändert von cocsy (31. Mär 2023 um 09:16 Uhr)
  Mit Zitat antworten Zitat
cocsy

Registriert seit: 12. Jul 2011
31 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Direct2D.Canvas in einer Bitmap speichern

  Alt 31. Mär 2023, 09:15
ich habe meinen Unterschied erkannt, ich arbeite mit Win64...
mit Win32 klappt es
Jan
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.077 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Direct2D.Canvas in einer Bitmap speichern

  Alt 31. Mär 2023, 09:48
Wild, in Win64 geht's bei mir auch nicht.
Ich kann aber auch nur die ersten 3307 Bytes von MappedRect.bits auslesen, danach ist Zugriffsverletzung.

Delphi-Quellcode:
...
                HR := CopyBitmap.Map(MapOptions, MappedRect);
                if Succeeded(HR) then
                begin
                    SetLength(NewPtr, MappedRect.pitch * SizeU.Height);
                    Stream := TBytesStream.Create(NewPtr);
                    Stream.Write(MappedRect.bits, (3 * 1024) + 235);
...
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.077 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Direct2D.Canvas in einer Bitmap speichern

  Alt 31. Mär 2023, 13:30
Kann auch gut sein, dass die Intel-Treiber da einen Hau weg haben.
Wenn es in 32-Bit geht und 64-Bit nicht ist schon komisch.
Auf Arbeit hatten wir mit alten Intel-Treibern auch irre Probleme mit OpenGL.
Das haben die auch erst kürzlich gelöst.
Vielleicht kannst du das Programm woanders mit dedizierter Grafikkarte von AMD oder Nvidia laufen lassen.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.464 Beiträge
 
Delphi 12 Athens
 
#5

AW: Direct2D.Canvas in einer Bitmap speichern

  Alt 31. Mär 2023, 14:34
Es gibt bei Bitmaps auch noch ein paar andere Punkte, auf die man mal achten könnte.

* Wenn es nicht 32 Bit pro Pixel sind, dann gibt es eventuell ein Alignment der einzelnen Lines (zumindestens beim Delphi/GDI-Bitmap)

* und wie rum liegen die Lines im Speicher
* * von unten links nach oben rechts oder von oben links nach unten rechts (also Line 0 gefolgt von den Anderen oder die anderen Lins vor der Line 0 ... wenn man alles zusammen kopiert und nicht jede Line einzeln abfragt)
* * oder liegen die Lines garnicht zusammenhängend im Speicher?
* * das wäre z.B. eine Erklärung für "Ich kann aber auch nur die ersten 3307 Bytes von MappedRect.bits auslesen, danach ist Zugriffsverletzung"
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (31. Mär 2023 um 14:37 Uhr)
  Mit Zitat antworten Zitat
cocsy

Registriert seit: 12. Jul 2011
31 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Direct2D.Canvas in einer Bitmap speichern

  Alt 3. Apr 2023, 08:55
Kann auch gut sein, dass die Intel-Treiber da einen Hau weg haben.
Wenn es in 32-Bit geht und 64-Bit nicht ist schon komisch.
Auf Arbeit hatten wir mit alten Intel-Treibern auch irre Probleme mit OpenGL.
Das haben die auch erst kürzlich gelöst.
Vielleicht kannst du das Programm woanders mit dedizierter Grafikkarte von AMD oder Nvidia laufen lassen.
Ich habe es getestet auf einem AMD-System, das verhalten ist gleich.
____


Ich vermute eine unterschiedliche Bit-Strucktur zw. Win32 und Win64. Auch wenn ich das als unlogisch empfinde.
Jan
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.464 Beiträge
 
Delphi 12 Athens
 
#7

AW: Direct2D.Canvas in einer Bitmap speichern

  Alt 3. Apr 2023, 10:04
Ich vermute eine unterschiedliche Bit-Strucktur zw. Win32 und Win64. Auch wenn ich das als unlogisch empfinde.
Wenn die selbe API, dann zumindestens Speicher-Alignment.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.077 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Direct2D.Canvas in einer Bitmap speichern

  Alt 3. Apr 2023, 13:27
Kein Plan warum es genau mit SetDIBits scheitert, vielleicht stimmt was mit Pitch und Width nicht.
Aber ich habe den SaveToFile-Pfad von TBitmap nachgebastelt und kopiere jetzt den Buffer von mappedrect.bits zeilenweise in ein Byte-Array, was dann in einen Filestream geschrieben wird.
Den Umweg über das Array kann man sich ggf. sparen und gleich in den Stream schreiben. Es sei dem geneigten Leser als Hausaufgabe überlassen.
Damit klappt es auch unter 64-Bit in den meisten Formaten (Höhe x Breite):
Delphi-Quellcode:
procedure DoSaveAsBitmapRaw(const ARenderTarget: ID2D1RenderTarget; ABitmapFileName: string = '');
var
    HR: HResult;
    DeviceContext: ID2D1DeviceContext;
    CopyBitmap: ID2D1Bitmap1;
    MapOptions: D2D1_MAP_OPTIONS;
    MappedRect: D2D1_MAPPED_RECT;
    SizeU: D2D1_SIZE_U;
    destPoint: D2D1_POINT_2U;
    srcRect: D2D1_RECT_U;
    BitmapProps: D2D1_BITMAP_PROPERTIES1;
    BitmapInfo: TBitmapInfo;
    MyBuffer: TBytes;
    Stream: TFileStream;
    I: Integer;
    BMF: TBitmapFileHeader;
    Colors: array [Byte] of TRGBQuad;
    ColorCount: Integer;
    HeaderSize: Integer;
    NewLine: Integer;
    Src: Pointer;
    Dst: Pointer;
    BufferSize: Integer;
    BytesPerPixel: Cardinal;
begin
    if Supports(ARenderTarget, ID2D1DeviceContext, DeviceContext) then
    begin
        DeviceContext.GetPixelFormat(BitmapProps._pixelFormat);
        if BitmapProps._pixelFormat.format = Winapi.DxgiFormat.DXGI_FORMAT_B8G8R8A8_UNORM then
        begin
            BytesPerPixel := 4;
        end else
            raise Exception.Create('Kümmere dich, hier stimmt was nicht!');


        DeviceContext.GetDpi(BitmapProps.dpiX, BitmapProps.dpiY);
        DeviceContext.GetPixelSize(SizeU);
        BitmapProps.bitmapOptions := D2D1_BITMAP_OPTIONS_CPU_READ or D2D1_BITMAP_OPTIONS_CANNOT_DRAW;

        HR := DeviceContext.CreateBitmap(SizeU, nil, 0, @BitmapProps, CopyBitmap);
        if Succeeded(HR) then
        begin
            FillChar(srcRect, SizeOf(srcRect), 0);
            srcRect.right := SizeU.Width;
            srcRect.bottom := SizeU.Height;

            FillChar(destPoint, SizeOf(destPoint), 0);
            HR := CopyBitmap.CopyFromRenderTarget(destPoint, DeviceContext, srcRect);
            if Succeeded(HR) then
            begin
                MapOptions := D2D1_MAP_OPTIONS_READ;
                FillChar(MappedRect, SizeOf(MappedRect), 0);
                HR := CopyBitmap.Map(MapOptions, MappedRect);
                if Succeeded(HR) and (MappedRect.bits <> nil) then
                begin
                    BufferSize := MappedRect.pitch * SizeU.Height;

                    Stream := TFileStream.Create(ABitmapFileName, fmCreate);
                    try
                        FillChar(BMF, SizeOf(BMF), 0);
                        HeaderSize := 40;
                        BMF.bfType := $4D42;
                        BMF.bfSize := BufferSize + HeaderSize + SizeOf(BMF);
                        BMF.bfOffBits := SizeOf(BMF) + HeaderSize;

                        Stream.Write(BMF, SizeOf(BMF));


                        FillChar(BitmapInfo, SizeOf(BitmapInfo), 0);
                        BitmapInfo.bmiHeader.biSize := SizeOf(BitmapInfo.bmiHeader);
                        BitmapInfo.bmiHeader.biHeight := -SizeU.Height;
                        BitmapInfo.bmiHeader.biWidth := Longint(MappedRect.pitch div BytesPerPixel);
                        BitmapInfo.bmiHeader.biPlanes := 1;
                        BitmapInfo.bmiHeader.biBitCount := 8 * BytesPerPixel;
                        BitmapInfo.bmiHeader.biCompression := BI_RGB;

                        Stream.WriteBuffer(BitmapInfo, Sizeof(BitmapInfo));


                        ColorCount := 0;

                        Stream.WriteBuffer(Colors, ColorCount * SizeOf(TRGBQuad));


                        SetLength(MyBuffer, BufferSize);
                        for I := 0 to SizeU.Height - 1 do
                        begin
                            NewLine := I * Integer(MappedRect.Pitch);
                            Src := Pointer(NativeInt(MappedRect.bits) + NewLine);
                            Dst := Pointer(NativeInt(@MyBuffer[0]) + NewLine);
                            Move(Src^, Dst^, NativeInt(SizeU.Width * BytesPerPixel));
                        end;

                        Stream.WriteBuffer((@MyBuffer[0])^, Length(MyBuffer));
                    finally
                        Stream.Free;
                    end;

                    CopyBitmap.Unmap;
                end;
            end;
        end;
    end;
end;
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:54 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz