結論:對於色彩較少的圖像,索引圖存儲效率遠高於 RGB 圖。
針對索引圖按行掃描產生的索引序列 [I1][I2]...[In],利用連續相同像素特性:
[C1][I1][C2][I2]...[Cm][Im]針對調色板色數較少(如 32 色)的情況,索引值高位固定為 0,造成空間浪費。USI 將計數值壓入索引字節的高位:
最終格式:[G1][G2]...[Gk] + 調色板 + 元數據 = USI 文件
private void load(String file) {
DataInputStream din = new DataInputStream(getClass().getResourceAsStream(file));
m_flags = din.readInt(); // 格式標記
m_count = din.readByte() & 0xff; // 調色板位數
m_mask = 0xff >> (8 - m_count); // 索引掩碼
int pal_count = din.readByte() & 0xff; // 調色板組數
int pal_len = din.readByte() & 0xff; // 每組色數
// 讀取調色板數據(12位色擴展為32位ARGB)
// 讀取圖塊尺寸/模型信息
// 讀取壓縮像素數據 m_data
// 讀取每個圖塊數據偏移量 m_dataOffset
}
private int[] BuildRle8bFrm(int model_id, int pal_id) {
int size = ...; // 圖塊寬×高
int[] m_bufB = new int[size];
int[] pal = m_pal[pal_id];
int offset = m_dataOffset[model_id];
int count, index, pos = 0;
while (pos < size) {
count = ((m_data[offset] & 0xFF) >> m_count) + 1; // 高位計數
index = pal[m_data[offset] & m_mask]; // 低位索引查色
offset++;
while (--count >= 0) {
m_bufB[pos++] = index;
}
}
return m_bufB; // ARGB 像素數組
}
public Image GetImage(int model_id, int pal_id) {
int[] argb = BuildRle8bFrm(model_id, pal_id);
int w = ..., h = ...; // 從 flags 或 models 獲取尺寸
Image img = Image.createRGBImage(argb, w, h, true);
return img;
}
m_count、m_mask 分離計數與索引,極致壓縮存儲USI 格式展示了在資源受限環境下,針對特定圖像特徵設計專用壓縮格式的經典思路,對嵌入式圖形開發極具參考價值。