// File: lvandeve[P]lodepng/lodepng_util.cpp
// Function: lodepng::convertFromXYZ_chrm(float*, float const*, unsigned int, unsigned int, LodePNGInfo const*, unsigned int, lodepng::LodePNGICC const*, float const*, unsigned int)
static unsigned convertFromXYZ_chrm(float* out, const float* in, unsigned w, unsigned h,
                                    const LodePNGInfo* info, unsigned use_icc, const LodePNGICC* icc,
                                    const float whitepoint[3], unsigned rendering_intent) {
  size_t i, n;

  float m[9]; /* XYZ to linear RGB matrix */
  float white[3]; /* The whitepoint (absolute) of the target RGB space */

  if(lodepng_mulofl((size_t)w, (size_t)h, &n)) return 92;

  if(getChrm(m, white, use_icc, icc, info)) return 1;
  if(invMatrix(m)) return 1; /* error, not invertible */

  /* for relative rendering intent (any except absolute "3"), must whitepoint adapt to the original whitepoint.
  this also ensures grayscale stays grayscale (with absolute, grayscale could become e.g. blue or sepia) */
  if(rendering_intent != 3) {
    float a[9] = {1,0,0, 0,1,0, 0,0,1};
    /* "white" = absolute whitepoint of the new target RGB space, read from the target color profile.
    "whitepoint" is original absolute whitepoint (input as parameter of this function) of an
    RGB space the XYZ data once had before it was converted to XYZ, in other words the whitepoint that
    we want to adapt our current data to to make sure values that had equal R==G==B in the old space have
    the same property now (white stays white and gray stays gray).
    Note: "absolute" whitepoint above means, can be used as-is, not needing further adaptation itself like icc.white does.*/
    if(getAdaptationMatrix(a, 1, whitepoint[0], whitepoint[1], whitepoint[2], white[0], white[1], white[2])) {
      return 1;
    }
    /* multiply the from xyz matrix with the adaptation matrix: in total,
    the resulting matrix first adapts in XYZ space, then converts to RGB*/
    mulMatrixMatrix(m, m, a);
  }

  /* Apply the above computed XYZ-to-linear-RGB matrix to the pixels.
  This transformation also includes the whitepoint adaptation. The transform
  can be skipped only if it's the unit matrix (only if grayscale profile and no
  whitepoint adaptation, such as with rendering intent 3)*/
  if(!use_icc || icc->inputspace == 2 || rendering_intent != 3) {
    for(i = 0; i < n; i++) {
      size_t j = i * 4;
      mulMatrix(&out[j + 0], &out[j + 1], &out[j + 2], m, in[j + 0], in[j + 1], in[j + 2]);
      out[j + 3] = in[j + 3];
    }
  } else {
    for(i = 0; i < n * 4; i++) {
      out[i] = in[i];
    }
  }

  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movl 0x20(%rbp), %eax
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movl %ecx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movl %r9d, -0x2c(%rbp)
movl -0x1c(%rbp), %eax
movl %eax, %edi
movl -0x20(%rbp), %eax
movl %eax, %esi
leaq -0x40(%rbp), %rdx
callq 0x1ef60
cmpl $0x0, %eax
je 0x1fe60
movl $0x5c, -0x4(%rbp)
jmp 0x20095
leaq -0x70(%rbp), %rdi
leaq -0x7c(%rbp), %rsi
movl -0x2c(%rbp), %edx
movq 0x10(%rbp), %rcx
movq -0x28(%rbp), %r8
callq 0x21940
cmpl $0x0, %eax
je 0x1fe89
movl $0x1, -0x4(%rbp)
jmp 0x20095
leaq -0x70(%rbp), %rdi
callq 0x22250
cmpl $0x0, %eax
je 0x1fea3
movl $0x1, -0x4(%rbp)
jmp 0x20095
cmpl $0x3, 0x20(%rbp)
je 0x1ff4c
leaq -0xa0(%rbp), %rdi
xorl %esi, %esi
movl $0x24, %edx
callq 0x3160
movss 0x92b2c(%rip), %xmm0    # 0xb29f4
movss %xmm0, -0xa0(%rbp)
movss 0x92b1c(%rip), %xmm0    # 0xb29f4
movss %xmm0, -0x90(%rbp)
movss 0x92b0c(%rip), %xmm0    # 0xb29f4
movss %xmm0, -0x80(%rbp)
leaq -0xa0(%rbp), %rdi
movq 0x18(%rbp), %rax
movss (%rax), %xmm0
movq 0x18(%rbp), %rax
movss 0x4(%rax), %xmm1
movq 0x18(%rbp), %rax
movss 0x8(%rax), %xmm2
movss -0x7c(%rbp), %xmm3
movss -0x78(%rbp), %xmm4
movss -0x74(%rbp), %xmm5
movl $0x1, %esi
callq 0x226e0
cmpl $0x0, %eax
je 0x1ff38
movl $0x1, -0x4(%rbp)
jmp 0x20095
leaq -0x70(%rbp), %rdi
leaq -0x70(%rbp), %rsi
leaq -0xa0(%rbp), %rdx
callq 0x22ac0
cmpl $0x0, -0x2c(%rbp)
je 0x1ff65
movq 0x10(%rbp), %rax
cmpl $0x2, (%rax)
je 0x1ff65
cmpl $0x3, 0x20(%rbp)
je 0x2004b
movq $0x0, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x40(%rbp), %rax
jae 0x20049
movq -0x38(%rbp), %rax
shlq $0x2, %rax
movq %rax, -0xa8(%rbp)
movq -0x10(%rbp), %rdi
movq -0xa8(%rbp), %rax
addq $0x0, %rax
shlq $0x2, %rax
addq %rax, %rdi
movq -0x10(%rbp), %rsi
movq -0xa8(%rbp), %rax
addq $0x1, %rax
shlq $0x2, %rax
addq %rax, %rsi
movq -0x10(%rbp), %rdx
movq -0xa8(%rbp), %rax
addq $0x2, %rax
shlq $0x2, %rax
addq %rax, %rdx
leaq -0x70(%rbp), %rcx
movq -0x18(%rbp), %rax
movq -0xa8(%rbp), %r8
movss (%rax,%r8,4), %xmm0
cvtss2sd %xmm0, %xmm0
movq -0x18(%rbp), %rax
movq -0xa8(%rbp), %r8
movss 0x4(%rax,%r8,4), %xmm1
cvtss2sd %xmm1, %xmm1
movq -0x18(%rbp), %rax
movq -0xa8(%rbp), %r8
movss 0x8(%rax,%r8,4), %xmm2
cvtss2sd %xmm2, %xmm2
callq 0x21b80
movq -0x18(%rbp), %rax
movq -0xa8(%rbp), %rcx
movss 0xc(%rax,%rcx,4), %xmm0
movq -0x10(%rbp), %rax
movq -0xa8(%rbp), %rcx
movss %xmm0, 0xc(%rax,%rcx,4)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x1ff6d
jmp 0x2008e
movq $0x0, -0x38(%rbp)
movq -0x38(%rbp), %rax
movq -0x40(%rbp), %rcx
shlq $0x2, %rcx
cmpq %rcx, %rax
jae 0x2008c
movq -0x18(%rbp), %rax
movq -0x38(%rbp), %rcx
movss (%rax,%rcx,4), %xmm0
movq -0x10(%rbp), %rax
movq -0x38(%rbp), %rcx
movss %xmm0, (%rax,%rcx,4)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x20053
jmp 0x2008e
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xb0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)