Italia
Fonte/ Codesnippets

Handle sehr grande Bilder Ole

 
- Page 1 -



Jörg
Sellmeyer
Ich hab jetzt via Ole (Dank an Andreas Miethe - immer wieder) ein funktionierendes Handle per Bitmaps (auch gif, ico und diverse andere Formate) ermitteln können, das dann ganz normal auf einem Bitmapstatic angezeigt werden kann. Mit der Ermittlung der Dimensione kann ich mich in dem Fall noch nicht ganz anfreunden. Wer da eine Idee hat - im Code ist die Stelle markiert.

Hier jedenfalls erstmal der Code, um ein gültiges Handle auch per grande Bilder zu erhalten.
Wenn man es im Programm häufiger verwendet, ist es sicher sinnvoller, die Init-Routine nur einmal am Anfang aufzurufen, aber so funktioniert es schon mal klaglos.
Bitte mal mit File größer als 5100 Pixeln testen. Aktuell habe ich es nur mit jpg und gif probiert. Icos sind ja größenmäßig nicht das Problem.
 $H windows.ph
'Konstanten
DEF &Picture_Release     8
DEF &Picture_GetHandle  12
DEF &Picture_GetType    20
DEF &Picture_Get_Width  24
DEF &Picture_Get_Height 28
DEF &Picture_Render     32
DEF &Picture_Select     44
'Globale Variablen
DECLARE IID_IPicture#
DECLARE PData#
DECLARE HMEM&
Declare OlePic#
Class OleImage = OleImage@,\
Ole_Init@,\
Ole_Free@,\
Ole_LoadImage@,\
Ole_GetType@,\
Ole_GetHandle@,\
Ole_FreeImage@,\
OLE32&,\
OLEPro32&,\
PictureObject&,\
hPic&,\
PicFormat&,\
Width&,\
Height&,\
GetSize@,\
Destroy@

Proc OleImage.OleImage

    Parameters File$
    .Ole_Init()
    .PictureObject& = .Ole_LoadImage(File$)
    .PicFormat& = .Ole_GetType(.PictureObject&)
    .hPic& = .Ole_GetHandle()
    Print .PictureObject&,.PicFormat&,.hpic&

EndProc

Proc OleImage.Ole_Init

    .OLE32& = UseDll("OLE32")
    .OLEPRO32& = UseDll("OLEPRO32")
    External("OLE32","OleInitialize",0)
    Dim IID_IPicture#,16
    Long IID_IPicture#,0 = $7BF80980
    Word IID_IPicture#,4 = $BF32
    Word IID_IPicture#,6 = $101A
    Byte IID_IPicture#,8 = $8B
    Byte IID_IPicture#,9 = $BB
    Byte IID_IPicture#,10 = $00
    Byte IID_IPicture#,11 = $AA
    Byte IID_IPicture#,12 = $00
    Byte IID_IPicture#,13 = $30
    Byte IID_IPicture#,14 = $0C
    Byte IID_IPicture#,15 = $AB

EndProc

Proc OleImage.Ole_Free

    ~GlobalFree(Hmem&)
    External("OLE32","OleUninitialize")
    FreeDll .OLE32&
    FreeDll .OLEPRO32&
    DISPOSE IID_IPicture#

EndProc

Proc OleImage.Ole_LoadImage

    Declare MemPointer&,PStream&,PictureObject&,PSize&
    Parameters Picture$
    '------------------------
    Set("Filemode", 0)
    PSIZE& = Filesize(Picture$)
    Dim PData#,PSIZE&
    BlockRead(Picture$,PData#,0,PSIZE&)'Daten in Bereichsvariable einlesen
    '------------------------
    ~GlobalFree(Hmem&)
    HMem& = ~GlobalAlloc($022,PSize&)'Speicher reservieren
    Mempointer& = ~GlobalLock(Hmem&)'Pointer auf Speicher
    ~RtlMoveMemory(MemPointer&,PData#,PSize&)'Bereichsvariable in Speicher schieben
    DISPOSE PData#'Bereichsvariable freigeben
    ~GlobalUnlock(HMem&)'Speicher zum Gebrauch freigeben
    External("Ole32","CreateStreamOnHGlobal",Hmem&,1,addr(PStream&))'Stream-Pointer erstellen
    External("OlePro32","OleLoadPicture",PStream&,PSIZE&,0,IID_IPicture#,ADDR(PictureObject&))'Pointer fuer Pictureobject
    '------------------------
    Case PictureObject& > 0 : Return PictureObject&
    Case PictureObject& = 0 : Return 0

EndProc

Proc OleImage.Ole_GetType

    Declare Command&,PicFormat&
    Command& = Long(.PictureObject&,0)
    Call(@Long(Command&,&Picture_GetType),.PictureObject&,addr(PicFormat&))
    Return PicFormat&

EndProc

Proc OleImage.GetSize

    Parameters DC&
    Declare Command&,w&,h&,xpixels&,ypixels&
    Command& = Long(.PictureObject&,0)
    'hier wird die Bildschirmauflösung pro Zoll abgefragt - bei mir 96x96.
    'Allerdings weiß ich nicht, welche Funktion in welcher dll da angesprochen wird.
    Call(@Long(Command&,&Picture_Get_Width),.PictureObject&,addr(w&))
    Call(@Long(Command&,&Picture_Get_Height),.PictureObject&,addr(h&))
    'die Dimensione des Fensters wird ermittelt
    xpixels& = ~GetDeviceCaps(DC&, 88)
    ypixels& = ~GetDeviceCaps(DC&, 90)
    'Umrechnung der Bildschirmauflösung auf die Fenstergröße.
    'Ich hab allerdings keine Ahnung, wie der Wert 2540 zustande kommt.
    .Width&  = Round((w&*xpixels&)/2540,0)
    .Height& = Round((h&*ypixels&)/2540,0)

EndProc

Proc OleImage.Ole_GetHandle

    Declare Command&,PicHandle&
    Command& = Long(.PictureObject&,0)
    Call(@Long(Command&,&Picture_GetHandle),.PictureObject&,addr(PicHandle&))
    Return PicHandle&

EndProc

Proc OleImage.Ole_FreeImage

    Parameters PictureObject&
    Declare Command&
    Command& = Long(PictureObject&,0)
    Call(@Long(Command&,&Picture_Release),PictureObject&)

EndProc

Proc OleImage.Destroy

    DeleteObject .hPic&,.PictureObject&
    .Ole_Free()

EndProc

Declare hbtn&,Bild$,hFont&,Anzeige&,OleAnzeige&,TestHandle&
UserMessages $10
~SetWindowLong(%hwnd,~GWL_STYLE,(~GetWindowLong(%hwnd,~GWL_STYLE) | $300000))
Window %maxx,%maxy
WindowTitle "Handle per OLE"
hFont& = Create("Font","Western ",14,0,0,0,0)
SetDialogFont hFont&
hbtn& = Create("Button",%hwnd,"Bild laden",%maxx-80,40,60,24)

WhileNot %key = 27'ESC beendet das Programm

    If GetText$(%hwnd) <> "Handle per OLE"

        WaitInput 4000
        WindowTitle "Handle per OLE"
        ShowWindow(hbtn&,5)

    EndIf

    WaitInput
    Case %uMessage = $10:Break

    If Clicked(hbtn&)

        Bild$ = LoadFile$("ÖFFNE","alle unterstützten Formate|*.dib;*.bmp;*.rle;*.jpe;*.jpeg;*.jpg;*.gif;*.ico;*.cur;*.emf;*.wmf|\
        Bitmap (bmp,rle,dib)|*.bmp;*.rle;*.dib|Jpeg (jpg,jpe,jpeg)|*.jpg;*.jpe;*.jpeg|Gif (gif)|*.gif|\
        Enhanced Metafile (emf)|*.emf|Metafile (wmf)|*.wmf|Icons (Ico)|*.ico|Cursor (cur)|*.cur")

        If Bild$ > ""

            TestHandle& = Create("hPic",-1,Bild$)
            'bei grande Bildern ist hier das Ergebnis 0
            WindowTitle Str$(TestHandle&) + " Bei sehr grande Bildern ist das Ergebnis hier 0"
            DeleteObject TestHandle&

            If SizeOf(OlePic#)

                DestroyWindow(OleAnzeige&)
                OlePic#.Destroy()
                Dispose OlePic#

            EndIf

            OlePic# = New(OleImage,Bild$)

            If Anzeige&

                DestroyWindow(Anzeige&)
                waitinput
                Cls

            EndIf

            With OlePic#

                'die Handleermittlung via Ole bringt ein verwertbares Handle:
                OlePic#.GetSize(%hdc2)
                Print .Width&,.Height&,"Typ:",.Ole_GetType()

                If .PicFormat& = 1

                    OleAnzeige& = Create("Bitmap",%hwnd,.hPic&,0,0)
                    .GetSize(%hdc2)
                    Print .Width&,OlePic#.Height&

                ElseIf .PicFormat& = 3

                    Print "Icon ist Typ:",.PicFormat&,"und kann schneller mit Profanmitteln angezeigt werden."

                EndIf

            EndWith

        EndIf

    EndIf

Wend

If SizeOf(OlePic#)

    OlePic#.Destroy()
    Dispose OlePic#

EndIf

DeleteObject hFont&
End

Basierend auf diesem Code  [...]  von Andreas Methe
 
Windows XP SP2 XProfan X4
... und hier mal was ganz anderes als Profan ...
03.06.2020  
 



 
- Page 2 -



Jörg
Sellmeyer
Leider lässt du uns im Unklaren, mit welchem Code du das Bild geladen hast.
Bei mir zumindest ist es mit dem Code von Matthias - also mit rein profanen Mitteln - nicht ladbar. Das è, es wird nicht angezeigt und es wird auch kein Handle erzeugt, sondern hPic& ist 0.

Mit meinem Code (mit Ole) dagegen gibt es ein gültiges Handle und das Bild wird angezeigt. Es wird naturalmente nur ein kleiner Ausschnitt angezeigt, weil der Code auch nichts weiter vorsieht.

Sollte es am zu geringen Speicher liegen, ist es ja trotzdem offensichtlich, dass die Ole-Methode die bessere ist, da die ja dann auf meinem System (mit zu wenig Speicher) funktioniert, während Create("hPic",...) da versagt.
 
XProfan X4
Windows XP SP2 XProfan X4
... und hier mal was ganz anderes als Profan ...
10.06.2020  
 




Matthias
Arlt
64k-Grenze wäre vielleicht ein Erklärungsversuch. Zu wenig Speicher eher nicht, ich habe aktuell 2.5GB RAM.

Jörg Sellmeyer (10.06.2020)
Sollte es am zu geringen Speicher liegen, ist es ja trotzdem offensichtlich, dass die Ole-Methode die bessere ist, da die ja dann auf meinem System (mit zu wenig Speicher) funktioniert, während Create("hPic",...) da versagt.


Das sehe ich auch so. Trotzdem wäre interessant, ob es am Speicherausbau des Rechners hängt, was ich wie gesagt eher nicht annehme, oder an der Speicherbitmap von Profan. Letzeres kann wohl nur Roland sicher beantworten. Bisher hat ja dieses Problem nicht zur Diskussion gestanden. Wohl weil es no aufgefallen ist...wann hat man schon mal solch Riesenbild.
 
WinXP SP2, Win7 - XProfan 10/11/FreeProfan32 - Xpia
10.06.2020  
 




Jörg
Sellmeyer
In einer Auflösung von 300 dpi kneift Profan da schon viel früher. Wenn man etwas Grafikbearbeitung macht, ist man schnell bei solchen Größen. Bisher habe ich per die Anzeige solcher Bilder immer ein Create("HTMLWin", H, S, N, X, Y, DX, DY).
Da muss man dann aber bei der Ermittlung der Maße immer wieder auf andere, nichtprofane Mittel zurückgreifen, was Zeit kostet und lästig ist.
Außerdem will ich eigentlich nur ungern ein Element vom Internetexplorer in mein Programm integrieren.
Ein weiterer Vorteil von dem HTMLWin ist übrigens noch die problemlose Nutzung als scrollbares Element. Das ist in Profan bisher auch nur suboptimal gelöst.
 
Windows XP SP2 XProfan X4
... und hier mal was ganz anderes als Profan ...
11.06.2020  
 




Matthias
Arlt
Jörg Sellmeyer (11.06.2020)
Außerdem will ich eigentlich nur ungern ein Element vom Internetexplorer in mein Programm integrieren.


Kann ich gut nachvollziehen...

Hier mal noch eine etwas schlankere Variante...
declare hBtn&,Pic$,GDIP_DLL&,GDPS#,GdipStatus&,PicObject&,hPic&,PicWidth&,PicHeight&,hdc&,bmp&,wChar$
GDIP_DLL& = UseDLL("GDIPLUS.DLL")
window 0,0-%maxx,%maxy
hBtn&=create("BUTTON",%hwnd,"Bild...",20,20,60,22)

proc LoadImageFile

    parameters Pic$
    dim GDPS#,16
    long GDPS#,0 = 1
    long GDPS#,4 = 0
    long GDPS#,8 = 0
    long GDPS#,12 = 0
    external("GDIPLUS.DLL","GdiplusStartup",addr(GdipStatus&),GDPS#,0)
    dispose GDPS#
    wChar$ = space$((len(Pic$)*2)+1)
    external("KERNEL32","MultiByteToWideChar",0,0,addr(Pic$),-1,addr(wChar$),len(wChar$)+1)
    external("GDIPLUS.DLL","GdipLoadImageFromFile",addr(wChar$),addr(PicObject&))
    external("GDIPLUS.DLL","GdipCreateHBITMAPFromBitmap",PicObject&,addr(hPic&),0)
    external("GDIPLUS.DLL","GdipGetImageWidth",PicObject&,addr(PicWidth&))
    external("GDIPLUS.DLL","GdipGetImageHeight",PicObject&,addr(PicHeight&))
    hdc& = external("GDI32","CreateCompatibleDC",0)
    bmp& = external("GDI32","CreateCompatibleBitmap",%hdc,PicWidth&,PicHeight&)
    external("GDI32","SelectObject",hdc&,hPic&)
    external("GDI32","BitBlt",%hdc,0,0,width(%hwnd),height(%hwnd),hdc&,0,0,$CC0020)
    external("GDI32","BitBlt",%hdc2,0,0,width(%hwnd),height(%hwnd),hdc&,0,0,$CC0020)
    external("GDI32","DeleteObject",bmp&)
    external("GDI32","DeleteDC",hdc&)
    external("GDIPLUS.DLL","GdipDisposeImage",PicObject&)
    external("GDIPLUS.DLL","GdiplusShutdown",GdipStatus&)

endproc

while 1

    waitinput

    if clicked(hBtn&)

        Pic$=LoadFile$("Bild laden...","*.*")

        if FileExists(pic$)

            UseCursor 2
            LoadImageFile(Pic$)
            UseCursor 0

        endif

    endif

wend

FreeDLL GDIP_DLL&
end

Es scheint also definitiv an der Speicherbitmap von Profan zu liegen, denn mit Workarround per API funtioniert es ja.
 
WinXP SP2, Win7 - XProfan 10/11/FreeProfan32 - Xpia
11.06.2020  
 




RGH
Ich habe gerade mal nachgeschaut: Die XProfan-Befehle und -Funktionen, die Bilder aus File laden (MLoadBmp, DrawPic, DrawSizedPic und Create("hPic",...)), nutzen eine OLE-Routine, die an Andreas' Code angelehnt ist. Hier sollte es keine Probleme mit grande Bitmaps geben. Ich muss das mal näher überprüfen.

(Das gilt nicht per FreeProfan, da ich FreePascal noch nicht mit OLE-Objekten verheiraten konnte.)

Saluto
Roland
 
XProfan X4
Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4
11.06.2020  
 




RGH
Ach ja: zu negativen Handles: In Windows sind die Handles unsigned Integer (ohne Vorzeichen). Der Wertebereich geht also von 0 bis etwas circa 4 Milliarden. Die Handles und Integer in XProfan sind signed Integer (mit Vorzeichen) mit einem Wertebereich von - 2 Milliarden bis + 2 Milliarden. Windows-Handles, die circa 2147483647 liegen, werden daher negativ dargestellt, was aber nichts an ihrer Funktion ändert. Handles kleiner als 0 sind also ebenso gültig.

Saluto
Roland
 
XProfan X4
Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4
11.06.2020  
 




RGH
Gerade getestet: Mit Matthias' Code (reines XProfan) konnte ich meine größten Bilder (16 MPixel, Dateigröße circa 6 MB) problemlos laden. Größere Bilder habe ich nicht. Ich benutze meine aktuelle XProfan-Version.

Nachtrag: Und auch das oben verlinkte Afrika-Bild macht in höchster Auflösung (75 MPixel) keine Probleme.

Saluto
Roland
 
Intel Duo E8400 3,0 GHz / 4 GB RAM / 1000 GB HDD - ATI Radeon HD 4770 512 MB - Windows 7 Home Premium 32Bit - XProfan X4
11.06.2020  
 




Matthias
Arlt
Ich hatte mit 11.2 getestet und Jörg vmtl. mit X4. Dann scheinen da wohl noch andere Faktoren eine Rolle zu spielen...nur welche? Mir war das ja auch noch nie aufgefallen, da ich solch grande Bilder eben auch nicht habe.
Ach ja...wenn FreeProfan und OLE sich nicht so recht mögen...meine "schlankere" API-Variante kommt ja ganz ohne OLE aus.
 
WinXP SP2, Win7 - XProfan 10/11/FreeProfan32 - Xpia
11.06.2020  
 




Jörg
Sellmeyer
RGH (11.06.2020)
Ich habe gerade mal nachgeschaut: Die XProfan-Befehle und -Funktionen, die Bilder aus File laden (MLoadBmp, DrawPic, DrawSizedPic und Create("hPic",...)), nutzen eine OLE-Routine, die an Andreas' Code angelehnt ist. Hier sollte es keine Probleme mit grande Bitmaps geben. Ich muss das mal näher überprüfen.

(Das gilt nicht per FreeProfan, da ich FreePascal noch nicht mit OLE-Objekten verheiraten konnte.)

Saluto
Roland


RGH
Nachtrag: Und auch das oben verlinkte Afrika-Bild macht in höchster Auflösung (75 MPixel) keine Probleme.


Da frage ich mich aber, warum das bei mir nicht funktioniert. Ich hab zwar noch XP mit 2GB Ram aber mit meiner Variante von Andreas' Code funktioniert es ja, also kann es nicht generell am Speicher oder der Windowsversion liegen.
Vielleicht kannst du nochmal schauen, was da die Unterschiede in deiner Version zu meiner sind.
Der verschlankte Code von Matthias funktioniert bei mir übrigens auch nicht.

Außerdem fällt mir auf, dass Matthias print verwendet, um das Bild zu verarbeiten. Das wird in meinem Code vermieden, sondern nur durch Speicherschiebereien das Handle ermittelt.
 
Windows XP SP2 XProfan X4
... und hier mal was ganz anderes als Profan ...
11.06.2020  
 




Matthias
Arlt
@Jörg
Ich habe hier auf diesem PC ja auch XP SP2 drauf. Nachdem nun Roland keine Probleme beim Laden des Bildes hatte, hab ich das Ganze mal schnell in einem virtuellen Win 7 probiert. Und siehe da...dort gibt es auch kein Problem!

Wenn sich nun der profaninterne Code lt. Roland an das OLE-Prozedere von Andreas anlehnt, muß es aber doch Unterschiede geben, denn extern funtioniert es ja mittels OLE.

Das print in meinem Code steht dort eigentlich nur, weil ich das Handle angezeigt bekommen wollte. Warum aber diese API-Variante, die eigentlich nur GDI(+)-Funktionen nutzt, bei Dir nicht geht, ist mir nun wieder ein Rätsel.

Mysteriös...aber immerhin einen Schritt weiter...
 
WinXP SP2, Win7 - XProfan 10/11/FreeProfan32 - Xpia
11.06.2020  
 




Jörg
Sellmeyer
Ich habs jetzt auch auf nem Laptop mit Win7 und 4GB Ram getestet und es funktioniert mit deinem Code. Das erklärt aber immer noch nicht, warum es bei mir mit meinem Code auch auf mkeinem minderbemittelten Rechner funktioniert aber nicht mit deinem Code.
 
XProfan X4
Windows XP SP2 XProfan X4
... und hier mal was ganz anderes als Profan ...
11.06.2020  
 




Matthias
Arlt
Das ist ja das Mysterium...

GDI+ sollte bei XP ja standardmäßig vorhanden sein. Das ist es also vmtl. nicht.
Du könntest vlt. mal die Rückgabewerte schrittweise per jeden Funktionsaufruf ansehen. Eventuell führt das etwas weiter !?

Festhalten können wir jedenfalls, daß sich create("hPic" unter XP (und wohl nur dort) bei Bildern von annähernd 8000x8000 untypisch verhält. Kein Problem, wenn man das weiß oder solche Bilder nicht hat.

Den folgenden Passus kannst Du auch aus der OLE-Variante entfernen:

TestHandle& = Create("hPic",-1,Bild$)
WindowTitle Str$(TestHandle&) + " Bei sehr grande Bildern ist das Ergebnis hier 0"
DeleteObject TestHandle&

OLE kommt ohne ihn aus und necessario ihn nicht (systemunabhängig). Deshalb ist er dort m.E. auch nicht hilfreich (und stiftet vlt. Verwirrung).
 
WinXP SP2, Win7 - XProfan 10/11/FreeProfan32 - Xpia
11.06.2020  
 




Zum Quelltext


Topictitle, max. 100 characters.
 

Systemprofile:

Kein Systemprofil angelegt. [anlegen]

XProfan:

 Posting  Font  Smilies  ▼ 

Bitte anmelden um einen Beitrag zu verfassen.
 

Topic-Options

9.317 Views

Untitledvor 0 min.
Georg Teles23.05.2024
Sven Bader22.11.2023
Rainer Hoefs01.05.2023
Normann Strübli29.01.2023
Di più...

Themeninformationen



Admins  |  AGB  |  Applications  |  Autori  |  Chat  |  Informativa sulla privacy  |  Download  |  Entrance  |  Aiuto  |  Merchantportal  |  Impronta  |  Mart  |  Interfaces  |  SDK  |  Services  |  Giochi  |  Cerca  |  Support

Ein Projekt aller XProfaner, die es gibt!


Il mio XProfan
Private Notizie
Eigenes Ablageforum
Argomenti-Merkliste
Eigene Beiträge
Eigene Argomenti
Zwischenablage
Annullare
 Deutsch English Français Español Italia
Traduzioni

Informativa sulla privacy


Wir verwenden Cookies nur als Session-Cookies wegen der technischen Notwendigkeit und bei uns gibt es keine Cookies von Drittanbietern.

Wenn du hier auf unsere Webseite klickst oder navigierst, stimmst du unserer Erfassung von Informationen in unseren Cookies auf XProfan.Net zu.

Weitere Informationen zu unseren Cookies und dazu, wie du die Kontrolle darüber behältst, findest du in unserer nachfolgenden Datenschutzerklärung.


einverstandenDatenschutzerklärung
Ich möchte keinen Cookie