A mano
Se la memoria non è una risorsa molto scarsa, penso di lavorare in blocchi più grandi.
Ecco alcuni pseudo-codici.
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;
}
}
Questa implementazione è abbastanza ingenua.
Per uno, crea blocchi in getPixel (in pratica sarebbe bene restituire semplicemente 0 o giù di lì, se non fosse stato definito alcun blocco per quella posizione). In secondo luogo, si basa sul presupposto che si disponga di un'implementazione sufficientemente rapida e scalabile di Map. Per quanto ne sappia, ogni lingua decente ne ha una.
Inoltre dovrai giocare con le dimensioni del pezzo. Per bitmap dense, una buona dimensione del pezzo è buona, per bitmap sparse una dimensione del pezzo più piccola è migliore. In effetti per quelli molto sparsi, una "dimensione del blocco" di 1 è la migliore, rendendo obsoleti i "blocchi" e riducendo la struttura dei dati in una mappa int di una mappa int di pixel.
Prêt-à-porter
Un'altra soluzione potrebbe essere quella di esaminare alcune librerie grafiche. Sono in realtà abbastanza bravi a disegnare un buffer 2D in un altro. Ciò significherebbe che dovresti semplicemente allocare un buffer più grande e farti disegnare l'originale nelle coordinate corrispondenti.
Come strategia generale: quando si dispone di un "blocco di memoria a crescita dinamica", è consigliabile allocare un multiplo di esso, una volta esaurito. Questo è piuttosto intenso di memoria, ma riduce significativamente i costi di allocazione e copia . La maggior parte delle implementazioni vettoriali allocano il doppio della loro dimensione, quando viene superata. Quindi, specialmente se si utilizza la soluzione standard, non estendere il buffer solo di 1 pixel, poiché è stato richiesto solo un pixel. La memoria allocata è economica. La riallocazione, la copia e il rilascio sono costosi.