// File: manikandan5[P]Image-Matching-Stitching-Warping/./CImg.h
// Function: cimg_library::CImg<double>::_save_jpeg(_IO_FILE*, char const*, unsigned int) const
const CImg<T>& _save_jpeg(std::FILE *const file, const char *const filename, const unsigned int quality) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_jpeg(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(file,filename); return *this; }
      if (_depth>1)
        cimg::warn(_cimg_instance
                   "save_jpeg(): Instance is volumetric, only the first slice will be saved in file '%s'.",
                   cimg_instance,
                   filename?filename:"(FILE*)");

#ifndef cimg_use_jpeg
      if (!file) return save_other(filename,quality);
      else throw CImgIOException(_cimg_instance
                                 "save_jpeg(): Unable to save data in '(*FILE)' unless libjpeg is enabled.",
                                 cimg_instance);
#else
      unsigned int dimbuf = 0;
      J_COLOR_SPACE colortype = JCS_RGB;

      switch(_spectrum) {
      case 1 : dimbuf = 1; colortype = JCS_GRAYSCALE; break;
      case 2 : dimbuf = 3; colortype = JCS_RGB; break;
      case 3 : dimbuf = 3; colortype = JCS_RGB; break;
      default : dimbuf = 4; colortype = JCS_CMYK; break;
      }

      // Call libjpeg functions
      struct jpeg_compress_struct cinfo;
      struct jpeg_error_mgr jerr;
      cinfo.err = jpeg_std_error(&jerr);
      jpeg_create_compress(&cinfo);
      std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
      jpeg_stdio_dest(&cinfo,nfile);
      cinfo.image_width = _width;
      cinfo.image_height = _height;
      cinfo.input_components = dimbuf;
      cinfo.in_color_space = colortype;
      jpeg_set_defaults(&cinfo);
      jpeg_set_quality(&cinfo,quality<100?quality:100,TRUE);
      jpeg_start_compress(&cinfo,TRUE);

      JSAMPROW row_pointer[1];
      CImg<ucharT> buffer((unsigned long)_width*dimbuf);

      while (cinfo.next_scanline<cinfo.image_height) {
        unsigned char *ptrd = buffer._data;

        // Fill pixel buffer
        switch (_spectrum) {
        case 1 : { // Greyscale images
          const T *ptr_g = data(0, cinfo.next_scanline);
          for(unsigned int b = 0; b < cinfo.image_width; b++)
            *(ptrd++) = (unsigned char)*(ptr_g++);
        } break;
        case 2 : { // RG images
          const T *ptr_r = data(0,cinfo.next_scanline,0,0),
            *ptr_g = data(0,cinfo.next_scanline,0,1);
          for(unsigned int b = 0; b < cinfo.image_width; ++b) {
            *(ptrd++) = (unsigned char)*(ptr_r++);
            *(ptrd++) = (unsigned char)*(ptr_g++);
            *(ptrd++) = 0;
          }
        } break;
        case 3 : { // RGB images
          const T *ptr_r = data(0,cinfo.next_scanline,0,0),
            *ptr_g = data(0,cinfo.next_scanline,0,1),
            *ptr_b = data(0,cinfo.next_scanline,0,2);
          for(unsigned int b = 0; b < cinfo.image_width; ++b) {
            *(ptrd++) = (unsigned char)*(ptr_r++);
            *(ptrd++) = (unsigned char)*(ptr_g++);
            *(ptrd++) = (unsigned char)*(ptr_b++);
          }
        } break;
        default : { // CMYK images
          const T *ptr_r = data(0,cinfo.next_scanline,0,0),
            *ptr_g = data(0,cinfo.next_scanline,0,1),
            *ptr_b = data(0,cinfo.next_scanline,0,2),
            *ptr_a = data(0,cinfo.next_scanline,0,3);
          for(unsigned int b = 0; b < cinfo.image_width; ++b) {
            *(ptrd++) = (unsigned char)*(ptr_r++);
            *(ptrd++) = (unsigned char)*(ptr_g++);
            *(ptrd++) = (unsigned char)*(ptr_b++);
            *(ptrd++) = (unsigned char)*(ptr_a++);
          }
        }
        }
        *row_pointer = buffer._data;
        jpeg_write_scanlines(&cinfo,row_pointer,1);
      }
      jpeg_finish_compress(&cinfo);
      if (!file) cimg::fclose(nfile);
      jpeg_destroy_compress(&cinfo);
      return *this;
#endif
    }

// Assembly:
subq $0xe8, %rsp
movq %rdi, 0xd8(%rsp)
movq %rsi, 0xd0(%rsp)
movq %rdx, 0xc8(%rsp)
movl %ecx, 0xc4(%rsp)
movq 0xd8(%rsp), %rax
movq %rax, 0xa8(%rsp)
cmpq $0x0, 0xd0(%rsp)
jne 0x9d714
cmpq $0x0, 0xc8(%rsp)
jne 0x9d714
movl $0x4008, %edi           # imm = 0x4008
callq 0x5240
movq %rax, %rcx
movq 0xa8(%rsp), %rax
movq %rcx, 0x78(%rsp)
movl (%rax), %ecx
movl %ecx, 0x80(%rsp)
movl 0x4(%rax), %ecx
movl %ecx, 0x84(%rsp)
movl 0x8(%rax), %ecx
movl %ecx, 0x88(%rsp)
movl 0xc(%rax), %ecx
movl %ecx, 0x8c(%rsp)
movq 0x18(%rax), %rcx
movq %rcx, 0x90(%rsp)
movb 0x10(%rax), %dl
leaq 0x4b377(%rip), %rcx     # 0xe89d2
leaq 0x2c47f(%rip), %rax     # 0xc9ae1
testb $0x1, %dl
cmovneq %rcx, %rax
movq %rax, 0x98(%rsp)
callq 0x118f0
movq %rax, 0xa0(%rsp)
jmp 0x9d680
movl 0x8c(%rsp), %r9d
movl 0x88(%rsp), %r8d
movl 0x84(%rsp), %ecx
movl 0x80(%rsp), %edx
movq 0x78(%rsp), %rdi
movq 0x90(%rsp), %rsi
movq 0x98(%rsp), %r10
movq 0xa0(%rsp), %r11
movq %rsp, %rax
movq %r11, 0x10(%rax)
movq %r10, 0x8(%rax)
movq %rsi, (%rax)
leaq 0x4e400(%rip), %rsi     # 0xebad0
xorl %eax, %eax
callq 0x12220
jmp 0x9d6d9
movq 0x78(%rsp), %rdi
leaq 0x6247b(%rip), %rsi     # 0xffb60
leaq -0x8b28c(%rip), %rdx    # 0x12460
callq 0x5920
movq 0x78(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb8(%rsp)
movl %eax, 0xb4(%rsp)
callq 0x53a0
jmp 0x9d946
movq 0xa8(%rsp), %rdi
callq 0x10320
testb $0x1, %al
jne 0x9d727
jmp 0x9d751
movq 0xd0(%rsp), %rdi
movq 0xc8(%rsp), %rsi
callq 0x9c310
movq 0xa8(%rsp), %rax
movq %rax, 0xe0(%rsp)
jmp 0x9d936
movq 0xa8(%rsp), %rax
cmpl $0x1, 0x8(%rax)
jbe 0x9d81f
movq 0xa8(%rsp), %rax
movl (%rax), %ecx
movl %ecx, 0x50(%rsp)
movl 0x4(%rax), %ecx
movl %ecx, 0x54(%rsp)
movl 0x8(%rax), %ecx
movl %ecx, 0x58(%rsp)
movl 0xc(%rax), %ecx
movl %ecx, 0x5c(%rsp)
movq 0x18(%rax), %rcx
movq %rcx, 0x60(%rsp)
movb 0x10(%rax), %dl
leaq 0x2c348(%rip), %rax     # 0xc9ae1
leaq 0x4b232(%rip), %rcx     # 0xe89d2
testb $0x1, %dl
cmovneq %rcx, %rax
movq %rax, 0x68(%rsp)
callq 0x118f0
movq %rax, 0x70(%rsp)
cmpq $0x0, 0xc8(%rsp)
je 0x9d7d0
movq 0xc8(%rsp), %rax
movq %rax, 0x48(%rsp)
jmp 0x9d7de
leaq 0x4bcb3(%rip), %rax     # 0xe948a
movq %rax, 0x48(%rsp)
jmp 0x9d7de
movq 0x70(%rsp), %r10
movq 0x68(%rsp), %r11
movq 0x60(%rsp), %r9
movl 0x5c(%rsp), %r8d
movl 0x58(%rsp), %ecx
movl 0x54(%rsp), %edx
movl 0x50(%rsp), %esi
movq 0x48(%rsp), %rax
leaq 0x4e31f(%rip), %rdi     # 0xebb29
movq %r11, (%rsp)
movq %r10, 0x8(%rsp)
movq %rax, 0x10(%rsp)
movb $0x0, %al
callq 0x117e0
cmpq $0x0, 0xd0(%rsp)
jne 0x9d853
movq 0xa8(%rsp), %rdi
movq 0xc8(%rsp), %rsi
movl 0xc4(%rsp), %edx
callq 0x9b6b0
movq %rax, 0xe0(%rsp)
jmp 0x9d936
movl $0x4008, %edi           # imm = 0x4008
callq 0x5240
movq %rax, %rcx
movq 0xa8(%rsp), %rax
movq %rcx, 0x18(%rsp)
movl (%rax), %ecx
movl %ecx, 0x20(%rsp)
movl 0x4(%rax), %ecx
movl %ecx, 0x24(%rsp)
movl 0x8(%rax), %ecx
movl %ecx, 0x28(%rsp)
movl 0xc(%rax), %ecx
movl %ecx, 0x2c(%rsp)
movq 0x18(%rax), %rcx
movq %rcx, 0x30(%rsp)
movb 0x10(%rax), %dl
leaq 0x4b137(%rip), %rcx     # 0xe89d2
leaq 0x2c23f(%rip), %rax     # 0xc9ae1
testb $0x1, %dl
cmovneq %rcx, %rax
movq %rax, 0x38(%rsp)
callq 0x118f0
movq %rax, 0x40(%rsp)
jmp 0x9d8ba
movl 0x2c(%rsp), %r9d
movl 0x28(%rsp), %r8d
movl 0x24(%rsp), %ecx
movl 0x20(%rsp), %edx
movq 0x18(%rsp), %rdi
movq 0x30(%rsp), %rsi
movq 0x38(%rsp), %r10
movq 0x40(%rsp), %r11
movq %rsp, %rax
movq %r11, 0x10(%rax)
movq %r10, 0x8(%rax)
movq %rsi, (%rax)
leaq 0x4e2b8(%rip), %rsi     # 0xebbad
xorl %eax, %eax
callq 0x5c880
jmp 0x9d8fe
movq 0x18(%rsp), %rdi
leaq 0x62366(%rip), %rsi     # 0xffc70
leaq -0x40e51(%rip), %rdx    # 0x5cac0
callq 0x5920
movq 0x18(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb8(%rsp)
movl %eax, 0xb4(%rsp)
callq 0x53a0
jmp 0x9d946
movq 0xe0(%rsp), %rax
addq $0xe8, %rsp
retq
movq 0xb8(%rsp), %rdi
callq 0x5970
nopw %cs:(%rax,%rax)
nopl (%rax)