badbatchcoder
Goto Top

Alle Pixel eines PNGs mit Formel neu einfärben

Hat jemand eine Idee für ein kleines Programm, womit sich alle Pixel in einem png-Bild durch andere austauschen lassen?
Oder wäre das zu aufwendig?

Hier ein Beispiel:
Ein Pixel mit den RGB-Werten 216;216;216 (Hellgrau) soll mit 48;83;242 (Blau) ausgetauscht werden.
Für jeden RGB Wert, also Rot, Grün und Blau soll nun folgende Formel angewendet werden:
Rneu=RBlau/255*RHellgrau
-> Rneu=48/255*216 -> Rneu=41 (auf natürliche Zahl gerundet)
Das gleiche auch für Grün und Blau:
Gneu=GBlau/255*GHellgrau -> Gneu=83/255*216 -> Gneu=70 (auf natürliche Zahl gerundet)
Bneu=BBlau/255*BHellgrau -> Bneu=242/255*216 -> Bneu=205 (auf natürliche Zahl gerundet)

Nun erhält man den neuen Pixel: 41;70;205
Die Transparenz des neuen Pixels soll erhalten bleiben und somit die gleiche wie die vom Ursprünglichen, Hellgrauen Pixel bleiben.

Dieser Vorgang, den ich gerade im Beispiel beschrieben habe, soll nun mit allen Pixeln der png-Datei durchgeführt werden. Man soll beim Starten des Programms die RGB-Werte der Farbe eingeben können, mit der die Bildpixel verrechnet werden.

Vielen Dank im Voraus
LG BadBatchCoder

Content-Key: 957883974

Url: https://administrator.de/contentid/957883974

Printed on: April 27, 2024 at 14:04 o'clock

Member: Lochkartenstanzer
Solution Lochkartenstanzer Jul 09, 2021 at 17:01:40 (UTC)
Goto Top
Moin,

Einfach einen PNG-Parser schreiben. face-smile

Oder einen Filter für Photoshop/Gimp/Imagemagick.

lks
Member: colinardo
Solution colinardo Jul 10, 2021 updated at 11:20:57 (UTC)
Goto Top
Servus,
würde ich auch über nen Filter machen wie LKS schreibt aber hier mal ein Beispiel mit der Powershell (ohne Multihreading nicht schnell bei großen Bildern, wollte das Beispiel jetzt nicht verkomplizieren/aufblähen) (mit Dialogen für Eingabe-, Ausgabedatei und Farbwert über Color-Dialog damit auch der DAU damit klar kommt face-wink). Als *.ps1 speichern, Kontextmenü => mit Powershell ausführen.
# Load needed assemblies
Add-Type -A System.Drawing
Add-Type -A System.Windows.Forms
Add-Type –MemberDefinition '[DllImport("user32.dll")]public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);' -name Window -namespace W32  

# hide powershell console
[void][W32.Window]::ShowWindow((Get-Process -id $pid).MainWindowHandle, 0) 

# show file chooser dialog
$odlg = New-Object System.Windows.Forms.OpenFileDialog
$odlg.Filter = "PNG-Dateien | *.png"  
if($odlg.ShowDialog() -ne 'OK'){  
    return
}
# show color dialog
$colorDialog = New-Object System.Windows.Forms.ColorDialog -Property @{FullOpen = $true}
if ($colorDialog.ShowDialog() -ne 'OK'){  
    return
}
# assign color from dialog to variable
$color = $colorDialog.Color

# Show info
[System.Windows.Forms.MessageBox]::Show("Color filter will be applied when you press OK, please wait until the save dialog will be shown!","Color-Filter",0,64)  

# create system drawing image
$img = [System.Drawing.Image]::FromFile($odlg.FileName)
# parse als pixels from image
for ($x = 0; $x -lt $img.Width; $x++){ 
    for ($y = 0; $y -lt $img.Height; $y++){
        $p = $img.GetPixel($x,$y)
        $img.SetPixel($x,$y,[System.Drawing.Color]::FromArgb($p.A,[int]($color.R/255*$p.R),[int]($color.G/255*$p.G),[int]($color.B/255*$p.B)))
    }    
}

# show save file dialog
$sdlg = New-Object System.Windows.Forms.SaveFileDialog
$sdlg.FileName = [System.IO.Path]::GetFileNameWithoutExtension($odlg.FileName) + "_new.png"  
$sdlg.Filter = "PNG-Dateien | *.png"  
if($sdlg.ShowDialog() -eq 'OK'){  
    # save image to file
    $img.Save($sdlg.FileName,'Png')  
}
# cleanup handle
$img.Dispose()
Grüße Uwe

Powershell Link-Leitfaden für Anfänger
Member: BadBatchCoder
BadBatchCoder Jul 11, 2021 at 19:52:05 (UTC)
Goto Top
Vielen Dank, funktioniert super! =)
Member: BadBatchCoder
BadBatchCoder Jul 12, 2021 at 14:52:49 (UTC)
Goto Top
Hallo Uwe,
könntest du das Skript ein bisschen verändern, sodass man statt einzelnen Dateien, gleich ganze Ordner auswählen kann, alle enthaltenen Dateien mit der gleichen Farbe umgewandelt und dann in einem gemeinsamen Zielordner gespeichert werden?
Ich muss das nämlich mit ziemlich vielen Dateien machen und es würde ewig dauern, jedes Bild einzeln umzuwandeln.
Vielen Dank im Voraus!
LG
Member: colinardo
colinardo Jul 12, 2021 updated at 15:27:24 (UTC)
Goto Top
Zitat von @BadBatchCoder:
könntest du das Skript ein bisschen verändern, sodass man statt einzelnen Dateien, gleich ganze Ordner auswählen kann, alle enthaltenen Dateien mit der gleichen Farbe umgewandelt und dann in einem gemeinsamen Zielordner gespeichert werden?
Nimmst du halt nen Folderbrowser zum wählen der Files statt nen Filebrowser und ein Foreach über alle Dateien, wo ist jetzt das Problem?!
Ich muss das nämlich mit ziemlich vielen Dateien machen und es würde ewig dauern, jedes Bild einzeln umzuwandeln.
Das ist die Strafe für Copy n' Paster face-big-smile
# Load needed assemblies
Add-Type -A System.Drawing
Add-Type -A System.Windows.Forms
Add-Type –MemberDefinition '[DllImport("user32.dll")]public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);' -name Window -namespace W32  

# hide powershell console
[void][W32.Window]::ShowWindow((Get-Process -id $pid).MainWindowHandle, 0) 

# show file chooser dialog
$odlg = New-Object System.Windows.Forms.FolderBrowserDialog
$odlg.Description = "Select source folder"  
if($odlg.ShowDialog() -ne 'OK'){  
    return
}
# show file chooser dialog
$sdlg = New-Object System.Windows.Forms.FolderBrowserDialog
$sdlg.Description = "Select target folder to save modified files to"  
if($sdlg.ShowDialog() -ne 'OK'){  
    return
}

# show color dialog
$colorDialog = New-Object System.Windows.Forms.ColorDialog -Property @{FullOpen = $true}
if ($colorDialog.ShowDialog() -ne 'OK'){  
    return
}
# assign color from dialog to variable
$color = $colorDialog.Color

# Show info
[void][System.Windows.Forms.MessageBox]::Show("Color filter will be applied when you press OK, please wait until the save dialog will be shown!","Color-Filter",0,64)  


foreach($file in (ls $odlg.SelectedPath -Filter *.png -File)){
    # create system drawing image
    $img = [System.Drawing.Image]::FromFile($file.FullName)
    # parse als pixels from image
    for ($x = 0; $x -lt $img.Width; $x++){ 
        for ($y = 0; $y -lt $img.Height; $y++){
            $p = $img.GetPixel($x,$y)
            $img.SetPixel($x,$y,[System.Drawing.Color]::FromArgb($p.A,[int]($color.R/255*$p.R),[int]($color.G/255*$p.G),[int]($color.B/255*$p.B)))
        }    
    }
    $img.Save((join-path $sdlg.SelectedPath $file.Name),'Png')  
    # cleanup handle
    $img.Dispose()
}
Du könntest dem Script die Ordner und die Farbe natürlich auch mittels Parameter übergeben, wie man es halt braucht.

Vielleicht mal den oben verlinkten Linkleitfaden einverleiben, danach ist ein Anpassen an eigene Bedürfnisse ein leichtes face-wink.