Von Hand
Wenn Speicher keine sehr spärliche Ressource ist, denke ich darüber nach, in größeren Blöcken zu arbeiten.
Hier ist ein Pseudocode.
class Chunk {
Chunk new(int size) {...}
void setPixel(int x, int y, int value) {...}
int getPixel(int x, int y) {...}
}
class Grid {
Map<int, Map<Chunk>> chunks;
Grid new(int chunkSize) {...}
void setPixel(int x, int y, int value) {
getChunk(x,y).setPixel(x % chunkSize, y % chunkSize, value);//actually the modulo could be right in Chunk::setPixel and getPixel for more safety
}
int getPixel(int x, int y) { /*along the lines of setPixel*/ }
private Chunk getChunk(int x, int y) {
x /= chunkSize;
y /= chunkSize;
Map<Chunk> row = chunks.get(y);
if (row == null) chunks.set(y, row = new Map<Chunk>());
Chunk ret = row.get(x);
if (ret == null) row.set(x, ret = new Chunk(chunkSize));
return ret;
}
}
Diese Implementierung ist ziemlich naiv.
Zum einen werden Chunks in getPixel erstellt (im Grunde wäre es in Ordnung, einfach 0 oder so zurückzugeben, wenn für diese Position keine Chunks definiert wurden). Zweitens wird davon ausgegangen, dass Sie eine ausreichend schnelle und skalierbare Implementierung von Map haben. Meines Wissens hat jede anständige Sprache eine.
Außerdem müssen Sie mit der Blockgröße spielen. Für dichte Bitmaps ist eine große Blockgröße gut, für spärliche Bitmaps ist eine kleinere Blockgröße besser. Tatsächlich ist für sehr spärliche eine "Blockgröße" von 1 die beste, wodurch die "Blockblöcke" selbst veraltet werden und die Datenstruktur auf eine int-Karte einer int-Karte von Pixeln reduziert wird.
Ab Lager
Eine andere Lösung könnte darin bestehen, sich einige Grafikbibliotheken anzusehen. Sie sind eigentlich ziemlich gut darin, einen 2D-Puffer in einen anderen zu zeichnen. Das würde bedeuten, dass Sie einfach einen größeren Puffer zuweisen und das Original an den entsprechenden Koordinaten darin zeichnen würden.
Als allgemeine Strategie: Wenn Sie einen "dynamisch wachsenden Speicherblock" haben, ist es eine gute Idee, ein Vielfaches davon zuzuweisen, sobald er aufgebraucht ist. Dies ist ziemlich speicherintensiv, senkt jedoch die Zuordnungs- und Kopierkosten erheblich . Die meisten Vektorimplementierungen weisen die doppelte Größe zu, wenn sie überschritten werden. Wenn Sie sich also für die Standardlösung entscheiden, sollten Sie Ihren Puffer nicht nur um 1 Pixel erweitern, da nur ein Pixel angefordert wurde. Der zugewiesene Speicher ist billig. Das Neuzuweisen, Kopieren und Freigeben ist teuer.