// File: mhe[P]raytracerframework_cpp/lodepng.cpp
// Function: LodePNG_encode(LodePNG_Encoder*, unsigned char**, unsigned long*, unsigned char const*, unsigned int, unsigned int)
void LodePNG_encode(LodePNG_Encoder* encoder, unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h)
{
  LodePNG_InfoPng info;
  ucvector outv;
  unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/
  size_t datasize = 0;
  
  /*provide some proper output values if error will happen*/
  *out = 0;
  *outsize = 0;
  encoder->error = 0;
  
  info = encoder->infoPng; /*UNSAFE copy to avoid having to cleanup! but we will only change primitive parameters, and not invoke the cleanup function nor touch the palette's buffer so we use it safely*/
  info.width = w;
  info.height = h;
  
  if(encoder->settings.autoLeaveOutAlphaChannel && isFullyOpaque(image, w, h, &encoder->infoRaw.color))
  {
    /*go to a color type without alpha channel*/
    if(info.color.colorType == 6) info.color.colorType = 2;
    else if(info.color.colorType == 4) info.color.colorType = 0;
  }
  
  if(encoder->settings.zlibsettings.windowSize > 32768) { encoder->error = 60; return; } /*error: windowsize larger than allowed*/
  if(encoder->settings.zlibsettings.btype > 2) { encoder->error = 61; return; } /*error: unexisting btype*/
  if(encoder->infoPng.interlaceMethod > 1) { encoder->error = 71; return; } /*error: unexisting interlace mode*/
  if((encoder->error = checkColorValidity(info.color.colorType, info.color.bitDepth))) return; /*error: unexisting color type given*/
  if((encoder->error = checkColorValidity(encoder->infoRaw.color.colorType, encoder->infoRaw.color.bitDepth))) return; /*error: unexisting color type given*/
  
  if(!LodePNG_InfoColor_equal(&encoder->infoRaw.color, &info.color))
  {
    unsigned char* converted;
    size_t size = (w * h * LodePNG_InfoColor_getBpp(&info.color) + 7) / 8;
    
    if((info.color.colorType != 6 && info.color.colorType != 2) || (info.color.bitDepth != 8)) { encoder->error = 59; return; } /*for the output image, only these types are supported*/
    converted = (unsigned char*)malloc(size);
    if(!converted && size) encoder->error = 9955; /*error: malloc failed*/
    if(!encoder->error) encoder->error = LodePNG_convert(converted, image, &info.color, &encoder->infoRaw.color, w, h);
    if(!encoder->error) preProcessScanlines(&data, &datasize, converted, &info);/*filter(data.data, converted.data, w, h, LodePNG_InfoColor_getBpp(&info.color));*/
    free(converted);
  }
  else preProcessScanlines(&data, &datasize, image, &info);/*filter(data.data, image, w, h, LodePNG_InfoColor_getBpp(&info.color));*/
  
  ucvector_init(&outv);
  while(!encoder->error) /*not really a while loop, this is only used to break out if an error happens to avoid goto's to do the ucvector cleanup*/
  {
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
    size_t i;
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
    /*write signature and chunks*/
    writeSignature(&outv);
    /*IHDR*/
    addChunk_IHDR(&outv, w, h, info.color.bitDepth, info.color.colorType, info.interlaceMethod);
#ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS
    /*unknown chunks between IHDR and PLTE*/
    if(info.unknown_chunks.data[0]) { encoder->error = addUnknownChunks(&outv, info.unknown_chunks.data[0], info.unknown_chunks.datasize[0]); if(encoder->error) break; }
#endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/
    /*PLTE*/
    if(info.color.colorType == 3)
    {
      if(info.color.palettesize == 0 || info.color.palettesize > 256) { encoder->error = 68; break; }
      addChunk_PLTE(&outv, &info.color);
    }
    if(encoder->settings.force_palette && (info.color.colorType == 2 || info.color.colorType == 6))
    {
      if(info.color.palettesize == 0 || info.color.palettesize > 256) { encoder->error = 68; break; }
      addChunk_PLTE(&outv, &info.color);
    }
    /*tRNS*/
    if(info.color.colorType == 3 && !isPaletteFullyOpaque(info.color.palette, info.color.palettesize)) addChunk_tRNS(&outv, &info.color);
    if((info.color.colorType == 0 || info.color.colorType == 2) && info.color.key_defined) addChunk_tRNS(&outv, &info.color);
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
    /*bKGD (must come between PLTE and the IDAt chunks*/
    if(info.background_defined) addChunk_bKGD(&outv, &info);
    /*pHYs (must come before the IDAT chunks)*/
    if(info.phys_defined) addChunk_pHYs(&outv, &info);
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
#ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS
    /*unknown chunks between PLTE and IDAT*/
    if(info.unknown_chunks.data[1]) { encoder->error = addUnknownChunks(&outv, info.unknown_chunks.data[1], info.unknown_chunks.datasize[1]); if(encoder->error) break; }
#endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/
    /*IDAT (multiple IDAT chunks must be consecutive)*/
    encoder->error = addChunk_IDAT(&outv, data, datasize, &encoder->settings.zlibsettings);
    if(encoder->error) break;
#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS
    /*tIME*/
    if(info.time_defined) addChunk_tIME(&outv, &info.time);
    /*tEXt and/or zTXt*/
    for(i = 0; i < info.text.num; i++)
    {
      if(strlen(info.text.keys[i]) > 79) { encoder->error = 66; break; }
      if(strlen(info.text.keys[i]) < 1) { encoder->error = 67; break; }
      if(encoder->settings.text_compression)
        addChunk_zTXt(&outv, info.text.keys[i], info.text.strings[i], &encoder->settings.zlibsettings);
      else
        addChunk_tEXt(&outv, info.text.keys[i], info.text.strings[i]);
    }
    /*LodePNG version id in text chunk*/
    if(encoder->settings.add_id)
    {
      unsigned alread_added_id_text = 0;
      for(i = 0; i < info.text.num; i++)
        if(!strcmp(info.text.keys[i], "LodePNG")) { alread_added_id_text = 1; break; }
      if(alread_added_id_text == 0)
        addChunk_tEXt(&outv, "LodePNG", VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/
    }
    /*iTXt*/
    for(i = 0; i < info.itext.num; i++)
    {
      if(strlen(info.itext.keys[i]) > 79) { encoder->error = 66; break; }
      if(strlen(info.itext.keys[i]) < 1) { encoder->error = 67; break; }
      addChunk_iTXt(&outv, encoder->settings.text_compression,
                    info.itext.keys[i], info.itext.langtags[i], info.itext.transkeys[i], info.itext.strings[i], 
                    &encoder->settings.zlibsettings);
    }
#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/
#ifdef LODEPNG_COMPILE_UNKNOWN_CHUNKS
    /*unknown chunks between IDAT and IEND*/
    if(info.unknown_chunks.data[2]) { encoder->error = addUnknownChunks(&outv, info.unknown_chunks.data[2], info.unknown_chunks.datasize[2]); if(encoder->error) break; }
#endif /*LODEPNG_COMPILE_UNKNOWN_CHUNKS*/
    /*IEND*/
    addChunk_IEND(&outv);
    
    break; /*this isn't really a while loop; no error happened so break out now!*/
  }
  
  free(data);
  /*instead of cleaning the vector up, give it to the output*/
  *out = outv.data;
  *outsize = outv.size;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x160, %rsp            # imm = 0x160
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
movl %r9d, -0x28(%rbp)
movq $0x0, -0x128(%rbp)
movq $0x0, -0x130(%rbp)
movq -0x10(%rbp), %rax
movq $0x0, (%rax)
movq -0x18(%rbp), %rax
movq $0x0, (%rax)
movq -0x8(%rbp), %rax
movl $0x0, 0x128(%rax)
movq -0x8(%rbp), %rsi
addq $0x20, %rsi
leaq -0x108(%rbp), %rdi
movl $0xe0, %edx
callq 0x5320
movl -0x24(%rbp), %eax
movl %eax, -0x108(%rbp)
movl -0x28(%rbp), %eax
movl %eax, -0x104(%rbp)
movq -0x8(%rbp), %rax
cmpl $0x0, 0xc(%rax)
je 0x29e0d
movq -0x20(%rbp), %rdi
movl -0x24(%rbp), %esi
movl -0x28(%rbp), %edx
movq -0x8(%rbp), %rcx
addq $0x100, %rcx            # imm = 0x100
callq 0x2a5a0
cmpl $0x0, %eax
je 0x29e0d
cmpl $0x6, -0xf0(%rbp)
jne 0x29df6
movl $0x2, -0xf0(%rbp)
jmp 0x29e0b
cmpl $0x4, -0xf0(%rbp)
jne 0x29e09
movl $0x0, -0xf0(%rbp)
jmp 0x29e0b
jmp 0x29e0d
movq -0x8(%rbp), %rax
cmpl $0x8000, 0x8(%rax)      # imm = 0x8000
jbe 0x29e2d
movq -0x8(%rbp), %rax
movl $0x3c, 0x128(%rax)
jmp 0x2a58a
movq -0x8(%rbp), %rax
cmpl $0x2, (%rax)
jbe 0x29e49
movq -0x8(%rbp), %rax
movl $0x3d, 0x128(%rax)
jmp 0x2a58a
movq -0x8(%rbp), %rax
cmpl $0x1, 0x30(%rax)
jbe 0x29e66
movq -0x8(%rbp), %rax
movl $0x47, 0x128(%rax)
jmp 0x2a58a
movl -0xf0(%rbp), %edi
movl -0xec(%rbp), %esi
callq 0x281b0
movq -0x8(%rbp), %rcx
movl %eax, 0x128(%rcx)
cmpl $0x0, %eax
je 0x29e8b
jmp 0x2a58a
movq -0x8(%rbp), %rax
movl 0x100(%rax), %edi
movq -0x8(%rbp), %rax
movl 0x104(%rax), %esi
callq 0x281b0
movq -0x8(%rbp), %rcx
movl %eax, 0x128(%rcx)
cmpl $0x0, %eax
je 0x29eb8
jmp 0x2a58a
movq -0x8(%rbp), %rdi
addq $0x100, %rdi            # imm = 0x100
leaq -0x108(%rbp), %rsi
addq $0x18, %rsi
callq 0x26350
cmpl $0x0, %eax
jne 0x29ff9
movl -0x24(%rbp), %eax
imull -0x28(%rbp), %eax
movl %eax, -0x150(%rbp)
leaq -0x108(%rbp), %rdi
addq $0x18, %rdi
callq 0x26220
movl %eax, %ecx
movl -0x150(%rbp), %eax
imull %ecx, %eax
addl $0x7, %eax
shrl $0x3, %eax
movl %eax, %eax
movq %rax, -0x140(%rbp)
cmpl $0x6, -0xf0(%rbp)
je 0x29f25
cmpl $0x2, -0xf0(%rbp)
jne 0x29f2e
cmpl $0x8, -0xec(%rbp)
je 0x29f41
movq -0x8(%rbp), %rax
movl $0x3b, 0x128(%rax)
jmp 0x2a58a
movq -0x140(%rbp), %rdi
callq 0x5570
movq %rax, -0x138(%rbp)
cmpq $0x0, -0x138(%rbp)
jne 0x29f76
cmpq $0x0, -0x140(%rbp)
je 0x29f76
movq -0x8(%rbp), %rax
movl $0x26e3, 0x128(%rax)    # imm = 0x26E3
movq -0x8(%rbp), %rax
cmpl $0x0, 0x128(%rax)
jne 0x29fbd
movq -0x138(%rbp), %rdi
movq -0x20(%rbp), %rsi
leaq -0x108(%rbp), %rdx
addq $0x18, %rdx
movq -0x8(%rbp), %rcx
addq $0x100, %rcx            # imm = 0x100
movl -0x24(%rbp), %r8d
movl -0x28(%rbp), %r9d
callq 0x27130
movl %eax, %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x128(%rax)
movq -0x8(%rbp), %rax
cmpl $0x0, 0x128(%rax)
jne 0x29feb
movq -0x138(%rbp), %rdx
leaq -0x128(%rbp), %rdi
leaq -0x130(%rbp), %rsi
leaq -0x108(%rbp), %rcx
callq 0x2a780
movq -0x138(%rbp), %rdi
callq 0x54b0
jmp 0x2a017
movq -0x20(%rbp), %rdx
leaq -0x128(%rbp), %rdi
leaq -0x130(%rbp), %rsi
leaq -0x108(%rbp), %rcx
callq 0x2a780
leaq -0x120(%rbp), %rdi
callq 0x25960
movq -0x8(%rbp), %rax
cmpl $0x0, 0x128(%rax)
setne %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x2a03c
jmp 0x2a562
leaq -0x120(%rbp), %rdi
callq 0x2abb0
movl -0x24(%rbp), %esi
movl -0x28(%rbp), %edx
movl -0xec(%rbp), %ecx
movl -0xf0(%rbp), %r8d
movl -0xf8(%rbp), %r9d
leaq -0x120(%rbp), %rdi
callq 0x2ac40
cmpq $0x0, -0x58(%rbp)
je 0x2a0a9
movq -0x58(%rbp), %rsi
movq -0x40(%rbp), %rdx
leaq -0x120(%rbp), %rdi
callq 0x2ad00
movl %eax, %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x128(%rax)
movq -0x8(%rbp), %rax
cmpl $0x0, 0x128(%rax)
je 0x2a0a7
jmp 0x2a562
jmp 0x2a0a9
cmpl $0x3, -0xf0(%rbp)
jne 0x2a0f3
cmpq $0x0, -0xe0(%rbp)
je 0x2a0c9
cmpq $0x100, -0xe0(%rbp) # imm = 0x100
jbe 0x2a0dc
movq -0x8(%rbp), %rax
movl $0x44, 0x128(%rax)
jmp 0x2a562
leaq -0x108(%rbp), %rsi
addq $0x18, %rsi
leaq -0x120(%rbp), %rdi
callq 0x2ad90
movq -0x8(%rbp), %rax
cmpl $0x0, 0x10(%rax)
je 0x2a150
cmpl $0x2, -0xf0(%rbp)
je 0x2a10f
cmpl $0x6, -0xf0(%rbp)
jne 0x2a150
cmpq $0x0, -0xe0(%rbp)
je 0x2a126
cmpq $0x100, -0xe0(%rbp) # imm = 0x100
jbe 0x2a139
movq -0x8(%rbp), %rax
movl $0x44, 0x128(%rax)
jmp 0x2a562
leaq -0x108(%rbp), %rsi
addq $0x18, %rsi
leaq -0x120(%rbp), %rdi
callq 0x2ad90
cmpl $0x3, -0xf0(%rbp)
jne 0x2a188
movq -0xe8(%rbp), %rdi
movq -0xe0(%rbp), %rsi
callq 0x2ae40
cmpl $0x0, %eax
jne 0x2a188
leaq -0x108(%rbp), %rsi
addq $0x18, %rsi
leaq -0x120(%rbp), %rdi
callq 0x2aea0
cmpl $0x0, -0xf0(%rbp)
je 0x2a19a
cmpl $0x2, -0xf0(%rbp)
jne 0x2a1ba
cmpl $0x0, -0xd8(%rbp)
je 0x2a1ba
leaq -0x108(%rbp), %rsi
addq $0x18, %rsi
leaq -0x120(%rbp), %rdi
callq 0x2aea0
cmpl $0x0, -0xc8(%rbp)
je 0x2a1d6
leaq -0x120(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x2b030
cmpl $0x0, -0x68(%rbp)
je 0x2a1ef
leaq -0x120(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0x2b190
cmpq $0x0, -0x50(%rbp)
je 0x2a22a
movq -0x50(%rbp), %rsi
movq -0x38(%rbp), %rdx
leaq -0x120(%rbp), %rdi
callq 0x2ad00
movl %eax, %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x128(%rax)
movq -0x8(%rbp), %rax
cmpl $0x0, 0x128(%rax)
je 0x2a228
jmp 0x2a562
jmp 0x2a22a
movq -0x128(%rbp), %rsi
movq -0x130(%rbp), %rdx
movq -0x8(%rbp), %rcx
leaq -0x120(%rbp), %rdi
callq 0x2b220
movl %eax, %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x128(%rax)
movq -0x8(%rbp), %rax
cmpl $0x0, 0x128(%rax)
je 0x2a266
jmp 0x2a562
cmpb $0x0, -0x78(%rbp)
je 0x2a286
leaq -0x108(%rbp), %rsi
addq $0x94, %rsi
leaq -0x120(%rbp), %rdi
callq 0x2b2a0
movq $0x0, -0x148(%rbp)
movq -0x148(%rbp), %rax
cmpq -0xb8(%rbp), %rax
jae 0x2a38e
movq -0xb0(%rbp), %rax
movq -0x148(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x5180
cmpq $0x4f, %rax
jbe 0x2a2d5
movq -0x8(%rbp), %rax
movl $0x42, 0x128(%rax)
jmp 0x2a38e
movq -0xb0(%rbp), %rax
movq -0x148(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x5180
cmpq $0x1, %rax
jae 0x2a305
movq -0x8(%rbp), %rax
movl $0x43, 0x128(%rax)
jmp 0x2a38e
movq -0x8(%rbp), %rax
cmpl $0x0, 0x18(%rax)
je 0x2a345
movq -0xb0(%rbp), %rax
movq -0x148(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
movq -0xa8(%rbp), %rax
movq -0x148(%rbp), %rcx
movq (%rax,%rcx,8), %rdx
movq -0x8(%rbp), %rcx
leaq -0x120(%rbp), %rdi
callq 0x2b380
jmp 0x2a375
movq -0xb0(%rbp), %rax
movq -0x148(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
movq -0xa8(%rbp), %rax
movq -0x148(%rbp), %rcx
movq (%rax,%rcx,8), %rdx
leaq -0x120(%rbp), %rdi
callq 0x2b4b0
jmp 0x2a377
movq -0x148(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x148(%rbp)
jmp 0x2a291
movq -0x8(%rbp), %rax
cmpl $0x0, 0x14(%rax)
je 0x2a42b
movl $0x0, -0x14c(%rbp)
movq $0x0, -0x148(%rbp)
movq -0x148(%rbp), %rax
cmpq -0xb8(%rbp), %rax
jae 0x2a406
movq -0xb0(%rbp), %rax
movq -0x148(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x21762(%rip), %rsi     # 0x4bb3c
callq 0x55c0
cmpl $0x0, %eax
jne 0x2a3f0
movl $0x1, -0x14c(%rbp)
jmp 0x2a406
jmp 0x2a3f2
movq -0x148(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x148(%rbp)
jmp 0x2a3b1
cmpl $0x0, -0x14c(%rbp)
jne 0x2a429
leaq -0x120(%rbp), %rdi
leaq 0x2171f(%rip), %rsi     # 0x4bb3c
leaq 0x21720(%rip), %rdx     # 0x4bb44
callq 0x2b4b0
jmp 0x2a42b
movq $0x0, -0x148(%rbp)
movq -0x148(%rbp), %rax
cmpq -0xa0(%rbp), %rax
jae 0x2a51e
movq -0x98(%rbp), %rax
movq -0x148(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x5180
cmpq $0x4f, %rax
jbe 0x2a47a
movq -0x8(%rbp), %rax
movl $0x42, 0x128(%rax)
jmp 0x2a51e
movq -0x98(%rbp), %rax
movq -0x148(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x5180
cmpq $0x1, %rax
jae 0x2a4a7
movq -0x8(%rbp), %rax
movl $0x43, 0x128(%rax)
jmp 0x2a51e
movq -0x8(%rbp), %rax
movl 0x18(%rax), %esi
movq -0x98(%rbp), %rax
movq -0x148(%rbp), %rcx
movq (%rax,%rcx,8), %rdx
movq -0x90(%rbp), %rax
movq -0x148(%rbp), %rcx
movq (%rax,%rcx,8), %rcx
movq -0x88(%rbp), %rax
movq -0x148(%rbp), %rdi
movq (%rax,%rdi,8), %r8
movq -0x80(%rbp), %rax
movq -0x148(%rbp), %rdi
movq (%rax,%rdi,8), %r9
movq -0x8(%rbp), %rax
leaq -0x120(%rbp), %rdi
movq %rax, (%rsp)
callq 0x2b590
movq -0x148(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x148(%rbp)
jmp 0x2a436
cmpq $0x0, -0x48(%rbp)
je 0x2a556
movq -0x48(%rbp), %rsi
movq -0x30(%rbp), %rdx
leaq -0x120(%rbp), %rdi
callq 0x2ad00
movl %eax, %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x128(%rax)
movq -0x8(%rbp), %rax
cmpl $0x0, 0x128(%rax)
je 0x2a554
jmp 0x2a562
jmp 0x2a556
leaq -0x120(%rbp), %rdi
callq 0x2b800
movq -0x128(%rbp), %rdi
callq 0x54b0
movq -0x120(%rbp), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
movq -0x118(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
addq $0x160, %rsp            # imm = 0x160
popq %rbp
retq
nopw %cs:(%rax,%rax)