Laden...

(Datei-)Größe einer Bitmap verkleinern

Erstellt von Mentor49 vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.741 Views
M
Mentor49 Themenstarter:in
35 Beiträge seit 2009
vor 15 Jahren
(Datei-)Größe einer Bitmap verkleinern

Hey.
Ich programmiere z.Z. ein "Remote Screen" - Tool.
(Heißt: Server wartet auf Client, Client verbindet sich, Server schickt in regelmäßigen Abständen den aktuellen Screen an den Client, sodass dieser sehen kann, was auf dem Server-Computer grade passiert)

Da mein Versuch, nur jede Veränderung die auf dem aktuellen zum vorherigem Screen zu sehen ist, zum Client zu senden, kräftig in die Hose gegangen ist, hab ich mich halt jetzt entscheiden, tatsächlich immer den kompletten Screen rüber zu schicken.
Würde ich allerdings immer das komplette Bitmap verschicken, wären das jedesmal 1440000 Bytes (1,44MB).
Zusammensetzung: 6008003 (600 = Höhe, 800 = Breite, 3 = R, G und B)
Und wenn ich dann 10 Frames pro Sekunde verschicken will..wären das 14,4MB/s...und das macht meine Leitung leider nicht mit 😄
Desshalb müsste ich das Bitmap irgendwie verkleinern.
Damit meine ich jetzt nicht die Auflösung, die sollte schon bei 800*600 bleiben...
Aber es gibt ja noch andere Formate, wie JFIF (JPEG), PNG usw.
Nur wie funktioniert die Umwandlung?
Ich könnte das Bitmap als JPEG abspeichern und dann wieder laden, allerdings würde mir das zu lange dauern, und iwie finde ich das eine unsaubere Lösung.
Hat jemand Ideen/Anregungen/Tipps für mich?
Wäre super (:

S
506 Beiträge seit 2006
vor 15 Jahren

MemoryStream....

Du speicherst dein BMP als PNG in einen Memory stream....

5.658 Beiträge seit 2006
vor 15 Jahren

Hi Mentor49,

du könntest das Bitmap im JPG-Format in einem Stream speichern, dafür gibt es eine Save-Methode. Dadurch würdest du dir das Speichern und Laden der Datei sparen.

Evtl. wäre für diesen Zweck auch eine Art Videostreaming geeignet...?

Christian

Weeks of programming can save you hours of planning

C
114 Beiträge seit 2008
vor 15 Jahren

Abgesehn davon, kannst du auch deine Idee verwirklichen, dass du nur Änderungen rüberschickst. Das wäre ein ähnliches Prinzip, wie bei Videos mit den Keyframes. Um da nicht zu Komplex zu werden: Vergleiche Original und neuen Frame. Wenn sich der Pixel geändert hat, setze die neuen Werte ganz normal. Wenn sich der Pixel nicht geändert hat, setze den Pixel auf 0 0 0 0. Hier nehm ich also im Normalfall 32bpp ARGB. Diese musst du dann, wie vorher schon besagt als JPEG oder (besser) PNG in nem MemoryStream speichern und den Schickst du rüber.

„Heute back ich, morgen brau ich,
übermorgen cast ich die Königin nach int;
ach, wie gut dass niemand weiß,
dass ich Rumpelstilzchen heiß!“

"Bei Stylefragen sollteste nen Mac-User oder ne Frau fragen."

M
Mentor49 Themenstarter:in
35 Beiträge seit 2009
vor 15 Jahren

Hey, danke erstmal für die Antworten.
Also z.Z. löse ich das ganze noch so:

        public byte[] GetScreen()
        {
            Bitmap screen = new Bitmap(SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height);
            Graphics gr = Graphics.FromImage(screen);
            gr.CopyFromScreen(0, 0, 0, 0, screen.Size);
            gr.Dispose();
            double sizeFactor = 600.0 / screen.Width;
            double newHeigth = sizeFactor * screen.Height;
            Bitmap newImage = new Bitmap(600, (int)newHeigth);
            using (Graphics g = Graphics.FromImage(newImage))
            {
                g.InterpolationMode = InterpolationMode.HighQualityBilinear;
                g.DrawImage(screen, new Rectangle(0, 0, 600, (int)newHeigth));
            }
            MemoryStream IS = new MemoryStream();
            newImage.Save(IS, System.Drawing.Imaging.ImageFormat.Jpeg);
            IS.Flush();
            return IS.ToArray();
        }

Die Idee von Chicklord, nur Änderungen im Bild rüberzusenden, finde ich sehr gut.
Hab da auch schonmal was probiert, aber das ist wie gesagt kräftig in die Hose gegangen ist.
Allerdings verstehe ich nicht ganz, wie du das meinst.
Also ich habe meinen Screen als Bitmap.
Diesen Screen vergleiche ich (außer beim ersten Durchlauf) mit dem vorherigem Screen. Jeder Pixel der anders ist bleibt, jeder der gleich geblieben ist, wird dann zu 0 0 0 (Ich verwende meistens 24Bpp). Das Bitmap wandele ich dann wie bisher in JPEG um, und schicke das Jpeg-Bild dann zum Client.
Nur würde das JPEG Bild doch dann beim Client verdammt merkwürdig aussehen?!
Überall würden durch die (0 0 0) schwarze Punkte/Fläöchen sein.
Oder wie meintest du das?

Um da nicht zu Komplex zu werden:

Ich bitte dich darum, komplex zu werden 😉
Ruhig schön ausführlich, wenns dir nichts ausmacht (:

Evtl. wäre für diesen Zweck auch eine Art Videostreaming geeignet...

Hört sich ebenfalls gut an, allerdings weiß ich nicht genau wie Video-Stream funktionieren, aber ich denke mal, nicht sehr anders als was Chickenlord da beschreibt, oder?

Danke nochmal für eure Hilfe 😉
Lg

C
114 Beiträge seit 2008
vor 15 Jahren

Du kannst das an dieser Stelle nicht mit 24 BPP machen. Warum siehst du gleich.
Also erstmal schickt man mindestens am Anfang, besser in einem bestimmten Abstand, immer ein Bild rüber an dem nichts geändert wurde. Die darauf folgenden Frames vergleichst du, wie ich das vorher schon gesagt habe. Und jetzt warum du keine 24bpp haben kannst: Du musst irgendwie kennzeichnen, dass es sich um einen Pixel handelt, der nicht verändert wurde. Dafür nimmst du ein viertes Byte hinzu, dass du auf 0 setzt, falls der Pixel nicht verändert wurde im Vergleich zum Vorgänger, sonst auf einen beliebigen anderen Wert. (Ich nehm meistens 255.) Weil du dann aber auch die RGB Farbinformationen nicht mehr brauchst, setzt du auch die auf 0. Der Grund dafür ist, dass so die Kompressionsrate erhöht wird. Wenn du diesen veränderten Frame an den Client schickst, dann tust du damit folgendes: Der Client nimmt sich das originale, unbearbeitete Bild und ersetzt hier alle Pixel, bei denen keine 0 als 4tes Byte steht (die also verändert wurden), durch die aus dem neuen Frame. Somit hast du den neuen Frame dargestellt und dabei aber deutlich weniger Daten verschickt, als wenn du das Bild einfach so rübergeworfen hättest.
Der Grund, warum du in einem Festgelegten Abstand immer wieder ein neues "Original" rüberschicken solltest, liegt darin, dass auf dauer die Menge der unveränderten Pixel gegen 0 geht und somit auch deine Ersparnis, bei der Größe.

So, ich hoffe, jetzt Kommt es deutlicher rüber. Die "Originale" heißen im Video-Bereich übrigens Keyframe und das Grundprinzip nach dem da gearbeitet wird ist nahezu das gleiche.

„Heute back ich, morgen brau ich,
übermorgen cast ich die Königin nach int;
ach, wie gut dass niemand weiß,
dass ich Rumpelstilzchen heiß!“

"Bei Stylefragen sollteste nen Mac-User oder ne Frau fragen."