Manchmal muss ich mehr Dokumentation schreiben als nur Kommentare im Code. Und manchmal benötigen diese Erklärungen Screenshots. Manchmal sind die Bedingungen für einen solchen Screenshot so seltsam, dass ich einen Entwickler auffordere, einen Screenshot für mich zu machen. Manchmal entspricht der Screenshot nicht meinen Spezifikationen und ich muss seine Größe ändern, damit er gut aussieht.
Wie Sie sehen, ist es sehr unwahrscheinlich, dass der magische "Lossless Screenshot Resizer" benötigt wird. Wie auch immer, für mich scheint es, dass ich es jeden Tag brauche. Aber es existiert noch nicht.
Ich habe dich hier auf PCG schon einmal beim Lösen großartiger Grafik-Rätsel gesehen , also denke ich, dass dieses für dich ziemlich langweilig ist ...
Spezifikation
- Das Programm erstellt einen Screenshot eines einzelnen Fensters als Eingabe
- Der Screenshot verwendet keine Glaseffekte oder ähnliches (Sie müssen sich also nicht mit Hintergrundmaterial befassen, das durchscheint).
- Das Eingabedateiformat ist PNG (oder ein anderes verlustfreies Format, damit Sie keine Komprimierungsartefakte verarbeiten müssen).
- Das Ausgabedateiformat ist dasselbe wie das Eingabedateiformat
- Das Programm erstellt als Ausgabe einen Screenshot unterschiedlicher Größe. Die Mindestanforderung ist eine Größenverringerung.
- Der Benutzer muss die erwartete Ausgabegröße angeben. Wenn Sie Hinweise zur Mindestgröße geben können, die Ihr Programm anhand der angegebenen Eingabe erzeugen kann, ist dies hilfreich.
- Der Ausgabe-Screenshot darf nicht weniger Informationen enthalten, wenn er von einem Menschen interpretiert wird. Sie dürfen keine Text- oder Bildinhalte entfernen, sondern nur Bereiche mit Hintergrund. Siehe Beispiele unten.
- Wenn es nicht möglich ist, die erwartete Größe zu erhalten, sollte das Programm dies anzeigen und nicht einfach abstürzen oder Informationen ohne weitere Ankündigung entfernen.
- Wenn das Programm die Bereiche angibt, die aus Überprüfungsgründen entfernt werden, sollte dies seine Popularität erhöhen.
- Das Programm benötigt möglicherweise eine andere Benutzereingabe, z. B. um den Startpunkt für die Optimierung zu ermitteln.
Regeln
Dies ist ein Beliebtheitswettbewerb. Die Antwort mit den meisten Stimmen am 08.03.2015 wird angenommen.
Beispiele
Windows XP-Screenshot. Originalgröße: 1003 x 685 Pixel.
Beispielbereiche (rot: vertikal, gelb: horizontal), die entfernt werden können, ohne dass Informationen (Text oder Bilder) verloren gehen. Beachten Sie, dass der rote Balken nicht zusammenhängend ist. Dieses Beispiel zeigt nicht alle möglichen Pixel an, die möglicherweise entfernt werden könnten.
Verlustfrei verkleinert: 783x424 Pixel.
Windows 10-Screenshot. Originalgröße: 999 x 593 Pixel.
Beispielbereiche, die entfernt werden können.
Verlustfrei verkleinerter Screenshot: 689x320 Pixel.
Beachten Sie, dass der Titeltext ("Downloads") und "Dieser Ordner ist leer" nicht mehr zentriert sind. Natürlich wäre es schöner, wenn es zentriert wäre, und wenn Ihre Lösung dies vorsieht, sollte es populärer werden.
quelle
Antworten:
Python
Die Funktion
delrows
löscht alle bis auf eine doppelte Zeile und gibt das transponierte Bild zurück. Durch zweimaliges Anwenden werden auch die Spalten gelöscht und wieder transponiert. Steuert zusätzlichthreshold
, wie viele Pixel sich unterscheiden können, damit zwei Zeilen immer noch als gleich geltenWenn Sie den Komparator
mask
von>
bis einklappen ,<=
werden stattdessen die entfernten Bereiche ausgegeben, bei denen es sich hauptsächlich um leere Bereiche handelt.golfed (weil warum nicht)
Anstatt jedes Pixel zu vergleichen, wird nur die Summe betrachtet. Als Nebeneffekt wird dadurch auch der Screenshot in Graustufen umgewandelt, und es treten Probleme mit summenerhaltenden Permutationen auf, z. B. mit dem Abwärtspfeil in der Adressleiste von Win8 Bildschirmfoto
quelle
Java: Versuchen Sie es verlustfrei und greifen Sie auf inhaltsbewusste Funktionen zurück
(Bisher bestes verlustfreies Ergebnis!)
Als ich diese Frage zum ersten Mal betrachtete, dachte ich, dies sei kein Rätsel oder eine Herausforderung, nur jemand, der dringend ein Programm und Code benötigt !
Ich habe mir den folgenden Ansatz und die Kombination von Algorithmen ausgedacht.
Im Pseudocode sieht es so aus:
Verwendete Techniken:
Das Programm
Das Programm kann Screenshots verlustfrei zuschneiden, kann jedoch auf inhaltsbewusstes Zuschneiden zurückgreifen, das nicht zu 100% verlustfrei ist. Die Argumente des Programms können optimiert werden, um bessere Ergebnisse zu erzielen.
Hinweis: Das Programm kann auf viele Arten verbessert werden (ich habe nicht so viel Freizeit!)
Argumente
Code
Ergebnisse
XP Screenshot verlustfrei ohne gewünschte Größe (Max verlustfreie Komprimierung)
Argumente: "image.png" 1 1 5 10 false 0
Ergebnis: 836 x 323
XP Screenshot auf 800x600
Argumente: "image.png" 800 600 6 10 true 60
Ergebnis: 800 x 600
Der verlustfreie Algorithmus entfernt ungefähr 155 horizontale Linien, als der Algorithmus auf inhaltsbewusstes Entfernen zurückgreift, wodurch einige Artefakte sichtbar werden.
Windows 10 Screenshot auf 700x300
Argumente: "image.png" 700 300 6 10 true 60
Ergebnis: 700 x 300
Der verlustfreie Algorithmus entfernt 270 horizontale Linien, als der Algorithmus auf inhaltsbewusstes Entfernen zurückgreift, wodurch weitere 29 entfernt werden. Vertikal wird nur der verlustfreie Algorithmus verwendet.
Windows 10 Screenshot inhaltsbewusst bis 400x200 (Test)
Argumente: "image.png" 400 200 5 10 true 600
Ergebnis: 400 x 200
Dies war ein Test, um zu sehen, wie das resultierende Bild nach strenger Verwendung der inhaltsbewussten Funktion aussehen würde. Das Ergebnis ist stark beschädigt, aber nicht unkenntlich.
quelle
C #, Algorithmus wie ich es manuell machen würde
Dies ist mein erstes Bildbearbeitungsprogramm und es hat eine Weile gedauert, bis es mit all dem
LockBits
Zeug usw. implementiert wurde . Aber ich wollte, dass es schnell (mitParallel.For
) ist, um ein fast sofortiges Feedback zu erhalten.Grundsätzlich basiert mein Algorithmus auf Beobachtungen, wie ich Pixel manuell aus einem Screenshot entferne:
Im Moment mache ich es nur horizontal. Das vertikale Ergebnis kann denselben Algorithmus verwenden und mit einem um 90 ° gedrehten Bild arbeiten. Theoretisch ist dies also möglich.
Ergebnisse
Dies ist ein Screenshot meiner Anwendung mit erkannten Regionen:
Und dies ist das Ergebnis für den Windows 10-Screenshot und die 48-Pixel-Schwelle. Die Ausgabe ist 681 Pixel breit. Leider ist es nicht perfekt (siehe "Downloads durchsuchen" und einige der vertikalen Spaltenbalken).
Und noch eine mit 64 Pixel Schwelle (567 Pixel breit). Das sieht noch besser aus.
Gesamtergebnis beim Drehen des Zuschnitts auch von unten (567 x 304 Pixel).
Unter Windows XP musste ich den Code etwas ändern, da die Pixel nicht genau gleich sind. Ich wende eine Ähnlichkeitsschwelle von 8 (Unterschied im RGB-Wert) an. Beachten Sie einige Artefakte in den Spalten.
Code
Naja, mein erster Versuch zur Bildbearbeitung. Sieht nicht besonders gut aus, oder? Hier wird nur der Kernalgorithmus aufgeführt, nicht die Benutzeroberfläche und nicht die 90 ° -Drehung.
quelle
Haskell, mit naiver Entfernung von doppelten sequentiellen Linien
Leider bietet dieses Modul nur eine Funktion mit der sehr allgemeinen Art
Eq a => [[a]] -> [[a]]
, da ich keine Ahnung, wie zu bearbeiten Bilddateien in Haskell, aber ich bin sicher , es ist möglich , ein PNG - Bild zu einem tranform[[Color]]
Wert und ich kann mich vorstellen ,instance Eq Color
zu sein leicht definierbar.Die fragliche Funktion ist
resizeL
.Code:
Erläuterung:
Hinweis:
a : b
bedeutet , dass der Liste des Typs des Elements eina
Präfix vorangestellt wird , was zu einer Liste führt. Dies ist die grundlegende Konstruktion von Listen. bezeichnet die leere Liste.a
[]
Hinweis:
a :: b
bedeuteta
ist vom Typb
. Zum Beispiel, wenna :: k
, dann(a : []) :: [k]
, wo[x]
bezeichnet eine Liste, die Dinge vom Typ enthältx
.Dies bedeutet, dass
(:)
sich ohne Argumente:: a -> [a] -> [a]
. Das->
bezeichnet eine Funktion von etwas zu etwas.Das
import Data.List
bringt einfach etwas Arbeit, die andere für uns getan haben, und lässt uns ihre Funktionen nutzen, ohne sie neu zu schreiben.Definieren Sie zunächst eine Funktion
nubSequential :: Eq a => [a] -> [a]
.Diese Funktion entfernt nachfolgende Elemente einer Liste, die identisch sind.
Also
nubSequential [1, 2, 2, 3] === [1, 2, 3]
. Wir werden diese Funktion nun abkürzen alsnS
.Wenn
nS
auf eine leere Liste angewendet wird, kann nichts getan werden, und wir geben einfach eine leere Liste zurück.Wenn
nS
auf eine Liste mit Inhalten angewendet wird, kann die eigentliche Verarbeitung erfolgen. Dazu benötigen wir eine zweite Funktion, hier in einerwhere
-Klausel, um die Rekursion zu verwenden, da wirnS
kein Element verfolgen , mit dem wir vergleichen können.Wir nennen diese Funktion
g
. Es vergleicht sein erstes Argument mit dem Kopf der Liste, die ihm gegeben wurde, und verwirft den Kopf, wenn er übereinstimmt, und ruft sich selbst mit dem alten ersten Argument auf. Wenn dies nicht der Fall ist, wird der Kopf an den Schwanz angehängt und der Kopf als neues erstes Argument durch ihn hindurchgeführt.Um es zu benutzen
g
, geben wir den Kopf des Arguments vonnS
und den Schwanz als seine zwei Argumente an.nS
ist jetzt vom TypEq a => [a] -> [a]
, nimmt eine Liste und gibt eine Liste zurück. Es erfordert, dass wir die Gleichheit zwischen den Elementen überprüfen können, wie dies in der Funktionsdefinition geschieht.Dann wir komponieren die Funktionen
nS
undtranspose
mit dem(.)
Betreiber.Composing Funktionen bedeutet folgendes:
(f . g) x = f (g (x))
.In unserem Beispiel wird
transpose
eine Tabelle um 90 ° gedreht,nS
alle sequentiell gleichen Elemente aus der Liste entfernt, in diesem Fall andere Listen (das ist eine Tabelle),transpose
zurückgedreht undnS
erneut sequentiell gleiche Elemente entfernt. Dies bedeutet im Wesentlichen, nachfolgende doppelte Zeilen und Spalten zu entfernen.Dies ist möglich, weil, wenn
a
es auf equality (instance Eq a
) überprüfbar[a]
ist, dies auch ist.Zusamenfassend:
instance Eq a => Eq [a]
quelle