bool ezImageConversion::IsConvertible(ezImageFormat::Enum sourceFormat, ezImageFormat::Enum targetFormat)
{
  if (!s_conversionTableValid)
  {
    RebuildConversionTable();
  }

  ezUInt32 tableIndex = MakeKey(sourceFormat, targetFormat);
  return s_conversionTable.Contains(tableIndex);
}
Exemple #2
0
ezResult ezImageConversionBase::Convert(const ezImage& source, ezImage& target, ezImageFormat::Enum targetFormat)
{
  ezImageFormat::Enum sourceFormat = source.GetImageFormat();

  // Trivial copy
  if (sourceFormat == targetFormat)
  {
    target = source;
    return EZ_SUCCESS;
  }

  if (!s_bConversionTableValid)
  {
    RebuildConversionTable();
  }

  ezUInt32 uiCurrentTableIndex = GetTableIndex(sourceFormat, targetFormat);

  // No conversion known
  if (s_conversionTable[uiCurrentTableIndex] == nullptr)
  {
    return EZ_FAILURE;
  }

  const ezImageConversionBase* pConversion = s_conversionTable[uiCurrentTableIndex];
  const SubConversion& subConversion = pConversion->m_subConversions[s_subConversionTable[uiCurrentTableIndex]];

  if (subConversion.m_targetFormat == targetFormat)
  {
    if (&source == &target && !subConversion.m_flags.IsSet(ezImageConversionFlags::InPlace))
    {
      ezImage copy = source;
      return pConversion->DoConvert(copy, target, subConversion.m_targetFormat);
    }
    else
    {
      return pConversion->DoConvert(source, target, subConversion.m_targetFormat);
    }
  }
  else
  {
    ezImage intermediate;
    if (pConversion->DoConvert(source, intermediate, subConversion.m_targetFormat) == EZ_FAILURE)
    {
      return EZ_FAILURE;
    }

    return Convert(intermediate, target, targetFormat);
  }
}
Exemple #3
0
ezImageFormat::Enum ezImageConversionBase::FindClosestCompatibleFormat(ezImageFormat::Enum format, const ezImageFormat::Enum* pCompatibleFormats, ezUInt32 uiNumCompatible)
{
  if (!s_bConversionTableValid)
  {
    RebuildConversionTable();
  }

  float fBestCost = ezMath::BasicType<float>::GetInfinity();
  ezImageFormat::Enum bestFormat = ezImageFormat::UNKNOWN;

  for (ezUInt32 uiTargetIndex = 0; uiTargetIndex < uiNumCompatible; uiTargetIndex++)
  {
    float fCost = s_costTable[GetTableIndex(format, pCompatibleFormats[uiTargetIndex])];
    if (fCost < fBestCost)
    {
      fBestCost = fCost;
      bestFormat = pCompatibleFormats[uiTargetIndex];
    }
  }

  return bestFormat;
}
ezImageFormat::Enum ezImageConversion::FindClosestCompatibleFormat(ezImageFormat::Enum format,
                                                                   ezArrayPtr<const ezImageFormat::Enum> compatibleFormats)
{
  if (!s_conversionTableValid)
  {
    RebuildConversionTable();
  }

  TableEntry bestEntry;
  ezImageFormat::Enum bestFormat = ezImageFormat::UNKNOWN;

  for (ezUInt32 targetIndex = 0; targetIndex < ezUInt32(compatibleFormats.GetCount()); targetIndex++)
  {
    ezUInt32 tableIndex = MakeKey(format, compatibleFormats[targetIndex]);
    TableEntry candidate;
    if (s_conversionTable.TryGetValue(tableIndex, candidate) && candidate < bestEntry)
    {
      bestEntry = candidate;
      bestFormat = compatibleFormats[targetIndex];
    }
  }

  return bestFormat;
}
ezResult ezImageConversion::BuildPath(ezImageFormat::Enum sourceFormat, ezImageFormat::Enum targetFormat, bool bSourceEqualsTarget,
                                      ezHybridArray<ezImageConversion::ConversionPathNode, 16>& path_out, ezUInt32& numScratchBuffers_out)
{
  path_out.Clear();
  numScratchBuffers_out = 0;

  if (sourceFormat == targetFormat)
  {
    ConversionPathNode node;
    node.m_sourceFormat = sourceFormat;
    node.m_targetFormat = targetFormat;
    node.m_inPlace = bSourceEqualsTarget;
    node.m_sourceBufferIndex = 0;
    node.m_targetBufferIndex = 0;
    node.m_step = nullptr;
    path_out.PushBack(node);
    return EZ_SUCCESS;
  }

  if (!s_conversionTableValid)
  {
    RebuildConversionTable();
  }

  for (ezImageFormat::Enum current = sourceFormat; current != targetFormat;)
  {
    ezUInt32 currentTableIndex = MakeKey(current, targetFormat);

    TableEntry entry;

    if (!s_conversionTable.TryGetValue(currentTableIndex, entry))
    {
      return EZ_FAILURE;
    }

    ezImageConversion::ConversionPathNode step;
    step.m_sourceFormat = entry.m_sourceFormat;
    step.m_targetFormat = entry.m_targetFormat;
    step.m_inPlace = entry.m_flags.IsAnySet(ezImageConversionFlags::InPlace);
    step.m_step = entry.m_step;

    current = entry.m_targetFormat;

    path_out.PushBack(step);
  }

  ezHybridArray<IntermediateBuffer, 16> scratchBuffers;
  scratchBuffers.PushBack(IntermediateBuffer(ezImageFormat::GetBitsPerBlock(targetFormat)));

  for (int i = path_out.GetCount() - 1; i >= 0; --i)
  {
    if (i == path_out.GetCount() - 1)
      path_out[i].m_targetBufferIndex = 0;
    else
      path_out[i].m_targetBufferIndex = path_out[i + 1].m_sourceBufferIndex;

    if (i > 0)
    {
      if (path_out[i].m_inPlace)
      {
        path_out[i].m_sourceBufferIndex = path_out[i].m_targetBufferIndex;
      }
      else
      {
        ezUInt32 bitsPerBlock = ezImageFormat::GetBitsPerBlock(path_out[i].m_sourceFormat);

        path_out[i].m_sourceBufferIndex = allocateScratchBufferIndex(scratchBuffers, bitsPerBlock, path_out[i].m_targetBufferIndex);
      }
    }
  }

  if (bSourceEqualsTarget)
  {
    // Enforce constraint that source == target
    path_out[0].m_sourceBufferIndex = 0;

    // Did we accidentally break the in-place invariant?
    if (path_out[0].m_sourceBufferIndex == path_out[0].m_targetBufferIndex && !path_out[0].m_inPlace)
    {
      if (path_out.GetCount() == 1)
      {
        // Only a single step, so we need to add a copy step
        ezImageConversion::ConversionPathNode copy;
        copy.m_inPlace = false;
        copy.m_sourceFormat = sourceFormat;
        copy.m_targetFormat = sourceFormat;
        copy.m_sourceBufferIndex = path_out[0].m_sourceBufferIndex;
        copy.m_targetBufferIndex = allocateScratchBufferIndex(scratchBuffers, ezImageFormat::GetBitsPerBlock(path_out[0].m_sourceFormat),
                                                              path_out[0].m_sourceBufferIndex);
        path_out[0].m_sourceBufferIndex = copy.m_targetBufferIndex;
        copy.m_step = nullptr;
        path_out.Insert(copy, 0);
      }
      else
      {
        // Turn second step to non-inplace
        path_out[1].m_inPlace = false;
        path_out[1].m_sourceBufferIndex = allocateScratchBufferIndex(
            scratchBuffers, ezImageFormat::GetBitsPerBlock(path_out[1].m_sourceFormat), path_out[0].m_sourceBufferIndex);
        path_out[0].m_targetBufferIndex = path_out[1].m_sourceBufferIndex;
      }
    }
  }
  else
  {
    path_out[0].m_sourceBufferIndex = scratchBuffers.GetCount();
  }

  numScratchBuffers_out = scratchBuffers.GetCount() - 1;

  return EZ_SUCCESS;
}