Die Sache mit dem Alphakanal

  • Hallo Community

    Ich habe eine Frage die sich vermutlich nicht so einfach beantworten lässt...

    Um ein wenig Platz zu sparen habe ich mir ein kleines Programm gebastelt das meine Fotos einliest, den Alphakanal jedes Pixels auf 11 setzt und dann wieder speichert (GDI Plus).
    Funktioniert Prima!

    Nun möchte ich das Gegenstück basteln um meine Fotos wieder mit dem vollen Alphakanal anzeigen zu lassen - und stehe vor einem Rätsel.

    Die Modifikation des Alpha-Kanals hat dazu geführt dass die Funktion _GDIPlus_GetPixel mir die Pixel zwar anzeigt, diese jedoch einen ganz anderen Wert haben als vorher.

    Gibt es eine Möglichkeit den Alphakanal wieder in voller Stärke anzeigen zu lassen und so die Originalfarben wieder herzustellen?

    Ich bin sicher dass es hierfür eine Formel gibt, verzweifle jedoch weil ich nirgends Hilfe finde...

    Vielen Dank im Voraus für eure Unterstützung.

    Liebe Grüsse

  • $brush = "0x11" & $charset <-- Hier wird der Alphakanal zusammen mit den Farbwerten gespeichert, Beispiel: Alphakanal 11
    $hBrush = _GDIPlus_BrushCreateSolid($brush)

    $hDrawGUI = _GDIPlus_GraphicsFillRect($hGraphic, $x, $y, 1, 1, $hBrush)

  • Bin ehrlich gesagt am verzweifeln... hab ich soeben meine ganze Fotosammlung ruiniert oder gibt es eine Möglichkeit die Farben wieder hinzukriegen?

  • omfg...das meinst du doch etwa nicht Ernst?

    Hier im Forum gibt es hunderte von Scripten welche die einzelnen Farbkanäle bearbeiten oder zumindest zeigen wie man das macht (jedenfalls NICHT per BRUSH! ).....und du schreibst ein Script wo du GLAUBST, dass es funktioniert und lässt das auf deine Orginalfotos los?

    Zeig mal bitte dein komplettes Script und auch 2 oder 3 deiner ORGINAL-Fotos (die bearbeiteten). Dann kann man dir vielleicht weiterhelfen!

    Btw, wie kommst du zu der Annahme, dass durch einen Alphakanal von 11 die Bilder kleiner werden?
    Es ist völlig egal, welchen Wert der Alphakanal annimmt, solange dafür im Bitmap-Format ein Byte reserviert ist, bleibt die Bildgrösse gleich!

  • Hallo Andy

    Leider hast Du recht... die Fotos sind nicht kleiner geworden... nur die Farben sind enorm viel schwächer und die Fotos beinahe unbrauchbar.
    Das Script und die Fotos kann ich zur Zeit leider nicht posten da ich die Dateien und auch das Script in der Firma habe und zur Zeit im Urlaub bin.

    Ich denke aber dass das Problem auch so klar sein sollte. Jedes eingelesene Pixel eines Fotos habe ich mit Alphakanal 20 versehen (vorher 255 (FF)) und wieder gespeichert.
    In der Vorschau (Thumbnail) macht das beinahe nix aus... aber wenn man es dann öffnet sind alle Farben falsch :(

    Ich war der Meinung dass es reichen würde die Differenz von Alphakanal 20 bis zu Alphakanal 255 wieder zum Bild hinzu zu fügen um dann den Originalwert zu erhalten.
    Ging leider daneben. Da es sich bei den Fotos glücklicherweise "nur" um Arbeitsaufnahmen handelt die mehr Erinnerungswert als etwas anderes haben ist das nicht ganz so schlimm... aber es nervt total.

  • Die Funktion zum Einlesen des Originalbildes war _GDIPlus_BitmapCreateFromFile

    Vielleicht hilft das weiter.

  • Hi,

    naja, vielleicht ist ja noch nicht alles verloren, stell mal 2-3 Bilder online oder schicke sie per PM.
    Eine Funktion, welche die Farben bzw die Farbkanäle anpasst ist ja in wenigen Zeilen schnell geschrieben.

  • ...wenn ich doch nur könnte... hab die Fotos wie gesagt in der Firma. Was ich gemacht habe war ganz einfach... Datei Pixel für Pixel einlesen, Alphakanal auf 20 gesetzt und dann wiede gespeichert. Ein Loop der das im ganzen Verzeichnis für jpg-Dateien gemacht hat rundete das Ganze ab.

    Einmal editiert, zuletzt von SORUS (8. April 2013 um 20:41)

  • Speicher die Bilder doch einfach ohne Alpha Kanal wider ab ist zwar nicht perfekt, aber ein Anfang (sofern es Bilder mit Direktem Alphakanal sind). Die GDI Cracks haben bestimmt noch viel bessere lösungen die meinen Horizont leider um ein vielfaches übersteigen. Jedoch können sie auch nicht ohne ein beispiel oder zumindest deinem code arbeiten.

    Spoiler anzeigen

    Wenn ich mich nicht irre kann man so den Alpha Kanal entfernen :?: (pfusch lösung)

    [autoit]

    #include<gdiplus.au3>
    _GDIPlus_Startup()
    $hFile = FileOpenDialog("", "", "Images (*.jpg;*.bmp;*.png)")
    $hImage = _GDIPlus_BitmapCreateFromFile($hFile)
    $iX = _GDIPlus_ImageGetWidth($hImage)
    $iY = _GDIPlus_ImageGetHeight($hImage)
    $hClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iX, $iY, $GDIP_PXF32RGB)
    _GDIPlus_ImageSaveToFile($hClone, InputBox("" ,"Neuer Name" ,"")&".bmp")

    [/autoit]
  • Bevor du jetzt an den Orginaldateien rumexperimentierst, mach erstmal Sicherungskopien.
    Ich vermute, beim Schreiben/Speichern ist etwas durcheinandergekommen.
    Solange du nicht versucht hast, an den schon verpfuschten Dateien weiter rumzuexperimentieren, ist ggf. noch etwas zu retten....

  • Das schreit eigentlich nach ASM, aber dazu war ich jetzt zu faul :P
    Hier gibts schonmal eine potentielle Lösung des Problems.
    Die Funktion läd ein Bild, ändert die Transparenz und speichert es unter einem anderen Namen ab.
    Damit müsste es Dir möglich sein ein Skript zu bauen um alle Bilder zu verändern.
    Hab es hier nur kurz getestet. bevor du damit auf Nutzdaten losgehst muss das umfassend getestet werden !
    Falls du bei der Änderung des Alphakanals die Farben beeinflusst hast ist ein Informationsverlust wahrscheinlich.
    Zur (teilweisen) Rekonstruktion ist dein Skript in diesem Fall unerlässlich.

    Skript
    [autoit]

    #include <GDIPlus.au3>

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    _SetAlpha('Test1.png', 'Test2.png', 100)
    Sleep(1000) ; Damit die Festplatte hinterherkommt
    _SetAlpha('Test2.png', 'Test3.png', 255)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; Diese Funktion kann man überall einsetzen

    [/autoit] [autoit][/autoit] [autoit]

    Func _SetAlpha($sPfad1, $sPfad2, $iAlpha)
    _GDIPlus_Startup()
    Local $aImg = _Image_CreateFromFile($sPfad1)
    Local $iW = _GDIPlus_ImageGetWidth($aImg[0])
    Local $iH = _GDIPlus_ImageGetHeight($aImg[0])
    Local $iPtr = $aImg[2], $vBmp = $aImg[1], $hBmp = $aImg[0], $xAlpha = Hex(Int($iAlpha),2)
    For $i = 1 To $iW * $iH Step 1
    DllStructSetData($vBmp, 1, '0x' & $xAlpha & StringRight(Hex(Int(DllStructGetData($vBmp, 1, $i)),8),6), $i)
    Next
    _GDIPlus_ImageSaveToFile($hBmp, $sPfad2)
    _Image_DeleteGDIPlus($aImg)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ; !!! Achtung folgendes ist inkompatibel zu _Image_Create !!!
    ; Die folgenden Funktionen sind auf das Problem zugeschnitten und nutzen GDI+ statt GDI

    [/autoit] [autoit][/autoit] [autoit]

    Func _Image_CreateFromFile($sPfad)
    Local $hBmp = _GDIPlus_ImageLoadFromFile($sPfad)
    Local $aImg = _Image_CreateGDIPlus(_GDIPlus_ImageGetWidth($hBmp), _GDIPlus_ImageGetHeight($hBmp))
    Local $hGFX = _GDIPlus_ImageGetGraphicsContext($aImg[0])
    _GDIPlus_GraphicsDrawImage($hGFX, $hBmp, 0, 0)
    _GDIPlus_GraphicsDispose($hGFX)
    Return $aImg
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _Image_CreateGDIPlus($iW, $iH)
    Local $iPtr, $hBmp, $aTmp, $vBmp
    $vBmp = DllStructCreate('int[' & $iW * $iH & ']')
    $aTmp = DllCall('GDIPlus.dll', 'uint', 'GdipCreateBitmapFromScan0', 'int', $iW, 'int', $iH, 'int', $iW * 4, 'int', 0x0026200A, 'ptr', DllStructGetPtr($vBmp), 'int*', 0)
    $hBmp = $aTmp[6]
    $iPtr = DllStructGetPtr($vBmp)
    Local $a[3] = [$hBmp, $vBmp, $iPtr]
    Return $a
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _Image_DeleteGDIPlus(ByRef $a)
    _GDIPlus_BitmapDispose($a[0])
    $a = 0
    EndFunc

    [/autoit]


    lg
    Mars