/*
 * Copyright 2016 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "guetzli/jpeg_data.h"

#include <assert.h>
#include <string.h>

namespace guetzli {

bool JPEGData::Is420() const {
  return (components.size() == 3 &&
          max_h_samp_factor == 2 &&
          max_v_samp_factor == 2 &&
          components[0].h_samp_factor == 2 &&
          components[0].v_samp_factor == 2 &&
          components[1].h_samp_factor == 1 &&
          components[1].v_samp_factor == 1 &&
          components[2].h_samp_factor == 1 &&
          components[2].v_samp_factor == 1);
}

bool JPEGData::Is444() const {
  return (components.size() == 3 &&
          max_h_samp_factor == 1 &&
          max_v_samp_factor == 1 &&
          components[0].h_samp_factor == 1 &&
          components[0].v_samp_factor == 1 &&
          components[1].h_samp_factor == 1 &&
          components[1].v_samp_factor == 1 &&
          components[2].h_samp_factor == 1 &&
          components[2].v_samp_factor == 1);
}

void InitJPEGDataForYUV444(int w, int h, JPEGData* jpg) {
  jpg->width = w;
  jpg->height = h;
  jpg->max_h_samp_factor = 1;
  jpg->max_v_samp_factor = 1;
  jpg->MCU_rows = (h + 7) >> 3;
  jpg->MCU_cols = (w + 7) >> 3;
  jpg->quant.resize(3);
  jpg->components.resize(3);
  for (int i = 0; i < 3; ++i) {
    JPEGComponent* c = &jpg->components[i];
    c->id = i;
    c->h_samp_factor = 1;
    c->v_samp_factor = 1;
    c->quant_idx = i;
    c->width_in_blocks = jpg->MCU_cols;
    c->height_in_blocks = jpg->MCU_rows;
    c->num_blocks = c->width_in_blocks * c->height_in_blocks;
    c->coeffs.resize(c->num_blocks * kDCTBlockSize);
  }
}

void SaveQuantTables(const int q[3][kDCTBlockSize], JPEGData* jpg) {
  const size_t kTableSize = kDCTBlockSize * sizeof(q[0][0]);
  jpg->quant.clear();
  int num_tables = 0;
  for (size_t i = 0; i < jpg->components.size(); ++i) {
    JPEGComponent* comp = &jpg->components[i];
    // Check if we have this quant table already.
    bool found = false;
    for (int j = 0; j < num_tables; ++j) {
      if (memcmp(&q[i][0], &jpg->quant[j].values[0], kTableSize) == 0) {
        comp->quant_idx = j;
        found = true;
        break;
      }
    }
    if (!found) {
      JPEGQuantTable table;
      memcpy(&table.values[0], &q[i][0], kTableSize);
      table.precision = 0;
      for (int k = 0; k < kDCTBlockSize; ++k) {
        assert(table.values[k] >= 0);
        assert(table.values[k] < (1 << 16));
        if (table.values[k] > 0xff) {
          table.precision = 1;
        }
      }
      table.index = num_tables;
      comp->quant_idx = num_tables;
      jpg->quant.push_back(table);
      ++num_tables;
    }
  }
}

}  // namespace guetzli
