Bild mit 256 Farben erstellen

  • huhu Community

    Ich hätte gerne ein Bild mit 256 Farben erstellt. Gibt es hierzu eine Möglichkeit oder wird ein Bild das man in einer GUI malt immer mit 16.7 Millionen Farben erstellt?

  • Hallo Jolie,
    wilkommen im Forum.

    Du kannst ein Bild mit 256 Farben darstellen und speichern indem du es mit

    [autoit]

    _GDIPlus_BitmapCloneArea($hBmp,0, 0, $iWidth, $iHeight,$GDIP_PXF08INDEXED)

    [/autoit]


    clonst und dann mit

    [autoit]

    _GDIPlus_ImageSaveToFile

    [/autoit]

    abspeicherst

    Das $GDIP_PXF08INDEXED beschreibt die Farbtiefe also 8 Bit pro Pixel sind 256 Farben.
    2^8=256

    wenn du noch nicht so viel mit GDIPlus gearbeitet hast empfiehlt es sich erst einmal ein paar versuche zu machen und sich die Beispiele aus der Hilfe anzusehen

    Einmal editiert, zuletzt von bollen (11. April 2013 um 18:27)

  • Guten Morgen bollen

    Vielen herzlichen Dank für die schnelle Erklärung.Ich hab das mit _GDIPlus_BitmapLockBits versucht... war wohl falsch *grins"

    Mit BitmapCloneArea funktioniert das jetzt bestens! Wozu dient denn eigentlich BitmapLockBits und gibt es keine Möglichkeit ein Bild sofort mit 256 Farben zu zeichnen?

    Mein "Clone" hat letztendlich andere Farben als das von mir angefertigte Originalbild. Ich hätte das gerne vermieden...

    Einmal editiert, zuletzt von Jolie (12. April 2013 um 07:38)

  • Hallo Cracks

    Wie sieht denn das jetzt aus mit meinem Problem? Ist es nicht möglich ein Bild direkt mit 256 Farben zu zeichnen? Muss ich wirklich den Umweg über Clone machen?

  • Hi,

    Zitat

    wird ein Bild das man in einer GUI malt immer mit 16.7 Millionen Farben erstellt?


    Das Bild das DU in DEINE Gui malst, wird grundsätzlich in so vielen Farben gemalt wie DU das vorgibst!
    Will sagen, wer hindert dich daran, 2,3,17 oder 957 Farben vorzugeben?!

    Zitat

    Ist es nicht möglich ein Bild direkt mit 256 Farben zu zeichnen? Muss ich wirklich den Umweg über Clone machen?

    s.o. natürlich musst du den Weg über Clone nicht gehen, das ist "ein" möglicher Weg der Problemlösung.
    Zeige doch erstmal dein Script.

    Zitat

    Mein "Clone" hat letztendlich andere Farben als das von mir angefertigte Originalbild. Ich hätte das gerne vermieden...

    Das hat mit den Farbtabellen zu tun, zeig einfach mal dein Script^^

  • Da liegst du leider daneben...
    Es kommt auf das Dateiformat an und deren beinhalteten Farbtabelle...
    Das *.gif Format unterstützt maximal nur 256 Farben. Restliche Farben werden einfach zu einer Farbe in der Farbtabelle konvertiert.
    Manche Formate haben aber auch gar keine Farbtabelle wie die *.png Dateien wenn ich mich nicht irre!
    Da muss man dann selber für die konvertierung der Farben sorgen.

    Wenn du den Farbwert nach deine Idee konvertieren willst, bleiben trzd. Genau soviele Farben übrig. Nur mit dem Unterschied dass die Farbe nun ne andere Farbe ist!

  • Hi,
    Make-Grafik hat Recht!
    Am einfachsten ist wieder mal das "Oldschool"-Bitmap-Format BMP, da wird einfach hinter den Header die Farbtabelle gehängt. Diese kann man einfach beschreiben und so seine "eigenen" Farben verwenden bzw. konvertieren.
    Irgendwo hier im Forum müssten einige Scripte von mir rumschwirren, die sowohl den Aufbau des Headers als auch die Farbtabelle beinhalten. Wenn ich das richtig in Erinnerung habe, wurden die "Bilder" damit ohne Umweg über eine "Zeichnung" bzw. GUI direkt in die Datei geschrieben....
    Da das Dateiformat so einfach ist, könnte man eine "leere" BMP-Datei mit den Parametern des Bildes erstellen und die Farben direkt in die Farbtabelle eintragen.
    Dann müssen nur noch die "Pixel" ausgefüllt werden und alles ist paletti.

  • Man sollte hier zwischen 256 Farben und einer 8 Bit Bitmap differenzieren. Ein 24-bit Bild kann theoretisch auch nur 256 Farben beinhalten, aber ein 8 Bit Bild niemals mehr als 256 Farben.

    Hier 2 kleine Snippets.

    1) Benötigt kein GDI+ v1.1:

    Spoiler anzeigen
    [autoit]


    #include <GDIPlus.au3>
    $sFile = FileOpenDialog("Bitte ein Bild selektieren", "", "Bilder (*.jpg;*.bmp;*.png)", 3)
    If @error Then Exit
    _GDIPlus_Startup()
    $hBitmap = _GDIPlus_BitmapCreateFromFile($sFile)
    $iWidth = _GDIPlus_ImageGetWidth($hBitmap)
    $iHeight = _GDIPlus_ImageGetHeight($hBitmap)
    $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $iWidth, "int", $iHeight, "int", 0, "int", $GDIP_PXF08INDEXED, "ptr", 0, "int*", 0)
    $hBmp8bit = $aResult[6]
    $hCtxt = _GDIPlus_ImageGetGraphicsContext($hBmp8bit)
    _GDIPlus_GraphicsDrawImageRect($hCtxt, $hBitmap, 0, 0, $iWidth, $iHeight)
    _GDIPlus_GraphicsDispose($hCtxt)
    _GDIPlus_BitmapDispose($hBitmap)
    $sOutputFile = @ScriptDir & "\Test_8bit.png"
    _GDIPlus_ImageSaveToFile($hBmp8bit, $sOutputFile)
    _GDIPlus_BitmapDispose($hBmp8bit)
    _GDIPlus_Shutdown()
    ShellExecute($sOutputFile)

    [/autoit]

    2) Benötigt GDI+ v1.1 (Vista oder höhere):

    Spoiler anzeigen
    [autoit]


    #include <ScreenCapture.au3>

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

    If @OSBuild < 6000 Then Exit MsgBox(16, "Error", "GDI+ v1.1 needed -> Vista+ OS!", 10)

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

    Global Const $GDIP_PXF32CMYK = 0x0000200F
    Global Const $GDIP_PXFMAX = 0x00000010

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

    Global Enum $DitherTypeNone = 0, $DitherTypeSolid, $DitherTypeOrdered4x4, $DitherTypeOrdered8x8, $DitherTypeOrdered16x16, $DitherTypeOrdered91x91, $DitherTypeSpiral4x4, $DitherTypeSpiral8x8, $DitherTypeDualSpiral4x4, $DitherTypeDualSpiral8x8, $DitherTypeErrorDiffusion
    Global Enum $PaletteTypeCustom = 0, $PaletteTypeOptimal, $PaletteTypeFixedBW, $PaletteTypeFixedHalftone8, $PaletteTypeFixedHalftone27, $PaletteTypeFixedHalftone64, $PaletteTypeFixedHalftone125, $PaletteTypeFixedHalftone216, $PaletteTypeFixedHalftone252, $PaletteTypeFixedHalftone256

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

    _GDIPlus_Startup()
    $iW = 300
    $iH = 300
    $hHBitmap = _ScreenCapture_Capture("", 0, 0, $iW, $iH) ;24 bit screen capture
    $hBitmap_screen = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap) ;convert bitmap format

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

    $iColorCount = 1024
    $DitherType = $DitherTypeDualSpiral8x8
    $PaletteType = $PaletteTypeFixedHalftone256
    $PixelFormat = $GDIP_PXF08INDEXED

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

    $tPalette = DllStructCreate("uint Flags; uint Count; uint Entries[" & $iColorCount & "];")
    DllStructSetData($tPalette, "Flags", $PaletteType)
    DllStructSetData($tPalette, "Count", $iColorCount)

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

    ConsoleWrite("> Init Palette: " & _GDIPlus_InitializePalette($tPalette, $PaletteType, 0, True, 0) & @CRLF)
    ConsoleWrite("! Error: " & @error & " Extended: " & @extended & @CRLF)

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

    ConsoleWrite("> Convert: " & _GDIPlus_BitmapConvertFormat($hBitmap_screen, $PixelFormat, $DitherType, $PaletteType, $tPalette, 0) & @CRLF)
    ConsoleWrite("! Error: " & @error & " Extended: " & @extended & @CRLF)

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

    _GDIPlus_ImageSaveToFile($hBitmap_screen, @ScriptDir & "\Test.png")
    _WinAPI_DeleteObject($hHBitmap)
    _GDIPlus_BitmapDispose($hBitmap_screen)
    _GDIPlus_Shutdown()
    ShellExecute(@ScriptDir & "\Test.png")
    Exit

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

    Func _GDIPlus_BitmapConvertFormat($hBitmap, $iPixelFormat, $iDitherType, $iPaletteType, $tPalette, $falphaThresholdPercent = 0) ;http://msdn.microsoft.com/en-us/library/…6(v=VS.85).aspx
    Local $aResult = DllCall($ghGDIPDll, "bool", "GdipBitmapConvertFormat", "handle", $hBitmap, "long", $iPixelFormat, "long", $iDitherType, "long", $iPaletteType, "struct*", $tPalette, "float", $falphaThresholdPercent)
    If @error Then Return SetError(@error, @extended, -1)
    Return $aResult[0]
    EndFunc ;==>_GDIPlus_BitmapConvertFormat

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

    Func _GDIPlus_InitializePalette($tPalette, $iPaletteType, $iOptimalColors = 0, $bUseTransparentColor = True, $hBitmap = 0) ;http://msdn.microsoft.com/en-us/library/…9(v=vs.85).aspx
    Local $aResult = DllCall($ghGDIPDll, "bool", "GdipInitializePalette", "struct*", $tPalette, "long", $iPaletteType, "int", $iOptimalColors, "bool", $bUseTransparentColor, "handle", $hBitmap)
    If @error Then Return SetError(@error, @extended, -1)
    Return $aResult[0]
    EndFunc ;==>_GDIPlus_InitializePalette

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

    #cs
    http://msdn.microsoft.com/en-us/library/…6(v=vs.85).aspx
    VOID Example_ConvertFormat(HDC hdc)
    {
    Graphics graphics(hdc);
    Bitmap myBitmap(L"Photo.jpg");
    INT width = myBitmap.GetWidth();
    INT height = myBitmap.GetHeight();

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

    graphics.DrawImage(&myBitmap, 20, 20, width, height);

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

    // PaletteTypeFixedHalftone27 has 36 entries. A ColorPalette structure has
    // room for one entry, so space is allocated for an additional 35 entries.
    ColorPalette* pal = (ColorPalette*)malloc(sizeof(ColorPalette) + 35*sizeof(ARGB));
    pal->Count = 36;
    pal->Flags = 0;

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

    Bitmap::InitializePalette(pal, PaletteTypeFixedHalftone27, 0, TRUE, NULL);

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

    myBitmap.ConvertFormat(
    PixelFormat8bppIndexed,
    DitherTypeOrdered8x8,
    PaletteTypeFixedHalftone27,
    pal,
    0);

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

    graphics.DrawImage(&myBitmap, width + 40, 20, width, height);

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

    free(pal);
    }
    #ce

    [/autoit]

    Es gibt bestimmt noch andere Möglichkeiten 8 Bit Bilder zu erstellen (siehe Andy's kommentar).

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯