背景画像のロードに失敗していた問題の修正

This commit is contained in:
tateisu 2019-10-07 00:58:18 +09:00
parent 0286543fd4
commit 0a03e8d529
6 changed files with 91 additions and 115 deletions

View File

@ -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}")

View File

@ -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
}
}
// 画像のサイズを調べる

View File

@ -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) {

View File

@ -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)
}
}

View File

@ -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

View File

@ -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.