Qual è l'algoritmo per copiare una regione di una bitmap, in una regione in un'altra?

4

Nel mio progetto (e sono sicuro che molti altri), ho bisogno di copiare un sottoinsieme (R2) di un'immagine bitmap (R1), in una regione (R3) in un altro, dove la regione di destinazione può essere di qualsiasi dimensione ( allungamento e ridimensionamento laddove necessario).

Sono sicuro che questo è un problema risolto ma non riesco a trovare alcun esempio; qual è l'algoritmo più semplice per eseguire questa operazione? (L'interpolazione lineare sarebbe sufficiente per riempire i pixel quando la sorgente è ridimensionata verso l'alto, se questo è il metodo più rapido (dal punto di vista computazionale)

    
posta sebf 10.05.2012 - 22:42
fonte

4 risposte

2

Ecco lo pseudocodice C-like. Puoi capire come gestire i casi limite (ad esempio ritaglio, mirroring, ecc.). Lascerò a te la possibilità di capire come utilizzare questo integer o la matematica a virgola fissa se le prestazioni sono un problema.

struct {
    bitmap bmp;
    float x, y, width, height;
} xfer_param;

scaled_xfer(xfer_param src, xfer_param det)
{
    float src_dx = dst.width / src.width;
    float src_dy = dst.height / src.height;
    float src_maxx = src.x + src.width;
    float src_maxy = src.y + src.height;
    float dst_maxx = dst.x + dst.width;
    float dst_maxy = dst.y + dst.height;
    float src_cury = src.y;

    for (float y = dst.y; y < dst_maxy; y++)
    {
        float src_curx = src.x;   
        for (float x = dst.x; x < dst_maxx; x++)
        {
            // Point sampling - you can also impl as bilinear or other
            dst.bmp[x,y] = src.bmp[src_curx, src_cury];
            src_curx += src_dx;
        }

        src_cury += src_dy;
    }
}

Per eseguire l'interpolazione sub-pixel, è possibile campionare i 4 pixel attorno al punto in virgola mobile src_curx, src_cury e prendere una media ponderata. Uno dei metodi di più alta qualità consiste nell'effettuare effettivamente un rettangolo campione nell'immagine sorgente corrispondente a un singolo pixel nell'immagine dest. Quindi devi solo calcolare la media di tutti i valori e scrivere il pixel di destinazione. Tuttavia, il rect probabilmente non cadrà sui confini dei pixel puliti, quindi vorrete prendere i pixel del bordo ritagliato e pesarli di conseguenza.

    
risposta data 11.05.2012 - 02:43
fonte
3

Forse il meccanismo che cerchi è l'algoritmo BitBlt ?

Bit blit (also written BITBLT, BIT BLT, BitBLT, Bit BLT, Bit Blt etc., which stands for bit-level block transfer) is a computer graphics operation in which several bitmaps are combined into one using a raster operator.

The operation involves at least two bitmaps, a source and destination, possibly a third that is often called the "mask" and sometimes a fourth used to create a stencil. The pixels of each are combined bitwise according to the specified raster operation (ROP) and the result is then written to the destination. The ROP is essentially a boolean formula. The most obvious ROP overwrites the destination with the source. Other ROPs may involve AND, OR, XOR, and NOT operations...

    
risposta data 03.05.2013 - 23:42
fonte
2

Per ridimensionare correttamente un'immagine (in particolare, per ridurre le dimensioni di un'immagine), hai bisogno di un'interpolazione filtro ridimensionato a più piccolo delle dimensioni di origine e di destinazione.

Sfortunatamente, se il tuo buffer di destinazione è davvero un bitmap, non hai modo di memorizzare i pixel in scala di grigi che otterrai dal filtro. Il meglio che puoi fare (a meno di misure straordinarie) è la soglia dei risultati al 50%, in modo da ottenere un valore di pixel binario da memorizzare nel buffer di output.

In molti casi, un rapido & il programma sporco non si preoccuperà di provare a ridimensionare correttamente una bitmap con scala arbitraria, semplicemente afferreranno il pixel di origine più vicino alla posizione target interpolata, come descritto. Questo è sicuramente veloce, ma sembra abbastanza brutto, soprattutto per la riduzione delle dimensioni (come suggerisce la tua domanda), o per lo stretching dinamico (animato o interattivo).

Tuttavia, se stai facendo tutto con le bitmap, forse quel particolare tipo di brutto potrebbe essere utile per un po 'di credenziali a 8 bit ...

    
risposta data 10.05.2012 - 23:20
fonte
0

Generalmente il modo migliore è lavorare su una griglia nella destinazione e interpolare il pixel sorgente. In questo modo sei sicuro che non ci sono spazi vuoti o effetti alias nella destinazione.

    
risposta data 11.05.2012 - 01:21
fonte

Leggi altre domande sui tag