[C#, GDI] Donker maken plaatje

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben nog steeds aan het puzzelen met mijn plaatjes ;)
Mijn input plaatje is eentje met een witte achtergrond en lichtgrijze lijnen.
Ik will hier graag eentje met een witte achtergrond en zwarte lijnen van maken.

Het pixel voor pixel veranderen is geen optie, want het gaat hier om plaatjes van ca. 6200*4500 pixel.
Unsafe code gebruiken kan ook niet.

Na veel geGoogle ben ik met de ColorMatrix gaan stoeien. Die lijkt te doen wat ik wil (met een value van -200), maar de achtergrond wordt ook donkerder. En dan moet nu juist niet.

De documentatie voor ColorMatrix is erg summier en ik kom dan ook niet verder.

Zit ik wel op het juiste spoor of moet ik in een andere richting zoeken?
Ik zat bijvoorbeeld ook aan imagemagick te denken. Maar daar heb ik ook geen ervaring mee.
Elk advies is welkom.


C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private static void DarkenImage(string inputFileName, int value)
{        
    float sb = (float)value / 255F;
    float[][] colorMatrixElements =
              {
                    new float[] {1,  0,  0,  0, 0},
                    new float[] {0,  1,  0,  0, 0},
                    new float[] {0,  0,  1,  0, 0},
                    new float[] {0,  0,  0,  1, 0},
                    new float[] {sb, sb, sb, 1, 1}
              };
    
    ColorMatrix cm = new ColorMatrix(colorMatrixElements);
    using (Bitmap bmpIn = (Bitmap)Bitmap.FromFile(inputFileName))
    {
        using (Bitmap converted = new Bitmap(bmpIn.Width, bmpIn.Height, PixelFormat.Format32bppArgb))
        {
            using (ImageAttributes imgattr = new ImageAttributes())
            {
                Rectangle rc = new Rectangle(0, 0, bmpIn.Width, bmpIn.Height);

                using (Graphics g = Graphics.FromImage(converted))
                {
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    imgattr.SetColorMatrix(cm);
                    g.DrawImage(bmpIn, rc, 0, 0, converted.Width, converted.Height, GraphicsUnit.Pixel, imgattr);
                }
            }
            // TODO: Save as 8Bit PNG again
            converted.Save(System.IO.Path.ChangeExtension(inputFileName, ".darken" + value.ToString() + ".png"));        
        }
    }        
}

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 16-09 09:15

Janoz

Moderator Devschuur®

!litemod

Het pixel voor pixel veranderen is geen optie, want het gaat hier om plaatjes van ca. 6200*4500 pixel.
Unsafe code gebruiken kan ook niet.
Denk je dat of weet je dat zeker?

Hoe denk je dat de de DrawImage werkt?

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • jmzeeman
  • Registratie: April 2007
  • Laatst online: 12-09 16:17
Op zich zou je er uiteindelijk met veel gepruts wel met een ColorMatrix kunnen uitkomen. Maar ImageAttributes heeft ook een SetThreshold() functie die exact doet wat je wil. Deze zet alle kleuren boven de opgegeven waarde naar het maximum en alle kleuren eronder naar het minimum.
Janoz schreef op woensdag 09 juni 2010 @ 16:03:
[...]

Denk je dat of weet je dat zeker?

Hoe denk je dat de de DrawImage werkt?
Als je zonder unsafe code (dus met met getpixel en setpixel) er door heen loopt gaat dat inderdaad belachelijk traag. Alle .net drawing functies gebuiken intern GDI, GDI+ of een unsafe implementatie die allemaal stukken sneller gaan.

[ Voor 63% gewijzigd door jmzeeman op 09-06-2010 16:44 ]


Acties:
  • 0 Henk 'm!

  • Phyxion
  • Registratie: April 2004
  • Niet online

Phyxion

_/-\o_

Als ik zo even Google wil je die ColorMatrix ook anders doen dan dat je nu hebt.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
            Bitmap origanalImage;
            Bitmap adjustedImage;
            double brightness = 1.0f; // no change in brightness
            double constrast = 2.0f; // twice the contrast
            double gamma = 1.0f; // no change in gamma

            float adjustedBrightness = brightness - 1.0f;
            // create matrix that will brighten and contrast the image
            float[][] ptsArray ={
                    new float[] {contrast, 0, 0, 0, 0}, // scale red
                    new float[] {0, contrast, 0, 0, 0}, // scale green
                    new float[] {0, 0, contrast, 0, 0}, // scale blue
                    new float[] {0, 0, 0, 1.0f, 0}, // don't scale alpha
                    new float[] {adjustedBrightness, adjustedBrightness, adjustedBrightness, 0, 1}};

            imageAttributes = new ImageAttributes();
            imageAttributes.ClearColorMatrix();
            imageAttributes.SetColorMatrix(new ColorMatrix(ptsArray), ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
            imageAttributes.SetGamma(gamma, ColorAdjustType.Bitmap);
            Graphics g = Graphics.FromImage(adjustedImage);
            g.DrawImage(originalImage, new Rectangle(0,0,adjustedImage.Width,adjustedImage.Height)
                ,0,0,bitImage.Width,bitImage.Height,
                GraphicsUnit.Pixel, imageAttributes);

'You like a gay cowboy and you look like a gay terrorist.' - James May


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb het getest met de SetThreshold() suggestie van jmzeeman en met de colormatrix suggestie van Phyxion en het resultaat is praktisch gelijk. Wel zag ik dat SetThreshold() 1 tot 2 tiende van een seconde langzamer is maar dat het plaatje wel ca. 30kB (2.5%) kleiner is.

Hier kan ik mee verder. Bedankt allen voor jullie hulp.

Nu moet ik alleen nog uitzoeken hoe ik het nieuwe plaatje weer als 8Bit PNG kan opslaan, want het origineel is 205kB en de gewijzigde ca. 1100 kB.

Acties:
  • 0 Henk 'm!

  • CodeIT
  • Registratie: Juni 2002
  • Laatst online: 15-09 21:49

CodeIT

Code IT

Je zou de volgende link eens kunnen bekijken: http://msdn.microsoft.com/en-us/library/Aa479306
Volgens mij is dit met unmanaged code, maar dat is door getpixel en setpixel te vervangen (dat maakt het wel traag).
Als je van libraries gebruik mag maken, kun je eens kijken naar FreeImage. Dat is een opensource image library, met wrappers voor .NET.
Pagina: 1