package org.kne.codec.kif;

import org.kne.membandboost.MembandBoost;

/**
 * 位平面编码工具
 * 将字节数组按位平面重排：先存所有最高位，再存次高位，...，最后存最低位
 * 例如：输入 [0x01, 0x02, 0x03]
 *       二进制: 00000001, 00000010, 00000011
 *       位平面拆分: bit7: 000, bit6: 000, ..., bit1: 011, bit0: 101
 *       输出: [00000000, 00000000, ..., 00000011, 00000101]
 */
public class BitPlane {

    

	/**
	 * 位平面编码（矩阵转置风格）
	 * 
	 * 核心逻辑：
	 *   对于输出数组的每个字节，依次从输入数组的8个位平面各取1个bit
	 *   即：输出字节的 bit i = 输入数组第 i 个位平面的当前位
	 * 
	 * 等价于：把 8×len 的 bit 矩阵转置为 len×8 的 bit 矩阵
	 */
	public static byte[] encodePacked(byte[] input) {
	    int len = input.length;
	    byte[] output = MembandBoost.allocateUninitializedByteArray(len);
	    
	    
	    // 输出数组的每个字节，由8个位平面的各1个bit组成
	    for (int outIdx = 0; outIdx < len; outIdx++) {
	        int outByte = 0;
	        // 从8个位平面各取1个bit，组装成一个字节
	        for (int plane = 0; plane < 8; plane++) {
	            // 当前位平面：bitShift
	            // 从输入数组的 inputPos 位置取 bit
	        	int bitpos=(outIdx<<3)+plane;
	    	    int inputPos = bitpos%len;
	    	    int bitShift = bitpos/len;
	            int bit = (input[inputPos] >> (7-bitShift)) & 1;
	            outByte |= (bit << plane);  // 放到输出字节的第 plane 位
	           
	        }
	        output[outIdx] = (byte) outByte;
	    }
	    return output;
	}

    /**
     * 位平面编码（极速版）
     * 按位平面批量处理，利用位平面内部的连续性
     */
   /* public static byte[] encodePacked(byte[] input) {
        int len = input.length;
        byte[] output = new byte[len];
        
        for (int plane = 0; plane < 8; plane++) {
            int bit = 7 - plane;
            int planeStart = plane * len;
            int planeByteStart = planeStart >> 3;
            int planeBitOffset = planeStart & 7;
            
            // 处理当前位平面
            // 收集位平面数据到一个 int（最多 32 位），批量写入
            for (int i = 0; i < len; i++) {
                int inputBit = (input[i] >> bit) & 1;
                if (inputBit == 1) {
                    int bytePos = planeByteStart + ((i + planeBitOffset) >> 3);
                    int bitPos = 7 - ((i + planeBitOffset) & 7);
                    output[bytePos] |= (1 << bitPos);
                }
            }
        }
        return output;
    }*/

	
	/**
	 * 位平面解码（矩阵转置逆操作）
	 * 
	 * 核心逻辑：
	 *   对于输出数组的每个字节，从输入数组的8个字节中各取1个bit
	 *   即：输出字节的 bit i = 输入数组第 i 个字节的第 plane 位
	 */
	public static byte[] decodePacked(byte[] input) {
	    byte[] output = MembandBoost.allocateUninitializedByteArray(input.length);
	    
	    // 输出数组的每个字节，由8个输入字节的对应bit组成
	    for (int outIdx = 0; outIdx < output.length; outIdx++) {
	        int outByte = 0;
	        for (int plane = 0; plane < 8; plane++) {
	            // 从输入数组的当前字节取第 bitShift 位
	        	int bitpos2=plane*input.length+outIdx;
	        	int inputpos=bitpos2>>3;
	        	int inputshift=bitpos2&0b111;
	            int bit = (input[inputpos] >> inputshift) & 1;
	            outByte |= (bit << (7-plane));
	        }
	        output[outIdx] = (byte) outByte;
	    }
	    return output;
	}
	
    /**
     * 位平面解码（极速版）
     */
    /*public static byte[] decodePacked(byte[] input) {
        byte[] output = new byte[length];
        
        for (int plane = 0; plane < 8; plane++) {
            int bit = 7 - plane;
            int planeStart = plane * len;
            int planeByteStart = planeStart >> 3;
            int planeBitOffset = planeStart & 7;
            
            for (int i = 0; i < len; i++) {
                int bytePos = planeByteStart + ((i + planeBitOffset) >> 3);
                int bitPos = 7 - ((i + planeBitOffset) & 7);
                int inputBit = (input[bytePos] >> bitPos) & 1;
                if (inputBit == 1) {
                    output[i] |= (1 << bit);
                }
            }
        }
        return output;
    }*/
   
    
    public static void main(String[] args) {
	    // 测试数据：0-255 的字节
	    byte[] testData = new byte[16];
	    for (int i = 0; i < testData.length; i++) {
	        testData[i] = (byte) i;
	    }
	    
	    // 打包版编码
	    byte[] encoded = BitPlane.encodePacked(testData);
	    System.out.println("原始长度: " + testData.length);
	    System.out.println("编码后长度: " + encoded.length);
	    
	    // 解码
	    byte[] decoded = BitPlane.decodePacked(encoded);
	    
	    
	    // 查看位平面结构
	    System.out.println("\n前 16 个字节的测试数据:");
	    for (int i = 0; i < 16; i++) {
	        System.out.printf("%02X ", testData[i]);
	    }
	    

	    System.out.println("\n前 16 个字节的位平面编码:");
	    for (int i = 0; i < 16; i++) {
	        System.out.printf("%02X ", encoded[i]);
	    }
	    


	    System.out.println("\n前 16 个字节的位平面解码:");
	    for (int i = 0; i < 16; i++) {
	        System.out.printf("%02X ", decoded[i]);
	    }
	    

	    // 验证
	    boolean ok = true;
	    for (int i = 0; i < testData.length; i++) {
	        if (testData[i] != decoded[i]) {
	            ok = false;
	            System.out.println("❌ 第 " + i + " 个字节不一致");
	            break;
	        }
	    }
	    System.out.println("无损还原: " + (ok ? "✅" : "❌"));
	}
}