Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5077210 authored by Ruben Brunk's avatar Ruben Brunk
Browse files

camera2: Adding TIFF writing utilities.

Adds a native image utilities library with support for:
- Writing TIFF 6.0 and TIFF EP compliant file headers.
- Additional tags defined in EXIF 2.3 and DNG 1.4 specs.

Change-Id: I7a4fef74bd5254d92baf08a3cf61af5de1b7ca83
parent c1a4e7cf
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
# Copyright 2014 The Android Open Source Project
#
# 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 $(call all-subdir-makefiles)
+82 −0
Original line number Diff line number Diff line
/*
 * Copyright 2014 The Android Open Source Project
 *
 * 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.
 */

#ifndef IMG_UTILS_BYTE_ARRAY_OUTPUT_H
#define IMG_UTILS_BYTE_ARRAY_OUTPUT_H

#include <img_utils/Output.h>

#include <utils/Errors.h>
#include <utils/Vector.h>

#include <cutils/compiler.h>
#include <stdint.h>

namespace android {
namespace img_utils {

/**
 * Utility class that accumulates written bytes into a buffer.
 */
class ANDROID_API ByteArrayOutput : public Output {
    public:

        ByteArrayOutput();

        virtual ~ByteArrayOutput();

        /**
         * Open this ByteArrayOutput.
         *
         * Returns OK on success, or a negative error code.
         */
        virtual status_t open();

        /**
         * Write bytes from the given buffer.  The number of bytes given in the count
         * argument will be written.  Bytes will be written from the given buffer starting
         * at the index given in the offset argument.
         *
         * Returns OK on success, or a negative error code.
         */
        virtual status_t write(const uint8_t* buf, size_t offset, size_t count);

        /**
         * Close this ByteArrayOutput.
         *
         * Returns OK on success, or a negative error code.
         */
        virtual status_t close();

        /**
         * Get current size of the array of bytes written.
         */
        virtual size_t getSize() const;

        /**
         * Get pointer to array of bytes written.  It is not valid to use this pointer if
         * open, write, or close is called after this method.
         */
        virtual const uint8_t* getArray() const;

    protected:
        Vector<uint8_t> mByteArray;
};

} /*namespace img_utils*/
} /*namespace android*/

#endif /*IMG_UTILS_BYTE_ARRAY_OUTPUT_H*/
+132 −0
Original line number Diff line number Diff line
/*
 * Copyright 2014 The Android Open Source Project
 *
 * 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.
 */

#ifndef IMG_UTILS_DNG_UTILS_H
#define IMG_UTILS_DNG_UTILS_H

#include <img_utils/ByteArrayOutput.h>
#include <img_utils/EndianUtils.h>

#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/RefBase.h>

#include <cutils/compiler.h>
#include <stdint.h>

namespace android {
namespace img_utils {

#define NELEMS(x) ((int) (sizeof(x) / sizeof((x)[0])))

/**
 * Utility class for building values for the OpcodeList tags specified
 * in the Adobe DNG 1.4 spec.
 */
class ANDROID_API OpcodeListBuilder : public LightRefBase<OpcodeListBuilder> {
    public:
        enum CfaLayout {
            CFA_RGGB = 0,
            CFA_GRBG,
            CFA_GBRG,
            CFA_BGGR,
        };

        OpcodeListBuilder();
        virtual ~OpcodeListBuilder();

        /**
         * Get the total size of this opcode list in bytes.
         */
        virtual size_t getSize() const;

        /**
         * Get the number of opcodes defined in this list.
         */
        virtual uint32_t getCount() const;

        /**
         * Write the opcode list into the given buffer.  This buffer
         * must be able to hold at least as many elements as returned
         * by calling the getSize() method.
         *
         * Returns OK on success, or a negative error code.
         */
        virtual status_t buildOpList(/*out*/ uint8_t* buf) const;

        /**
         * Add GainMap opcode(s) for the given metadata parameters.  The given
         * CFA layout must match the layout of the shading map passed into the
         * lensShadingMap parameter.
         *
         * Returns OK on success, or a negative error code.
         */
        virtual status_t addGainMapsForMetadata(uint32_t lsmWidth,
                                                uint32_t lsmHeight,
                                                uint32_t activeAreaTop,
                                                uint32_t activeAreaLeft,
                                                uint32_t activeAreaBottom,
                                                uint32_t activeAreaRight,
                                                CfaLayout cfa,
                                                const float* lensShadingMap);


        /**
         * Add a GainMap opcode with the given fields.  The mapGains array
         * must have mapPointsV * mapPointsH * mapPlanes elements.
         *
         * Returns OK on success, or a negative error code.
         */
        virtual status_t addGainMap(uint32_t top,
                                    uint32_t left,
                                    uint32_t bottom,
                                    uint32_t right,
                                    uint32_t plane,
                                    uint32_t planes,
                                    uint32_t rowPitch,
                                    uint32_t colPitch,
                                    uint32_t mapPointsV,
                                    uint32_t mapPointsH,
                                    double mapSpacingV,
                                    double mapSpacingH,
                                    double mapOriginV,
                                    double mapOriginH,
                                    uint32_t mapPlanes,
                                    const float* mapGains);

        // TODO: Add other Opcode methods
    protected:
        static const uint32_t FLAG_OPTIONAL = 0x1u;
        static const uint32_t FLAG_OPTIONAL_FOR_PREVIEW = 0x2u;

        enum {
            GAIN_MAP_ID = 9,
            LSM_R_IND = 0,
            LSM_GE_IND = 1,
            LSM_GO_IND = 2,
            LSM_B_IND = 3,
        };

        uint32_t mCount;
        ByteArrayOutput mOpList;
        EndianOutput mEndianOut;

};

} /*namespace img_utils*/
} /*namespace android*/

#endif /*IMG_UTILS_DNG_UTILS_H*/
+250 −0
Original line number Diff line number Diff line
/*
 * Copyright 2014 The Android Open Source Project
 *
 * 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.
 */

#ifndef IMG_UTILS_ENDIAN_UTILS
#define IMG_UTILS_ENDIAN_UTILS

#include <img_utils/Output.h>

#include <cutils/compiler.h>
#include <utils/Errors.h>
#include <stdint.h>
#include <endian.h>
#include <assert.h>

namespace android {
namespace img_utils {

/**
 * Endianness types supported.
 */
enum ANDROID_API Endianness {
    UNDEFINED_ENDIAN, // Default endianness will be used.
    BIG,
    LITTLE
};

/**
 * Convert from the native device endianness to big endian.
 */
template<typename T>
T convertToBigEndian(T in);

/**
 * Convert from the native device endianness to little endian.
 */
template<typename T>
T convertToLittleEndian(T in);

/**
 * A utility class for writing to an Output with the given endianness.
 */
class ANDROID_API EndianOutput : public Output {
    public:
        /**
         * Wrap the given Output.  Calling write methods will result in
         * writes to this output.
         */
        EndianOutput(Output* out, Endianness end=LITTLE);

        virtual ~EndianOutput();

        /**
         * Call open on the wrapped output.
         */
        virtual status_t open();

        /**
         * Call close on the wrapped output.
         */
        virtual status_t close();

        /**
         * Set the endianness to use when writing.
         */
        virtual void setEndianness(Endianness end);

        /**
         * Get the currently configured endianness.
         */
        virtual Endianness getEndianness() const;

        /**
         * Get the current number of bytes written by this EndianOutput.
         */
        virtual uint32_t getCurrentOffset() const;


        // TODO: switch write methods to uint32_t instead of size_t,
        // the max size of a TIFF files is bounded

        /**
         * The following methods will write elements from given input buffer to the output.
         * Count elements in the buffer will be written with the endianness set for this
         * EndianOutput.  If the given offset is greater than zero, that many elements will
         * be skipped in the buffer before writing.
         *
         * Returns OK on success, or a negative error code.
         */
        virtual status_t write(const uint8_t* buf, size_t offset, size_t count);

        virtual status_t write(const int8_t* buf, size_t offset, size_t count);

        virtual status_t write(const uint16_t* buf, size_t offset, size_t count);

        virtual status_t write(const int16_t* buf, size_t offset, size_t count);

        virtual status_t write(const uint32_t* buf, size_t offset, size_t count);

        virtual status_t write(const int32_t* buf, size_t offset, size_t count);

        virtual status_t write(const uint64_t* buf, size_t offset, size_t count);

        virtual status_t write(const int64_t* buf, size_t offset, size_t count);

        virtual status_t write(const float* buf, size_t offset, size_t count);

        virtual status_t write(const double* buf, size_t offset, size_t count);

    protected:
        template<typename T>
        inline status_t writeHelper(const T* buf, size_t offset, size_t count);

        uint32_t mOffset;
        Output* mOutput;
        Endianness mEndian;
};

template<typename T>
inline status_t EndianOutput::writeHelper(const T* buf, size_t offset, size_t count) {
    assert(offset <= count);
    status_t res = OK;
    size_t size = sizeof(T);
    switch(mEndian) {
        case BIG: {
            for (size_t i = offset; i < count; ++i) {
                T tmp = convertToBigEndian<T>(buf[offset + i]);
                if ((res = mOutput->write(reinterpret_cast<uint8_t*>(&tmp), 0, size))
                        != OK) {
                    return res;
                }
                mOffset += size;
            }
            break;
        }
        case LITTLE: {
            for (size_t i = offset; i < count; ++i) {
                T tmp = convertToLittleEndian<T>(buf[offset + i]);
                if ((res = mOutput->write(reinterpret_cast<uint8_t*>(&tmp), 0, size))
                        != OK) {
                    return res;
                }
                mOffset += size;
            }
            break;
        }
        default: {
            return BAD_VALUE;
        }
    }
    return res;
}

template<>
inline uint8_t convertToBigEndian(uint8_t in) {
    return in;
}

template<>
inline int8_t convertToBigEndian(int8_t in) {
    return in;
}

template<>
inline uint16_t convertToBigEndian(uint16_t in) {
    return htobe16(in);
}

template<>
inline int16_t convertToBigEndian(int16_t in) {
    return htobe16(in);
}

template<>
inline uint32_t convertToBigEndian(uint32_t in) {
    return htobe32(in);
}

template<>
inline int32_t convertToBigEndian(int32_t in) {
    return htobe32(in);
}

template<>
inline uint64_t convertToBigEndian(uint64_t in) {
    return htobe64(in);
}

template<>
inline int64_t convertToBigEndian(int64_t in) {
    return htobe64(in);
}

template<>
inline uint8_t convertToLittleEndian(uint8_t in) {
    return in;
}

template<>
inline int8_t convertToLittleEndian(int8_t in) {
    return in;
}

template<>
inline uint16_t convertToLittleEndian(uint16_t in) {
    return htole16(in);
}

template<>
inline int16_t convertToLittleEndian(int16_t in) {
    return htole16(in);
}

template<>
inline uint32_t convertToLittleEndian(uint32_t in) {
    return htole32(in);
}

template<>
inline int32_t convertToLittleEndian(int32_t in) {
    return htole32(in);
}

template<>
inline uint64_t convertToLittleEndian(uint64_t in) {
    return htole64(in);
}

template<>
inline int64_t convertToLittleEndian(int64_t in) {
    return htole64(in);
}

} /*namespace img_utils*/
} /*namespace android*/

#endif /*IMG_UTILS_ENDIAN_UTILS*/
+76 −0
Original line number Diff line number Diff line
/*
 * Copyright 2014 The Android Open Source Project
 *
 * 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.
 */

#ifndef IMG_UTILS_FILE_INPUT_H
#define IMG_UTILS_FILE_INPUT_H

#include <img_utils/Input.h>

#include <cutils/compiler.h>
#include <utils/Errors.h>
#include <utils/String8.h>
#include <stdio.h>
#include <stdint.h>

namespace android {
namespace img_utils {

/**
 * Utility class for reading from a file.
 */
class ANDROID_API FileInput : public Input {
    public:
        /**
         * Create a file input for the given path.
         */
        FileInput(String8 path);

        virtual ~FileInput();

        /**
         * Open a file descriptor to the path given in the constructor.
         *
         * Returns OK on success, or a negative error code.
         */
        virtual status_t open();

        /**
         * Read bytes from the file into the given buffer.  At most, the number
         * of bytes given in the count argument will be read.  Bytes will be written
         * into the given buffer starting at the index given in the offset argument.
         *
         * Returns the number of bytes read.  If an error has occurred, the value pointed
         * to by the given status_t pointer will be set to a negative error code.
         */
        virtual size_t read(uint8_t* buf, size_t offset, size_t count, status_t* err);

        /**
         * Close the file descriptor to the path given in the constructor.
         *
         * Returns OK on success, or a negative error code.
         */
        virtual status_t close();
    private:
        FILE *mFp;
        String8 mPath;
        bool mOpen;
};

} /*namespace img_utils*/
} /*namespace android*/


#endif /*IMG_UTILS_INPUT_H*/
Loading