## Copyright (C) 2014-2025 Andreas Weber <andy.weber.aw@gmail.com>
##
## This program is free software; you can redistribute it and/or modify it under
## the terms of the GNU General Public License as published by the Free Software
## Foundation; either version 3 of the License, or (at your option) any later
## version.
##
## This program is distributed in the hope that it will be useful, but WITHOUT
## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
## details.
##
## You should have received a copy of the GNU General Public License along with
## this program; if not, see <http:##www.gnu.org/licenses/>.
##
## This script is based on mjpeg2jpeg.py from Laurent Pinchart and Luc Saillard.
## https://github.com/TimSC/mjpeg/blob/master/mjpeg2jpeg.py has a copy

## -*- texinfo -*-
## @deftypefn {Function File} save_mjpeg_as_jpg (@var{fn}, @var{mjpeg})
## Add a huffman table to the MPJEG capture and save it as JPG.
## Useful if you have set VideoFormat of videoinput to MJPEG and want
## to convert the result from getsnapshot to JPG.
## @seealso{@@videoinput/getsnapshot}
## @end deftypefn

function save_mjpeg_as_jpg (fn, mjpeg)

  persistent huffman_table = uint8(...
     [0xFF 0xC4 0x01 0xA2 0x00 0x00 0x01 0x05 0x01 0x01 0x01 0x01 ...
      0x01 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x02 ...
      0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x01 0x00 0x03 ...
      0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x01 0x00 0x00 0x00 ...
      0x00 0x00 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 ...
      0x0A 0x0B 0x10 0x00 0x02 0x01 0x03 0x03 0x02 0x04 0x03 0x05 ...
      0x05 0x04 0x04 0x00 0x00 0x01 0x7D 0x01 0x02 0x03 0x00 0x04 ...
      0x11 0x05 0x12 0x21 0x31 0x41 0x06 0x13 0x51 0x61 0x07 0x22 ...
      0x71 0x14 0x32 0x81 0x91 0xA1 0x08 0x23 0x42 0xB1 0xC1 0x15 ...
      0x52 0xD1 0xF0 0x24 0x33 0x62 0x72 0x82 0x09 0x0A 0x16 0x17 ...
      0x18 0x19 0x1A 0x25 0x26 0x27 0x28 0x29 0x2A 0x34 0x35 0x36 ...
      0x37 0x38 0x39 0x3A 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4A ...
      0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5A 0x63 0x64 0x65 0x66 ...
      0x67 0x68 0x69 0x6A 0x73 0x74 0x75 0x76 0x77 0x78 0x79 0x7A ...
      0x83 0x84 0x85 0x86 0x87 0x88 0x89 0x8A 0x92 0x93 0x94 0x95 ...
      0x96 0x97 0x98 0x99 0x9A 0xA2 0xA3 0xA4 0xA5 0xA6 0xA7 0xA8 ...
      0xA9 0xAA 0xB2 0xB3 0xB4 0xB5 0xB6 0xB7 0xB8 0xB9 0xBA 0xC2 ...
      0xC3 0xC4 0xC5 0xC6 0xC7 0xC8 0xC9 0xCA 0xD2 0xD3 0xD4 0xD5 ...
      0xD6 0xD7 0xD8 0xD9 0xDA 0xE1 0xE2 0xE3 0xE4 0xE5 0xE6 0xE7 ...
      0xE8 0xE9 0xEA 0xF1 0xF2 0xF3 0xF4 0xF5 0xF6 0xF7 0xF8 0xF9 ...
      0xFA 0x11 0x00 0x02 0x01 0x02 0x04 0x04 0x03 0x04 0x07 0x05 ...
      0x04 0x04 0x00 0x01 0x02 0x77 0x00 0x01 0x02 0x03 0x11 0x04 ...
      0x05 0x21 0x31 0x06 0x12 0x41 0x51 0x07 0x61 0x71 0x13 0x22 ...
      0x32 0x81 0x08 0x14 0x42 0x91 0xA1 0xB1 0xC1 0x09 0x23 0x33 ...
      0x52 0xF0 0x15 0x62 0x72 0xD1 0x0A 0x16 0x24 0x34 0xE1 0x25 ...
      0xF1 0x17 0x18 0x19 0x1A 0x26 0x27 0x28 0x29 0x2A 0x35 0x36 ...
      0x37 0x38 0x39 0x3A 0x43 0x44 0x45 0x46 0x47 0x48 0x49 0x4A ...
      0x53 0x54 0x55 0x56 0x57 0x58 0x59 0x5A 0x63 0x64 0x65 0x66 ...
      0x67 0x68 0x69 0x6A 0x73 0x74 0x75 0x76 0x77 0x78 0x79 0x7A ...
      0x82 0x83 0x84 0x85 0x86 0x87 0x88 0x89 0x8A 0x92 0x93 0x94 ...
      0x95 0x96 0x97 0x98 0x99 0x9A 0xA2 0xA3 0xA4 0xA5 0xA6 0xA7 ...
      0xA8 0xA9 0xAA 0xB2 0xB3 0xB4 0xB5 0xB6 0xB7 0xB8 0xB9 0xBA ...
      0xC2 0xC3 0xC4 0xC5 0xC6 0xC7 0xC8 0xC9 0xCA 0xD2 0xD3 0xD4 ...
      0xD5 0xD6 0xD7 0xD8 0xD9 0xDA 0xE2 0xE3 0xE4 0xE5 0xE6 0xE7 ...
      0xE8 0xE9 0xEA 0xF2 0xF3 0xF4 0xF5 0xF6 0xF7 0xF8 0xF9 0xFA]);

  if (! isvector (mjpeg))
    error ("MJPEG hast to be a vector");
  endif

  mjpeg = mjpeg(:);

  [fid, msg] = fopen (fn, "w");
  if (fid < 0)
    error ("Failed to create file %s for writing. %s", fn, msg);
  endif

  hdr = mjpeg(1:2);
  mjpeg(1:2) = [];

  if (hdr != [0xFF; 0xD8])
    error ("img header (first two bytes) not valid. [0x%2x 0x%2x]", hdr)
  endif

  fwrite (fid, uint8(hdr));
  has_dht = false;

  while (! has_dht)
    hdr = mjpeg(1:4);
    mjpeg(1:4) = [];

    if (hdr(1) != 0xFF)
      error ("img header not valid")
    endif

    if (hdr(2) == 0xC4)
      has_dht = true;
    elseif (hdr(2) == 0xDA)
      break;
    endif

    # Skip to the next marker.
    s = hdr(3) * 2^8 + hdr(4);
    fwrite (fid, uint8(hdr));
    fwrite (fid, mjpeg(1:s-2));
    mjpeg(1:s-2) = [];

  endwhile
  if (! has_dht)
    fwrite (fid, huffman_table);
    fwrite (fid, hdr);
  endif

  # Process the remaining data in one go
  fwrite (fid, mjpeg);
  fclose (fid);

endfunction
