bng_fast.h

The optimized encoder and decoder in C. One file, tables and all, every function static inline, and byte for byte the same output as the reference — download, 29596 bytes, 697 lines.

#ifndef BNG_FAST_H
#define BNG_FAST_H

#include <stddef.h>
#include <stdint.h>
#include <string.h>

#if defined(__SSE2__)
#include <emmintrin.h>
#endif

#define TDIR 63
#define KEXP 6
#define ALPHA 144
#define TOK_EOL (2 * TDIR + 1 + 2 * (8 - KEXP))
#define TOK_RUN (TOK_EOL + 1)
#define MAXCODE 12
#define MAXCODE_MASK ((1u << MAXCODE) - 1)
#define PIC_MAX_PIXELS (1u << 28)

#define P4_MAGIC "\xFF\x0E\x38\x30\x2A\x1A\x18"
#define P4_VERSION 0x01
#define P4_HEADER 20
#define P4_RAW_FLAG 0x80000000u
#define P4_COUNT_MASK 0x7FFFFFFFu
#define BNG_MAX_ENCODED(w, h) ((size_t)P4_HEADER + 4 * (size_t)(w) * (size_t)(h))

#define P4_B 0
#define P4_G 1
#define P4_R 2
#define P4_X 3

typedef struct {
   int16_t base;
   uint8_t len;
   uint8_t nbits;
   uint8_t kind;
   uint8_t pad[3];
} Dec_Entry;

static const uint32_t mask_lut[13] = {
   0u, 1u, 3u, 7u, 15u, 31u, 63u, 127u, 255u, 511u, 1023u, 2047u, 4095u,
};

static const uint32_t ecl[ALPHA] = {
   196608u, 196609u, 196610u, 262150u, 262151u, 262152u, 262153u, 327702u,
   327703u, 393264u, 393265u, 393266u, 393267u, 458858u, 458859u, 458860u,
   458861u, 458862u, 458863u, 524518u, 524519u, 524520u, 524521u, 524522u,
   524523u, 524524u, 524525u, 590302u, 590303u, 590304u, 590305u, 590306u,
   590307u, 590308u, 590309u, 590310u, 590311u, 656340u, 656341u, 656342u,
   656343u, 656344u, 656345u, 656346u, 656347u, 656348u, 656349u, 656350u,
   656351u, 656352u, 656353u, 656354u, 656355u, 722892u, 722893u, 722894u,
   722895u, 722896u, 722897u, 722898u, 722899u, 722900u, 722901u, 722902u,
   722903u, 722904u, 722905u, 722906u, 722907u, 722908u, 722909u, 722910u,
   722911u, 790470u, 790471u, 790472u, 790473u, 790474u, 790475u, 790476u,
   790477u, 790478u, 790479u, 790480u, 790481u, 790482u, 790483u, 790484u,
   790485u, 790486u, 790487u, 790488u, 790489u, 790490u, 790491u, 790492u,
   790493u, 790494u, 790495u, 790496u, 790497u, 790498u, 790499u, 790500u,
   790501u, 790502u, 790503u, 790504u, 790505u, 790506u, 790507u, 790508u,
   790509u, 790510u, 790511u, 790512u, 790513u, 790514u, 790515u, 790516u,
   790517u, 790518u, 790519u, 790520u, 790521u, 722912u, 790522u, 458864u,
   458865u, 790523u, 722913u, 590312u, 262154u, 393268u, 458866u, 524526u,
   590313u, 656356u, 656357u, 722914u, 790524u, 790525u, 790526u, 790527u,
};

static const uint8_t exp_of[256] = {
   0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
   5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
};

static const Dec_Entry dtab[256] = {
   {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}},
   {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}},
   {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}},
   {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}},
   {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}},
   {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}},
   {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}},
   {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}}, {0,3,0,0,{0,0,0}},
   {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}},
   {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}},
   {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}},
   {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}},
   {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}},
   {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}},
   {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}},
   {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}}, {1,3,0,0,{0,0,0}},
   {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}},
   {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}},
   {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}},
   {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}},
   {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}},
   {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}},
   {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}},
   {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}}, {1,3,0,1,{0,0,0}},
   {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}},
   {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}},
   {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}},
   {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}}, {2,4,0,0,{0,0,0}},
   {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}},
   {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}},
   {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}},
   {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}}, {2,4,0,1,{0,0,0}},
   {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}},
   {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}},
   {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}},
   {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}}, {3,4,0,0,{0,0,0}},
   {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}},
   {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}},
   {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}},
   {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}}, {3,4,0,1,{0,0,0}},
   {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}},
   {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}},
   {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}},
   {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}}, {2,4,1,3,{0,0,0}},
   {4,5,0,0,{0,0,0}}, {4,5,0,0,{0,0,0}}, {4,5,0,0,{0,0,0}}, {4,5,0,0,{0,0,0}},
   {4,5,0,0,{0,0,0}}, {4,5,0,0,{0,0,0}}, {4,5,0,0,{0,0,0}}, {4,5,0,0,{0,0,0}},
   {4,5,0,1,{0,0,0}}, {4,5,0,1,{0,0,0}}, {4,5,0,1,{0,0,0}}, {4,5,0,1,{0,0,0}},
   {4,5,0,1,{0,0,0}}, {4,5,0,1,{0,0,0}}, {4,5,0,1,{0,0,0}}, {4,5,0,1,{0,0,0}},
   {5,6,0,0,{0,0,0}}, {5,6,0,0,{0,0,0}}, {5,6,0,0,{0,0,0}}, {5,6,0,0,{0,0,0}},
   {5,6,0,1,{0,0,0}}, {5,6,0,1,{0,0,0}}, {5,6,0,1,{0,0,0}}, {5,6,0,1,{0,0,0}},
   {6,6,0,0,{0,0,0}}, {6,6,0,0,{0,0,0}}, {6,6,0,0,{0,0,0}}, {6,6,0,0,{0,0,0}},
   {6,6,0,1,{0,0,0}}, {6,6,0,1,{0,0,0}}, {6,6,0,1,{0,0,0}}, {6,6,0,1,{0,0,0}},
   {4,6,2,3,{0,0,0}}, {4,6,2,3,{0,0,0}}, {4,6,2,3,{0,0,0}}, {4,6,2,3,{0,0,0}},
   {7,7,0,0,{0,0,0}}, {7,7,0,0,{0,0,0}}, {7,7,0,1,{0,0,0}}, {7,7,0,1,{0,0,0}},
   {8,7,0,0,{0,0,0}}, {8,7,0,0,{0,0,0}}, {8,7,0,1,{0,0,0}}, {8,7,0,1,{0,0,0}},
   {9,7,0,0,{0,0,0}}, {9,7,0,0,{0,0,0}}, {9,7,0,1,{0,0,0}}, {9,7,0,1,{0,0,0}},
   {64,7,6,0,{0,0,0}}, {64,7,6,0,{0,0,0}}, {64,7,6,1,{0,0,0}}, {64,7,6,1,{0,0,0}},
   {8,7,3,3,{0,0,0}}, {8,7,3,3,{0,0,0}}, {10,8,0,0,{0,0,0}}, {10,8,0,1,{0,0,0}},
   {11,8,0,0,{0,0,0}}, {11,8,0,1,{0,0,0}}, {12,8,0,0,{0,0,0}}, {12,8,0,1,{0,0,0}},
   {13,8,0,0,{0,0,0}}, {13,8,0,1,{0,0,0}}, {16,8,4,3,{0,0,0}}, {0,0,0,0,{0,0,0}},
   {1,0,0,0,{0,0,0}}, {2,0,0,1,{0,0,0}}, {3,0,0,0,{0,0,0}}, {4,0,0,1,{0,0,0}},
   {16,0,0,1,{0,0,0}}, {5,0,0,0,{0,0,0}}, {6,0,0,1,{0,0,0}}, {7,0,0,0,{0,0,0}},
   {8,0,0,1,{0,0,0}}, {9,0,0,0,{0,0,0}}, {10,0,0,1,{0,0,0}}, {11,0,0,0,{0,0,0}},
   {12,0,0,1,{0,0,0}}, {13,0,0,0,{0,0,0}}, {14,0,0,1,{0,0,0}}, {15,0,0,0,{0,0,0}},
};

static const Dec_Entry dsub[272] = {
   {14,9,0,0,{0,0,0}}, {14,9,0,0,{0,0,0}}, {14,9,0,0,{0,0,0}}, {14,9,0,0,{0,0,0}},
   {14,9,0,0,{0,0,0}}, {14,9,0,0,{0,0,0}}, {14,9,0,0,{0,0,0}}, {14,9,0,0,{0,0,0}},
   {14,9,0,1,{0,0,0}}, {14,9,0,1,{0,0,0}}, {14,9,0,1,{0,0,0}}, {14,9,0,1,{0,0,0}},
   {14,9,0,1,{0,0,0}}, {14,9,0,1,{0,0,0}}, {14,9,0,1,{0,0,0}}, {14,9,0,1,{0,0,0}},
   {15,9,0,0,{0,0,0}}, {15,9,0,0,{0,0,0}}, {15,9,0,0,{0,0,0}}, {15,9,0,0,{0,0,0}},
   {15,9,0,0,{0,0,0}}, {15,9,0,0,{0,0,0}}, {15,9,0,0,{0,0,0}}, {15,9,0,0,{0,0,0}},
   {15,9,0,1,{0,0,0}}, {15,9,0,1,{0,0,0}}, {15,9,0,1,{0,0,0}}, {15,9,0,1,{0,0,0}},
   {15,9,0,1,{0,0,0}}, {15,9,0,1,{0,0,0}}, {15,9,0,1,{0,0,0}}, {15,9,0,1,{0,0,0}},
   {16,9,0,0,{0,0,0}}, {16,9,0,0,{0,0,0}}, {16,9,0,0,{0,0,0}}, {16,9,0,0,{0,0,0}},
   {16,9,0,0,{0,0,0}}, {16,9,0,0,{0,0,0}}, {16,9,0,0,{0,0,0}}, {16,9,0,0,{0,0,0}},
   {16,9,0,1,{0,0,0}}, {16,9,0,1,{0,0,0}}, {16,9,0,1,{0,0,0}}, {16,9,0,1,{0,0,0}},
   {16,9,0,1,{0,0,0}}, {16,9,0,1,{0,0,0}}, {16,9,0,1,{0,0,0}}, {16,9,0,1,{0,0,0}},
   {17,9,0,0,{0,0,0}}, {17,9,0,0,{0,0,0}}, {17,9,0,0,{0,0,0}}, {17,9,0,0,{0,0,0}},
   {17,9,0,0,{0,0,0}}, {17,9,0,0,{0,0,0}}, {17,9,0,0,{0,0,0}}, {17,9,0,0,{0,0,0}},
   {17,9,0,1,{0,0,0}}, {17,9,0,1,{0,0,0}}, {17,9,0,1,{0,0,0}}, {17,9,0,1,{0,0,0}},
   {17,9,0,1,{0,0,0}}, {17,9,0,1,{0,0,0}}, {17,9,0,1,{0,0,0}}, {17,9,0,1,{0,0,0}},
   {18,9,0,0,{0,0,0}}, {18,9,0,0,{0,0,0}}, {18,9,0,0,{0,0,0}}, {18,9,0,0,{0,0,0}},
   {18,9,0,0,{0,0,0}}, {18,9,0,0,{0,0,0}}, {18,9,0,0,{0,0,0}}, {18,9,0,0,{0,0,0}},
   {18,9,0,1,{0,0,0}}, {18,9,0,1,{0,0,0}}, {18,9,0,1,{0,0,0}}, {18,9,0,1,{0,0,0}},
   {18,9,0,1,{0,0,0}}, {18,9,0,1,{0,0,0}}, {18,9,0,1,{0,0,0}}, {18,9,0,1,{0,0,0}},
   {19,10,0,0,{0,0,0}}, {19,10,0,0,{0,0,0}}, {19,10,0,0,{0,0,0}}, {19,10,0,0,{0,0,0}},
   {19,10,0,1,{0,0,0}}, {19,10,0,1,{0,0,0}}, {19,10,0,1,{0,0,0}}, {19,10,0,1,{0,0,0}},
   {20,10,0,0,{0,0,0}}, {20,10,0,0,{0,0,0}}, {20,10,0,0,{0,0,0}}, {20,10,0,0,{0,0,0}},
   {20,10,0,1,{0,0,0}}, {20,10,0,1,{0,0,0}}, {20,10,0,1,{0,0,0}}, {20,10,0,1,{0,0,0}},
   {21,10,0,0,{0,0,0}}, {21,10,0,0,{0,0,0}}, {21,10,0,0,{0,0,0}}, {21,10,0,0,{0,0,0}},
   {21,10,0,1,{0,0,0}}, {21,10,0,1,{0,0,0}}, {21,10,0,1,{0,0,0}}, {21,10,0,1,{0,0,0}},
   {22,10,0,0,{0,0,0}}, {22,10,0,0,{0,0,0}}, {22,10,0,0,{0,0,0}}, {22,10,0,0,{0,0,0}},
   {22,10,0,1,{0,0,0}}, {22,10,0,1,{0,0,0}}, {22,10,0,1,{0,0,0}}, {22,10,0,1,{0,0,0}},
   {23,10,0,0,{0,0,0}}, {23,10,0,0,{0,0,0}}, {23,10,0,0,{0,0,0}}, {23,10,0,0,{0,0,0}},
   {23,10,0,1,{0,0,0}}, {23,10,0,1,{0,0,0}}, {23,10,0,1,{0,0,0}}, {23,10,0,1,{0,0,0}},
   {24,10,0,0,{0,0,0}}, {24,10,0,0,{0,0,0}}, {24,10,0,0,{0,0,0}}, {24,10,0,0,{0,0,0}},
   {24,10,0,1,{0,0,0}}, {24,10,0,1,{0,0,0}}, {24,10,0,1,{0,0,0}}, {24,10,0,1,{0,0,0}},
   {25,10,0,0,{0,0,0}}, {25,10,0,0,{0,0,0}}, {25,10,0,0,{0,0,0}}, {25,10,0,0,{0,0,0}},
   {25,10,0,1,{0,0,0}}, {25,10,0,1,{0,0,0}}, {25,10,0,1,{0,0,0}}, {25,10,0,1,{0,0,0}},
   {26,10,0,0,{0,0,0}}, {26,10,0,0,{0,0,0}}, {26,10,0,0,{0,0,0}}, {26,10,0,0,{0,0,0}},
   {26,10,0,1,{0,0,0}}, {26,10,0,1,{0,0,0}}, {26,10,0,1,{0,0,0}}, {26,10,0,1,{0,0,0}},
   {64,10,6,3,{0,0,0}}, {64,10,6,3,{0,0,0}}, {64,10,6,3,{0,0,0}}, {64,10,6,3,{0,0,0}},
   {128,10,7,3,{0,0,0}}, {128,10,7,3,{0,0,0}}, {128,10,7,3,{0,0,0}}, {128,10,7,3,{0,0,0}},
   {27,11,0,0,{0,0,0}}, {27,11,0,0,{0,0,0}}, {27,11,0,1,{0,0,0}}, {27,11,0,1,{0,0,0}},
   {28,11,0,0,{0,0,0}}, {28,11,0,0,{0,0,0}}, {28,11,0,1,{0,0,0}}, {28,11,0,1,{0,0,0}},
   {29,11,0,0,{0,0,0}}, {29,11,0,0,{0,0,0}}, {29,11,0,1,{0,0,0}}, {29,11,0,1,{0,0,0}},
   {30,11,0,0,{0,0,0}}, {30,11,0,0,{0,0,0}}, {30,11,0,1,{0,0,0}}, {30,11,0,1,{0,0,0}},
   {31,11,0,0,{0,0,0}}, {31,11,0,0,{0,0,0}}, {31,11,0,1,{0,0,0}}, {31,11,0,1,{0,0,0}},
   {32,11,0,0,{0,0,0}}, {32,11,0,0,{0,0,0}}, {32,11,0,1,{0,0,0}}, {32,11,0,1,{0,0,0}},
   {33,11,0,0,{0,0,0}}, {33,11,0,0,{0,0,0}}, {33,11,0,1,{0,0,0}}, {33,11,0,1,{0,0,0}},
   {34,11,0,0,{0,0,0}}, {34,11,0,0,{0,0,0}}, {34,11,0,1,{0,0,0}}, {34,11,0,1,{0,0,0}},
   {35,11,0,0,{0,0,0}}, {35,11,0,0,{0,0,0}}, {35,11,0,1,{0,0,0}}, {35,11,0,1,{0,0,0}},
   {36,11,0,0,{0,0,0}}, {36,11,0,0,{0,0,0}}, {36,11,0,1,{0,0,0}}, {36,11,0,1,{0,0,0}},
   {63,11,0,0,{0,0,0}}, {63,11,0,0,{0,0,0}}, {128,11,7,1,{0,0,0}}, {128,11,7,1,{0,0,0}},
   {256,11,8,3,{0,0,0}}, {256,11,8,3,{0,0,0}}, {37,12,0,0,{0,0,0}}, {37,12,0,1,{0,0,0}},
   {38,12,0,0,{0,0,0}}, {38,12,0,1,{0,0,0}}, {39,12,0,0,{0,0,0}}, {39,12,0,1,{0,0,0}},
   {40,12,0,0,{0,0,0}}, {40,12,0,1,{0,0,0}}, {41,12,0,0,{0,0,0}}, {41,12,0,1,{0,0,0}},
   {42,12,0,0,{0,0,0}}, {42,12,0,1,{0,0,0}}, {43,12,0,0,{0,0,0}}, {43,12,0,1,{0,0,0}},
   {44,12,0,0,{0,0,0}}, {44,12,0,1,{0,0,0}}, {45,12,0,0,{0,0,0}}, {45,12,0,1,{0,0,0}},
   {46,12,0,0,{0,0,0}}, {46,12,0,1,{0,0,0}}, {47,12,0,0,{0,0,0}}, {47,12,0,1,{0,0,0}},
   {48,12,0,0,{0,0,0}}, {48,12,0,1,{0,0,0}}, {49,12,0,0,{0,0,0}}, {49,12,0,1,{0,0,0}},
   {50,12,0,0,{0,0,0}}, {50,12,0,1,{0,0,0}}, {51,12,0,0,{0,0,0}}, {51,12,0,1,{0,0,0}},
   {52,12,0,0,{0,0,0}}, {52,12,0,1,{0,0,0}}, {53,12,0,0,{0,0,0}}, {53,12,0,1,{0,0,0}},
   {54,12,0,0,{0,0,0}}, {54,12,0,1,{0,0,0}}, {55,12,0,0,{0,0,0}}, {55,12,0,1,{0,0,0}},
   {56,12,0,0,{0,0,0}}, {56,12,0,1,{0,0,0}}, {57,12,0,0,{0,0,0}}, {57,12,0,1,{0,0,0}},
   {58,12,0,0,{0,0,0}}, {58,12,0,1,{0,0,0}}, {59,12,0,0,{0,0,0}}, {59,12,0,1,{0,0,0}},
   {60,12,0,0,{0,0,0}}, {60,12,0,1,{0,0,0}}, {61,12,0,0,{0,0,0}}, {61,12,0,1,{0,0,0}},
   {62,12,0,0,{0,0,0}}, {62,12,0,1,{0,0,0}}, {63,12,0,1,{0,0,0}}, {128,12,7,0,{0,0,0}},
   {512,12,9,3,{0,0,0}}, {1024,12,10,3,{0,0,0}}, {2048,12,11,3,{0,0,0}}, {4096,12,12,3,{0,0,0}},
   {8192,9,0,2,{0,0,0}}, {8192,9,0,2,{0,0,0}}, {8192,9,0,2,{0,0,0}}, {8192,9,0,2,{0,0,0}},
   {8192,9,0,2,{0,0,0}}, {8192,9,0,2,{0,0,0}}, {8192,9,0,2,{0,0,0}}, {8192,9,0,2,{0,0,0}},
   {32,9,5,3,{0,0,0}}, {32,9,5,3,{0,0,0}}, {32,9,5,3,{0,0,0}}, {32,9,5,3,{0,0,0}},
   {32,9,5,3,{0,0,0}}, {32,9,5,3,{0,0,0}}, {32,9,5,3,{0,0,0}}, {32,9,5,3,{0,0,0}},
};

static inline int med(int L, int T, int TL) {
   int mn = L < T ? L : T, mx = L > T ? L : T;
   int g = L + T - TL;
   g = g < mn ? mn : g;
   return g > mx ? mx : g;
}
static inline void to_ycocg(uint8_t *y, uint8_t *co, uint8_t *cg, int R, int G,
                     int B) {
   int c = (R - B) & 0xFF;
   int t = (B + ((int8_t)c >> 1)) & 0xFF;
   int g = (G - t) & 0xFF;
   *co = (uint8_t)c;
   *cg = (uint8_t)g;
   *y = (uint8_t)((t + ((int8_t)g >> 1)) & 0xFF);
}

#if defined(__SSE2__)
static __attribute__((noinline)) void ycocg_row_rgba(const uint8_t *Y, const uint8_t *Co,
                           const uint8_t *Cg, const uint8_t *A, uint8_t *out,
                           int w_) {
   const __m128i m7f = _mm_set1_epi8(0x7f);
   const __m128i m80 = _mm_set1_epi8((char)0x80);
   int x = 0;
   for (; x + 16 <= w_; x += 16) {
      __m128i y = _mm_loadu_si128((const __m128i *)(Y + x));
      __m128i co = _mm_loadu_si128((const __m128i *)(Co + x));
      __m128i cg = _mm_loadu_si128((const __m128i *)(Cg + x));
      __m128i a = _mm_loadu_si128((const __m128i *)(A + x));
      __m128i cgs = _mm_or_si128(_mm_and_si128(_mm_srli_epi16(cg, 1), m7f),
                                 _mm_and_si128(cg, m80));
      __m128i t = _mm_sub_epi8(y, cgs);
      __m128i g = _mm_add_epi8(cg, t);
      __m128i cos = _mm_or_si128(_mm_and_si128(_mm_srli_epi16(co, 1), m7f),
                                 _mm_and_si128(co, m80));
      __m128i b = _mm_sub_epi8(t, cos);
      __m128i r = _mm_add_epi8(b, co);

      __m128i rg0 = _mm_unpacklo_epi8(b, g);
      __m128i rg1 = _mm_unpackhi_epi8(b, g);
      __m128i ba0 = _mm_unpacklo_epi8(r, a);
      __m128i ba1 = _mm_unpackhi_epi8(r, a);
      _mm_storeu_si128((__m128i *)(out + x * 4 + 0),
                       _mm_unpacklo_epi16(rg0, ba0));
      _mm_storeu_si128((__m128i *)(out + x * 4 + 16),
                       _mm_unpackhi_epi16(rg0, ba0));
      _mm_storeu_si128((__m128i *)(out + x * 4 + 32),
                       _mm_unpacklo_epi16(rg1, ba1));
      _mm_storeu_si128((__m128i *)(out + x * 4 + 48),
                       _mm_unpackhi_epi16(rg1, ba1));
   }
   for (; x < w_; x++) {
      int t = (Y[x] - ((int8_t)Cg[x] >> 1)) & 0xFF;
      int g = (Cg[x] + t) & 0xFF;
      int b = (t - ((int8_t)Co[x] >> 1)) & 0xFF;
      out[x * 4 + P4_R] = (uint8_t)((b + Co[x]) & 0xFF);
      out[x * 4 + P4_G] = (uint8_t)g;
      out[x * 4 + P4_B] = (uint8_t)b;
      out[x * 4 + P4_X] = A[x];
   }
}
#endif

#if !defined(__SSE2__)
static inline void from_ycocg(int y, int co, int cg, uint8_t *R, uint8_t *G,
                       uint8_t *B) {
   int t = (y - ((int8_t)cg >> 1)) & 0xFF;
   int g = (cg + t) & 0xFF;
   int b = (t - ((int8_t)co >> 1)) & 0xFF;
   *R = (uint8_t)((b + co) & 0xFF);
   *G = (uint8_t)g;
   *B = (uint8_t)b;
}
#endif

typedef struct {
   uint8_t *buf;
   size_t cap, n;
   uint64_t acc;
   int nbits;
   int overflow;
} Bit_Writer;

static inline void bw_flush(Bit_Writer *w) {
   while (w->nbits >= 8) {
      w->nbits -= 8;
      if (w->n < w->cap) w->buf[w->n] = (uint8_t)(w->acc >> w->nbits);
      else w->overflow = 1;
      w->n++;
   }
   if (w->nbits) {
      if (w->n < w->cap) w->buf[w->n] = (uint8_t)(w->acc << (8 - w->nbits));
      else w->overflow = 1;
      w->n++;
      w->nbits = 0;
   }
}

typedef struct {
   const uint8_t *p, *end;
   uint64_t acc;
   int nbits;
   int pad;
   int bad;
} Bit_Reader;

static __attribute__((noinline)) void encode_row(Bit_Writer *w,
                                                 const int8_t *rc, int w_) {
   uint8_t *buf = w->buf;
   size_t cap = w->cap, n = w->n;
   uint64_t acc = w->acc;
   int nbits = w->nbits, ovf = w->overflow;
   int x = 0;

#define PUTC(cl_)                                                             \
   do {                                                                       \
      uint32_t p_ = (cl_);                                                    \
      PUT(p_ & 0xFFFF, (int)(p_ >> 16));                                      \
   } while (0)
#define PUT(code_, len_)                                                      \
   do {                                                                       \
      acc = (acc << (len_)) | (uint64_t)(code_);                              \
      nbits += (len_);                                                        \
      if (nbits >= 32) {                                                      \
         uint32_t v_ = __builtin_bswap32((uint32_t)(acc >> (nbits - 32)));    \
                       \
         if (n + 4 <= cap) memcpy(buf + n, &v_, 4);                           \
         else ovf = 1;                                                        \
         n += 4;                                                              \
         nbits -= 32;                                                         \
      }                                                                       \
   } while (0)

   while (x < w_) {
      int e = rc[x];
      if (e) {
         int a = e < 0 ? -e : e, tk;
         if (a <= TDIR) {
            tk = 2 * a - 1 + (e < 0);
            PUTC(ecl[tk]);
         } else {
            int ex = exp_of[a];
            tk = 2 * TDIR + 1 + 2 * (ex - KEXP) + (e < 0);
            PUTC(ecl[tk]);
            PUT((uint32_t)(a - (1 << ex)), ex);
         }
         x++;
         continue;
      }
      {

         int i = x + 1, run, j = 0;
         while (i + 8 <= w_) {
            uint64_t v;
            memcpy(&v, rc + i, 8);
            if (v) {
               i += __builtin_ctzll(v) >> 3;
               break;
            }
            i += 8;
         }
         while (i < w_ && rc[i] == 0) i++;
         run = i - x;
         if (x + run == w_) {
            PUTC(ecl[TOK_EOL]);
            x = w_;
            continue;
         }
         if (run == 1) {
            PUTC(ecl[0]);
            x++;
            continue;
         }
         if (run > 8191) run = 8191;
         while (run >> (j + 1)) j++;
         PUTC(ecl[TOK_RUN + j - 1]);
         PUT((uint32_t)(run - (1 << j)), j);
         x += run;
      }
   }
#undef PUT
#undef PUTC
   w->n = n;
   w->acc = acc;
   w->nbits = nbits;
   w->overflow = ovf;
}

#define BINBLK 64

static __attribute__((noinline)) int unpack_row(Bit_Reader *r, int8_t *rc,
                                                int w_) {
   const uint8_t *p = r->p, *end = r->end;
   uint64_t acc = r->acc;
   int nbits = r->nbits, pad = r->pad;
   int x = 0, ok = 1;

   memset(rc, 0, (size_t)w_);
   while (x < w_) {
      uint32_t idx, m;
      Dec_Entry d;
      if (nbits < 32) {
         if (p + 8 <= end) {
            int take = (64 - nbits) >> 3;
            uint64_t v;
            memcpy(&v, p, 8);
            v = __builtin_bswap64(v);
            acc |= v >> nbits;
            p += take;
            nbits += take << 3;
         } else {
            while (nbits <= 56) {
               uint64_t b = 0;
               if (p < end) {
                  b = *p++;
               } else if (++pad > 16) {
                  ok = 0;
                  break;
               }
               acc |= b << (56 - nbits);
               nbits += 8;
            }
            if (!ok) break;
         }
      }
      idx = (uint32_t)(acc >> 52);
      d = dtab[idx >> 4];
      if (!d.len) {
         d = dsub[(size_t)d.base * 16 + (idx & 15)];
         if (!d.len) { ok = 0; break; }
      }
      acc <<= d.len;
      nbits -= (int)d.len;
      m = (uint32_t)(((acc >> 32) >> (32 - d.nbits)) & mask_lut[d.nbits]);
      acc <<= d.nbits;
      nbits -= (int)d.nbits;
      {
         int v = d.base + (int)m;
         int isrun = d.kind >> 1;
         int neg = d.kind & 1;
         int adv, rem = w_ - x;
         int val = neg ? -v : v;
         val = isrun ? 0 : val;
         adv = isrun ? v : 1;
         if (adv > rem) adv = rem;
         if (adv <= 0) { ok = 0; break; }
         rc[x] = (int8_t)val;
         x += adv;
      }
   }
   r->p = p;
   r->acc = acc;
   r->nbits = nbits;
   r->pad = pad;
   if (!ok) r->bad = 1;
   return ok;
}

static __attribute__((noinline)) void reconstruct_row4(uint8_t *cur[4], const uint8_t *prv[4],
                             const int8_t *rc[4], int w_, int y) {
   if (!y) {
      for (int p = 0; p < 4; p++) {
         int acc = 0;
         for (int x = 0; x < w_; x++) {
            acc = (acc + rc[p][x]) & 0xFF;
            cur[p][x] = (uint8_t)acc;
         }
      }
      return;
   }
   for (int p = 0; p < 4; p++)
      cur[p][0] = (uint8_t)((prv[p][0] + rc[p][0]) & 0xFF);
   for (int x = 1; x < w_; x++) {
#define REC(P_)                                                               \
   do {                                                                       \
      int T_ = prv[P_][x], L_ = cur[P_][x - 1], TL_ = prv[P_][x - 1];         \
      int mn_ = L_ < T_ ? L_ : T_;                                            \
      int mx_ = L_ > T_ ? L_ : T_;                                            \
      int g_ = L_ + T_ - TL_;                                                 \
      g_ = g_ < mn_ ? mn_ : g_;                                               \
      g_ = g_ > mx_ ? mx_ : g_;                                               \
      cur[P_][x] = (uint8_t)((g_ + rc[P_][x]) & 0xFF);                        \
   } while (0)
      REC(0);
      REC(1);
      REC(2);
      REC(3);
#undef REC
   }
}

static inline void put32(uint8_t *p, uint32_t v) {
   p[0] = (uint8_t)v;
   p[1] = (uint8_t)(v >> 8);
   p[2] = (uint8_t)(v >> 16);
   p[3] = (uint8_t)(v >> 24);
}
static inline uint32_t get32(const uint8_t *p) {
   return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) |
          ((uint32_t)p[3] << 24);
}

static inline size_t bng_encode_scratch(int w, int h) {
   (void)h;
   return 12 * (size_t)w + 64;
}

static inline size_t bng_decode_scratch(int w, int h) {
   (void)h;
   return 16 * (size_t)w + 64;
}

static inline int bng_info(const uint8_t *file, size_t len, int *w, int *h) {
   if (len < P4_HEADER || memcmp(file, P4_MAGIC, 7)) return 0;
   if (file[7] != P4_VERSION) return 0;
   *w = (int)get32(file + 8);
   *h = (int)get32(file + 12);
   if (*w <= 0 || *h <= 0) return 0;
   if ((uint64_t)*w * (uint64_t)*h > PIC_MAX_PIXELS) return 0;
   return 1;
}

static inline size_t pic_encode_body(const uint8_t *px, int w, int h, size_t pitch,
                              uint8_t *buf, size_t cap, uint8_t *scratch) {
   Bit_Writer w4;
   uint8_t *sbuf = scratch;
   int8_t *rbuf = (int8_t *)(scratch + (size_t)w * 8 + 32);
   uint8_t *cur[4], *prv[4];
   memset(&w4, 0, sizeof w4);
   w4.buf = buf;
   w4.cap = cap;
   for (int pl = 0; pl < 4; pl++) {
      cur[pl] = sbuf + (size_t)pl * w;
      prv[pl] = sbuf + (size_t)(pl + 4) * w;
   }
      {

         for (int y = 0; y < h; y++) {
            const uint8_t *src = px + (size_t)y * pitch;
            for (int x = 0; x < w; x++) {
               to_ycocg(&cur[0][x], &cur[1][x], &cur[2][x], src[x * 4 + P4_R],
                        src[x * 4 + P4_G], src[x * 4 + P4_B]);
               cur[3][x] = src[x * 4 + P4_X];
            }
            for (int pl = 0; pl < 4; pl++) {
               const uint8_t *row = cur[pl], *prev = prv[pl];
               int8_t *rr = rbuf + (size_t)pl * w;
               if (!y) {
                  rr[0] = (int8_t)row[0];
                  for (int x = 1; x < w; x++)
                     rr[x] = (int8_t)((row[x] - row[x - 1]) & 0xFF);
               } else {
                  rr[0] = (int8_t)((row[0] - prev[0]) & 0xFF);
                  for (int x = 1; x < w; x++)
                     rr[x] = (int8_t)((row[x] - med(row[x - 1], prev[x],
                                                    prev[x - 1])) &
                                      0xFF);
               }
            }
            for (int pl = 0; pl < 4; pl++)
               encode_row(&w4, rbuf + (size_t)pl * w, w);
            for (int pl = 0; pl < 4; pl++) {
               uint8_t *t = cur[pl];
               cur[pl] = prv[pl];
               prv[pl] = t;
            }
         }
      }
   bw_flush(&w4);
   return w4.n;
}

static inline size_t bng_encode(const uint8_t *px, int w, int h, size_t pitch, uint8_t *out,
                  size_t out_cap, void *scratch, size_t scratch_len) {
   size_t n = (size_t)w * (size_t)h;
   size_t raw_bytes = 4 * n;
   size_t got;

   if (w <= 0 || h <= 0) return 0;
   if (pitch < (size_t)w * 4) return 0;
   if (out_cap < P4_HEADER + raw_bytes) return 0;
   if (scratch_len < bng_encode_scratch(w, h)) return 0;

   got = pic_encode_body(px, w, h, pitch, out + P4_HEADER, raw_bytes,
                         (uint8_t *)scratch);

   memcpy(out, P4_MAGIC, 7);
   out[7] = P4_VERSION;
   put32(out + 8, (uint32_t)w);
   put32(out + 12, (uint32_t)h);
   if (got >= raw_bytes) {
      for (int y = 0; y < h; y++)
         memcpy(out + P4_HEADER + (size_t)y * w * 4, px + (size_t)y * pitch,
                (size_t)w * 4);
      put32(out + 16, (uint32_t)(raw_bytes | P4_RAW_FLAG));
      return P4_HEADER + raw_bytes;
   }
   put32(out + 16, (uint32_t)got);
   return P4_HEADER + got;
}

static inline int bng_decode(const uint8_t *file, size_t len, uint8_t *out, size_t out_pitch,
               size_t out_cap, void *scratch, size_t scratch_len) {
   int w, h, raw;
   size_t n, stream_byte_count;
   Bit_Reader r;
   uint8_t *sp = (uint8_t *)scratch;

   if (!bng_info(file, len, &w, &h)) return 0;
   n = (size_t)w * (size_t)h;
   {
      uint32_t field = get32(file + 16);
      raw = (field & P4_RAW_FLAG) != 0;
      stream_byte_count = field & P4_COUNT_MASK;
   }

   if (stream_byte_count > len - P4_HEADER) return 0;
   len = P4_HEADER + stream_byte_count;
   if (out_pitch < (size_t)w * 4) return 0;
   if (out_cap < (size_t)(h - 1) * out_pitch + (size_t)w * 4) return 0;

   if (raw) {

      if (stream_byte_count != 4 * n) return 0;
      for (int y = 0; y < h; y++)
         memcpy(out + (size_t)y * out_pitch,
                file + P4_HEADER + (size_t)y * w * 4, (size_t)w * 4);
      return 1;
   }
   if (scratch_len < bng_decode_scratch(w, h)) return 0;
   if ((uint64_t)stream_byte_count * 8 < (uint64_t)h) return 0;

   memset(&r, 0, sizeof r);
   r.p = file + P4_HEADER;
   r.end = file + len;
   {

      int8_t *rbuf = (int8_t *)sp;
      uint8_t *sbuf = sp + (size_t)w * 8 + 32;
      int8_t *rc[4], *rp[4];
      uint8_t *cur[4], *prv[4];
      int fail = 0;
      for (int p = 0; p < 4; p++) {
         rc[p] = rbuf + (size_t)p * w;
         rp[p] = rbuf + (size_t)(p + 4) * w;
         cur[p] = sbuf + (size_t)p * w;
         prv[p] = sbuf + (size_t)(p + 4) * w;
      }
      memset(rbuf, 0, (size_t)w * 8);
      memset(sbuf, 0, (size_t)w * 8);
      for (int y = 0; y < h && !fail; y++) {
         uint8_t *o = out + (size_t)y * out_pitch;
         for (int p = 0; p < 4; p++)
            if (!unpack_row(&r, rc[p], w)) {
               fail = 1;
               break;
            }
         if (fail) break;
         reconstruct_row4(cur, (const uint8_t **)prv, (const int8_t **)rc, w,
                          y);
#if defined(__SSE2__)
         ycocg_row_rgba(cur[0], cur[1], cur[2], cur[3], o, w);
#else
         for (int x = 0; x < w; x++) {
            from_ycocg(cur[0][x], cur[1][x], cur[2][x], &o[x * 4 + P4_R],
                       &o[x * 4 + P4_G], &o[x * 4 + P4_B]);
            o[x * 4 + P4_X] = cur[3][x];
         }
#endif
         for (int p = 0; p < 4; p++) {
            int8_t *t = rc[p];
            uint8_t *u = cur[p];
            rc[p] = rp[p];
            rp[p] = t;
            cur[p] = prv[p];
            prv[p] = u;
         }
      }
      if (fail) return 0;
   }
   return 1;
}

#endif