[.NET] Bitmap resize lelijk border foutje

Pagina: 1
Acties:
  • 152 views sinds 30-01-2008
  • Reageer

  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Ik heb de volgende code geschreven om on the fly bitmaps te resizen. Het werkt prima maar ik zie telkens een terugkerende fout in de geresizede afbeelding die het script uitspuugt: Een dunne border rond de randen van de afbeelding.

In een hoekje van het internet had ik gevonden dat de interpolation van .NET niet helemaal jofel is en pixels langs de randen gaat interpoleren met pixels buiten de bitmap; pixels die dus niet bestaan waardoor de border altijd donkerder wordt.

Voorbeeld van een geresizede JPG (In het origineel zit die lichte grijze border dus niet):

Afbeeldingslocatie: http://www.xs4all.nl/~boutd/bundleart.JPG

Sample van mijn code:

code:
1
2
3
4
5
6
7
8
9
10
11
System.Drawing.Image    oImg        = System.Drawing.Image.FromFile(sFullJpgPath); 
System.Drawing.Image    oThumbNail  = new Bitmap(iWidth, iHeight, oImg.PixelFormat);
            
Rectangle   oRectangle  = new Rectangle(0, 0, iWidth, iHeight);
Graphics    oGraphic    = Graphics.FromImage(oThumbNail);
        
oGraphic.CompositingQuality     = CompositingQuality.HighQuality;
oGraphic.SmoothingMode      = SmoothingMode.HighQuality;
oGraphic.InterpolationMode  = InterpolationMode.HighQualityBicubic;

oGraphic.DrawImage(oImg, oRectangle);


De InterpolationMode veranderen naar NearestNeighbour helpt natuurlijk wel tegen de border maar geeft zoals je verwacht een zeer brakke kwaliteit.

Iemand een idee?

Download my music on SoundCloud


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13:49

Janoz

Moderator Devschuur®

!litemod

Je huidige rectangle is sowieso te groot. De rectangle die jij hebt is iWidth+1 breedt en iHeight+1 hoog. Een rectangle die precies op je thumbnail past is new Rectangle(0,0,iWidth-1,iHeight-1);

De zwarte rand zou door de interpolatie of door de smooth kunnen komen. In het eerste geval zit er een fout in het interpolatie algoritme. In het tweede geval zou het kunnen zijn dat de smoothing niet 'clamped' (=zodra een pixel buiten de border gesampled wordt, wordt de border pixel terug gegeven). Wat is het resultaat zonder smooth?

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


  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Als ik smoothing uitzet is de border weg..

De rectangle is idd te groot maar dit zou alleen tot problemen rechts en onder moeten leiden..

Edit: De rectangle kleiner maken heeft geen effect.

[ Voor 17% gewijzigd door dominic op 10-08-2005 13:50 ]

Download my music on SoundCloud


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13:49

Janoz

Moderator Devschuur®

!litemod

Hoe is het resultaat zonder smoothing? De msdn vind ik wat onduidelijk, maar volgens mij zou dit op de randen na geen enkele invloed op het plaatje moeten hebben. Het is waarschijnlijk dan ook beter om deze weg te laten. Ik kan verder niks vinden over mogelijke clamping. De enige andere oplossing zou dan zijn om de rectangle niet alleen rechtsonder te groot te laten zijn, maar ook linksboven (ie (-1,-1,iWidth,iHeight) )

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


  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Janoz schreef op woensdag 10 augustus 2005 @ 14:14:
Hoe is het resultaat zonder smoothing? De msdn vind ik wat onduidelijk, maar volgens mij zou dit op de randen na geen enkele invloed op het plaatje moeten hebben. Het is waarschijnlijk dan ook beter om deze weg te laten. Ik kan verder niks vinden over mogelijke clamping. De enige andere oplossing zou dan zijn om de rectangle niet alleen rechtsonder te groot te laten zijn, maar ook linksboven (ie (-1,-1,iWidth,iHeight) )
Oh sorry, de smoothing mode veranderen haalt niets uit, dit heeft inderdaad alleen betrekking op vector graphics..

Met de rectangle spelen haalt verder ook niets uit :(

Download my music on SoundCloud


  • Serpie
  • Registratie: Maart 2005
  • Laatst online: 05-02 21:24
Ik heb ook even met je code gespeeld, ik krijg hetzelfde effect. Met de methode GetThumbnailImage werkt het echter prima, en zou goed genoeg moeten werken als je image geen thumbnail heeft of als je thumbs klein blijven (iedergeval haal ik dat uit de remarks op onderstaande pagina).

http://msdn.microsoft.com...etthumbnailimagetopic.asp

  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Serpie schreef op woensdag 10 augustus 2005 @ 16:53:
Ik heb ook even met je code gespeeld, ik krijg hetzelfde effect. Met de methode GetThumbnailImage werkt het echter prima, en zou goed genoeg moeten werken als je image geen thumbnail heeft of als je thumbs klein blijven (iedergeval haal ik dat uit de remarks op onderstaande pagina).

http://msdn.microsoft.com...etthumbnailimagetopic.asp
Ik wil deze functie niet gebruiken (Heb er al eerder naar gekeken) en wel om de volgende reden:
If the Image object contains an embedded thumbnail image, then this method retrieves the embedded thumbnail and scales it to the requested size. If the Image object does not contain an embedded thumbnail image, this method creates a thumbnail image by scaling the main image.
Het gaat mij nl. niet per sé om kleine afbeeldingen maar ook om grote afbeeldingen van 2048x2048 te resizen naar 1024x1024. Als ik een standaard thumbnail upscale naar 1024x1024 ziet het er natuurlijk niet uit bij bitmaps waar al een thumbnail in zit..

Download my music on SoundCloud


  • Serpie
  • Registratie: Maart 2005
  • Laatst online: 05-02 21:24
Tja dat is precies wat ik zei :) maar dat gaat dus niet voor jouw op.
en zou goed genoeg moeten werken als je image geen thumbnail heeft of als je thumbs klein blijven
De PixelOffsetMode op HighQuality zetten geeft wel een beter resultaat zonder border.

  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Serpie schreef op donderdag 11 augustus 2005 @ 08:27:
Tja dat is precies wat ik zei :) maar dat gaat dus niet voor jouw op.
[...]


De PixelOffsetMode op HighQuality zetten geeft wel een beter resultaat zonder border.
Maar het gaat mij echt om volwaardige kwaliteit afbeeldingen te genereren, geen previews oid.. De kwaliteit moet gewoon perfect zijn, en dat krijg je er gewoon niet uit met de thumbnail functie..

[ Voor 12% gewijzigd door dominic op 11-08-2005 13:50 ]

Download my music on SoundCloud


  • Serpie
  • Registratie: Maart 2005
  • Laatst online: 05-02 21:24
dominic schreef op donderdag 11 augustus 2005 @ 13:49:
[...]
Maar het gaat mij echt om volwaardige kwaliteit afbeeldingen te genereren, geen previews oid.. De kwaliteit moet gewoon perfect zijn, en dat krijg je er gewoon niet uit met de thumbnail functie..
Precies, naja we praten langs elkaar heen denk ik, sorry.

Iedergeval, als je de PixelOffsetMode op HighQuality zet:

oGraphic.CompositingQuality = CompositingQuality.HighQuality;
oGraphic.SmoothingMode = SmoothingMode.HighQuality;
oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
oGraphic.PixelOffsetMode = PixelOffsetMode.HighQuality;

Dan doet jouw code het wel goed.

  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Serpie schreef op donderdag 11 augustus 2005 @ 13:57:
[...]
Precies, naja we praten langs elkaar heen denk ik, sorry.

Iedergeval, als je de PixelOffsetMode op HighQuality zet:

oGraphic.CompositingQuality = CompositingQuality.HighQuality;
oGraphic.SmoothingMode = SmoothingMode.HighQuality;
oGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
oGraphic.PixelOffsetMode = PixelOffsetMode.HighQuality;

Dan doet jouw code het wel goed.
Ow verrek ik ga het ff proberen..

Download my music on SoundCloud


  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Serpie bedankt, het werkt 99%, de border is nog wel zichtbaar maar een stuk minder.. ik laat het maar zo..

Hieronder zie je het huidige resultaat:

Afbeeldingslocatie: http://www.xs4all.nl/~boutd/bundleart2.JPG

Nog steeds een lichte border dus.

[ Voor 105% gewijzigd door dominic op 11-08-2005 14:27 ]

Download my music on SoundCloud


  • Serpie
  • Registratie: Maart 2005
  • Laatst online: 05-02 21:24
Das vaag, ik heb de code nog maar eens erbij gepakt, het was mij niet opgevallen omdat ik een grijze achtergrond gebruikte in mijn picturebox.

Het heeft te maken met de rectangle, zo het lijkt is deze niet te groot maar te klein voor de bitmap? Iedergeval als ik die 1 pixel groter maakt dan is de border helemaal weg, wel vaag.

Het lijkt erop dat de dimensies van een rectangle gelden -1 pixel ofzo? heeft een rectangle ook een border?

  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Serpie schreef op donderdag 11 augustus 2005 @ 14:51:
Das vaag, ik heb de code nog maar eens erbij gepakt, het was mij niet opgevallen omdat ik een grijze achtergrond gebruikte in mijn picturebox.

Het heeft te maken met de rectangle, zo het lijkt is deze niet te groot maar te klein voor de bitmap? Iedergeval als ik die 1 pixel groter maakt dan is de border helemaal weg, wel vaag.

Het lijkt erop dat de dimensies van een rectangle gelden -1 pixel ofzo? heeft een rectangle ook een border?
Je hebt bijna gelijk, de border rechts en onder is dan weg, maar links en boven staat ie nog steeds. Ik kan hem wel eens voor de grap van -1 tot width+1 en -1 tot height+1 laten lopen en kijken wat het resultaat is.. Maar dan clipt ie mijn image wel volgens mij..

Download my music on SoundCloud


  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Helaas, met new Rectangle(-1, -1, iWidth+1, iHeight+1); hou ik nog steeds een heel dunne border links en boven. Rechts en onder is ie weg..

Download my music on SoundCloud


  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 13:49

Janoz

Moderator Devschuur®

!litemod

Dat zei ik eerder ook al ;).
Janoz schreef op woensdag 10 augustus 2005 @ 14:14:
De enige andere oplossing zou dan zijn om de rectangle niet alleen rechtsonder te groot te laten zijn, maar ook linksboven (ie (-1,-1,iWidth,iHeight) )
Bedenk trouwens dat width+1 ed niet nodig is omdat je dat effectief nu al doet. Verder blijf ik het vreemd vinden dat ze bij ms blijkbaar de resize/resample methode niet fatsoenlijk kunnen implementeren.

---
Dat ie rechtsonder weg is komt omdat je rectangle daar 2 pixels uitsteekt. Misschien -2,-2 proberen voor links boven?

[ Voor 12% gewijzigd door Janoz op 11-08-2005 15:24 ]

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


  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Janoz schreef op donderdag 11 augustus 2005 @ 15:23:
Dat zei ik eerder ook al ;).


[...]


Bedenk trouwens dat width+1 ed niet nodig is omdat je dat effectief nu al doet. Verder blijf ik het vreemd vinden dat ze bij ms blijkbaar de resize/resample methode niet fatsoenlijk kunnen implementeren.

---
Dat ie rechtsonder weg is komt omdat je rectangle daar 2 pixels uitsteekt. Misschien -2,-2 proberen voor links boven?
Hahah, op het moment dat jij het zei leek het me wat minder logisch.

Anyway, met -2,-2 krijg ik nog steeds hetzelfde resultaat. Het lijkt alsof die coördinaten niet negatief mogen zijn?

Download my music on SoundCloud


  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 01-05 19:54

Bosmonster

*zucht*

Smoothing op een JPEG is nogal zonde van de kwaliteit (als het de smoothing is die ik denk dat het is). Hij blurd het beeld om meer compressie te kunnen bereiken.

Je JPEG kwaliteit is ook vrij dramatisch, dat kan ook wel een flink stuk hoger.

Andere mogelijkheid is nog PNG te genereren ipv JPG, maar dat gaat wel ten koste van bestandsgrootte.

  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Bosmonster schreef op donderdag 11 augustus 2005 @ 16:37:
Smoothing op een JPEG is nogal zonde van de kwaliteit (als het de smoothing is die ik denk dat het is). Hij blurd het beeld om meer compressie te kunnen bereiken.

Je JPEG kwaliteit is ook vrij dramatisch, dat kan ook wel een flink stuk hoger.

Andere mogelijkheid is nog PNG te genereren ipv JPG, maar dat gaat wel ten koste van bestandsgrootte.
De smoothing heeft alleen betrekking op vector graphics (Shapes en fonts). PNG is geen mogelijkheid, het is nl. voor snelle weergave in een browser.

Download my music on SoundCloud


  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 01-05 19:54

Bosmonster

*zucht*

dominic schreef op donderdag 11 augustus 2005 @ 17:21:
[...]


De smoothing heeft alleen betrekking op vector graphics (Shapes en fonts). PNG is geen mogelijkheid, het is nl. voor snelle weergave in een browser.
K, dan is die smoothing toch wat anders :)

Maar kun je de compressie niet wat verlagen?

  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Bosmonster schreef op donderdag 11 augustus 2005 @ 18:03:
[...]


K, dan is die smoothing toch wat anders :)

Maar kun je de compressie niet wat verlagen?
Dat kan wellicht, maar lost het probleem niet op, het gaat mij om die irri border..

Download my music on SoundCloud


  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Iemand nog een idee?

Download my music on SoundCloud


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Mischien kan je microsoft even mailen of ze een oplossing voor deze bug hebben.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Had het niet iets met de blending mode te maken? Ik ken herken het probleem ik kan me alleen de oplossing niet meer hierinneren :x

Of misschien de Compositing Mode. Zet die op source copy. Ik dacht dat hij de randen wilt blenden met de achtergrondkleur.

Maar goed, ik doe maar een wilde gok. Een van die properties is het... maar welke...

[ Voor 63% gewijzigd door Infinitive op 17-08-2005 17:33 ]

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 20:35

TeeDee

CQB 241

Kan me herinneren dat ik dit ook had.
Die "border" die je zit is geen border.
Dat is namelijk het canvas. Deze is bij default zwart.
Kortom, gooi eerst eens een complete wit vlak over je canvas, en dan je image erop.

Dus:
C#:
1
oGraphics.FillRectangle(new System.Drawing.SolidBrush(Color.White), 0, 0, iWidth, iHeight);
iWidth / iHeight kan ook andersom staan, weet ik niet precies meer :+

[ Voor 44% gewijzigd door TeeDee op 17-08-2005 17:59 ]

Heart..pumps blood.Has nothing to do with emotion! Bored


  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
TeeDee schreef op woensdag 17 augustus 2005 @ 17:54:
Kan me herinneren dat ik dit ook had.
Die "border" die je zit is geen border.
Dat is namelijk het canvas. Deze is bij default zwart.
Kortom, gooi eerst eens een complete wit vlak over je canvas, en dan je image erop.

Dus:
C#:
1
oGraphics.FillRectangle(new System.Drawing.SolidBrush(Color.White), 0, 0, iWidth, iHeight);
iWidth / iHeight kan ook andersom staan, weet ik niet precies meer :+
Goed idee, maar dan krijgen 'grijze' afbeeldingen weer een witte rand :|

Download my music on SoundCloud


  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Infinitive schreef op woensdag 17 augustus 2005 @ 17:26:
Had het niet iets met de blending mode te maken? Ik ken herken het probleem ik kan me alleen de oplossing niet meer hierinneren :x

Of misschien de Compositing Mode. Zet die op source copy. Ik dacht dat hij de randen wilt blenden met de achtergrondkleur.

Maar goed, ik doe maar een wilde gok. Een van die properties is het... maar welke...
Compositingmode is het niet iig..

Download my music on SoundCloud


  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Er is in ieder geval een rigoreuze oplossing. Als je het plaatje opent als bitmap dan kan je in een stukje unsafe code direct bij de pixeldata komen. Vervolgens zou je zelf de resize kunnen doen. Maar zoiets doe je beter maar niet :+

Dus kan je beter deze pagina eens checken, dat geeft antwoord op het waarom, en waarschijnlijk ook wel een oplossing: http://www.codeproject.com/csharp/ImgResizOutperfGDIPlus.asp.

[ Voor 9% gewijzigd door Infinitive op 18-08-2005 10:36 ]

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • dominic
  • Registratie: Juli 2000
  • Laatst online: 08-02 14:55

dominic

will code for food

Topicstarter
Infinitive schreef op donderdag 18 augustus 2005 @ 10:35:
Er is in ieder geval een rigoreuze oplossing. Als je het plaatje opent als bitmap dan kan je in een stukje unsafe code direct bij de pixeldata komen. Vervolgens zou je zelf de resize kunnen doen. Maar zoiets doe je beter maar niet :+

Dus kan je beter deze pagina eens checken, dat geeft antwoord op het waarom, en waarschijnlijk ook wel een oplossing: http://www.codeproject.com/csharp/ImgResizOutperfGDIPlus.asp.
Yep, dit stuk had ik ook al gevonden inderdaad.. Helaas is een unsafe functie toch niet de weg die ik wil inslaan.

Download my music on SoundCloud


  • MrSleeves
  • Registratie: Februari 2004
  • Laatst online: 10-04 19:23

MrSleeves

You'll thank me later.

Het lijkt een beetje op slechte compressie.
Wat je kan proberen is deze manier (werkt bij mij goed, maar geval als dit niet gechecked):
Je maakt de bitmap zoals je 'm wilt hebben en bij het opslaan doe je het volgende:
code:
1
2
bmp.Save(fi.FullName,  Images.GetImageCodecInfo("image/jpeg"), _
     Images.GetEncoderParameters(Imaging.EncoderValue.CompressionLZW, 90, 24))

met de functie Images.GetEncoderParameters:
code:
1
2
3
4
5
6
7
8
Public Shared Function GetEncoderParameters(ByVal Compression As Imaging.EncoderValue, ByVal Quality As Long, ByVal ColorDepth As Long) As Imaging.EncoderParameters
        Dim EPs As New Imaging.EncoderParameters(3)
        EPs.Param(0) = New Imaging.EncoderParameter(Imaging.Encoder.Compression, CLng(Compression))
        EPs.Param(1) = New Imaging.EncoderParameter(Imaging.Encoder.Quality, Quality)
        EPs.Param(2) = New Imaging.EncoderParameter(Imaging.Encoder.ColorDepth, ColorDepth)

        Return EPs
    End Function


Imaging zit overigens in System.Drawing.
En er zijn natuurlijk nog een hele berg EncoderParameters; ik had er alleen niet meer nodig.


En eventueel maak je zelf een nieuwe Bitmap aan en m.b.v. Graphics.DrawImage zet je het origineel erin (al resizend). De nieuwe bitmap sla je dan op bovenstaande manier op.

[ Voor 20% gewijzigd door MrSleeves op 18-08-2005 11:16 ]

30Drie Web Design & IT Consultancy | Raven Consultancy Services


  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Dan is het volgende een niet-zo-elegante oplossing:

Teken je afbeelding in het midden van een iets grotere afbeelding die initieel de juiste achtergrondkleur heeft (bijv. wit). Resize deze afbeelding en knip de echte afbeelding eruit. Je zult dan wel goed moeten uitrekenen aan de hand van de grootte van de thumbnail en de echte afbeelding, wat de formaten van de "extended"-afbeelding moet zijn. Dit zorgt ervoor dat de resize op de randen van de oorspronkelijke afbeelding goed gaat met respect tot omliggende pixels. Als je achtergrondkleur niet vaststaat (wat effect kan hebben i.v.m. anti-aliassing), duppliceer dan de randen van je afbeelding.

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 20:35

TeeDee

CQB 241

Hier wat handige snippets die ik altijd gebruik als ik met GDI+ aan de slag ga.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
        ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            int j;
            ImageCodecInfo[] encoders;
            encoders = ImageCodecInfo.GetImageEncoders();
            for(j = 0; j < encoders.Length; ++j)
            {
                if(encoders[j].MimeType == mimeType)
                    return encoders[j];
            }
            return null;
        }


En opslaan:
C#:
1
2
3
4
5
6
7
8
            //save het image
            EncoderParameters eps = new EncoderParameters(1);
            eps.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
            ImageCodecInfo ici = GetEncoderInfo("image/jpeg");
            originalImage.Dispose();
    
            _newimage.Save(_imgsavepath, ici, eps);
            _newimage.Dispose();

Dit zijn snippets uit wat eigen projecten. Ik hoop dat je er wat aan hebt.

[ Voor 28% gewijzigd door TeeDee op 18-08-2005 11:22 ]

Heart..pumps blood.Has nothing to do with emotion! Bored

Pagina: 1