Results 1 to 10 of 10

Thread: PNG image => kleuren pixels wijzigen

  1. #1

    PNG image => kleuren pixels wijzigen

    Beste leden,

    Hoe kan ik van onderstaande tekening (png image) bvb de rode pixels wijzigen naar een andere kleur?
    Iemand enig idee hoe ik dit probleem moet aanpakken?

    Onderstaande tekening is louter ter illustratie, de te wijzigen pixels kunnen een willekeurige vorm zijn (dus het probleem moet pixel per pixel aangepakt worden).

    Alvast dank.
    Attached Images Attached Images  

  2. #2
    Quote Originally Posted by John1965 View Post
    Hoe kan ik van onderstaande tekening (png image) bvb de rode pixels wijzigen naar een andere kleur?
    Volgens mij moet je daar FloodFill-functie voor kunnen gebruiken. Bepaal een punt met de rode kleur en met het uitvoeren van deze functie worden alle aangrenzende pixels van dezelfde kleur ook gewijzigd tot ie een andere kleur tegenkomt. Je moet dit echter wel zelf doen met alle vlakken die rood zijn.

    Een andere optie is de kleur pallet te wijzigen maar daarvan weet ik zo even niet uit mijn hoofd hoe dat moet. (Iets met het bepalen welke index de rode kleur heeft en dan kun je in de kleur pallet die kleur veranderen. Dan heb je gelijk alle vlakken van dezelfde kleur te pakken, dus niet voor gebruik bij elk vak individueel)

  3. #3
    Fornicatorus Formicidae VideoRipper's Avatar
    Join Date
    Mar 2005
    Location
    Vicus Saltus Orientalem
    Posts
    5,708
    Als laatste optie kun je alle pixels afgaan en kijken welke er rood zijn; deze maak
    je dan die andere kleur.
    Je zult dan wel eerst die PNG moeten omzetten naar een bitmap.
    Hou er ook rekening mee dat je wellicht "Ruim" moet zijn bij het interpreteren wat
    precies rood is; bij gecomprimeerde (JPEG, PNG, ...) plaatjes is dat niet altijd even
    duidelijk (je moet dus een bepaalde tolerantie inbouwen).

    Greetz,

    Peter.
    TMemoryLeak.Create(Nil);

  4. #4
    @VideoRipper PNG is wel gecomprimeerd, maar heeft niet het probleem dat jpg wel heeft (kleine kleurafwijkingen door de compressie). Natuurlijk kunnen kleuren wel afwijken, maar dat is dan meestal anti-aliasing, en is meer een 'feature' die tekenprogramma's bij het opslaan toepassen, ongeacht welk bitmapformaat je gebruikt.
    1+1=b

  5. #5
    Hier de oplossing met het wijzigen van de Palette.

    Het plaatje moet wel naar 8-bit omgezet worden voordat er een palette beschikbaar is, volgens mij.
    Daarna moet je de precieze RGB waarden voor dat "rood" hebben want die index wil je wijzigen.
    (bij mijn test met jouw plaatje was dat 51,51,255)

    Quick en dirty testje:

    Delphi Code:
    1. procedure TForm.Button1Click(Sender: TObject);
    2. var
    3.   Bmp: TBitmap;
    4.   NewCol: TRGBQuad;
    5.   OldCol: TRGBQuad;
    6.   i: Integer;
    7. begin
    8.   Bmp := TBitmap.Create;
    9.   try
    10.     Bmp.LoadFromFile('c:\temp\test.bmp');
    11.  
    12.     // voor een palette moet het plaatje omgezet zijn naar 8 bit
    13.     Bmp.PixelFormat := pf8Bit;
    14.  
    15.     // even opslaan zodat je in het resulterende plaatje de precieze RGB-waarden op kunt zoeken
    16.     Bmp.SaveToFile('c:\temp\test2.bmp');
    17.  
    18.     Image1.Picture.Assign(Bmp); // before
    19.  
    20.     // voor een palette moet het plaatje omgezet zijn naar 8 bit
    21.     if Bmp.PixelFormat <> pf8Bit then
    22.     begin
    23.       Showmessage('ERROR, Bitmap is NOT 8 Bit');
    24.       Exit;
    25.     end;
    26.  
    27.     NewCol.rgbBlue := 255;
    28.     NewCol.rgbGreen := 0;
    29.     NewCol.rgbRed := 0;
    30.     NewCol.rgbReserved := 0;
    31.  
    32.     for i := 0 to 256 - 1 do
    33.     begin
    34.       // haal de kleur op uit index i uit de palette
    35.       if GetDIBColorTable(Bmp.Canvas.Handle, i, 1, OldCol) = 1 then
    36.       begin
    37.         // hier de precieze RGB waarden opgeven die je wilt veranderen
    38.         if (OldCol.rgbBlue = 51) and (OldCol.rgbGreen = 51) and (OldCol.rgbRed = 255) then
    39.         begin
    40.           bleep;
    41.           // zet de kleur op index i op de NewCol
    42.           if SetDIBColorTable(Bmp.Canvas.Handle, i, 1, NewCol) = 0 then
    43.               Showmessage(format('ERROR, System did not change palette-index %d, bitmap may be 24 bit', [i]));
    44.         end;
    45.       end;
    46.     end;
    47.  
    48.     Image1.Picture.Assign(Bmp); // after
    49.  
    50.   finally
    51.  
    52.       Bmp.Free;
    53.  
    54.   end;
    55.  
    56. end;

  6. #6
    Alvast nu al bedankt voor de reacties.
    Ik zal in de loop van het weekend wat proberen te testen. Ik laat nog wel iets weten.

  7. #7
    Tussendoor nog een vraagje.

    Mijn originele image is een PNG met transparante achtergrond.
    Ik vrees wanneer ik die omzet naar een BMP image die geen tranparency ondersteunt?
    Het eindresultaat zou terug een PNG moeten zijn.

    Kan er mij iemand hierover uitsluitsel geven?

    Bedankt!

  8. #8
    Het moet wel mogelijk zijn om van TBitmap weer terug te gaan naar PNG en die dan op te slaan met transparantie.
    Zie http://stackoverflow.com/questions/1...ge-from-bitmap

    Maar misschien is de conversie stap naar (een weer terug) TBitmap wel over te slaan als je in de TPngimage direct toegang hebt tot de palette.
    Welke Delphi versie gebruik je en waar heb je het PNG-component vandaan?

  9. #9
    Quote Originally Posted by rvk View Post
    Het moet wel mogelijk zijn om van TBitmap weer terug te gaan naar PNG en die dan op te slaan met transparantie.
    Zie http://stackoverflow.com/questions/1...ge-from-bitmap

    Maar misschien is de conversie stap naar (een weer terug) TBitmap wel over te slaan als je in de TPngimage direct toegang hebt tot de palette.
    Welke Delphi versie gebruik je en waar heb je het PNG-component vandaan?
    Ik gebruik Delphi XE5. Mijn png images zijn zelf gemaakt met Photoshop.
    Maar ik denk met de link die je mij gegeven hebt kan ik weer wat verder kan.

    Ik zal wat experimenteren met jouw code (waarvoor dank).
    Een ander optie i.p.v. de palette is met scanline te werken (dit had ik na wat speurwerk ondertussen zelf gevonden).

    Ik weet echter niet als je met scanline direct toegang hebt tot een png object (ik vrees van niet => werkt volgens sommige bronnen enkel met een pf24bits - pf32bits bitmap)

    Als ik ergens 'vastloop' horen jullie me wel.

  10. #10
    Ik weet echter niet als je met scanline direct toegang hebt tot een png object (ik vrees van niet => werkt volgens sommige bronnen enkel met een pf24bits - pf32bits bitmap)
    Dat zal denk ik dan afhangen van het object/class zelf. Naar alle waarschijnlijkheid niet niet erg behulpzaam, maar ik denk dat dat ook de reden is dat freepascal/lazarus de images (tegenwoordig) standaard in 64-bit afhandeld. Je zou misshien een speciale (externe) image library kunnen overwegen om je behulpzaam te kunnen zijn.

    In pricipe zou je gewoon de scanline moeten kunnen aanspreken en dienovereenkomstig de r/g/b-waarden (en alpha channel niet te vergeten) inlezen en wijzigen naar gelang uw blieft om, vervolgens het plaatje weer op te slaan (met de wijzigingen).

    Overigens, ik weet niet hoe het precies werkt met png images, maar ik denk toch niet echt dat een plaatje met een diepte van 64-bit een palette hanteert (dat zou namelijk een beetje veel palette data opleveren ). Normaliter is alles tot 256 kleuren mogelijk met een palette, ga je daaarboven dan worden er normaliter gewoon rgb waarden voor elke individuele pixel gehanteerd (uitzondering in sommige bestandformaten van sommige typen plaatjes daargelaten).
    Last edited by flabber; 31-May-14 at 12:09.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •