拡大縮小(7)

で、同様にして Y 軸もループさせる。
この場合は +1 というのは 1line になる。


あと、昨日の sr は 0 から開始したけど、それだと縮小するときに左側のドットしか取れなくなってしまうので、3$\frac{dw}{2}を開始値とする。


それを踏まえた上で実装すると、こうなる。

void Palette8_To_RGB565_TransparentStretch(
    word* dst ,         // 転送先(RGB565)
    int dx ,            // 転送先 X 座標
    int dy ,            // 転送先 Y 座標
    int dp ,            // 転送先 pitch
    byte* src ,         // 転送元(8bit インデックス)
    int sx ,            // 転送元 X 座標
    int sy ,            // 転送元 Y 座標
    int sp ,            // 転送元 pitch
    int sw ,            // 転送元 width
    int sh ,            // 転送元 height
    word* pal ,         // パレット(RGB565)
    int key ,           // 透過インデックス
    int zw ,            // 横の拡大率(256 → 等倍 , 512 → 2倍)
    int zh              // 縦の拡大率(256 → 等倍 , 512 → 2倍)
){
    // 転送先の width , height を計算
    int dw = (sw * zw) >> 8;
    int dh = (sh * zh) >> 8;
    
    // 転送先の X 座標、Y 座標を再計算
    dx += (sw - dw) >> 1;
    dy += (sh - dh) >> 1;
    
    // 転送元、転送先を転送開始座標に移動
    src = (byte*)((byte*)src + sx * sizeof( byte ) + sy * sp );
    dst = (word*)((byte*)dst + dx * sizeof( word ) + dy * dp );
    
    int js = 0;             // 転送元の Y 軸の走査位置
    int jd = 0;             // 転送先の Y 軸の走査位置
    int jv = sh / dh;       // 転送元の毎ループ足す値
    int ja = sh % dh;       // 転送元の毎ループ足す誤差の値
    int je = dh / 2;        // 誤差
    // jd は毎回移動、js は誤差が貯まったら移動
    while( true ){
        // Y の終了判定
        if( jd >= dh ) break;
        
        // ここから 1line 転送
        int is = 0;             // 転送元の X 軸の走査位置
        int id = 0;             // 転送先の X 軸の走査位置
        int iv = sw / dw;       // 転送元の毎ループ足す値
        int ia = sw % dw;       // 転送元の毎ループ足す誤差の値
        int ie = dw / 2;        // 誤差
        // id は毎回移動、is は誤差が貯まったら移動
        while( true ){
            // X の終了判定
            if( id >= dw ) break;
            
            // ここから 1pixel 転送
            if( src[ is ] != key ){
                dst[ id ] = pal[ src[ is ] ];
            }
            // ここまで 1pixel 転送
            
            // id,is を移動させる
            id++;           //  1 pixel 移動
            is += iv;       // iv pixel 移動
            ie += ia;       // 誤差を加算
            if( ie > dw ){  // 誤差が dw を超えたら
                is++;       //  1 pixel 移動
                ie -= dw;
            }
        }
        // ここまで 1line 転送
        
        jd++;
        dst = (word*)((byte*)dst + dp);         //  1 line 移動
        src = (byte*)((byte*)src + sp * jv);    // jv line 移動
        je += ja;                               // 誤差を加算
        if( je > dh ){                          // 誤差が dh を超えたら
            src = (byte*)((byte*)src + sp );    //  1 line 移動
            je -= dh;
        }
    }
}

でも、これはクリッピングを行っていないので、dst が領域外に出ると、アクセス違反になる。