public abstract Bitmap Load(QOIFHeader header, BinaryReader rd);
public override Bitmap Load(QOIFHeader header, BinaryReader rd) { Bitmap bitmap = new(header.Width, header.Height, PixelFormat.Format32bppArgb); RGBAColor[] indexed = new RGBAColor[64]; RGBAColor previous = RGBAColor.Black; int end_match = 0; #if DEBUG_LOG StringBuilder sb = new StringBuilder().AppendLine(header.ToString()).AppendLine("DECODING"); #endif bitmap.LockRGBAPixels((ptr, w, h) => { int index = 0; #if DEBUG_LOG void set_pixel(RGBAColor color, string log) #else void set_pixel(RGBAColor color) #endif { if (index < w * h) { int cache = GetIndex(color); #if DEBUG_LOG sb.AppendLine($"I={index,6} X={index % w,5} Y={index / w,5} P={previous,12} C={color,12} (CH={cache,2}) {log}"); #endif indexed[cache] = color; ptr[index++] = color; if (previous != color) { previous = color; } } #if DEBUG_LOG else { sb.AppendLine($" <<<< index {index} >= {w}x{h} = {w * h} >>>>"); } #endif } try { while (index < w * h && end_match < END.Length && rd.ReadByte() is byte @byte) { if (@byte is TAG_OP_RGB or TAG_OP_RGBA) { RGBAColor color = new( rd.ReadByte(), rd.ReadByte(), rd.ReadByte() ); if (@byte is TAG_OP_RGBA) { color.A = rd.ReadByte(); } #if DEBUG_LOG set_pixel(color, "EXPLICIT"); #else set_pixel(color); #endif } else { int op = @byte & MASK_TAG2; byte data = (byte)(@byte & ~MASK_TAG2); if (op is TAG_OP_INDEX) { #if DEBUG_LOG set_pixel(indexed[data], $"INDEXED {@byte:x2} I={data}"); #else set_pixel(indexed[data]); #endif if (@byte == END[end_match]) { ++end_match; } else { end_match = 0; } } else if (op is TAG_OP_DIFF) { int dr = (@byte & MASK_DIFF_R) >> SHIFT_DIFF_R; int dg = (@byte & MASK_DIFF_G) >> SHIFT_DIFF_G; int db = @byte & MASK_DIFF_B; RGBAColor color = ComputeFrom2BitDistance(previous, dr, dg, db); #if DEBUG_LOG set_pixel(color, $"2BITDIFF {@byte:x2} ({dr} {dg} {db})"); #else set_pixel(color); #endif } else if (op is TAG_OP_LUMA) { @byte = rd.ReadByte(); int drg = (@byte & MASK_LUMA_RG) >> SHIFT_LUMA_RG; int dbg = @byte & MASK_LUMA_BG; RGBAColor color = ComputeFromLuma(previous, 6, 4, drg, data, dbg); #if DEBUG_LOG set_pixel(color, $"LUMADIFF {op | data:x2}{@byte:x2} ({data} {drg} {dbg})"); #else set_pixel(color); #endif } else if (op is TAG_OP_RUN) { for (int i = 0, c = data + 1; i < c && index < w * h; ++i) #if DEBUG_LOG { set_pixel(previous, $"RUN {@byte:x2} R={data + 1}"); } #else { set_pixel(previous); } #endif } #if DEBUG_LOG else { sb.AppendLine($" <<<< UNKNOWN INSTRUCTION {@byte:x2} >>>>"); } #endif } } }