背景画像のロードに失敗していた問題の修正
This commit is contained in:
parent
0286543fd4
commit
0a03e8d529
|
@ -245,8 +245,7 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
|
|||
override fun background(client : TootApiClient) : TootApiResult? {
|
||||
try {
|
||||
val backgroundDir = Column.getBackgroundImageDir(this@ActColumnCustomize)
|
||||
val file =
|
||||
File(backgroundDir, "${column.column_id}:${System.currentTimeMillis()}")
|
||||
val file = File(backgroundDir, "${column.column_id}:${System.currentTimeMillis()}")
|
||||
val fileUri = Uri.fromFile(file)
|
||||
|
||||
client.publishApiProgress("loading image from ${uriArg}")
|
||||
|
|
|
@ -51,12 +51,17 @@ fun createResizedBitmap(
|
|||
|
||||
// EXIF回転情報の取得
|
||||
val orientation : Int? = context.contentResolver.openInputStream(uri)?.use { inStream ->
|
||||
val exif = ExifInterface()
|
||||
exif.readExif(
|
||||
inStream,
|
||||
ExifInterface.Options.OPTION_IFD_0 or ExifInterface.Options.OPTION_IFD_1 or ExifInterface.Options.OPTION_IFD_EXIF
|
||||
)
|
||||
exif.getTagIntValue(ExifInterface.TAG_ORIENTATION)
|
||||
try {
|
||||
val exif = ExifInterface()
|
||||
exif.readExif(
|
||||
inStream,
|
||||
ExifInterface.Options.OPTION_IFD_0 or ExifInterface.Options.OPTION_IFD_1 or ExifInterface.Options.OPTION_IFD_EXIF
|
||||
)
|
||||
exif.getTagIntValue(ExifInterface.TAG_ORIENTATION)
|
||||
}catch(ex:Throwable){
|
||||
log.w(ex,"createResizedBitmap: exif parse failed." )
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
// 画像のサイズを調べる
|
||||
|
|
|
@ -97,10 +97,10 @@ class ExifInterface {
|
|||
*/
|
||||
val thumbnailBytes : ByteArray?
|
||||
get() = when {
|
||||
mData.hasCompressedThumbnail() -> mData.compressedThumbnail
|
||||
mData.hasUncompressedStrip() -> null // TODO: implement this
|
||||
else -> null
|
||||
}
|
||||
mData.hasCompressedThumbnail() -> mData.compressedThumbnail
|
||||
mData.hasUncompressedStrip() -> null // TODO: implement this
|
||||
else -> null
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the thumbnail if it is jpeg compressed, or null if none exists.
|
||||
|
@ -308,16 +308,12 @@ class ExifInterface {
|
|||
* @throws java.io.IOException for I/O error
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
fun readExif(inStream : InputStream?, options : Int) {
|
||||
requireNotNull(inStream) { NULL_ARGUMENT_STRING }
|
||||
val d : ExifData
|
||||
fun readExif(inStream : InputStream, options : Int) {
|
||||
try {
|
||||
d = ExifReader(this).read(inStream, options)
|
||||
mData = ExifReader(this).read(inStream, options)
|
||||
} catch(e : ExifInvalidFormatException) {
|
||||
throw IOException("Invalid exif format : $e")
|
||||
}
|
||||
|
||||
mData = d
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1223,12 +1219,12 @@ class ExifInterface {
|
|||
val t = getTag(tagId, ifdId) ?: return 0
|
||||
return t.componentCount
|
||||
}
|
||||
|
||||
|
||||
// Gets the defined type for a tag.
|
||||
// tagId : a defined tag constant, e.g. [.TAG_IMAGE_WIDTH].
|
||||
fun getDefinedTagType(tagId : Int) : Short {
|
||||
val info = tagInfo.get(tagId)
|
||||
return if(info == 0) - 1 else getTypeFromInfo(info)
|
||||
return if(info == 0) - 1 else getTypeFromInfo(info)
|
||||
}
|
||||
|
||||
fun buildUninitializedTag(tagId : Int) : ExifTag? {
|
||||
|
@ -1362,7 +1358,7 @@ class ExifInterface {
|
|||
}
|
||||
|
||||
private fun getTagDefinitionsForTagId(tagId : Short) : IntArray? {
|
||||
val ifds = IfdData.ifds
|
||||
val ifds = IfdId.list
|
||||
val defs = IntArray(ifds.size)
|
||||
var counter = 0
|
||||
val infos = tagInfo
|
||||
|
@ -2809,7 +2805,7 @@ class ExifInterface {
|
|||
// IFD Interoperability tags
|
||||
val TAG_INTEROPERABILITY_INDEX = defineTag(IfdId.TYPE_IFD_INTEROPERABILITY, 1.toShort())
|
||||
|
||||
val DEFAULT_BYTE_ORDER :ByteOrder = ByteOrder.BIG_ENDIAN
|
||||
val DEFAULT_BYTE_ORDER : ByteOrder = ByteOrder.BIG_ENDIAN
|
||||
private const val NULL_ARGUMENT_STRING = "Argument is null"
|
||||
|
||||
private const val GPS_DATE_FORMAT_STR = "yyyy:MM:dd"
|
||||
|
@ -2921,7 +2917,7 @@ class ExifInterface {
|
|||
|
||||
fun getAllowedIfdsFromInfo(info : Int) : IntArray? {
|
||||
val ifdFlags = getAllowedIfdFlagsFromInfo(info)
|
||||
val ifds = IfdData.ifds
|
||||
val ifds = IfdId.list
|
||||
val l = ArrayList<Int>()
|
||||
for(i in 0 until IfdId.TYPE_IFD_COUNT) {
|
||||
val flag = ifdFlags shr i and 1
|
||||
|
@ -3031,7 +3027,7 @@ class ExifInterface {
|
|||
return 0
|
||||
}
|
||||
var flags = 0
|
||||
val ifds = IfdData.ifds
|
||||
val ifds = IfdId.list
|
||||
for(i in 0 until IfdId.TYPE_IFD_COUNT) {
|
||||
for(j in allowedIfds) {
|
||||
if(ifds[i] == j) {
|
||||
|
@ -3106,7 +3102,7 @@ class ExifInterface {
|
|||
}
|
||||
|
||||
fun isIfdAllowed(info : Int, ifd : Int) : Boolean {
|
||||
val ifds = IfdData.ifds
|
||||
val ifds = IfdId.list
|
||||
val ifdFlags = getAllowedIfdFlagsFromInfo(info)
|
||||
for(i in ifds.indices) {
|
||||
if(ifd == ifds[i] && ifdFlags shr i and 1 == 1) {
|
||||
|
|
|
@ -26,37 +26,29 @@ import java.nio.charset.Charset
|
|||
import java.util.*
|
||||
import kotlin.math.min
|
||||
|
||||
internal open class ExifParser @Throws(IOException::class, ExifInvalidFormatException::class)
|
||||
internal open class ExifParser
|
||||
@Throws(IOException::class, ExifInvalidFormatException::class)
|
||||
private constructor(
|
||||
inputStream : InputStream?,
|
||||
inputStream : InputStream,
|
||||
private val mOptions : Int,
|
||||
private val mInterface : ExifInterface
|
||||
) {
|
||||
|
||||
private val mCorrespondingEvent = TreeMap<Int, Any>()
|
||||
private val mTiffStream : CountedDataInputStream?
|
||||
private var mIfdStartOffset = 0
|
||||
|
||||
/**
|
||||
* Gets number of tags in the current IFD area.
|
||||
*/
|
||||
// number of tags in the current IFD area.
|
||||
private var tagCountInCurrentIfd = 0
|
||||
|
||||
/**
|
||||
* Gets the ID of current IFD.
|
||||
* the ID of current IFD.
|
||||
*
|
||||
* @see IfdId.TYPE_IFD_0
|
||||
*
|
||||
* @see IfdId.TYPE_IFD_1
|
||||
*
|
||||
* @see IfdId.TYPE_IFD_GPS
|
||||
*
|
||||
* @see IfdId.TYPE_IFD_INTEROPERABILITY
|
||||
*
|
||||
* @see IfdId.TYPE_IFD_EXIF
|
||||
*/
|
||||
var currentIfd : Int = 0
|
||||
private set
|
||||
|
||||
/**
|
||||
* If [.next] return [.EVENT_NEW_TAG] or
|
||||
* [.EVENT_VALUE_OF_REGISTERED_TAG], call this function to get the
|
||||
|
@ -101,7 +93,7 @@ private constructor(
|
|||
private set
|
||||
var jpegProcess : Short = 0
|
||||
private set
|
||||
private val mSections : MutableList<Section>
|
||||
|
||||
var uncompressedDataPosition = 0
|
||||
private set
|
||||
|
||||
|
@ -135,41 +127,41 @@ private constructor(
|
|||
/**
|
||||
* Gets the byte order of the current InputStream.
|
||||
*/
|
||||
val byteOrder : ByteOrder?
|
||||
get() = mTiffStream?.byteOrder
|
||||
val byteOrder : ByteOrder
|
||||
get() = mTiffStream.byteOrder
|
||||
|
||||
val sections : List<Section>
|
||||
get() = mSections
|
||||
|
||||
private val mCorrespondingEvent = TreeMap<Int, Any>()
|
||||
|
||||
private val mSections = ArrayList<Section>(0)
|
||||
|
||||
private var mIfdStartOffset = 0
|
||||
|
||||
private val mTiffStream : CountedDataInputStream = seekTiffData(inputStream)
|
||||
|
||||
init {
|
||||
if(inputStream == null) {
|
||||
throw IOException("Null argument inputStream to ExifParser")
|
||||
}
|
||||
|
||||
Log.v(TAG, "Reading exif...")
|
||||
mSections = ArrayList(0)
|
||||
mTiffStream = seekTiffData(inputStream)
|
||||
|
||||
// Log.d( TAG, "sections size: " + mSections.size() );
|
||||
|
||||
val tiffStream = mTiffStream
|
||||
if(tiffStream != null) {
|
||||
parseTiffHeader(tiffStream)
|
||||
|
||||
val offset = tiffStream.readUnsignedInt()
|
||||
if(offset > Integer.MAX_VALUE) {
|
||||
throw ExifInvalidFormatException("Invalid offset $offset")
|
||||
}
|
||||
mIfd0Position = offset.toInt()
|
||||
currentIfd = IfdId.TYPE_IFD_0
|
||||
|
||||
if(isIfdRequested(IfdId.TYPE_IFD_0) || needToParseOffsetsInCurrentIfd()) {
|
||||
registerIfd(IfdId.TYPE_IFD_0, offset)
|
||||
if(offset != DEFAULT_IFD0_OFFSET.toLong()) {
|
||||
val ba = ByteArray(offset.toInt() - DEFAULT_IFD0_OFFSET)
|
||||
mDataAboveIfd0 = ba
|
||||
read(ba)
|
||||
}
|
||||
|
||||
parseTiffHeader(tiffStream)
|
||||
|
||||
val offset = tiffStream.readUnsignedInt()
|
||||
if(offset > Integer.MAX_VALUE) {
|
||||
throw ExifInvalidFormatException("Invalid offset $offset")
|
||||
}
|
||||
mIfd0Position = offset.toInt()
|
||||
currentIfd = IfdId.TYPE_IFD_0
|
||||
|
||||
if(isIfdRequested(IfdId.TYPE_IFD_0) || needToParseOffsetsInCurrentIfd()) {
|
||||
registerIfd(IfdId.TYPE_IFD_0, offset)
|
||||
if(offset != DEFAULT_IFD0_OFFSET.toLong()) {
|
||||
val ba = ByteArray(offset.toInt() - DEFAULT_IFD0_OFFSET)
|
||||
mDataAboveIfd0 = ba
|
||||
read(ba)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,17 +181,17 @@ private constructor(
|
|||
}
|
||||
|
||||
@Throws(IOException::class, ExifInvalidFormatException::class)
|
||||
private fun seekTiffData(inputStream : InputStream) : CountedDataInputStream? {
|
||||
private fun seekTiffData(inputStream : InputStream) : CountedDataInputStream {
|
||||
val dataStream = CountedDataInputStream(inputStream)
|
||||
var tiffStream : CountedDataInputStream? = null
|
||||
|
||||
var a = dataStream.readUnsignedByte()
|
||||
val b = dataStream.readUnsignedByte()
|
||||
|
||||
if(a != 0xFF || b != JpegHeader.TAG_SOI) {
|
||||
Log.e(TAG, "invalid jpeg header")
|
||||
return null
|
||||
}
|
||||
|
||||
if(a == 137 && b == 80) error("maybe PNG image")
|
||||
|
||||
if(a != 0xFF || b != JpegHeader.TAG_SOI) error("invalid jpeg header")
|
||||
|
||||
while(true) {
|
||||
val itemlen : Int
|
||||
|
@ -218,7 +210,7 @@ private constructor(
|
|||
}
|
||||
|
||||
if(a > 10) {
|
||||
Log.w(TAG, "Extraneous " + (a - 1) + " padding bytes before section " + marker)
|
||||
Log.w(TAG, "Extraneous ${a - 1} padding bytes before section $marker")
|
||||
}
|
||||
|
||||
val section = Section()
|
||||
|
@ -257,7 +249,7 @@ private constructor(
|
|||
// stop before hitting compressed data
|
||||
mSections.add(section)
|
||||
uncompressedDataPosition = dataStream.readByteCount
|
||||
return tiffStream
|
||||
return tiffStream !!
|
||||
}
|
||||
|
||||
JpegHeader.TAG_M_DQT ->
|
||||
|
@ -267,10 +259,9 @@ private constructor(
|
|||
JpegHeader.TAG_M_DHT -> {
|
||||
}
|
||||
|
||||
// in case it's a tables-only JPEG stream
|
||||
JpegHeader.TAG_M_EOI -> {
|
||||
// in case it's a tables-only JPEG stream
|
||||
Log.w(TAG, "No image in jpeg!")
|
||||
return null
|
||||
error("\"No image in jpeg!\"")
|
||||
}
|
||||
|
||||
JpegHeader.TAG_M_COM ->
|
||||
|
@ -475,9 +466,8 @@ private constructor(
|
|||
* Equivalent to read(buffer, 0, buffer.length).
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
fun read(buffer : ByteArray) : Int {
|
||||
return mTiffStream?.read(buffer) ?: 0
|
||||
}
|
||||
fun read(buffer : ByteArray) : Int = mTiffStream.read(buffer)
|
||||
|
||||
//
|
||||
// /**
|
||||
// * Parses the the given InputStream with default options; that is, every IFD
|
||||
|
@ -504,7 +494,6 @@ private constructor(
|
|||
*/
|
||||
@Throws(IOException::class, ExifInvalidFormatException::class)
|
||||
operator fun next() : Int {
|
||||
mTiffStream ?: return EVENT_END
|
||||
|
||||
val offset = mTiffStream.readByteCount
|
||||
val endOfTags = mIfdStartOffset + OFFSET_SIZE + TAG_SIZE * tagCountInCurrentIfd
|
||||
|
@ -601,13 +590,11 @@ private constructor(
|
|||
*/
|
||||
@Throws(IOException::class, ExifInvalidFormatException::class)
|
||||
protected fun skipRemainingTagsInCurrentIfd() {
|
||||
if(mTiffStream == null) return
|
||||
|
||||
val endOfTags = mIfdStartOffset + OFFSET_SIZE + TAG_SIZE * tagCountInCurrentIfd
|
||||
var offset = mTiffStream.readByteCount
|
||||
if(offset > endOfTags) {
|
||||
return
|
||||
}
|
||||
if(offset > endOfTags) return
|
||||
|
||||
if(mNeedToParseOffsetsInCurrentIfd) {
|
||||
while(offset < endOfTags) {
|
||||
val tag = readTag()
|
||||
|
@ -632,7 +619,8 @@ private constructor(
|
|||
|
||||
@Throws(IOException::class)
|
||||
private fun skipTo(offset : Int) {
|
||||
mTiffStream?.skipTo(offset.toLong())
|
||||
mTiffStream.skipTo(offset.toLong())
|
||||
|
||||
// Log.v(TAG, "available: " + mTiffStream.available() );
|
||||
while(! mCorrespondingEvent.isEmpty() && mCorrespondingEvent.firstKey() < offset) {
|
||||
mCorrespondingEvent.pollFirstEntry()
|
||||
|
@ -649,7 +637,6 @@ private constructor(
|
|||
* @see .EVENT_VALUE_OF_REGISTERED_TAG
|
||||
*/
|
||||
fun registerForTagValue(tag : ExifTag) {
|
||||
mTiffStream ?: return
|
||||
if(tag.offset >= mTiffStream.readByteCount) {
|
||||
mCorrespondingEvent[tag.offset] = ExifTagEvent(tag, true)
|
||||
}
|
||||
|
@ -665,7 +652,6 @@ private constructor(
|
|||
|
||||
@Throws(IOException::class, ExifInvalidFormatException::class)
|
||||
private fun readTag() : ExifTag? {
|
||||
mTiffStream ?: return null
|
||||
|
||||
val tagId = mTiffStream.readShort()
|
||||
val dataFormat = mTiffStream.readShort()
|
||||
|
@ -802,7 +788,6 @@ private constructor(
|
|||
|
||||
@Throws(IOException::class)
|
||||
fun readFullTagValue(tag : ExifTag) {
|
||||
mTiffStream ?: return
|
||||
|
||||
// Some invalid images contains tags with wrong size, check it here
|
||||
val type = tag.dataType
|
||||
|
@ -869,10 +854,8 @@ private constructor(
|
|||
* Reads bytes from the InputStream.
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
protected fun read(buffer : ByteArray, offset : Int, length : Int) : Int {
|
||||
mTiffStream ?: return 0
|
||||
return mTiffStream.read(buffer, offset, length)
|
||||
}
|
||||
protected fun read(buffer : ByteArray, offset : Int, length : Int) : Int =
|
||||
mTiffStream.read(buffer, offset, length)
|
||||
|
||||
/**
|
||||
* Reads a String from the InputStream with US-ASCII charset. The parser
|
||||
|
@ -889,7 +872,7 @@ private constructor(
|
|||
@JvmOverloads
|
||||
protected fun readString(n : Int, charset : Charset = US_ASCII) : String =
|
||||
when {
|
||||
mTiffStream == null || n <= 0 -> ""
|
||||
n <= 0 -> ""
|
||||
else -> mTiffStream.readString(n, charset)
|
||||
}
|
||||
|
||||
|
@ -898,10 +881,8 @@ private constructor(
|
|||
* InputStream.
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
protected fun readUnsignedShort() : Int {
|
||||
val iv = mTiffStream?.readShort() ?: 0
|
||||
return iv.toInt() and 0xffff
|
||||
}
|
||||
protected fun readUnsignedShort() : Int =
|
||||
mTiffStream.readShort().toInt() and 0xffff
|
||||
|
||||
/**
|
||||
* Reads value of type [ExifTag.TYPE_UNSIGNED_LONG] from the
|
||||
|
@ -927,9 +908,8 @@ private constructor(
|
|||
* Reads value of type [ExifTag.TYPE_LONG] from the InputStream.
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
protected fun readLong() : Long {
|
||||
return mTiffStream?.readInt()?.toLong() ?: 0L
|
||||
}
|
||||
protected fun readLong() : Long =
|
||||
mTiffStream.readInt().toLong()
|
||||
|
||||
/**
|
||||
* Reads value of type [ExifTag.TYPE_RATIONAL] from the InputStream.
|
||||
|
@ -1184,8 +1164,7 @@ private constructor(
|
|||
* @throws ExifInvalidFormatException
|
||||
*/
|
||||
@Throws(IOException::class, ExifInvalidFormatException::class)
|
||||
fun parse(inputStream : InputStream, options : Int, iRef : ExifInterface) : ExifParser {
|
||||
return ExifParser(inputStream, options, iRef)
|
||||
}
|
||||
fun parse(inputStream : InputStream, options : Int, iRef : ExifInterface) : ExifParser =
|
||||
ExifParser(inputStream, options, iRef)
|
||||
}
|
||||
}
|
|
@ -37,7 +37,7 @@ internal class ExifReader(private val mInterface : ExifInterface) {
|
|||
@Throws(ExifInvalidFormatException::class, IOException::class)
|
||||
fun read(inputStream : InputStream, options : Int) : ExifData {
|
||||
val parser = ExifParser.parse(inputStream, options, mInterface)
|
||||
val exifData = ExifData(parser.byteOrder !!)
|
||||
val exifData = ExifData(parser.byteOrder )
|
||||
exifData.sections = parser.sections
|
||||
exifData.mUncompressedDataPosition = parser.uncompressedDataPosition
|
||||
|
||||
|
|
|
@ -30,6 +30,14 @@ object IfdId {
|
|||
const val TYPE_IFD_GPS = 4
|
||||
/* This is used in ExifData to allocate enough IfdData */
|
||||
const val TYPE_IFD_COUNT = 5
|
||||
|
||||
val list = intArrayOf(
|
||||
TYPE_IFD_0,
|
||||
TYPE_IFD_1,
|
||||
TYPE_IFD_EXIF,
|
||||
TYPE_IFD_INTEROPERABILITY,
|
||||
TYPE_IFD_GPS
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,17 +47,6 @@ internal class IfdData(
|
|||
// the ID of this IFD.
|
||||
val id : Int
|
||||
) {
|
||||
|
||||
companion object {
|
||||
val ifds = intArrayOf(
|
||||
IfdId.TYPE_IFD_0,
|
||||
IfdId.TYPE_IFD_1,
|
||||
IfdId.TYPE_IFD_EXIF,
|
||||
IfdId.TYPE_IFD_INTEROPERABILITY,
|
||||
IfdId.TYPE_IFD_GPS
|
||||
)
|
||||
}
|
||||
|
||||
private val mExifTags = HashMap<Short, ExifTag>()
|
||||
|
||||
// the offset of next IFD.
|
||||
|
|
Loading…
Reference in New Issue