/* -*- C++ -*-
 * Copyright 2019-2025 LibRaw LLC (info@libraw.org)
 *
 LibRaw is free software; you can redistribute it and/or modify
 it under the terms of the one of two licenses as you choose:

1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).

2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).

 */

#include "third_party/libraw/internal/libraw_cxx_defs.h"

int LibRaw::dcraw_process(void)
{
  int quality, i;

  int iterations = -1, dcb_enhance = 1, noiserd = 0;
  float preser = 0;
  float expos = 1.0;

  CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
  //    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);

  try
  {

    int no_crop = 1;

    if (~O.cropbox[2] && ~O.cropbox[3])
      no_crop = 0;

	for(int c = 0; c < 4; c++)
		if (O.aber[c]< 0.001 || O.aber[c] > 1000.f)
			O.aber[c] = 1.0;

    libraw_decoder_info_t di;
    get_decoder_info(&di);

    bool is_bayer = (imgdata.idata.filters || P1.colors == 1);
    int subtract_inline =
        !O.bad_pixels && !O.dark_frame && is_bayer && !IO.zero_is_bad;

    int rc = raw2image_ex(subtract_inline); // allocate imgdata.image and copy data!
	if (rc != LIBRAW_SUCCESS)
		return rc;

    // Adjust sizes

    int save_4color = O.four_color_rgb;

    if (IO.zero_is_bad)
    {
      remove_zeroes();
      SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES);
    }

    if (O.bad_pixels && no_crop)
    {
      bad_pixels(O.bad_pixels);
      SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS);
    }

    if (O.dark_frame && no_crop)
    {
      subtract(O.dark_frame);
      SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME);
    }
    /* pre subtract black callback: check for it above to disable subtract
     * inline */

    if (callbacks.pre_subtractblack_cb)
      (callbacks.pre_subtractblack_cb)(this);

    quality = 2 + !IO.fuji_width;

    if (O.user_qual >= 0)
      quality = O.user_qual;

    if (!subtract_inline || !C.data_maximum)
    {
      adjust_bl();
      subtract_black_internal();
    }

    if (!(di.decoder_flags & LIBRAW_DECODER_FIXEDMAXC))
      adjust_maximum();

    if (O.user_sat > 0)
      C.maximum = O.user_sat;

    if (P1.is_foveon)
    {
      if (load_raw == &LibRaw::x3f_load_raw)
      {
        // Filter out zeroes
        for (int q = 0; q < S.height * S.width; q++)
        {
          for (int c = 0; c < 4; c++)
            if ((short)imgdata.image[q][c] < 0)
              imgdata.image[q][c] = 0;
        }
      }
      SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE);
    }

    if (O.green_matching && !O.half_size)
    {
      green_matching();
    }

    if (callbacks.pre_scalecolors_cb)
      (callbacks.pre_scalecolors_cb)(this);

    if (!O.no_auto_scale)
    {
      scale_colors();
      SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS);
    }

    if (callbacks.pre_preinterpolate_cb)
      (callbacks.pre_preinterpolate_cb)(this);

    pre_interpolate();

    SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);

    if (O.dcb_iterations >= 0)
      iterations = O.dcb_iterations;
    if (O.dcb_enhance_fl >= 0)
      dcb_enhance = O.dcb_enhance_fl;
    if (O.fbdd_noiserd >= 0)
      noiserd = O.fbdd_noiserd;

    /* pre-exposure correction callback */

    if (O.exp_correc > 0)
    {
      expos = O.exp_shift;
      preser = O.exp_preser;
      exp_bef(expos, preser);
    }

    if (callbacks.pre_interpolate_cb)
      (callbacks.pre_interpolate_cb)(this);

    /* post-exposure correction fallback */
    if (P1.filters && !O.no_interpolation)
    {
	  int real_colors = P1.colors;
	  int bad_bayer = 0;
	  if (P1.filters > 1000)
		  for (int r = 0; r < 4; r++)
			  for (int c = 0; c < 8; c++)
			  {
				  real_colors = MAX(COLOR(r, c) + 1, real_colors);
				  if (P1.filters > 1000)
				  {
					  // Normal bayer: adjacent pixels horizontally/vertically have different colors
					  bad_bayer += (FC(r, c) == FC(r + 1, c));
					  bad_bayer += (FC(r, c) == FC(r, c + 1));
				  }
			  }

      if (noiserd > 0 && P1.colors == 3 && real_colors == 3 && P1.filters > 1000)
        fbdd(noiserd);

      if (P1.filters > 1000 && callbacks.interpolate_bayer_cb)
        (callbacks.interpolate_bayer_cb)(this);
      else if (P1.filters == 9 && callbacks.interpolate_xtrans_cb)
        (callbacks.interpolate_xtrans_cb)(this);
      else if (quality == 0)
        lin_interpolate();
      else if (quality == 1 || P1.colors > 3 || real_colors > 3 || bad_bayer || (P1.filters != LIBRAW_XTRANS && P1.filters <= 1000))
        vng_interpolate();
      else if (quality == 2 && P1.filters > 1000)
        ppg_interpolate();
      else if (P1.filters == LIBRAW_XTRANS)
      {
        // Fuji X-Trans
        xtrans_interpolate(quality > 2 ? 3 : 1);
      }
      else if (quality == 3)
        ahd_interpolate(); // really don't need it here due to fallback op
      else if (quality == 4)
        dcb(iterations, dcb_enhance);

      else if (quality == 11)
        dht_interpolate();
      else if (quality == 12)
        aahd_interpolate();
      // fallback to AHD
      else
      {
        ahd_interpolate();
        imgdata.process_warnings |= LIBRAW_WARN_FALLBACK_TO_AHD;
      }

      SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE);
    }
    if (IO.mix_green)
    {
      for (P1.colors = 3, i = 0; i < S.height * S.width; i++)
        imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
      SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
    }

    if (callbacks.post_interpolate_cb)
      (callbacks.post_interpolate_cb)(this);
    else if (!P1.is_foveon && P1.colors == 3 && O.med_passes > 0)
    {
      median_filter();
      SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
    }

    if (O.highlight == 2)
    {
      blend_highlights();
      SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
    }

    if (O.highlight > 2)
    {
      recover_highlights();
      SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
    }

    if (O.use_fuji_rotate)
    {
      fuji_rotate();
      SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
    }

    if (!libraw_internal_data.output_data.histogram)
    {
      libraw_internal_data.output_data.histogram =
          (int(*)[LIBRAW_HISTOGRAM_SIZE])calloc(1,
              sizeof(*libraw_internal_data.output_data.histogram) * 4);
    }
#ifndef NO_LCMS
    if (O.camera_profile)
    {
      apply_profile(O.camera_profile, O.output_profile);
      SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
    }
#endif

    if (callbacks.pre_converttorgb_cb)
      (callbacks.pre_converttorgb_cb)(this);

    convert_to_rgb();
    SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);

    if (callbacks.post_converttorgb_cb)
      (callbacks.post_converttorgb_cb)(this);

    if (O.use_fuji_rotate)
    {
      stretch();
      SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
    }
    O.four_color_rgb = save_4color; // also, restore

    return 0;
  }
  catch (const std::bad_alloc&)
  {
      recycle();
      return LIBRAW_UNSUFFICIENT_MEMORY;
  }
  catch (const LibRaw_exceptions& err)
  {
    EXCEPTION_HANDLER(err);
  }
}
