Die Steinchen, aus denen jedes Mosaik besteht

Saturday, 15. April, 2006

Dieser Artikel zeigt, wie die Steinchen auf BunteSuppe eigentlich gemacht sind.

Technisch gesehen ist jedes Steinchen ein “div”, also ein Standard HTML Blockelement. Indem wir CSS verwenden, definieren wir die Width und Height, die Background Color und den Border.

Der Border wird so verwendet, dass sich ein subtiler 3D Bevel Effekt ergibt, der die viereckigen Steinchen ein bisschen wie kleine Fliesen ausschauen läßt.

Animation der Steinchen

Die x/y Positionen der Steinchen werden mit Hilfe von JavaScript manipuliert. Lese hier mehr darüber wie die Steinchen animiert werden.

Welche Farben sollten die Steinchen haben?

Raum Inhaber, die sich für ein eigenes, Room-spezifisches Mosaik entscheiden, haben die Möglichkeit die Farben der Steinchen zu bestimmen.

mona lisa

Wir verwenden Bilder, um die Farben der Steinchen zu bestimmmen. Mit anderen Worten, ein Quellbild wird auf seine RGB Farben analysiert, Pixel für Pixel, und jede RGB Farbe wird dann einem Steinchen zugeteilt. Das bedeutet, dass ein Room Inhaber ein Bild uploaden kann (von seiner Account/Room Seite) und voila, alle Steinchen ändern dementsprechend ihre Farbe.

Es macht echt Spaß, ein JPEG von der Mona Lisa hoch zu laden und dann zu versuchen, sie wieder zusammenzusetzen, obgleich die Farbpalette ein bisschen mühsam sein kann mit den vielen Brauns und Grüns!

Wir haben ein paar sehr interessante psychologische Effekt bemerkt, die auf der Farbwahl beruhen. Lese mehr über die Wahl der Steinchenfarben.

Um sicherzustellen, dass wir alle Farben bekommen, müssen wir erst einmal die Größe des Quellbilds anpassen, so dass es aus genau (oder fast genau) so vielen Pixel besteht, wie wir Steinchen haben. Der Größenanpassungs-Algorithmus (siehe Teile der GD Library für PHP) verwendet eine kubische Interpolation, so dass wir eine gute Annäherung an alle Farben des Quellbilds erreichen.

Berechnung der Border Farben

tiles

Um einen 3D Bevel Effekt zu erreichen, machen wir den Top-Border und den Left-Border ein bisschen heller und den Right-Border und den Bottom-Border ein bisschen dünkler als die Steinchenfarbe.

Dafür verwenden wir einen simplen, aber effektiven Algorithmus, indem wir einen helleren und einen dünkleren Faktor einer jeden Komponente des RGB Farbenwerts benutzen. Zum Beispiel: Um eine Farbe zu berechnen, die ein bisschen dünkler ist, können wir 90% des RGB Werts verwenden. Das wäre also: R x 0.9, G x 0.9, B x 0.9. Gleichermaßen würden wir für eine hellere Farbe 110% verwenden, das wäre dann: R x 1.1, G x 1.1, B x 1.1.

RGB Bearbeitung in JavaScript

Hier ist der JavaScript Code, den wir schließlich in der Endversion von BunteSuppe verwenden. Beachte, dass wir einen Array mit drei Elementen als Datentyp für jeden RGB Wert benutzen.

function makeLighter(rgb) {
  var r=Math.min(Math.round(rgb[0]*1.07),255);
  var g=Math.min(Math.round(rgb[1]*1.07),255);
  var b=Math.min(Math.round(rgb[2]*1.07),255);
  return 'rgb('+r+','+g+','+b+') ';
}

function makeDarker(rgb) {
  var r=Math.round(rgb[0]*0.913);
  var g=Math.round(rgb[1]*0.913);
  var b=Math.round(rgb[2]*0.913);
  return 'rgb('+r+','+g+','+b+') ';
}

RGB Bearbeitung in PHP

Manchmal müssen wir diese Border-Colors (die helleren und dünkleren Farben) auch mittels PHP berechnen, beispielsweise für die Snapshot Funktion, die tatsächliche Bilder aus den Mosaiks macht.

Hier ist der entsprechende PHP Code. Beachte, dass die Datenstrukturen assoziative Arrays sind, wie sie auch von der GD Library verwendet werden. LIGHTEN_FACTOR und DARKEN_FACTOR sind Konstanten, die global überall auf BunteSuppe.de benutzt werden. Diese Konstanten werden ebenfalls benutzt, wenn der JavaScript Code (wie oben gezeigt) via PHP erzeugt wird.

function col_lighten($rgb) {
  $rgb['red']=(int)min($rgb['red']*LIGHTEN_FACTOR,255);
  $rgb['green']=(int)min($rgb['green']*LIGHTEN_FACTOR,255);
  $rgb['blue']=(int)min($rgb['blue']*LIGHTEN_FACTOR,255);
  return $rgb;
} 

function col_darken($rgb) {
  $rgb['red']=(int)($rgb['red']*DARKEN_FACTOR);
  $rgb['green']=(int)($rgb['green']*DARKEN_FACTOR);
  $rgb['blue']=(int)($rgb['blue']*DARKEN_FACTOR);
  return $rgb;
}

Warum arbeiten wir nicht mit dem HSL Farbraum?

Wir haben anfangs mit komplizierteren Border-Color-Algorithmen experimentiert, die die Saturation (Farbsättigung) und Lightness (Helligkeit) unabhängig bearbeiteten. Der Algorithmus konvertierte den RGB Wert in den HSL oder HSB Farbraum, aber das Ganze hat mehr produziert als das es gut war. Und war außerdem viel langsamer in der Ausführung.

Der Effekt unseres kleinen Direkt-in-RGB Algorithmus ist angenehmer für’s Auge, läuft schneller und der Effekt ist sehr viel einfacher zu steuern.

Warum verwenden wir nicht den border-style in CSS?

Ja, wir hätten auch border-style:outset; verwenden können, anstatt unsere eigenen Border Colors zu berechnen:

I’m ugly!

Also warum haben nicht border-style verwendet? Ganz einfach – der Effekt ist ein bisschen unvorhersehbar und typischerweise zu stark. Unsere eigene Funktion kreiert einen viel subtileren Effekt:

I’m beautiful!