Example #1
0
ezResult ezTexConv2::WriteTexFile(ezStreamWriter& stream, const ezImage& image)
{
  ezAssetFileHeader asset;
  asset.SetFileHashAndVersion(m_Processor.m_Descriptor.m_uiAssetHash, m_Processor.m_Descriptor.m_uiAssetVersion);

  asset.Write(stream);

  ezTexFormat texFormat;
  texFormat.m_bSRGB = ezImageFormat::IsSrgb(image.GetImageFormat());
  texFormat.m_AddressModeU = m_Processor.m_Descriptor.m_AddressModeU;
  texFormat.m_AddressModeV = m_Processor.m_Descriptor.m_AddressModeV;
  texFormat.m_AddressModeW = m_Processor.m_Descriptor.m_AddressModeW;
  texFormat.m_TextureFilter = m_Processor.m_Descriptor.m_FilterMode;

  texFormat.WriteTextureHeader(stream);

  ezDdsFileFormat ddsWriter;
  if (ddsWriter.WriteImage(stream, image, ezLog::GetThreadLocalLogSystem(), "dds").Failed())
  {
    ezLog::Error("Failed to write DDS image chunk to ezTex file.");
    return EZ_FAILURE;
  }

  return EZ_SUCCESS;
}
Example #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);
  }
}
Example #3
0
ezResult ezBmpFileFormat::WriteImage(ezStreamWriterBase& stream, const ezImage& image, ezLogInterface* pLog) const
{
  // Technically almost arbitrary formats are supported, but we only use the common ones.
  ezImageFormat::Enum compatibleFormats[] =
  {
    ezImageFormat::B8G8R8X8_UNORM,
    ezImageFormat::B8G8R8A8_UNORM,
    ezImageFormat::B8G8R8_UNORM,
    ezImageFormat::B5G5R5X1_UNORM,
    ezImageFormat::B5G6R5_UNORM,
  };

  // Find a compatible format closest to the one the image currently has
  ezImageFormat::Enum format = ezImageConversionBase::FindClosestCompatibleFormat(image.GetImageFormat(), compatibleFormats);

  if (format == ezImageFormat::UNKNOWN)
  {
    ezLog::Error(pLog, "No conversion from format '%s' to a format suitable for BMP files known.", ezImageFormat::GetName(image.GetImageFormat()));
    return EZ_FAILURE;
  }

  // Convert if not already in a compatible format
  if (format != image.GetImageFormat())
  {
    ezImage convertedImage;
    if (ezImageConversionBase::Convert(image, convertedImage, format) != EZ_SUCCESS)
    {
      // This should never happen
      EZ_ASSERT_DEV(false, "ezImageConversion::Convert failed even though the conversion was to the format returned by FindClosestCompatibleFormat.");
      return EZ_FAILURE;
    }

    return WriteImage(stream, convertedImage, pLog);
  }
  
  ezUInt32 uiRowPitch = image.GetRowPitch(0);

  ezUInt32 uiHeight = image.GetHeight(0);

  int dataSize = uiRowPitch * uiHeight;

  ezBmpFileInfoHeader fileInfoHeader;
  fileInfoHeader.m_width = image.GetWidth(0);
  fileInfoHeader.m_height = uiHeight;
  fileInfoHeader.m_planes = 1;
  fileInfoHeader.m_bitCount = ezImageFormat::GetBitsPerPixel(format);

  fileInfoHeader.m_sizeImage = 0; // Can be zero unless we store the data compressed

  fileInfoHeader.m_xPelsPerMeter = 0;
  fileInfoHeader.m_yPelsPerMeter = 0;
  fileInfoHeader.m_clrUsed = 0;
  fileInfoHeader.m_clrImportant = 0;

  bool bWriteColorMask = false;

  // Prefer to write a V3 header
  ezUInt32 uiHeaderVersion = 3;

  switch (format)
  {
  case ezImageFormat::B8G8R8X8_UNORM:
  case ezImageFormat::B5G5R5X1_UNORM:
  case ezImageFormat::B8G8R8_UNORM:
    fileInfoHeader.m_compression = RGB;
    break;

  case ezImageFormat::B8G8R8A8_UNORM:
    fileInfoHeader.m_compression = BITFIELDS;
    uiHeaderVersion = 4;
    break;

  case ezImageFormat::B5G6R5_UNORM:
    fileInfoHeader.m_compression = BITFIELDS;
    bWriteColorMask = true;
    break;

  default:
    return EZ_FAILURE;
  }

  EZ_ASSERT_DEV(!bWriteColorMask || uiHeaderVersion <= 3, "Internal bug");

  ezUInt32 uiFileInfoHeaderSize = sizeof(ezBmpFileInfoHeader);
  ezUInt32 uiHeaderSize = sizeof(ezBmpFileHeader);

  if (uiHeaderVersion >= 4)
  {
    uiFileInfoHeaderSize += sizeof(ezBmpFileInfoHeaderV4);
  }
  else if (bWriteColorMask)
  {
    uiHeaderSize += 3 * sizeof(ezUInt32);
  }

  uiHeaderSize += uiFileInfoHeaderSize;

  fileInfoHeader.m_size = uiFileInfoHeaderSize;

  ezBmpFileHeader header;
  header.m_type = ezBmpFileMagic;
  header.m_size = uiHeaderSize + dataSize;
  header.m_reserved1 = 0;
  header.m_reserved2 = 0;
  header.m_offBits = uiHeaderSize;


  const void* dataPtr = image.GetDataPointer<void>();
  
  // Write all data
  if (stream.WriteBytes(&header, sizeof(header)) != EZ_SUCCESS)
  {
    ezLog::Error(pLog, "Failed to write header.");
    return EZ_FAILURE;
  }

  if (stream.WriteBytes(&fileInfoHeader, sizeof(fileInfoHeader)) != EZ_SUCCESS)
  {
    ezLog::Error(pLog, "Failed to write fileInfoHeader.");
    return EZ_FAILURE;
  }

  if (uiHeaderVersion >= 4)
  {
    ezBmpFileInfoHeaderV4 fileInfoHeaderV4;
    memset(&fileInfoHeaderV4, 0, sizeof(fileInfoHeaderV4));

    fileInfoHeaderV4.m_redMask = ezImageFormat::GetRedMask(format);
    fileInfoHeaderV4.m_greenMask = ezImageFormat::GetGreenMask(format);
    fileInfoHeaderV4.m_blueMask = ezImageFormat::GetBlueMask(format);
    fileInfoHeaderV4.m_alphaMask = ezImageFormat::GetAlphaMask(format);

    if (stream.WriteBytes(&fileInfoHeaderV4, sizeof(fileInfoHeaderV4)) != EZ_SUCCESS)
    {
      ezLog::Error(pLog, "Failed to write fileInfoHeaderV4.");
      return EZ_FAILURE;
    }
  }
  else if (bWriteColorMask)
  {
    struct
    {
      ezUInt32 m_red;
      ezUInt32 m_green;
      ezUInt32 m_blue;
    } colorMask;


    colorMask.m_red = ezImageFormat::GetRedMask(format);
    colorMask.m_green = ezImageFormat::GetGreenMask(format);
    colorMask.m_blue = ezImageFormat::GetBlueMask(format);

    if (stream.WriteBytes(&colorMask, sizeof(colorMask)) != EZ_SUCCESS)
    {
      ezLog::Error(pLog, "Failed to write colorMask.");
      return EZ_FAILURE;
    }
  }

  const ezUInt32 uiPaddedRowPitch = ((uiRowPitch - 1) / 4 + 1) * 4;
  // Write rows in reverse order
  for (ezInt32 iRow = uiHeight - 1; iRow >= 0; iRow--)
  {
    if (stream.WriteBytes(image.GetPixelPointer<void>(0, 0, 0, 0, iRow, 0), uiPaddedRowPitch) != EZ_SUCCESS)
    {
      ezLog::Error(pLog, "Failed to write data.");
      return EZ_FAILURE;
    }
  }
  
  return EZ_SUCCESS;
}