/** * Zigzag 映射:将有符号字节映射为非负字节 * 0→0, -1→1, 1→2, -2→3, 2→4, ... */ uchar zigzag_map(char x) { int v = (int)x; // char 转为 int(保留符号) return (uchar)((v >= 0) ? (v << 1) : ((-v << 1) - 1)); } /** * Zigzag 逆映射:将非负字节还原为有符号字节 * 0→0, 1→-1, 2→1, 3→-2, 4→2, ... */ char zigzag_unmap(uchar y) { int v = (int)y; // 转为无符号 0~255 return (char)((v & 1) == 0 ? (v >> 1) : (-((v + 1) >> 1))); } /** * 像素安全加法:RGBA 四个通道分别相加,结果裁剪到 0~255 */ int pixelAdd(int a, int b) { int ar = (a >> 16) & 0xFF; int ag = (a >> 8) & 0xFF; int ab = a & 0xFF; int aa = (a >> 24) & 0xFF; int br = (b >> 16) & 0xFF; int bg = (b >> 8) & 0xFF; int bb = b & 0xFF; int ba = (b >> 24) & 0xFF; int r = ar + br; int g = ag + bg; int bv = ab + bb; int av = aa + ba; // 用 &0xFF 替代 min/max,保留低 8 位(自动溢出,等同于裁剪) return ((av & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (bv & 0xFF); } /** * 像素安全减法(等效于 Java 的 pixelSub) * 逐通道相减,结果裁剪到 0~255,组装回 ARGB */ int pixelSub(int a, int b) { int ar = (a >> 16) & 0xFF; int ag = (a >> 8) & 0xFF; int ab = a & 0xFF; int aa = (a >> 24) & 0xFF; int br = (b >> 16) & 0xFF; int bg = (b >> 8) & 0xFF; int bb = b & 0xFF; int ba = (b >> 24) & 0xFF; int r = ar - br; int g = ag - bg; int bv = ab - bb; int av = aa - ba; return ((av & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (bv & 0xFF); } /** * 位平面编码(矩阵转置风格)- 等效于 Java 版本 * * 核心逻辑: * 对于输出数组的每个字节,依次从输入数组的8个位平面各取1个bit * 即:输出字节的 bit i = 输入数组第 i 个位平面的当前位 * * 输出数组的每个字节,由8个位平面的各1个bit组成 * 等价于:把 8×len 的 bit 矩阵转置为 len×8 的 bit 矩阵 */ __kernel void encodePacked( __global const uchar* input, // 输入字节数组 __global uchar* output, // 输出字节数组(长度与输入相同) int len // 输入/输出长度 ) { int outIdx = get_global_id(0); if (outIdx >= len) return; int outByte = 0; // 从8个位平面各取1个bit,组装成一个字节 for (int plane = 0; plane < 8; plane++) { int bitpos = (outIdx << 3) + plane; int inputPos = bitpos % len; int bitShift = bitpos / len; int bit = (input[inputPos] >> (7 - bitShift)) & 1; outByte |= (bit << plane); } output[outIdx] = (uchar)outByte; } __kernel void decodePacked(__global const unsigned char* datain, __global unsigned char* dataout, int size) { int outIdx = get_global_id(0); // 边界检查 if (outIdx >= size) { return; } int outByte = 0; // 从 8 个位平面各取 1 个 bit,组装成一个字节 // plane 0 → bit7, plane 1 → bit6, ..., plane 7 → bit0 for (int plane = 0; plane < 8; plane++) { int bitpos = plane * size + outIdx; int inputpos = bitpos >> 3; int inputshift = bitpos & 0b111; int bit = (datain[inputpos] >> inputshift) & 1; outByte |= (bit << (7 - plane)); } dataout[outIdx] = (unsigned char)outByte; } /** * 序列化 + Zigzag 映射(RGBA 交错) */ __kernel void serializeRGBAWithZigzag( __global int* pixels, __global uchar* output, int size ) { int i = get_global_id(0); if (i >= size) return; int pixel = pixels[i]; char r = (char)((pixel >> 16) & 0xFF); char g = (char)((pixel >> 8) & 0xFF); char b = (char)(pixel & 0xFF); char a = (char)((pixel >> 24) & 0xFF); int idx = i * 4; output[idx + 0] = zigzag_map(r); output[idx + 1] = zigzag_map(g); output[idx + 2] = zigzag_map(b); output[idx + 3] = zigzag_map(a); } // 对应 deserializeRGBAWithZigzag __kernel void deserializeRGBAWithZigzag( __global const uchar* data, // 输入:Zigzag 映射后的字节流(RGBA 交错) __global int* pixels, // 输出:像素数组(ARGB) int size // 像素数量 (w * h) ) { int i = get_global_id(0); if (i >= size) return; int idx = i * 4; // 读取并逆映射四个通道 uchar r_raw = data[idx]; uchar g_raw = data[idx + 1]; uchar b_raw = data[idx + 2]; uchar a_raw = data[idx + 3]; char r = zigzag_unmap(r_raw); char g = zigzag_unmap(g_raw); char b = zigzag_unmap(b_raw); char a = zigzag_unmap(a_raw); // 组装成 ARGB (Java 的 int 格式) // 注意:OpenCL 的 int 是 32 位有符号,和 Java 一致 pixels[i] = ((int)(a & 0xFF) << 24) | ((int)(r & 0xFF) << 16) | ((int)(g & 0xFF) << 8) | (int)(b & 0xFF); } /** * 序列化 + Zigzag 映射(平面 RGBA) */ __kernel void serializePlannarRGBAWithZigzag( __global int* pixels, __global uchar* output, int size ) { int i = get_global_id(0); if (i >= size) return; int pixel = pixels[i]; char r = (char)((pixel >> 16) & 0xFF); char g = (char)((pixel >> 8) & 0xFF); char b = (char)(pixel & 0xFF); char a = (char)((pixel >> 24) & 0xFF); int rOffset = 0; int gOffset = size; int bOffset = size * 2; int aOffset = size * 3; output[rOffset + i] = zigzag_map(r); output[gOffset + i] = zigzag_map(g); output[bOffset + i] = zigzag_map(b); output[aOffset + i] = zigzag_map(a); } // 对应 deserializePlannarRGBAWithZigzag __kernel void deserializePlannarRGBAWithZigzag( __global const uchar* data, // 输入:Zigzag 映射后的字节流(RRRR...GGGG...BBBB...AAAA...) __global int* pixels, // 输出:像素数组(ARGB) int size // 像素数量 (w * h) ) { int i = get_global_id(0); if (i >= size) return; int rOffset = 0; int gOffset = size; int bOffset = size * 2; int aOffset = size * 3; // 从四个平面分别读取并逆映射 uchar r_raw = data[rOffset + i]; uchar g_raw = data[gOffset + i]; uchar b_raw = data[bOffset + i]; uchar a_raw = data[aOffset + i]; char r = zigzag_unmap(r_raw); char g = zigzag_unmap(g_raw); char b = zigzag_unmap(b_raw); char a = zigzag_unmap(a_raw); // 组装成 ARGB pixels[i] = ((int)(a & 0xFF) << 24) | ((int)(r & 0xFF) << 16) | ((int)(g & 0xFF) << 8) | (int)(b & 0xFF); } /** * 水平预测(非原地,完美并行) * residual = pixelSub(current, left) * 每个线程独立处理一个像素 */ __kernel void horizontalPredictParallel( __global const int* input, // 原始像素 __global int* output, // 残差输出 int w, int h ) { int idx = get_global_id(0); int size = w * h; if (idx >= size) return; int x = idx % w; if (x == 0) { // 第一列:残差 = 原值(没有左邻居) output[idx] = input[idx]; } else { int left = input[idx - 1]; output[idx] = pixelSub(input[idx], left); } } /** * 垂直预测(非原地,完美并行) * residual = pixelSub(current, above) * 每个线程独立处理一个像素 */ __kernel void verticalPredictParallel( __global const int* input, // 原始像素(或水平预测后的残差) __global int* output, // 残差输出 int w, int h ) { int idx = get_global_id(0); int size = w * h; if (idx >= size) return; int y = idx / w; if (y == 0) { // 第一行:残差 = 原值(没有上邻居) output[idx] = input[idx]; } else { int above = input[idx - w]; output[idx] = pixelSub(input[idx], above); } } /** * 水平预测(使用 pixelSub) * residual = pixelSub(current, left) * 从右向左,保证 left 是原始值 */ __kernel void horizontalPredictInPlace( __global int* data, int w, int h ) { int row = get_global_id(0); if (row >= h) return; int base = row * w; // 从右向左(第一列不变) for (int x = w - 1; x >= 1; x--) { int idx = base + x; int left = data[idx - 1]; data[idx] = pixelSub(data[idx], left); } } /** * 水平逆预测(原地操作) * 每个工作组处理一行,行内从左到右串行 * * 数据依赖:左侧像素 (x-1, y) 必须先被还原 *//** * 水平逆预测(寄存器优化版) * * 核心优化:预测值在寄存器中传递,减少显存读取 */ __kernel void horizontalInverseInPlace( __global int* data, int w, int h ) { int row = get_global_id(0); if (row >= h) return; int base = row * w; // 第一列保持不变 // 直接用 data[base] 作为初始预测值 int pred = data[base]; // ✅ 只读一次显存 // 行内从左到右串行,但 pred 在寄存器中传递 for (int x = 1; x < w; x++) { int idx = base + x; int residual = data[idx]; // ✅ 只读残差 int result = pixelAdd(pred, residual); data[idx] = result; // ✅ 只写一次显存 pred = result; // ✅ 寄存器传递(下次循环直接使用) } } /** * 垂直预测(使用 pixelSub) * residual = pixelSub(current, above) * 从下向上,保证 above 是原始值 */ __kernel void verticalPredictInPlace( __global int* data, int w, int h ) { int col = get_global_id(0); if (col >= w) return; // 从下向上(第一行不变) for (int y = h - 1; y >= 1; y--) { int idx = y * w + col; int above = data[(y - 1) * w + col]; data[idx] = pixelSub(data[idx], above); } } /** * 垂直逆预测(原地操作) * 每个工作组处理一列,列内从上到下串行 * * 数据依赖:上方像素 (x, y-1) 必须先被还原 *//** * 垂直逆预测(寄存器优化版) */ __kernel void verticalInverseInPlace( __global int* data, int w, int h ) { int col = get_global_id(0); if (col >= w) return; // 第一行:用 data[col] 作为初始预测值 int pred = data[col]; // ✅ 只读一次显存 for (int y = 1; y < h; y++) { int idx = y * w + col; int residual = data[idx]; // ✅ 只读残差 int result = pixelAdd(pred, residual); data[idx] = result; pred = result; // ✅ 寄存器传递 } } /** * RGBA 颜色变换(原地版本)- 等效于 Java 的 colorTransformRGBAInPlace * * 编码:R' = R - G, G' = G, B' = B - G, A' = A * 结果存储为:A | R' | G | B'(与 Java 版本完全一致) */ __kernel void colorTransformRGBAInPlace( __global int* data, // 输入/输出像素数组 int size // 像素总数 (w * h) ) { int idx = get_global_id(0); if (idx >= size) return; int pixel = data[idx]; int r = (pixel >> 16) & 0xFF; int g = (pixel >> 8) & 0xFF; int b = pixel & 0xFF; int a = (pixel >> 24) & 0xFF; int rg = r - g; // 范围 -255 ~ 255 int bg = b - g; // 范围 -255 ~ 255 // 与 Java 版本完全一致: // ((a & 0xFF) << 24) | ((rg & 0xFF) << 16) | ((g & 0xFF) << 8) | (bg & 0xFF) data[idx] = ((a & 0xFF) << 24) | ((rg & 0xFF) << 16) | ((g & 0xFF) << 8) | (bg & 0xFF); } /** * 颜色逆变换(RGBA,逐像素并行)- 与 colorTransformRGBAInPlace 完全对应 * * Java 版本: * a = (packed >> 24) & 0xFF * rg = (packed >> 16) & 0xFF * g = (packed >> 8) & 0xFF * bg = packed & 0xFF * r = g + rg * b = g + bg * result = (a << 24) | (r << 16) | (g << 8) | b */ __kernel void colorInverseRGBAInPlace( __global int* data, // 输入:颜色差分数据,输出:还原后的 RGBA int size // 像素总数 (w * h) ) { int idx = get_global_id(0); if (idx >= size) return; int packed = data[idx]; // 提取各通道 int a = (packed >> 24) & 0xFF; int rg = (packed >> 16) & 0xFF; int g = (packed >> 8) & 0xFF; int bg = packed & 0xFF; // 还原 R 和 B int r = g + rg; int b = g + bg; // 裁剪到 0~255(用 &0xFF 保留低 8 位) r = r & 0xFF; b = b & 0xFF; // 组装回 ARGB data[idx] = ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF); }