Laden...

[gelöst] Fehlerhafte Bitmap-Erzeugung bei Zusammenführung von Bildern

Erstellt von Abt vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.858 Views
Abt Themenstarter:in
16.842 Beiträge seit 2008
vor 10 Jahren
[gelöst] Fehlerhafte Bitmap-Erzeugung bei Zusammenführung von Bildern

Hallo,

ich versuche mich gerade zwanghaft an der automatisierten Generierung von CSS Sprites mit Hilfe von IIS.
Als Basis habe ich mehrere hundert Icons (16x16) im PNG Format, die zu einem Bild (16px Breite, variable Höhe) zusammengesetzt werden sollen.

Mein Output sieht sauber aus, aber das Bild ist laut Browser fehlerhaft und kann nicht geladen werden.> Fehlermeldung:

Sprite.png kann nicht geladen werden, da es Fehler enthält.

Mehr Info wird nicht ausgespuckt; und dementsprechend mager ist die Fehlersuche im Netz.

Alle Windows-Anzeigen, die mir zur Verfügung stehen, können das Bild problemlos laden. Öffne ich es in Paint.NET und speicher es direkt ab, dann funktioniert es auch im Browser.
Die Icons lassen sich davor im Browser problem anzeigen; nur zusammengesetzt nicht.

Jetzt die Frage: was macht Paint.NET anders, als ich? Oder anders gefragt: wo erzeuge ich den Defekt im Bild?


// Bilder gruppiert nach Höhe
var totalHeight = group.Sum( t => t.Height );

// currentWidth entspricht der Breite der Gruppe der Icons, zB 16px
var outputBitmap = new Bitmap( currentWidth, totalHeight );
var y = 0;

var g = Graphics.FromImage( outputBitmap );
g.FillRectangle( Brushes.White, 0, 0, currentWidth, totalHeight );

foreach ( var imageData in group )
{
	using ( var sourceImage = Image.FromFile( imageData.Fullname ) )
	{
		var outputRect = new Rectangle( 0, y, sourceImage.Width, sourceImage.Height );
		
		g.DrawImage( sourceImage, outputRect );
		y += sourceImage.Height;
	}
}
outputBitmap.Save( Path.Combine( outputDirectory, imageFilename ), imageFormat );	

Danke, Abt

P
1.090 Beiträge seit 2011
vor 10 Jahren

So sieht es für mich eigendlich ganz gut aus.
Ich vermisse nur den Aufruf von Dispose.

Sollte man mal gelesen haben:

Clean Code Developer
Entwurfsmuster
Anti-Pattern

Abt Themenstarter:in
16.842 Beiträge seit 2008
vor 10 Jahren

Der ist da. Nur nicht hier im Code-Ausschnitt.

S
417 Beiträge seit 2008
vor 10 Jahren

Hallo,

der Code sieht gut aus.
Ich habe es mal mit zwei Icons versucht und habe kein Problem mit der Anzeige im Browser.
Evtl. ist ja eines der Icons fehlerhaft und Paint.NET korrigiert das bei der Speicherung.

Abt Themenstarter:in
16.842 Beiträge seit 2008
vor 10 Jahren

Meine Test Icons sind: http://p.yusukekamiyamane.com/ (alle 3570 Stück)

Der IE zeigt einfach nur ein weißes Bild an und der Firefox sagt "Bild enthält Fehler".
Beispiel Output angehängt. (Edit: Super.. hier wirds natürlich angezeigt...).

849 Beiträge seit 2006
vor 10 Jahren

Hallo,

was gibst Du als Image format rein? Aber so einfach wird es wohl nicht sein 😃

Abt Themenstarter:in
16.842 Beiträge seit 2008
vor 10 Jahren

Mehr oder minder ist das alles:

 public void Sprite( )
{
	var images = new List<ImageMetadata>( );
	foreach ( var file in Directory.EnumerateFiles( _sourceDirectory ).Where( IsValidImageType ) )
	{
		var fs = new FileStream( file, FileMode.Open, FileAccess.Read );
		using ( var i = Image.FromStream( fs, false, false ) )
		{
			images.Add( new ImageMetadata( file, i.Height, i.Width ) );
		}
	}

	var groupedImages = images.GroupBy( i => i.Width ).ToList( );

	foreach ( var groupI in groupedImages )
	{
		CreateSprite( _outputDirectory, ImageFormat.Png, groupI );
	}
}

private static void CreateSprite( String outputDirectory, ImageFormat imageFormat, IGrouping<int, ImageMetadata> group )
{
	var currentWidth = group.Key;

	var imageExtension = imageFormat.ToString( ).ToLower( );
	var imageFilename = fileNamePrefix + "_" + currentWidth + "." + imageExtension;
	
	var totalHeight = group.Sum( t => t.Height );

	using ( var outputBitmap = new Bitmap( currentWidth, totalHeight ) )
	{
		var y = 0;

		var g = Graphics.FromImage( outputBitmap );
		g.FillRectangle( Brushes.White, 0, 0, currentWidth, totalHeight );

		foreach ( var imageData in group )
		{
			using ( var outputImage = Image.FromFile( imageData.Fullname ) )
			{
				var outputRect = new Rectangle( 0, y, outputImage.Width, outputImage.Height );
				g.DrawImage( outputImage, outputRect );
				y += outputImage.Height;
			}
		}
		outputBitmap.Save( Path.Combine( outputDirectory, imageFilename ), imageFormat );
	}
}

Hab auch schon Gif und Jpeg probiert; gleiches Spiel.

S
417 Beiträge seit 2008
vor 10 Jahren

Ein Test hat gezeigt, dass ab einer Kombination von 2048 Bildern (2048 * 16 = 32768) ein Problem entsteht. Das hängt evtl. mit GDI+ zusammen (GDI+ Bitmap size limitation?).
Ich denke das ist schonmal ein Ansatz für die weitere Recherche.

Abt Themenstarter:in
16.842 Beiträge seit 2008
vor 10 Jahren

Ahhh danke.
Von einem Problem mit dem 2GB Limit hab ich gelesen; von Pixeln nicht.