Hi,
ich bin grad völligst am verzweifeln. Ich verwende von Codeproject (Fast Bitmaps) diese Klasse um ein Bild zu erstellen und bearbeiten.
Problem ist, das es mir das ganze Bild verzerrt. siehe Screenshot.
Ich hab jetzt rausbekommen das es wohl an der falsch gelesen Farbtiefe liegt.
Ich hab mal ein Testprogramm gemacht:
public static void Main(string[] args)
{
Bitmap bmp = (Bitmap)Image.FromFile(@"C:\_trash\pdfdiff\t_24bit.bmp");
Console.WriteLine(Bitmap.GetPixelFormatSize(bmp.PixelFormat));
Console.ReadKey(true);
}
Dieser gibt mir dann schon die falsche Farbtiefe aus. Im Windows Explorer Eigenschaften-Fenster steht die Richtige.
Anbei noch die Testbilder (in Photoshop CS2 gespeichert). Das absolut noch dubiosere ist, dass wenn ich ein PDF im Acrobat mit speichern unter "JPG" mache, das Tool ohne Probleme funktioniert. Aber alle anderen Bilder (getestet Ghostscript, Photoshop, Paint) Probleme machen.
Dateiformat ist auch egal (PNG, BMP, JPG).
Ich weiss leider echt nicht mehr weiter. Hat jemand schon mal ein ähnliches Problem gehabt?
Vielen Dank
Hi toxic,
ein Bild zu erstellen und bearbeiten.
Dann solltest du mal erklären oder zeigen was du machst. Wenn du nur das Ergebnis postest, kann es doch keiner nachvollziehen!
Dieser gibt mir dann schon die falsche Farbtiefe aus. Im Windows Explorer Eigenschaften-Fenster steht die Richtige.
Was wird denn ausgegeben und was ist die von dir erwartete Ausgabe? Bitte beachte [Hinweis] Wie poste ich richtig?, Punkt 5!
Christian
Weeks of programming can save you hours of planning
Hallo Christian,
ich habe geschrieben, dass ich bereits eine Vermutung für den Fehler hab. Deswegen hab ich einen Code eingestellt der die Farbtiefe aus Bilder ausließt und hab dazu Testbilder gepackt.
Die Dateinamen heißen so, mit welcher Farbtiefe das Bild gespeichert wurde. Wenn ich mir die Farbtiefe im Explorer anzeigen lassen passt diese. Wenn ich sie mir über .Net mit der obenen genannten Funktion ausgeben lassen, stimmt diese nicht überein. z.B. Bild hat 16 Bit Farbtiefe, Ausgabe 8 Bit
Sorry wenn das ganze unverständlich war...
Hier nochmal ein Bild zur Verdäutlichung:
Ich hab das Bild mit 16 Bit (Wird auch im Explorer angezeigt) eingelesen. Im .Net bekomm ich aber die Anzeige 32 Bit?! Deswegen komm ich dann auch mit den LockBits-Funktion nicht richtig zu Rande.
Das Grundproblem ist, dass ich nicht die richtige Farbtiefe bekomme
IIRC kann Image.FromFile()
erst mal nur mit 32 Bit arbeiten. Beim Laden ist es 32 Bit und der Cast hilft Dir hier auch nicht.
Du musst ein neues Bitmap
-Objekt erstellen mit dem gewünschten 16-Bit Parameter und dann das originale Image in das neue Objekt laden.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Das tolle ist aber das:
Bild: Ausgabe:
16 --> 32
24 --> 24
32 --> 24
Das gibt doch überhaupt keinen Sinn!
*grml*
Ist doch völlig egal, wie die Ausgabe von irgendwelchen Programmen aussehen, wenn du nicht zeigst, wie du das Bild erstellst. Da wird nämlich das eigentliche Problem liegen.
Christian
Weeks of programming can save you hours of planning
Das gibt doch überhaupt keinen Sinn!
*grml*
Doch. Siehe auch Loading image from 32 bits bitmap file.
Bestätigt meine Aussage.
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hi,
nochmal ich hab das Bitmap mit verschiedenen Programmen erstellt. in dem Fall wie oben geschrieben mit Adobe Photoshop CS 2. Datei Speichern unter BMP und die verschiedenen Farbtiefen ausgewählt...ich versuch sie doch nur zu laden...
Ignorierst meine Beiträge mit Absicht?
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Nein Abt, sorry. Schau ich mir gerade an das Thema. Ich wollte nur Christian drauf hinweisen, das ich bereits erklärt habe wo die Bilder herkommen die ich laden will.
Ich will keinen Verärgern. Vielen Dank für die Hilfe! Ich werd mich mal einlesen.
Hallo toxic,
im Explorer bekomme ich für die Dateien aus der Zip-Datei 16, 24, 24 Bit angezeigt. Kein Wunder, die Dateien t_24bit.bmp und t_32bit.bmp byteweise identisch.
Irfanview zeigt für alle Dateien 24 Bit an.
Ein anderes Programm zeigt mir bei der Datei t_16bit.bmp sogar:> Fehlermeldung:
can't read file header: bit count not 1, 4, 8 or 24
Die Ausgangssituation der Dateien in der Zip-Datei ist also nicht so, wie du sie vermutet/beschrieben hast.
herbivore
Hallo herbivore,
Danke das du dir es auch nochmal anschaust. Ich habe jetzt mal Vergleichsbilder gemacht. Die Ursprungsbilder wurden von einem PDF mit Ghostscript als jpg umgewandelt.
(D:\pdf\gs\gs9.09\bin>gswin32c.exe -sDEVICE=jpeg -r50 -dBATCH -dNOPAUSE -sOutputFile=D:\pdf\pdf1.jpg D:\pdf\pdf1.pdf)
Wenn ich das Bild über die Funktionen Bitmap.GetPixel() und Bitmap.SetPixel() bearbeite und auslese ist alles so wie gewollt. Wenn ich aber über LockBits gehe, verschiebt er mir alles.
Ich pack mal ein Beispielprojekt mit rein. Die LockBitmap-Klasse ist die, die ich oben schon verlinkt habe.
Ich komm irgendwie nicht weiter. Hab versucht wie Abt das geschrieben hat, das Bitmap zu laden. Leider ohne erfolg
Erklärung der Bilder:
pdf1.jpg -->Ausgangsbild Source
pdf2.jpg -->Ausgangsbild Compare
compare_bitmap.jpg --> So sollte es aussehen (mit GetPixel und SetPixel)
compare_lockbits.jpg --> So sieht es mit LockBits aus...
LockBits brauch ich wegen der Performance.
Vielen Dank an alle!
Hallo toxic,
das verzerrte Bild kommt (üblicherweise) durch die Nichtbeachtung des "Stride" zustande (wenn die Breite des Bildes "ungerade" ist). Hier eine Erklärung dafür: Using LockBits in GDI+.
Unter [RESOLVED] C# lockbits. gibt es korrekten Source-Code dafür (im unsafe-Modus).
Zeig mal deinen Code für LockBits. Benutzt du denn den Stride-Parameter?
Hi,
Vielen Dank für die Antwort. Nein von den Strides hab ich noc nichts gehört.
anbei der Code für die LockBits:
public class LockBitmap
{
Bitmap source = null;
IntPtr Iptr = IntPtr.Zero;
BitmapData bitmapData = null;
public byte[] Pixels { get; set; }
public int Depth { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; }
public Bitmap Image { get { return source; } }
public LockBitmap(Bitmap source)
{
this.source = source;
}
/// <summary>
/// Lock bitmap data
/// </summary>
public void LockBits()
{
try
{
// Get width and height of bitmap
Width = source.Width;
Height = source.Height;
// get total locked pixels count
int PixelCount = Width * Height;
// Create rectangle to lock
Rectangle rect = new Rectangle(0, 0, Width, Height);
// get source bitmap pixel format size
Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);
// Check if bpp (Bits Per Pixel) is 8, 24, or 32
if (Depth != 8 && Depth != 24 && Depth != 32)
{
throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
}
// Lock bitmap and return bitmap data
bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
source.PixelFormat);
// create byte array to copy pixel values
int step = Depth / 8;
Pixels = new byte[PixelCount * step];
Iptr = bitmapData.Scan0;
// Copy data from pointer to array
Marshal.Copy(Iptr, Pixels, 0, Pixels.Length);
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// Unlock bitmap data
/// </summary>
public void UnlockBits()
{
try
{
// Copy data from byte array to pointer
Marshal.Copy(Pixels, 0, Iptr, Pixels.Length);
// Unlock bitmap data
source.UnlockBits(bitmapData);
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// Get the color of the specified pixel
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <returns></returns>
public Color GetPixel(int x, int y)
{
Color clr = Color.Empty;
// Get color components count
int cCount = Depth / 8;
// Get start index of the specified pixel
int i = ((y * Width) + x) * cCount;
if (i > Pixels.Length - cCount)
throw new IndexOutOfRangeException();
if (Depth == 32) // For 32 bpp get Red, Green, Blue and Alpha
{
byte b = Pixels[i];
byte g = Pixels[i + 1];
byte r = Pixels[i + 2];
byte a = Pixels[i + 3]; // a
clr = Color.FromArgb(a, r, g, b);
}
if (Depth == 24) // For 24 bpp get Red, Green and Blue
{
byte b = Pixels[i];
byte g = Pixels[i + 1];
byte r = Pixels[i + 2];
clr = Color.FromArgb(r, g, b);
}
if (Depth == 8)
// For 8 bpp get color value (Red, Green and Blue values are the same)
{
byte c = Pixels[i];
clr = Color.FromArgb(c, c, c);
}
return clr;
}
/// <summary>
/// Set the color of the specified pixel
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
/// <param name="color"></param>
public void SetPixel(int x, int y, Color color)
{
// Get color components count
int cCount = Depth / 8;
// Get start index of the specified pixel
int i = ((y * Width) + x) * cCount;
if (Depth == 32) // For 32 bpp set Red, Green, Blue and Alpha
{
Pixels[i] = color.B;
Pixels[i + 1] = color.G;
Pixels[i + 2] = color.R;
Pixels[i + 3] = color.A;
}
if (Depth == 24) // For 24 bpp set Red, Green and Blue
{
Pixels[i] = color.B;
Pixels[i + 1] = color.G;
Pixels[i + 2] = color.R;
}
if (Depth == 8)
// For 8 bpp set color value (Red, Green and Blue values are the same)
{
Pixels[i] = color.B;
}
}
public Color GetBlackWhitePixel(int x, int y)
{
Color value = GetPixel(x, y);
int grey = (value.R + value.G + value.B) / 3;
if (grey > 127) return Color.White;
else return Color.Black;
}
}
Wenn du den Code so unverändert von deinem CodeProject-Link verwendest hast, dann mußt du noch den Stride-Parameter da einbauen.
Hier noch ein anderer Link, der das (für C# und VB.NET) erklärt: Using the LockBits method to access image data
PS. Es hätte gereicht, wenn du den relevanten Code gepostet hättest. Trotzdem geht aus deinen Code noch nicht heraus, wie du jetzt genau dein Bild erzeugst (also welche Methoden du konkret aufrufst).
PPS. Du kannst dir auch mal die folgenden beiden Links anschauen:
GetPixel und SetPixel um Längen geschlagen. 800 mal schneller
Bitmap-Manipulation (MemBitmap)
(diese verwenden beide korrekterweise den Stride-Parameter - anstatt den Width-Parameter)
Hi Th69,
du bist mein persönlicher Held des Tages! die beiden Links haben mir echt weiter geholfen. Das mit dem Stride habe ich nicht gewusst! Danach ist alles etwas klarer!
Vielen Dank nochmal und schönes WE! Auch an die anderen Vielen Dank für die Geduld!
PPS. Du kannst dir auch mal die folgenden beiden Links anschauen:
>
>
(diese verwenden beide korrekterweise den Stride-Parameter - anstatt den Width-Parameter)