// File: cloudinary[P]fuif/transform/dct.h
// Function: fwd_DCT(Image&, std::vector<int, std::allocator<int>>&)
bool fwd_DCT(Image &input, std::vector<int> &parameters) {
    Image tmp=input; // TODO: implement without copy
    std::vector<int> adj_params = parameters; // use a copy so empty (default) parameters remain empty

    int beginc = input.nb_meta_channels + adj_params[0];
    int endc = input.nb_meta_channels + adj_params[1];
    int nb_channels = endc-beginc+1;
    int offset = input.channel.size();
    meta_DCT(input, adj_params);

    v_printf(3,"Doing DCT on channels %i..%i with AC coefficients in channels %i..%i\n",beginc,endc,offset,offset+63*nb_channels-1);

    std::vector<std::vector<int>> ordering;
    std::vector<int> comp;
    std::vector<int> coeff;
    default_DCT_scanscript(nb_channels,ordering,comp,coeff);

    float DCoffset = (input.maxval + 1.0) * 4.0;

    for (int c=beginc; c<offset+63*nb_channels; c++) {
            input.channel[c].resize();
    }
    for (int c=beginc; c<=endc; c++) {
        int bw=input.channel[c].w;
        int bh=input.channel[c].h;
        v_printf(3,"  Channel %i : %ix%i image to %ix%i blocks\n",c,tmp.channel[c].w,tmp.channel[c].h,bw,bh);
        for (int by=0; by<bh; by++) {
          for (int bx=0; bx<bw; bx++) {
            double block[64];
            for (int i=0; i<64; i++) block[i] = tmp.channel[c].repeating_edge_value(by*8+(i>>3),bx*8+(i&7));
            ComputeBlockDCTDouble(block);
            input.channel[c].value(by,bx) = round(block[0]) - DCoffset;
            for (int i=1; i<64; i++) input.channel[offset-nb_channels+ ordering[c-beginc][jpeg_zigzag[i]]].value(by,bx) = round(block[i]);
          }
        }
    }

    return true;
}

// Assembly:
subq $0x3e8, %rsp            # imm = 0x3E8
movq %rdi, 0x3e0(%rsp)
movq %rsi, 0x3d8(%rsp)
movq 0x3e0(%rsp), %rsi
leaq 0x328(%rsp), %rdi
callq 0x12880
movq 0x3d8(%rsp), %rsi
leaq 0x310(%rsp), %rdi
callq 0x4c50
jmp 0x92d3
movq 0x3e0(%rsp), %rax
movl 0x6c(%rax), %eax
movl %eax, 0x68(%rsp)
xorl %eax, %eax
movl %eax, %esi
leaq 0x310(%rsp), %rdi
movq %rdi, 0x70(%rsp)
callq 0x12190
movq 0x70(%rsp), %rdi
movq %rax, %rcx
movl 0x68(%rsp), %eax
movl (%rcx), %ecx
addl %ecx, %eax
movl %eax, 0x300(%rsp)
movq 0x3e0(%rsp), %rax
movl 0x6c(%rax), %eax
movl %eax, 0x6c(%rsp)
movl $0x1, %esi
callq 0x12190
movq %rax, %rcx
movl 0x6c(%rsp), %eax
movl (%rcx), %ecx
addl %ecx, %eax
movl %eax, 0x2fc(%rsp)
movl 0x2fc(%rsp), %eax
movl 0x300(%rsp), %ecx
subl %ecx, %eax
incl %eax
movl %eax, 0x2f8(%rsp)
movq 0x3e0(%rsp), %rdi
callq 0x4b80
movq 0x70(%rsp), %rsi
movl %eax, 0x2f4(%rsp)
movq 0x3e0(%rsp), %rdi
callq 0x8540
jmp 0x937b
movl 0x300(%rsp), %edx
movl 0x2fc(%rsp), %ecx
movl 0x2f4(%rsp), %r8d
movl 0x2f8(%rsp), %eax
movl %eax, %edi
shll $0x6, %edi
subl %eax, %edi
movl %r8d, %eax
movl %edi, %esi
leal -0x1(%rax,%rsi), %r9d
leaq 0x3d4db(%rip), %rsi     # 0x4688b
xorl %eax, %eax
movl $0x3, %edi
callq 0x3a770
jmp 0x93be
leaq 0x2d8(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0x125d0
leaq 0x2c0(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0x125e0
leaq 0x2a8(%rsp), %rdi
movq %rdi, 0x60(%rsp)
callq 0x125e0
movq 0x50(%rsp), %rsi
movq 0x58(%rsp), %rdx
movq 0x60(%rsp), %rcx
movl 0x2f8(%rsp), %edi
callq 0x8180
jmp 0x9411
movq 0x3e0(%rsp), %rax
cvtsi2sdl 0x60(%rax), %xmm0
movsd 0x3cdc2(%rip), %xmm1    # 0x461e8
addsd %xmm1, %xmm0
movsd 0x3cdae(%rip), %xmm1    # 0x461e0
mulsd %xmm1, %xmm0
cvtsd2ss %xmm0, %xmm0
movss %xmm0, 0x2a4(%rsp)
movl 0x300(%rsp), %eax
movl %eax, 0x2a0(%rsp)
movl 0x2a0(%rsp), %eax
movl 0x2f4(%rsp), %ecx
imull $0x3f, 0x2f8(%rsp), %edx
addl %edx, %ecx
cmpl %ecx, %eax
jge 0x9517
movq 0x3e0(%rsp), %rdi
movslq 0x2a0(%rsp), %rsi
callq 0x4ba0
movq %rax, %rdi
callq 0x129c0
jmp 0x9490
jmp 0x9492
movl 0x2a0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2a0(%rsp)
jmp 0x9451
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x308(%rsp)
movl %eax, 0x304(%rsp)
jmp 0x9895
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x308(%rsp)
movl %eax, 0x304(%rsp)
jmp 0x9888
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x308(%rsp)
movl %eax, 0x304(%rsp)
leaq 0x2a8(%rsp), %rdi
callq 0x54f0
leaq 0x2c0(%rsp), %rdi
callq 0x54f0
leaq 0x2d8(%rsp), %rdi
callq 0x126d0
jmp 0x9888
movl 0x300(%rsp), %eax
movl %eax, 0x29c(%rsp)
movl 0x29c(%rsp), %eax
cmpl 0x2fc(%rsp), %eax
jg 0x983b
movq 0x3e0(%rsp), %rdi
movslq 0x29c(%rsp), %rsi
callq 0x4ba0
movl 0x18(%rax), %eax
movl %eax, 0x298(%rsp)
movq 0x3e0(%rsp), %rdi
movslq 0x29c(%rsp), %rsi
callq 0x4ba0
movl 0x1c(%rax), %eax
movl %eax, 0x294(%rsp)
movl 0x29c(%rsp), %eax
movl %eax, 0x48(%rsp)
movslq %eax, %rsi
leaq 0x328(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x4ba0
movq 0x40(%rsp), %rdi
movl 0x18(%rax), %eax
movl %eax, 0x4c(%rsp)
movslq 0x29c(%rsp), %rsi
callq 0x4ba0
movl 0x48(%rsp), %edx
movl 0x4c(%rsp), %ecx
movl 0x1c(%rax), %r8d
movl 0x298(%rsp), %r9d
movl 0x294(%rsp), %esi
movq %rsp, %rax
movl %esi, (%rax)
leaq 0x3d2fa(%rip), %rsi     # 0x468d1
xorl %eax, %eax
movl $0x3, %edi
callq 0x3a770
jmp 0x95e5
movl $0x0, 0x290(%rsp)
movl 0x290(%rsp), %eax
cmpl 0x294(%rsp), %eax
jge 0x9823
movl $0x0, 0x28c(%rsp)
movl 0x28c(%rsp), %eax
cmpl 0x298(%rsp), %eax
jge 0x980b
movl $0x0, 0x7c(%rsp)
cmpl $0x40, 0x7c(%rsp)
jge 0x96a3
movslq 0x29c(%rsp), %rsi
leaq 0x328(%rsp), %rdi
callq 0x4ba0
movq %rax, %rdi
movl 0x290(%rsp), %eax
movl 0x7c(%rsp), %edx
movl %edx, %esi
sarl $0x3, %esi
movl %eax, %ecx
movl %esi, %eax
leal (%rax,%rcx,8), %esi
movl 0x28c(%rsp), %eax
andl $0x7, %edx
movl %eax, %ecx
movl %edx, %eax
leal (%rax,%rcx,8), %edx
callq 0x129f0
movw %ax, 0x3e(%rsp)
jmp 0x967e
movw 0x3e(%rsp), %ax
cwtl
cvtsi2sd %eax, %xmm0
movslq 0x7c(%rsp), %rax
movsd %xmm0, 0x80(%rsp,%rax,8)
movl 0x7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x7c(%rsp)
jmp 0x962b
leaq 0x80(%rsp), %rdi
callq 0x8140
jmp 0x96b2
movsd 0x80(%rsp), %xmm0
callq 0x3180
movss 0x2a4(%rsp), %xmm1
cvtss2sd %xmm1, %xmm1
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movw %ax, 0x2e(%rsp)
movq 0x3e0(%rsp), %rdi
movslq 0x29c(%rsp), %rsi
callq 0x4ba0
movq %rax, %rdi
movl 0x290(%rsp), %esi
movl 0x28c(%rsp), %edx
callq 0x12110
movq %rax, 0x30(%rsp)
jmp 0x970c
movq 0x30(%rsp), %rax
movw 0x2e(%rsp), %cx
movw %cx, (%rax)
movl $0x1, 0x78(%rsp)
cmpl $0x40, 0x78(%rsp)
jge 0x97f3
movslq 0x78(%rsp), %rax
movsd 0x80(%rsp,%rax,8), %xmm0
callq 0x3180
cvttsd2si %xmm0, %eax
movw %ax, 0xe(%rsp)
movq 0x3e0(%rsp), %rax
movq %rax, 0x10(%rsp)
movl 0x2f4(%rsp), %eax
movl 0x2f8(%rsp), %ecx
subl %ecx, %eax
movl %eax, 0x1c(%rsp)
movl 0x29c(%rsp), %eax
movl 0x300(%rsp), %ecx
subl %ecx, %eax
movslq %eax, %rsi
leaq 0x2d8(%rsp), %rdi
callq 0x12540
movq %rax, %rdi
movslq 0x78(%rsp), %rcx
leaq 0x3ccc8(%rip), %rax     # 0x46460
movslq (%rax,%rcx,4), %rsi
callq 0x12190
movq 0x10(%rsp), %rdi
movq %rax, %rcx
movl 0x1c(%rsp), %eax
movl (%rcx), %ecx
addl %ecx, %eax
movslq %eax, %rsi
callq 0x4ba0
movq %rax, %rdi
movl 0x290(%rsp), %esi
movl 0x28c(%rsp), %edx
callq 0x12110
movq %rax, 0x20(%rsp)
jmp 0x97d6
movq 0x20(%rsp), %rax
movw 0xe(%rsp), %cx
movw %cx, (%rax)
movl 0x78(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x78(%rsp)
jmp 0x9721
jmp 0x97f5
movl 0x28c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x28c(%rsp)
jmp 0x960f
jmp 0x980d
movl 0x290(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x290(%rsp)
jmp 0x95f0
jmp 0x9825
movl 0x29c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x29c(%rsp)
jmp 0x9525
leaq 0x2a8(%rsp), %rdi
callq 0x54f0
leaq 0x2c0(%rsp), %rdi
callq 0x54f0
leaq 0x2d8(%rsp), %rdi
callq 0x126d0
leaq 0x310(%rsp), %rdi
callq 0x54f0
leaq 0x328(%rsp), %rdi
callq 0x12ab0
movb $0x1, %al
andb $0x1, %al
addq $0x3e8, %rsp            # imm = 0x3E8
retq
leaq 0x310(%rsp), %rdi
callq 0x54f0
leaq 0x328(%rsp), %rdi
callq 0x12ab0
movq 0x308(%rsp), %rdi
callq 0x36a0
nop