// File: cloudinary[P]fuif/transform/palette.h
// Function: fwd_palette(Image&, std::vector<int, std::allocator<int>>&)
bool fwd_palette(Image &input, std::vector<int> &parameters) {
    assert(parameters.size() == 3);
    int begin_c = input.nb_meta_channels+parameters[0];
    int end_c = input.nb_meta_channels+parameters[1];
    int &nb_colors = parameters[2];
    int nb = end_c - begin_c + 1;

    int w = input.channel[begin_c].w;
    int h = input.channel[begin_c].h;

    v_printf(8,"Trying to represent channels %i-%i using at most a %i-color palette.\n",begin_c,end_c,nb_colors);
    std::set< std::vector<pixel_type> > candidate_palette;
    std::vector<pixel_type> color(nb);
    for (int y=0; y<h; y++) {
        for (int x=0; x<w; x++) {
            for (int c=0; c<nb; c++) color[c] = input.channel[begin_c+c].value(y,x);
            candidate_palette.insert(color);
            if (candidate_palette.size() > nb_colors) return false; // too many colors
        }
    }
    nb_colors = candidate_palette.size();
    v_printf(6,"Channels %i-%i can be represented using a %i-color palette.\n",begin_c,end_c,nb_colors);

    Channel pch(nb_colors,nb, 0, 1);
    pch.hshift = -1;
    int x=0;
    for (auto pcol : candidate_palette) {
        v_printf(9,"Color %i :  ",x);
        for (int i=0; i<nb; i++) pch.value(i,x) = pcol[i];
        for (int i=0; i<nb; i++) v_printf(9,"%i ", pcol[i]);
        v_printf(9,"\n");
        x++;
    }
    for (int y=0; y<h; y++) {
        for (int x=0; x<w; x++) {
            for (int c=0; c<nb; c++) color[c] = input.channel[begin_c+c].value(y,x);
            int index=0;
            for ( ; index<nb_colors ; index++ ) {
                bool found=true;
                for (int c=0; c<nb; c++) if (color[c] != pch.value(c,index)) {found = false; break;}
                if (found) break;
            }
            input.channel[begin_c].value(y,x) = index;
        }
    }
    input.nb_meta_channels++;
    input.nb_channels -= nb-1;
    input.channel.erase(input.channel.begin()+begin_c+1,input.channel.begin()+end_c+1);
    input.channel.insert(input.channel.begin(),pch);
    return true;
}

// Assembly:
subq $0x278, %rsp            # imm = 0x278
movq %rdi, 0x268(%rsp)
movq %rsi, 0x260(%rsp)
movq 0x268(%rsp), %rax
movl 0x6c(%rax), %eax
movl %eax, 0xac(%rsp)
movq 0x260(%rsp), %rdi
xorl %eax, %eax
movl %eax, 0xb4(%rsp)
movl %eax, %esi
callq 0x12190
movq %rax, %rcx
movl 0xac(%rsp), %eax
movl (%rcx), %ecx
addl %ecx, %eax
movl %eax, 0x25c(%rsp)
movq 0x268(%rsp), %rax
movl 0x6c(%rax), %eax
movl %eax, 0xb0(%rsp)
movq 0x260(%rsp), %rdi
movl $0x1, %esi
callq 0x12190
movq %rax, %rcx
movl 0xb0(%rsp), %eax
movl (%rcx), %ecx
addl %ecx, %eax
movl %eax, 0x258(%rsp)
movq 0x260(%rsp), %rdi
movl $0x2, %esi
callq 0x12190
movq %rax, 0x250(%rsp)
movl 0x258(%rsp), %eax
movl 0x25c(%rsp), %ecx
subl %ecx, %eax
incl %eax
movl %eax, 0x24c(%rsp)
movq 0x268(%rsp), %rdi
movslq 0x25c(%rsp), %rsi
callq 0x4ba0
movl 0x18(%rax), %eax
movl %eax, 0x248(%rsp)
movq 0x268(%rsp), %rdi
movslq 0x25c(%rsp), %rsi
callq 0x4ba0
movq %rax, %rcx
movl 0xb4(%rsp), %eax
movl 0x1c(%rcx), %ecx
movl %ecx, 0x244(%rsp)
movl 0x25c(%rsp), %edx
movl 0x258(%rsp), %ecx
movq 0x250(%rsp), %rsi
movl (%rsi), %r8d
leaq 0x3bcd2(%rip), %rsi     # 0x46a7c
movl $0x8, %edi
callq 0x3a770
leaq 0x210(%rsp), %rdi
callq 0x12e50
movslq 0x24c(%rsp), %rax
movq %rax, 0xb8(%rsp)
leaq 0x1f7(%rsp), %rdi
movq %rdi, 0xc0(%rsp)
callq 0x12e60
movq 0xb8(%rsp), %rsi
movq 0xc0(%rsp), %rdx
leaq 0x1f8(%rsp), %rdi
callq 0x12e70
jmp 0xae05
leaq 0x1f7(%rsp), %rdi
callq 0x12ef0
movl $0x0, 0x1e0(%rsp)
movl 0x1e0(%rsp), %eax
cmpl 0x244(%rsp), %eax
jge 0xafe0
movl $0x0, 0x1dc(%rsp)
movl 0x1dc(%rsp), %eax
cmpl 0x248(%rsp), %eax
jge 0xafc8
movl $0x0, 0x1d8(%rsp)
movl 0x1d8(%rsp), %eax
cmpl 0x24c(%rsp), %eax
jge 0xaf37
movq 0x268(%rsp), %rdi
movl 0x25c(%rsp), %eax
movl 0x1d8(%rsp), %ecx
addl %ecx, %eax
movslq %eax, %rsi
callq 0x4ba0
movq %rax, %rdi
movl 0x1e0(%rsp), %esi
movl 0x1dc(%rsp), %edx
callq 0x12110
movq %rax, 0xa0(%rsp)
jmp 0xaeaf
movq 0xa0(%rsp), %rax
movw (%rax), %ax
movw %ax, 0x9e(%rsp)
movslq 0x1d8(%rsp), %rsi
leaq 0x1f8(%rsp), %rdi
callq 0x4bc0
movw 0x9e(%rsp), %cx
movw %cx, (%rax)
movl 0x1d8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1d8(%rsp)
jmp 0xae5b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1e8(%rsp)
movl %eax, 0x1e4(%rsp)
leaq 0x1f7(%rsp), %rdi
callq 0x12ef0
jmp 0xb68d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1e8(%rsp)
movl %eax, 0x1e4(%rsp)
jmp 0xb680
leaq 0x210(%rsp), %rdi
leaq 0x1f8(%rsp), %rsi
callq 0x12f00
movb %dl, 0x8f(%rsp)
movq %rax, 0x90(%rsp)
jmp 0xaf5d
movb 0x8f(%rsp), %al
movq 0x90(%rsp), %rcx
movq %rcx, 0x1c8(%rsp)
movb %al, 0x1d0(%rsp)
leaq 0x210(%rsp), %rdi
callq 0x12f60
movq 0x250(%rsp), %rcx
movslq (%rcx), %rcx
cmpq %rcx, %rax
jbe 0xafb0
movb $0x0, 0x277(%rsp)
movl $0x1, 0x1c4(%rsp)
jmp 0xb655
jmp 0xafb2
movl 0x1dc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1dc(%rsp)
jmp 0xae3c
jmp 0xafca
movl 0x1e0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1e0(%rsp)
jmp 0xae1d
leaq 0x210(%rsp), %rdi
callq 0x12f60
movl %eax, %ecx
movq 0x250(%rsp), %rax
movl %ecx, (%rax)
movl 0x25c(%rsp), %edx
movl 0x258(%rsp), %ecx
movq 0x250(%rsp), %rax
movl (%rax), %r8d
leaq 0x3baa9(%rip), %rsi     # 0x46ac2
xorl %eax, %eax
movl $0x6, %edi
callq 0x3a770
jmp 0xb027
movq 0x250(%rsp), %rax
movl (%rax), %esi
movl 0x24c(%rsp), %edx
movq %rsp, %rax
movl $0x0, 0x18(%rax)
movl $0x0, 0x10(%rax)
movl $0x0, 0x8(%rax)
movl $0x0, (%rax)
leaq 0x180(%rsp), %rdi
xorl %ecx, %ecx
movl $0x1, %r9d
movl %r9d, %r8d
callq 0x12200
jmp 0xb070
movl $0xffffffff, 0x1ac(%rsp) # imm = 0xFFFFFFFF
movl $0x0, 0x17c(%rsp)
leaq 0x210(%rsp), %rax
movq %rax, 0x170(%rsp)
movq 0x170(%rsp), %rdi
callq 0x12f70
movq %rax, 0x168(%rsp)
movq 0x170(%rsp), %rdi
callq 0x12fa0
movq %rax, 0x160(%rsp)
leaq 0x168(%rsp), %rdi
leaq 0x160(%rsp), %rsi
callq 0x12fd0
testb $0x1, %al
jne 0xb0de
jmp 0xb27e
leaq 0x168(%rsp), %rdi
callq 0x12ff0
movq %rax, %rsi
leaq 0x148(%rsp), %rdi
callq 0x13010
jmp 0xb0fd
movl 0x17c(%rsp), %edx
leaq 0x3b9f4(%rip), %rsi     # 0x46aff
xorl %eax, %eax
movl $0x9, %edi
callq 0x3a770
jmp 0xb119
movl $0x0, 0x144(%rsp)
movl 0x144(%rsp), %eax
cmpl 0x24c(%rsp), %eax
jge 0xb1dc
movslq 0x144(%rsp), %rsi
leaq 0x148(%rsp), %rdi
callq 0x4bc0
movw (%rax), %ax
movw %ax, 0x7e(%rsp)
movl 0x144(%rsp), %esi
movl 0x17c(%rsp), %edx
leaq 0x180(%rsp), %rdi
callq 0x12110
movq %rax, 0x80(%rsp)
jmp 0xb17a
movq 0x80(%rsp), %rax
movw 0x7e(%rsp), %cx
movw %cx, (%rax)
movl 0x144(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x144(%rsp)
jmp 0xb124
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1e8(%rsp)
movl %eax, 0x1e4(%rsp)
jmp 0xb646
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1e8(%rsp)
movl %eax, 0x1e4(%rsp)
leaq 0x148(%rsp), %rdi
callq 0x13110
jmp 0xb646
movl $0x0, 0x140(%rsp)
movl 0x140(%rsp), %eax
cmpl 0x24c(%rsp), %eax
jge 0xb239
movslq 0x140(%rsp), %rsi
leaq 0x148(%rsp), %rdi
callq 0x4bc0
movswl (%rax), %edx
leaq 0x3b8f6(%rip), %rsi     # 0x46b0c
xorl %eax, %eax
movl $0x9, %edi
callq 0x3a770
jmp 0xb224
jmp 0xb226
movl 0x140(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x140(%rsp)
jmp 0xb1e7
leaq 0x3d66d(%rip), %rsi     # 0x488ad
xorl %eax, %eax
movl $0x9, %edi
callq 0x3a770
jmp 0xb24e
movl 0x17c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x17c(%rsp)
leaq 0x148(%rsp), %rdi
callq 0x13110
leaq 0x168(%rsp), %rdi
callq 0x13170
jmp 0xb0c0
movl $0x0, 0x13c(%rsp)
movl 0x13c(%rsp), %eax
cmpl 0x244(%rsp), %eax
jge 0xb4a4
movl $0x0, 0x138(%rsp)
movl 0x138(%rsp), %eax
cmpl 0x248(%rsp), %eax
jge 0xb48c
movl $0x0, 0x134(%rsp)
movl 0x134(%rsp), %eax
cmpl 0x24c(%rsp), %eax
jge 0xb354
movq 0x268(%rsp), %rdi
movl 0x25c(%rsp), %eax
movl 0x134(%rsp), %ecx
addl %ecx, %eax
movslq %eax, %rsi
callq 0x4ba0
movq %rax, %rdi
movl 0x13c(%rsp), %esi
movl 0x138(%rsp), %edx
callq 0x12110
movq %rax, 0x70(%rsp)
jmp 0xb314
movq 0x70(%rsp), %rax
movw (%rax), %ax
movw %ax, 0x6e(%rsp)
movslq 0x134(%rsp), %rsi
leaq 0x1f8(%rsp), %rdi
callq 0x4bc0
movw 0x6e(%rsp), %cx
movw %cx, (%rax)
movl 0x134(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x134(%rsp)
jmp 0xb2c7
movl $0x0, 0x130(%rsp)
movl 0x130(%rsp), %eax
movq 0x250(%rsp), %rcx
cmpl (%rcx), %eax
jge 0xb42a
movb $0x1, 0x12f(%rsp)
movl $0x0, 0x128(%rsp)
movl 0x128(%rsp), %eax
cmpl 0x24c(%rsp), %eax
jge 0xb406
movslq 0x128(%rsp), %rsi
leaq 0x1f8(%rsp), %rdi
callq 0x4bc0
movswl (%rax), %eax
movl %eax, 0x5c(%rsp)
movl 0x128(%rsp), %esi
movl 0x130(%rsp), %edx
leaq 0x180(%rsp), %rdi
callq 0x12110
movq %rax, 0x60(%rsp)
jmp 0xb3d7
movl 0x5c(%rsp), %eax
movq 0x60(%rsp), %rcx
movswl (%rcx), %ecx
cmpl %ecx, %eax
je 0xb3f1
movb $0x0, 0x12f(%rsp)
jmp 0xb406
jmp 0xb3f3
movl 0x128(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x128(%rsp)
jmp 0xb389
testb $0x1, 0x12f(%rsp)
je 0xb412
jmp 0xb42a
jmp 0xb414
movl 0x130(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x130(%rsp)
jmp 0xb35f
movw 0x130(%rsp), %ax
movw %ax, 0x4e(%rsp)
movq 0x268(%rsp), %rdi
movslq 0x25c(%rsp), %rsi
callq 0x4ba0
movq %rax, %rdi
movl 0x13c(%rsp), %esi
movl 0x138(%rsp), %edx
callq 0x12110
movq %rax, 0x50(%rsp)
jmp 0xb469
movq 0x50(%rsp), %rax
movw 0x4e(%rsp), %cx
movw %cx, (%rax)
movl 0x138(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x138(%rsp)
jmp 0xb2a8
jmp 0xb48e
movl 0x13c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x13c(%rsp)
jmp 0xb289
movq 0x268(%rsp), %rax
movl 0x6c(%rax), %ecx
incl %ecx
movl %ecx, 0x6c(%rax)
movl 0x24c(%rsp), %edx
movq 0x268(%rsp), %rax
movl 0x64(%rax), %ecx
subl %edx, %ecx
incl %ecx
movl %ecx, 0x64(%rax)
movq 0x268(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x127d0
movq %rax, 0x108(%rsp)
movslq 0x25c(%rsp), %rsi
leaq 0x108(%rsp), %rdi
callq 0x12800
movq %rax, 0x110(%rsp)
leaq 0x110(%rsp), %rdi
movl $0x1, %esi
movq %rsi, 0x30(%rsp)
callq 0x12800
movq %rax, 0x118(%rsp)
leaq 0x120(%rsp), %rdi
leaq 0x118(%rsp), %rsi
callq 0x12840
movq 0x268(%rsp), %rdi
callq 0x127d0
movq %rax, 0xe8(%rsp)
movslq 0x258(%rsp), %rsi
leaq 0xe8(%rsp), %rdi
callq 0x12800
movq 0x30(%rsp), %rsi
movq %rax, 0xf0(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x12800
movq %rax, 0xf8(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0x12840
movq 0x38(%rsp), %rdi
movq 0x120(%rsp), %rsi
movq 0x100(%rsp), %rdx
callq 0x12730
movq %rax, 0x40(%rsp)
jmp 0xb5ba
movq 0x40(%rsp), %rax
movq %rax, 0xe0(%rsp)
movq 0x268(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x127d0
movq %rax, 0xd0(%rsp)
leaq 0xd8(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x12840
movq 0x20(%rsp), %rdi
movq 0xd8(%rsp), %rsi
leaq 0x180(%rsp), %rdx
callq 0x12c20
movq %rax, 0x28(%rsp)
jmp 0xb617
movq 0x28(%rsp), %rax
movq %rax, 0xc8(%rsp)
movb $0x1, 0x277(%rsp)
movl $0x1, 0x1c4(%rsp)
leaq 0x180(%rsp), %rdi
callq 0x12380
jmp 0xb655
leaq 0x180(%rsp), %rdi
callq 0x12380
jmp 0xb680
leaq 0x1f8(%rsp), %rdi
callq 0x13110
leaq 0x210(%rsp), %rdi
callq 0x131a0
movb 0x277(%rsp), %al
andb $0x1, %al
addq $0x278, %rsp            # imm = 0x278
retq
leaq 0x1f8(%rsp), %rdi
callq 0x13110
leaq 0x210(%rsp), %rdi
callq 0x131a0
movq 0x1e8(%rsp), %rdi
callq 0x36a0
nopw (%rax,%rax)