| |
VB.NET - Ein- und UmsteigerBitmap mit einer bestimmten Auflösung speichern | | | Autor: Kalli | Datum: 24.10.11 16:43 |
| Ich möchte eine Bitmap (original Bitmap.FromFile("xyz.bmp")) laden, ihr eine von mir bestimmte Resolution verpassen Bitmap.SetResolution(300,300) und dann als JPG wieder speichern.
Das Laden und SetResolution klappt. Die Auflösung der Bitmap beträgt nach SetResolution tatsächlich 300 DPI, wenn ich sie aber speichere "Bitmap.Save(Pfad,Imaging.ImageFormat.Jpeg)" wird die Auflösung nach erneutem Einlesen wieder mit 96 DPI (Standard) angegeben.
Mit dem ImageEncoder kann ich die Auflösung leider nicht festlegen, Qualität etc. sind mir in diesem Fall nicht so wichtig.
Hier der Code, den es zu verbessern gilt:
Dim vorschau as Bitmap
vorschau = Bitmap.FromFile("abc")
vorschau.SetResolution(300,300)
vorschau.Save("abcde",Imaging.ImageFormat.Jpeg)
vorschau.dispose() Ich habe das bisher per Freeimage.DLL ganz locker lösen können, aber obwohl ich als Plattform für's Debuggen x86 eingestellt habe, will das Programm die FreeImage.DLL nicht erkennen. Außerdem meine ich, das muß doch auch mit VB Net zu schaffen sein.
Ich wäre für Hilfe sehr dankbar
Kalle
Dont debug, because there will allways be one more bug | |
Re: Bitmap mit einer bestimmten Auflösung speichern | | | Autor: Manfred X | Datum: 24.10.11 18:10 |
| Hallo!
Dim vorschau As Bitmap
vorschau = CType(Bitmap.FromFile("abc.jpg"), Bitmap)
Dim output As New Bitmap(vorschau.Width, vorschau.Height, vorschau.PixelFormat)
output.SetResolution(300, 300)
Using g As Graphics = Graphics.FromImage(output)
g.DrawImage(vorschau, 0, 0)
End Using
output.Save("abcde.jpg", Imaging.ImageFormat.Jpeg)
vorschau.Dispose()
output.Dispose() Aufpassen. Die Größe des Output-Bildes muss anhand der
DPI-Werte entsprechend umgerechnet werden.
MfG
Manfred | |
Re: Bitmap mit einer bestimmten Auflösung speichern | | | Autor: Kalli | Datum: 24.10.11 18:30 |
| Suuper, ich hab's jetzt so schnell nicht testen können, vermute aber, dass es klappt.
Auf jeden Fall erstmal vielen Dank! Melde mich dann wieder.
Ich denke, mein Fehler war, dass ich die Bitmap nicht auf einen 300 mal 300 DPI-Unterlage neu gezeichnet habe.
Was die Größe angeht, will ich mit dem Setzen der Auflösung erreichen, dass anständige Bildbearbeitungsprogramme, wie Photoshop etc. solch ein JPG standardmäßig in der von mir gewünschten Größe ausdrucken. Dieser Trick klappt vorzüglich.
Kalle
Dont debug, because there will allways be one more bug | |
Re: Bitmap mit einer bestimmten Auflösung speichern | | | Autor: Kalli | Datum: 24.10.11 19:52 |
| So, getestet - klappt prima!
Die "Umrechnung" der Größe sieht bei mir folgendermaßen aus:
Dim vorschau, vorschau1 as Bitmap
vorschau = CType(Bitmap.FromFile(tempfile), Bitmap)
vorschau1 = New Bitmap(vorschau.Width, vorschau.Height)
vorschau1.SetResolution(300, 300)
Using g As Graphics = Graphics.FromImage(vorschau1)
g.DrawImage(vorschau, 0, 0, vorschau.Width, vorschau.Height)
End Using
vorschau1.Save("Abcd.jpg",Imaging.ImageFormat.Jpeg)
vorschau.Dispose()
vorschau1.Dispose() Wenn ich DrawImage nicht auf das ursprüngliche Rechteck (vorschau.width, vorschau.height)beschränkte, würde die Zeichnung (in meinem Falle) 300/96(momentane Bildschirmauflösung) mal so gross auf die Unterlage gezeichnet werden. Also hätte ich nur ca. 32% der Abbildung auf der Unterlage vorschau1.
So erhalte ich nun ein vollstädiges Bild in Originalgrösse, dass aber als Auflösung statt 96DPI 300DPI im Bitmapheader stehen hat.
Gebe ich dieses Bild jetzt z.B. an Photoshop weiter und lasse es dort ausdrucken, wird es standardmäßig genau so gross ausgedruckt, wie es erstellt wurde. Also eine mit 300 DPI eingescannte Din A4 - Seite würde bei hoher Qualität auch wieder als Din A4-Seite ausgedruckt werden, und zwar genau!!
Das war der Zweck des ganzen Aufstandes (zu verwirrend?)
Nochmal besten Dank!
Kalle
Dont debug, because there will allways be one more bug | |
Re: Bitmap mit einer bestimmten Auflösung speichern | | | Autor: Manfred X | Datum: 25.10.11 08:01 |
| Einige Anmerkungen dazu:
Wieso speicherst Du das Bild nicht bereits beim Scannen
mit der entsprechenden Auflösung?
Wenn Du diese Code-Variante wählst, verkleinerst Du beim
Neuzeichnen das Bild zugleich - es würde durch die DPI-
Erhöhung sonst vergrößert (Einheit: Pixel), um eine höhere
Info-Menge aufnehmen zu können.
Ich würde im Graphics-Objekt deshalb den Interpolationmode
auf "HighQualityBiCubic" setzen.
Das Speichern einer Bitmap im JPEG-Code führt zum Ersetzen des
Originalbildes durch ein speichersparendes Ersatzbild. Das ist
immer mit einem Verlust an Information verbunden und führt
sehr leicht zu den bekannten JPG-typischen Bildfehlern.
Ich würde deshalb den Qualitäts-Parameter des Net-eigenen
JPEG-Encoders nutzen und den Wert 95 verwenden. (Beispiele
findest Du unter dem Stichwort "EncoderParameters").
MfG
Manfred
Beitrag wurde zuletzt am 25.10.11 um 08:02:22 editiert. | |
Re: Bitmap mit einer bestimmten Auflösung speichern | | | Autor: Kalli | Datum: 25.10.11 12:43 |
| Vielen Dank für Deine Hilfe
Es ist hier alles, wie immer im Leben, viel komplizierter als ich es dargestellt habe. Es geht um komplette Layouts, die aus diversen, in unterschiedlicher Auflösung gescannten oder am PC gezeichneten Grafiken nebst Text und Grafikelementen bestehen. Diese Software habe ich selbst geschrieben, sodass das Dateiformat dieser Layouts auch nur mit besagter Software bearbeitet und gespeichert werden kann. Es kommt hier darauf an, dass alle Elemente, wenn das Layout aus dem Drucker kommt genau die Größe haben sollen, die ihnen bestimmt ist.
Wenn ich das Layout als eine Bitmap gefertigt habe und diese nach der Umstellung von 96 auf 300 DPI auf die Unterlage male, dann würde sie ohne "Verkleinerung" per Interpolation vergrößert werden, also keine Mehrinformation liefern. Durch die Beschränkung auf oben genanntes Rechteck erhalte ich aber genau wieder die Originalgröße. Dadurch, dass aber nun 300 DPI im Bitmapheader steht, wird beim Ausdruck auf Papier das JPG um genau das Maß an die Grafikumgebung des Kunden angepaßt, dass auf dem Papier das Bild in optimaler Qualität in genau der gewünschten Größe gedruckt wird.
Damit nicht alle meine Kunden auf meine Software angewiesen sind, muß ich diese Layoutseiten als komplette Grafiken so an sie weiterreichen können, dass sie diese auch, ohne besondere Einstellungen zu treffen, mit jedem vernünftigen Bildbearbeitungsprogamm in der "richtigen" Größe ausdrucken können (JPG, damits auch per Email geht (natürlich kann ich auch BMP, Tiff, Gif etc. liefern)).
Dont debug, because there will allways be one more bug | |
Re: Bitmap mit einer bestimmten Auflösung speichern | | | Autor: Manfred X | Datum: 25.10.11 13:26 |
| Hallo!
Das hatte ich schon verstanden,
Die Einstellung der Interpolationmode-Eigenschaft dient
dazu, um ein optimales Ergebnis bei der Verkleinerung
des Bildes zu erzielen.
Der Standardwert ist "Bilinear".
Dieser Modus ist NICHT dafür geeignet, ein Bild auf mehr als 50
Prozent seiner ursprünglichen Größe zu verkleinern. (VB-Doku!!)
Using g As Graphics = Graphics.FromImage(vorschau1)
g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic
g.DrawImage(vorschau, 0, 0, vorschau.Width, vorschau.Height)
End Using Der Qualitäts-Parameter ermöglicht die Ermittlung, bis zu
welchem Grad die Bilddatei verkleinert werden kann, ohne dass
es zu störenden Infoverlusten bzw. Bildfehlern kommt.
(Quality-Werte zwischen 60 und 95 ausprobieren).
Dim EncoderParameters As New Drawing.Imaging.EncoderParameters(1)
EncoderParameters.Param(0) = New Drawing.Imaging.EncoderParameter _
(Drawing.Imaging.Encoder.Quality, Quality)
vorschau1.Save(Filename, EncoderInfo("JPEG"), EncoderParameters) Hilfsfunktion:
Private Function EncoderInfo _
(ByVal FormatDescriptor As String) As Drawing.Imaging.ImageCodecInfo
' Formatdescriptoren: BMP JPEG GIF TIFF PNG
Dim i As Integer = 0
Dim encoders() As Drawing.Imaging.ImageCodecInfo = _
Drawing.Imaging.ImageCodecInfo.GetImageEncoders()
FormatDescriptor = Trim(UCase(FormatDescriptor))
While i < encoders.Length
If UCase(encoders(i).FormatDescription) = FormatDescriptor Then
Return encoders(i)
End If
i += 1
End While
Return Nothing
End Function
Beitrag wurde zuletzt am 25.10.11 um 13:39:24 editiert. | |
Re: Bitmap mit einer bestimmten Auflösung speichern | | | Autor: Kalli | Datum: 25.10.11 16:38 |
| Das ist natürlich ein interessanter Aspekt, ich denke jedoch, dass intern ersteinmal der endgültige Zoomfaktor berechnet wird, wobei dann 1 herauskommt. Das Bild "vorschau" also nicht zuerst der veränderten Auflösung entsprechend vergrößert und dann wieder um den gleichen Betrag verkleinert wird, sondern resultierend gar nichts passiert, außer dass im Bitmapheader jetzt 300 DPI für Resolution steht, was ich ja bezwecke.
Ich habe das mit einem farbigen Bild probiert, es treten selbst nach mehreren Aktionen (hier jetzt natürlich verlustfrei als BMP gespeichert) durch die Anpassung keine sichtbaren Verluste auf. Wenn Du es besser weißt, würde mich das sehr interessieren - einfach nur so - in meinem Fall handelt es sich zu 90% sowieso nur um mehr oder weniger Schwarz-weiß-Grafiken was die Farbe angeht, nicht die Farbtiefe, sodaß etwaige Mißhandlungen nicht so auffallen.
Die Tatsache, dass bei einem endgültigen Abspeichern als JPG Verluste auftreten, ist mir klar. Hast Du eine Ahnung, mit welcher Qualität VB NET ein JPG standardmäßig packt, wenn man es nicht explizit über den ImageEncoder bestimmt - allzu schlecht ist die jedenfalls nicht, wenn auch in der JPEGinfo darüber nichts angezeigt wird.
Ich komme erst nacher dazu, Deine interessante Qualitätsbestimmung auszutesten. Also bis denne!
Dont debug, because there will allways be one more bug | |
Re: Bitmap mit einer bestimmten Auflösung speichern | | | Autor: Manfred X | Datum: 25.10.11 18:33 |
| Falls die Bitmap-Dateien eine BitmapinfoHeader-Struktur
hinter der BitmapfileHeader-Struktur enthalten, kannst Du
die Auflösung direkt in die Datei eintragen (Filestream).
Neuzeichnen ist dann überflüssig. Das Bild kann geladen
und direkt als JPEG gespeichert werden.
http://en.wikipedia.org/wiki/BMP_file_format
Die Standard-Qualitätsstufe des JPEG-Decoders liegt
bei einem Wert von ca. 80.
Für SW-Graphiken ist das GIF-Format weit besser geeignet,
weil JPEGs in dem Fall gelegentlich hellgraue Quadrate in
weissen Flächen enthalten bzw. dunkelgraue in schwarzen Flächen.
MfG
Manfred
Beitrag wurde zuletzt am 25.10.11 um 18:54:51 editiert. | |
Re: Bitmap mit einer bestimmten Auflösung speichern | | | Autor: Kalli | Datum: 26.10.11 18:28 |
| Hier nocheinmal der direkte Eintrag der Auflösung in die Bilddatei. Ich schreibe das hier nocheinmal auf, weil mir die Sache doch ein wenig Kopfzebrechen gemacht hat, bis ich mich aus Atari-Tagen daran erinnerte dass bei solchen Sachen manchmal Hi- und Low-Bytes vertauscht sind (ja,ja lacht nur
dim auflösung as Integer = 300
dim pfad as string = "C:\testbild.bmp" 'das ist die Bitmap, die eine neue
' Auflösung bekommen soll
dim fs as new IO.FileStream(pfad,IO.Filemode.Open) 'Bild für Zugriff öffnen
'Nun kommt ein Trick, der leider nötig ist - Low- und Highbytes vertauschen
dim b() As Byte = BitConverter.GetBytes(CInt(auflösung/0.0254)) 'die Auflösung
' wird in Pixel pro Meter verlangt
'Jetzt alle vier Bytes in der richtigen Reihenfolge an die richtige Stelle in
' den Bitmapinfoheader schreiben
fs.Seek (38,0) 'Hier im Header steht die Horizontale Auflösung und vier Bytes
' weiter die Vertikale (s.Link oben von Manfred X auf Wikipedia)
dim bw As New IO.BinaryWriter(fs)
bw.Write(b,0,4) 'X-Auflösung
bw.Write(b,0,4) 'Y-Auflösung
bw.Close()
fs.Close()
fs.Dispose Dont debug, because there will allways be one more bug | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
sevZIP40 Pro DLL
Zippen und Unzippen wie die Profis!
Mit nur wenigen Zeilen Code statten Sie Ihre Anwendungen ab sofort mit schnellen Zip- und Unzip-Funktionen aus. Hierbei lassen sich entweder einzelnen Dateien oder auch gesamte Ordner zippen bzw. entpacken. Weitere InfosTipp des Monats TOP Entwickler-Paket
TOP-Preis!!
Mit der Developer CD erhalten Sie insgesamt 24 Entwickler- komponenten und Windows-DLLs. Die Einzelkomponenten haben einen Gesamtwert von 1605.50 EUR...
Jetzt nur 599,00 EURWeitere Infos
|