ja, spiegeln gehört wirklich zu den allereinfachsten aufgaben in der digitalen bildverarbeitung. man könnte es gerade zu als bilderbuchbeispiel heranziehen, um zu illustrieren, wie derartiges heute in unseren videobearbeitungsprogrammen umgesetzt wird.
hier also noch eine weitere lösung des problems, die sich sgn. shader bedient -- es also auch erlaubt, dass die abarbeitung direkt auf der grafikkarte in äußerst effizienter weise abgewickekt wird.
man nehme dazu
ShaderToy, mit man einfache fragment shader direkt im webrowser ausprobieren kann, oder aber das ShaderToy werkzeug im Natron, um die entsprechenden verarbeitungsanweisungen direkt aus dem videobearbeitungsprogram heraus auszuführen.
schritt 1:
um im ShaderToy dialekt ein bild bzw. eine textur einfach nur unverändert auszugeben, ist in etwa folgendes grungerüst nötig:
Code: Alles auswählen
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
fragColor = texture2D(iChannel0, uv);
}
wobei natürlich die textur selbst -- also 'iChannel0' -- im natron mit der entsprechenden bild- bzw. videoquelle verbunden sein muss und im ShaderToy webinterface über die buttons rechts unten ausgewählt wird.
der unterschied zu trationellener bildverarbeitungszugängen zeigt sich darin, dass hier nicht in ein-zwei verschachtelten schleifen alle pixel durchlaufen und gemäß den formulierten angaben abgearbeitet werden, sondern die anweisungen sich nur auf letzteres selbst beziehe, es wird von diesem code also jeweils nur einen bildpunkt, völlig unabhängig vom restlichen bild, berechnet. so kann das ganze auf der grafikkarte in meheren hundert instanzen parallel ausgeführt werden.
schritt 2:
um nun horizontale spiegelung des bilds zu errechen, ist nur eine sehr einfache zusätzliche anweisung nötig:
Code: Alles auswählen
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
uv.x = - uv.x;
fragColor = texture2D(iChannel0, uv);
}
die koodinaten angabe wird hier also mit einem unären vorzeichenoperator einfach negiert. selbstverständlich könnte man dazu auch den wert der x-komponente mit -1.0 multplizieren oder matrixoperationen bemühen.
schritt 3:
um das ganze nun, wie in der ursprünglichen anfrage gewünscht, nur auf die hälfte des bildes anzuwenden, und den rest unverändert zu übernehmen, klammert man den beschriebenen eingriff in eine bedingung ein:
Code: Alles auswählen
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
if (uv.x < 0.5) {
uv.x = - uv.x;
}
fragColor = texture2D(iChannel0, uv);
}
das ganze schaut dann im Natron ungefähr folgendermaßen aus:
man drückt dann nur mehr den "compile" butten, um den code in ausführbare form zu übersetzten, und schon läuft's!
das ist zwar sicher keine wirklich 'einfachere' lösung, aber vielleicht doch ganz interessant, weil es zumindest aufzeigt, wie effektiv und einfach, im technischen sinne, solche dinge hinter den kulissen oft gestaltet sein können, aber auch, wie sehr sich derartige prozesse von dem unterscheiden, wie wir die dinge handhaben, wenn wir nur mit verhältnismäßig oberflächlichen mitteln gleichartiges umzusetzen bzw. nachzumachen versuchen.
in der hinsichts machts's denn wieder spaß, mit derartigen dingen zu spielen und sich ein wenig um entsprechendes verständnis zu bemühen, auch wenn bei den meisten shadertoy oder gmic anwendungen leider dann letztlich ohnehin wieder nur kitsch herauskommt. ;)