Par la main
Si la mémoire n'est pas une ressource très rare, j'envisage de travailler en plus gros morceaux.
Voici un pseudo-code.
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;
}
}
Cette implémentation est assez naïve.
D'une part, il crée des morceaux dans getPixel (fondamentalement, il serait bien de simplement retourner 0 ou plus, si aucun morceau n'a été défini pour cette position). Deuxièmement, il est basé sur l'hypothèse que vous disposez d'une implémentation suffisamment rapide et évolutive de Map. À ma connaissance, chaque langue décente en a une.
Vous devrez également jouer avec la taille du morceau. Pour les bitmaps denses, une grande taille de bloc est bonne, pour les bitmaps clairsemés, une taille de bloc plus petite est meilleure. En fait, pour les plus rares, une "taille de bloc" de 1 est la meilleure, rendant les "morceaux" eux-mêmes obsolètes et réduisant la structure des données en une carte int d'une carte int de pixels.
Sur l'étagère
Une autre solution pourrait être de regarder certaines bibliothèques graphiques. Ils sont en fait assez bons pour dessiner un tampon 2D dans un autre. Cela signifierait que vous alloueriez simplement un tampon plus grand et que l'original serait dessiné dedans aux coordonnées correspondantes.
En tant que stratégie générale: lorsque vous avez un "bloc de mémoire à croissance dynamique", il est judicieux d'en allouer un multiple, une fois qu'il est épuisé. Ceci est plutôt intense en mémoire, mais réduit considérablement les coûts d' allocation et de copie . La plupart des implémentations vectorielles allouent deux fois leur taille, lorsqu'elle est dépassée. Donc, surtout si vous optez pour la solution standard, ne prolongez pas la mémoire tampon d'un pixel uniquement, car un seul pixel a été demandé. La mémoire allouée est bon marché. Réaffecter, copier et publier coûte cher.