Exemplo n.º 1
0
    bool ktx_texture::consistency_check() const
    {
        if (!check_header())
            return false;

        uint32_t block_dim = 0, bytes_per_block = 0;
        if ((!m_header.m_glType) || (!m_header.m_glFormat))
        {
            if ((m_header.m_glType) || (m_header.m_glFormat))
                return false;
            if (!ktx_get_ogl_fmt_desc(m_header.m_glInternalFormat, m_header.m_glType, block_dim, bytes_per_block))
                return false;
            if (block_dim == 1)
                return false;
            //if ((get_width() % block_dim) || (get_height() % block_dim))
            //   return false;
        }
        else
        {
            if (!ktx_get_ogl_fmt_desc(m_header.m_glFormat, m_header.m_glType, block_dim, bytes_per_block))
                return false;
            if (block_dim > 1)
                return false;
        }
        if ((m_block_dim != block_dim) || (m_bytes_per_block != bytes_per_block))
            return false;

        uint32_t total_expected_images = get_total_images();
        if (m_image_data.size() != total_expected_images)
            return false;

        for (uint32_t mip_level = 0; mip_level < get_num_mips(); mip_level++)
        {
            uint32_t mip_width, mip_height, mip_depth;
            get_mip_dim(mip_level, mip_width, mip_height, mip_depth);

            const uint32_t mip_row_blocks = (mip_width + m_block_dim - 1) / m_block_dim;
            const uint32_t mip_col_blocks = (mip_height + m_block_dim - 1) / m_block_dim;
            if ((!mip_row_blocks) || (!mip_col_blocks))
                return false;

            for (uint32_t array_element = 0; array_element < get_array_size(); array_element++)
            {
                for (uint32_t face = 0; face < get_num_faces(); face++)
                {
                    for (uint32_t zslice = 0; zslice < mip_depth; zslice++)
                    {
                        const uint8_vec &image_data = get_image_data(get_image_index(mip_level, array_element, face, zslice));

                        uint32_t expected_image_size = mip_row_blocks * mip_col_blocks * m_bytes_per_block;
                        if (image_data.size() != expected_image_size)
                            return false;
                    }
                }
            }
        }

        return true;
    }
Exemplo n.º 2
0
void RegistrationResult::show(std::ostream &out) const {
  algebra::VectorD<4> quaternion = R_.get_quaternion();
  out << "Name: " << get_name() << " Image index: " << get_image_index()
      << " Projection index: " << get_projection_index()
      << " (Phi,Theta,Psi) = ( " << get_phi() << " , " << get_theta() << " , "
      << get_psi() << " ) | Shift (x,y) " << get_shift()
      << " CCC = " << get_ccc() << " Quaternion " << quaternion;
}
Exemplo n.º 3
0
//! Writes a result line to a file
void RegistrationResult::write(std::ostream &out) const {
  algebra::VectorD<4> quaternion = R_.get_quaternion();
  char c = '|';
  out << get_image_index() << c << get_projection_index() << c << get_phi() << c
      << get_theta() << c << get_psi() << c << quaternion[0] << c
      << quaternion[1] << c << quaternion[2] << c << quaternion[3] << c
      << get_shift()[0] << c << get_shift()[1] << c << get_ccc() << c
      << std::endl;
}
Exemplo n.º 4
0
        void full_mapping_t::embed() const
        {
            unsigned pre_iter = preimage_interval.first, img_iter = image_interval.first;
            while (pre_iter < preimage_interval.second && img_iter < image_interval.second)
            {
                get_image_index(img_iter) = get_preimage_index(pre_iter);
                pre_iter++; img_iter++;
            }
//            for( unsigned pre_iter = preimage_interval.first, img_iter = image_interval.first;
//                 pre_iter < preimage_interval.second, img_iter < image_interval.second;
//                 pre_iter++, img_iter++ )
//            {
//                get_image_index(img_iter) = get_preimage_index(pre_iter);
//            }
        }
Exemplo n.º 5
0
    uint32_t ktx_texture::get_total_images() const
    {
        if (!is_valid() || !get_num_mips())
            return 0;

        // bogus:
        //return get_num_mips() * (get_depth() * get_num_faces() * get_array_size());

        // Naive algorithm, could just compute based off the # of mips
        uint32_t max_index = 0;
        for (uint32_t mip_level = 0; mip_level < get_num_mips(); mip_level++)
        {
            uint32_t total_zslices = math::maximum<uint32_t>(get_depth() >> mip_level, 1U);
            uint32_t index = get_image_index(mip_level, get_array_size() - 1, get_num_faces() - 1, total_zslices - 1);
            max_index = math::maximum<uint32_t>(max_index, index);
        }

        return max_index + 1;
    }
Exemplo n.º 6
0
    bool ktx_texture::write_to_stream(data_stream_serializer &serializer, bool no_keyvalue_data) const
    {
        if (!consistency_check())
        {
            VOGL_ASSERT_ALWAYS;
            return false;
        }

        memcpy(m_header.m_identifier, s_ktx_file_id, sizeof(m_header.m_identifier));
        m_header.m_endianness = m_opposite_endianness ? KTX_OPPOSITE_ENDIAN : KTX_ENDIAN;

        if (m_block_dim == 1)
        {
            m_header.m_glTypeSize = ktx_get_ogl_type_size(m_header.m_glType);
            m_header.m_glBaseInternalFormat = m_header.m_glFormat;
        }
        else
        {
            m_header.m_glBaseInternalFormat = ktx_get_ogl_compressed_base_internal_fmt(m_header.m_glInternalFormat);
        }

        m_header.m_bytesOfKeyValueData = 0;
        if (!no_keyvalue_data)
        {
            for (uint32_t i = 0; i < m_key_values.size(); i++)
                m_header.m_bytesOfKeyValueData += sizeof(uint32_t) + ((m_key_values[i].size() + 3) & ~3);
        }

        if (m_opposite_endianness)
            m_header.endian_swap();

        bool success = (serializer.write(&m_header, sizeof(m_header), 1) == 1);

        if (m_opposite_endianness)
            m_header.endian_swap();

        if (!success)
            return success;

        uint32_t total_key_value_bytes = 0;
        const uint8_t padding[3] = { 0, 0, 0 };

        if (!no_keyvalue_data)
        {
            for (uint32_t i = 0; i < m_key_values.size(); i++)
            {
                uint32_t key_value_size = m_key_values[i].size();

                if (m_opposite_endianness)
                    key_value_size = utils::swap32(key_value_size);

                success = (serializer.write(&key_value_size, sizeof(key_value_size), 1) == 1);
                total_key_value_bytes += sizeof(key_value_size);

                if (m_opposite_endianness)
                    key_value_size = utils::swap32(key_value_size);

                if (!success)
                    return false;

                if (key_value_size)
                {
                    if (serializer.write(&m_key_values[i][0], key_value_size, 1) != 1)
                        return false;
                    total_key_value_bytes += key_value_size;

                    uint32_t num_padding = 3 - ((key_value_size + 3) % 4);
                    if ((num_padding) && (serializer.write(padding, num_padding, 1) != 1))
                        return false;
                    total_key_value_bytes += num_padding;
                }
            }
            (void)total_key_value_bytes;
        }

        VOGL_ASSERT(total_key_value_bytes == m_header.m_bytesOfKeyValueData);

        for (uint32_t mip_level = 0; mip_level < get_num_mips(); mip_level++)
        {
            uint32_t mip_width, mip_height, mip_depth;
            get_mip_dim(mip_level, mip_width, mip_height, mip_depth);

            const uint32_t mip_row_blocks = (mip_width + m_block_dim - 1) / m_block_dim;
            const uint32_t mip_col_blocks = (mip_height + m_block_dim - 1) / m_block_dim;
            if ((!mip_row_blocks) || (!mip_col_blocks))
                return false;

            uint32_t image_size = mip_row_blocks * mip_col_blocks * m_bytes_per_block;
            if ((m_header.m_numberOfArrayElements) || (get_num_faces() == 1))
                image_size *= (get_array_size() * get_num_faces() * mip_depth);

            if (!image_size)
            {
                VOGL_ASSERT_ALWAYS;
                return false;
            }

            if (m_opposite_endianness)
                image_size = utils::swap32(image_size);

            success = (serializer.write(&image_size, sizeof(image_size), 1) == 1);

            if (m_opposite_endianness)
                image_size = utils::swap32(image_size);

            if (!success)
                return false;

            uint32_t total_mip_size = 0;
            uint32_t total_image_data_size = 0;

            if ((!m_header.m_numberOfArrayElements) && (get_num_faces() == 6))
            {
                // plain non-array cubemap
                for (uint32_t face = 0; face < get_num_faces(); face++)
                {
                    const uint8_vec &image_data = get_image_data(get_image_index(mip_level, 0, face, 0));
                    if ((!image_data.size()) || (image_data.size() != image_size))
                        return false;

                    if (m_opposite_endianness)
                    {
                        uint8_vec tmp_image_data(image_data);
                        utils::endian_swap_mem(&tmp_image_data[0], tmp_image_data.size(), m_header.m_glTypeSize);
                        if (serializer.write(&tmp_image_data[0], tmp_image_data.size(), 1) != 1)
                            return false;
                    }
                    else if (serializer.write(&image_data[0], image_data.size(), 1) != 1)
                        return false;

                    // Not +=, but =, because of the silly image_size plain cubemap exception in the KTX file format
                    total_image_data_size = image_data.size();

                    uint32_t num_cube_pad_bytes = 3 - ((image_data.size() + 3) % 4);
                    if ((num_cube_pad_bytes) && (serializer.write(padding, num_cube_pad_bytes, 1) != 1))
                        return false;

                    total_mip_size += image_size + num_cube_pad_bytes;
                }
            }
            else
            {
                // 1D, 2D, 3D (normal or array texture), or array cubemap
                for (uint32_t array_element = 0; array_element < get_array_size(); array_element++)
                {
                    for (uint32_t face = 0; face < get_num_faces(); face++)
                    {
                        for (uint32_t zslice = 0; zslice < mip_depth; zslice++)
                        {
                            const uint8_vec &image_data = get_image_data(get_image_index(mip_level, array_element, face, zslice));
                            if (!image_data.size())
                                return false;

                            if (m_opposite_endianness)
                            {
                                uint8_vec tmp_image_data(image_data);
                                utils::endian_swap_mem(&tmp_image_data[0], tmp_image_data.size(), m_header.m_glTypeSize);
                                if (serializer.write(&tmp_image_data[0], tmp_image_data.size(), 1) != 1)
                                    return false;
                            }
                            else if (serializer.write(&image_data[0], image_data.size(), 1) != 1)
                                return false;

                            total_image_data_size += image_data.size();

                            total_mip_size += image_data.size();
                        }
                    }
                }

                uint32_t num_mip_pad_bytes = 3 - ((total_mip_size + 3) % 4);
                if ((num_mip_pad_bytes) && (serializer.write(padding, num_mip_pad_bytes, 1) != 1))
                    return false;
                total_mip_size += num_mip_pad_bytes;
            }

            VOGL_ASSERT((total_mip_size & 3) == 0);
            VOGL_ASSERT(total_image_data_size == image_size);
        }

        return true;
    }
Exemplo n.º 7
0
    bool ktx_texture::read_from_stream(data_stream_serializer &serializer)
    {
        clear();

        // Read header
        if (serializer.read(&m_header, 1, sizeof(m_header)) != sizeof(ktx_header))
            return false;

        // Check header
        if (memcmp(s_ktx_file_id, m_header.m_identifier, sizeof(m_header.m_identifier)))
            return false;

        if ((m_header.m_endianness != KTX_OPPOSITE_ENDIAN) && (m_header.m_endianness != KTX_ENDIAN))
            return false;

        m_opposite_endianness = (m_header.m_endianness == KTX_OPPOSITE_ENDIAN);
        if (m_opposite_endianness)
        {
            m_header.endian_swap();

            if ((m_header.m_glTypeSize != sizeof(uint8_t)) && (m_header.m_glTypeSize != sizeof(uint16_t)) && (m_header.m_glTypeSize != sizeof(uint32_t)))
                return false;
        }

        if (!check_header())
            return false;

        if (!compute_pixel_info())
        {
#if VOGL_KTX_PVRTEX_WORKAROUNDS
            // rg [9/10/13] - moved this check into here, instead of in compute_pixel_info(), but need to retest it.
            if ((!m_header.m_glInternalFormat) && (!m_header.m_glType) && (!m_header.m_glTypeSize) && (!m_header.m_glBaseInternalFormat))
            {
                // PVRTexTool writes bogus headers when outputting ETC1.
                console::warning("ktx_texture::compute_pixel_info: Header doesn't specify any format, assuming ETC1 and hoping for the best\n");
                m_header.m_glBaseInternalFormat = KTX_RGB;
                m_header.m_glInternalFormat = KTX_ETC1_RGB8_OES;
                m_header.m_glTypeSize = 1;
                m_block_dim = 4;
                m_bytes_per_block = 8;
            }
            else
#endif
                return false;
        }

        uint8_t pad_bytes[3];

        // Read the key value entries
        uint32_t num_key_value_bytes_remaining = m_header.m_bytesOfKeyValueData;
        while (num_key_value_bytes_remaining)
        {
            if (num_key_value_bytes_remaining < sizeof(uint32_t))
                return false;

            uint32_t key_value_byte_size;
            if (serializer.read(&key_value_byte_size, 1, sizeof(uint32_t)) != sizeof(uint32_t))
                return false;

            num_key_value_bytes_remaining -= sizeof(uint32_t);

            if (m_opposite_endianness)
                key_value_byte_size = utils::swap32(key_value_byte_size);

            if (key_value_byte_size > num_key_value_bytes_remaining)
                return false;

            uint8_vec key_value_data;
            if (key_value_byte_size)
            {
                key_value_data.resize(key_value_byte_size);
                if (serializer.read(&key_value_data[0], 1, key_value_byte_size) != key_value_byte_size)
                    return false;
            }

            m_key_values.push_back(key_value_data);

            uint32_t padding = 3 - ((key_value_byte_size + 3) % 4);
            if (padding)
            {
                if (serializer.read(pad_bytes, 1, padding) != padding)
                    return false;
            }

            num_key_value_bytes_remaining -= key_value_byte_size;
            if (num_key_value_bytes_remaining < padding)
                return false;
            num_key_value_bytes_remaining -= padding;
        }

        // Now read the mip levels
        uint32_t total_faces = get_num_mips() * get_array_size() * get_num_faces() * get_depth();
        if ((!total_faces) || (total_faces > 65535))
            return false;

// See Section 2.8 of KTX file format: No rounding to block sizes should be applied for block compressed textures.
// OK, I'm going to break that rule otherwise KTX can only store a subset of textures that DDS can handle for no good reason.
#if 0
	const uint32_t mip0_row_blocks = m_header.m_pixelWidth / m_block_dim;
	const uint32_t mip0_col_blocks = VOGL_MAX(1, m_header.m_pixelHeight) / m_block_dim;
#else
        const uint32_t mip0_row_blocks = (m_header.m_pixelWidth + m_block_dim - 1) / m_block_dim;
        const uint32_t mip0_col_blocks = (VOGL_MAX(1, m_header.m_pixelHeight) + m_block_dim - 1) / m_block_dim;
#endif
        if ((!mip0_row_blocks) || (!mip0_col_blocks))
            return false;

        const uint32_t mip0_depth = VOGL_MAX(1, m_header.m_pixelDepth);
        VOGL_NOTE_UNUSED(mip0_depth);

        bool has_valid_image_size_fields = true;
        bool disable_mip_and_cubemap_padding = false;

#if VOGL_KTX_PVRTEX_WORKAROUNDS
        {
            // PVRTexTool has a bogus KTX writer that doesn't write any imageSize fields. Nice.
            size_t expected_bytes_remaining = 0;
            for (uint32_t mip_level = 0; mip_level < get_num_mips(); mip_level++)
            {
                uint32_t mip_width, mip_height, mip_depth;
                get_mip_dim(mip_level, mip_width, mip_height, mip_depth);

                const uint32_t mip_row_blocks = (mip_width + m_block_dim - 1) / m_block_dim;
                const uint32_t mip_col_blocks = (mip_height + m_block_dim - 1) / m_block_dim;
                if ((!mip_row_blocks) || (!mip_col_blocks))
                    return false;

                expected_bytes_remaining += sizeof(uint32_t);

                if ((!m_header.m_numberOfArrayElements) && (get_num_faces() == 6))
                {
                    for (uint32_t face = 0; face < get_num_faces(); face++)
                    {
                        uint32_t slice_size = mip_row_blocks * mip_col_blocks * m_bytes_per_block;
                        expected_bytes_remaining += slice_size;

                        uint32_t num_cube_pad_bytes = 3 - ((slice_size + 3) % 4);
                        expected_bytes_remaining += num_cube_pad_bytes;
                    }
                }
                else
                {
                    uint32_t total_mip_size = 0;
                    for (uint32_t array_element = 0; array_element < get_array_size(); array_element++)
                    {
                        for (uint32_t face = 0; face < get_num_faces(); face++)
                        {
                            for (uint32_t zslice = 0; zslice < mip_depth; zslice++)
                            {
                                uint32_t slice_size = mip_row_blocks * mip_col_blocks * m_bytes_per_block;
                                total_mip_size += slice_size;
                            }
                        }
                    }
                    expected_bytes_remaining += total_mip_size;

                    uint32_t num_mip_pad_bytes = 3 - ((total_mip_size + 3) % 4);
                    expected_bytes_remaining += num_mip_pad_bytes;
                }
            }

            if (serializer.get_stream()->get_remaining() < expected_bytes_remaining)
            {
                has_valid_image_size_fields = false;
                disable_mip_and_cubemap_padding = true;
                console::warning("ktx_texture::read_from_stream: KTX file size is smaller than expected - trying to read anyway without imageSize fields\n");
            }
        }
#endif

        for (uint32_t mip_level = 0; mip_level < get_num_mips(); mip_level++)
        {
            uint32_t mip_width, mip_height, mip_depth;
            get_mip_dim(mip_level, mip_width, mip_height, mip_depth);

            const uint32_t mip_row_blocks = (mip_width + m_block_dim - 1) / m_block_dim;
            const uint32_t mip_col_blocks = (mip_height + m_block_dim - 1) / m_block_dim;
            if ((!mip_row_blocks) || (!mip_col_blocks))
                return false;

            uint32_t image_size = 0;
            if (!has_valid_image_size_fields)
            {
                if ((!m_header.m_numberOfArrayElements) && (get_num_faces() == 6))
                {
                    // The KTX file format has an exception for plain cubemap textures, argh.
                    image_size = mip_row_blocks * mip_col_blocks * m_bytes_per_block;
                }
                else
                {
                    image_size = mip_depth * mip_row_blocks * mip_col_blocks * m_bytes_per_block * get_array_size() * get_num_faces();
                }
            }
            else
            {
                if (serializer.read(&image_size, 1, sizeof(image_size)) != sizeof(image_size))
                    return false;

                if (m_opposite_endianness)
                    image_size = utils::swap32(image_size);
            }

            if (!image_size)
                return false;

            uint32_t total_mip_size = 0;

            // The KTX file format has an exception for plain cubemap textures, argh.
            if ((!m_header.m_numberOfArrayElements) && (get_num_faces() == 6))
            {
                // plain non-array cubemap
                for (uint32_t face = 0; face < get_num_faces(); face++)
                {
                    VOGL_ASSERT(m_image_data.size() == get_image_index(mip_level, 0, face, 0));

                    m_image_data.push_back(uint8_vec());
                    uint8_vec &image_data = m_image_data.back();

                    image_data.resize(image_size);
                    if (serializer.read(&image_data[0], 1, image_size) != image_size)
                        return false;

                    if (m_opposite_endianness)
                        utils::endian_swap_mem(&image_data[0], image_size, m_header.m_glTypeSize);

                    uint32_t num_cube_pad_bytes = disable_mip_and_cubemap_padding ? 0 : (3 - ((image_size + 3) % 4));
                    if (serializer.read(pad_bytes, 1, num_cube_pad_bytes) != num_cube_pad_bytes)
                        return false;

                    total_mip_size += image_size + num_cube_pad_bytes;
                }
            }
            else
            {
                uint32_t num_image_bytes_remaining = image_size;

                // 1D, 2D, 3D (normal or array texture), or array cubemap
                for (uint32_t array_element = 0; array_element < get_array_size(); array_element++)
                {
                    for (uint32_t face = 0; face < get_num_faces(); face++)
                    {
                        for (uint32_t zslice = 0; zslice < mip_depth; zslice++)
                        {
                            uint32_t slice_size = mip_row_blocks * mip_col_blocks * m_bytes_per_block;
                            if ((!slice_size) || (slice_size > num_image_bytes_remaining))
                                return false;

                            uint32_t image_index = get_image_index(mip_level, array_element, face, zslice);
                            m_image_data.ensure_element_is_valid(image_index);

                            uint8_vec &image_data = m_image_data[image_index];

                            image_data.resize(slice_size);
                            if (serializer.read(&image_data[0], 1, slice_size) != slice_size)
                                return false;

                            if (m_opposite_endianness)
                                utils::endian_swap_mem(&image_data[0], slice_size, m_header.m_glTypeSize);

                            num_image_bytes_remaining -= slice_size;

                            total_mip_size += slice_size;
                        }
                    }
                }

                if (num_image_bytes_remaining)
                {
                    VOGL_ASSERT_ALWAYS;
                    return false;
                }
            }

            uint32_t num_mip_pad_bytes = disable_mip_and_cubemap_padding ? 0 : (3 - ((total_mip_size + 3) % 4));
            if (serializer.read(pad_bytes, 1, num_mip_pad_bytes) != num_mip_pad_bytes)
                return false;
        }
        return true;
    }