Skip to content

Commit

Permalink
Merge pull request #5465 from grzesiek2010/COLLECT-5435_2
Browse files Browse the repository at this point in the history
Fixed attaching gifs and scaling down images
  • Loading branch information
grzesiek2010 authored Mar 10, 2023
2 parents 9440f49 + 35d8f95 commit 34a0b91
Show file tree
Hide file tree
Showing 21 changed files with 587 additions and 598 deletions.
4 changes: 4 additions & 0 deletions androidshared/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ dependencies {
implementation Dependencies.androidx_fragment_ktx
implementation Dependencies.androidx_preference_ktx
implementation Dependencies.timber
implementation Dependencies.androidx_exinterface

testImplementation project(':testshared')
testImplementation Dependencies.junit
Expand All @@ -70,5 +71,8 @@ dependencies {
testImplementation Dependencies.robolectric
testImplementation Dependencies.mockito_kotlin

androidTestImplementation Dependencies.androidx_test_ext_junit
androidTestImplementation Dependencies.junit

debugImplementation project(':fragmentstest')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
/*
* Copyright 2017 Nafundi
*
* 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.
*/
package org.odk.collect.androidshared.bitmap

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import androidx.exifinterface.media.ExifInterface
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.MatcherAssert.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import java.io.File

@RunWith(AndroidJUnit4::class)
class ImageCompressorTest {
private lateinit var testImagePath: String
private val imageCompressor = ImageCompressor

@Test
fun imageShouldNotBeChangedIfMaxPixelsIsZero() {
saveTestBitmap(3000, 2000)
imageCompressor.execute(testImagePath, 0)

val image = ImageFileUtils.getBitmap(testImagePath, BitmapFactory.Options())!!

assertThat(3000, equalTo(image.width))
assertThat(2000, equalTo(image.height))
}

@Test
fun imageShouldNotBeChangedIfMaxPixelsIsSmallerThanZero() {
saveTestBitmap(3000, 2000)
imageCompressor.execute(testImagePath, -10)

val image = ImageFileUtils.getBitmap(testImagePath, BitmapFactory.Options())!!

assertThat(3000, equalTo(image.width))
assertThat(2000, equalTo(image.height))
}

@Test
fun imageShouldNotBeChangedIfMaxPixelsIsNotSmallerThanTheEdgeWhenWidthIsBiggerThanHeight() {
saveTestBitmap(3000, 2000)
imageCompressor.execute(testImagePath, 3000)

val image = ImageFileUtils.getBitmap(testImagePath, BitmapFactory.Options())!!

assertThat(3000, equalTo(image.width))
assertThat(2000, equalTo(image.height))
}

@Test
fun imageShouldNotBeChangedIfMaxPixelsIsNotSmallerThanTheLongEdgeWhenWidthIsSmallerThanHeight() {
saveTestBitmap(2000, 3000)
imageCompressor.execute(testImagePath, 4000)

val image = ImageFileUtils.getBitmap(testImagePath, BitmapFactory.Options())!!

assertThat(2000, equalTo(image.width))
assertThat(3000, equalTo(image.height))
}

@Test
fun imageShouldNotBeChangedIfMaxPixelsIsNotSmallerThanTheLongEdgeWhenWidthEqualsHeight() {
saveTestBitmap(3000, 3000)
imageCompressor.execute(testImagePath, 3000)

val image = ImageFileUtils.getBitmap(testImagePath, BitmapFactory.Options())!!

assertThat(3000, equalTo(image.width))
assertThat(3000, equalTo(image.height))
}

@Test
fun imageShouldBeCompressedIfMaxPixelsIsSmallerThanTheLongEdgeWhenWidthIsBiggerThanHeight() {
saveTestBitmap(4000, 3000)
imageCompressor.execute(testImagePath, 2000)

val image = ImageFileUtils.getBitmap(testImagePath, BitmapFactory.Options())!!

assertThat(2000, equalTo(image.width))
assertThat(1500, equalTo(image.height))
}

@Test
fun imageShouldBeCompressedIfMaxPixelsIsSmallerThanTheLongEdgeWhenWidthIsSmallerThanHeight() {
saveTestBitmap(3000, 4000)
imageCompressor.execute(testImagePath, 2000)

val image = ImageFileUtils.getBitmap(testImagePath, BitmapFactory.Options())!!

assertThat(1500, equalTo(image.width))
assertThat(2000, equalTo(image.height))
}

@Test
fun imageShouldBeCompressedIfMaxPixelsIsSmallerThanTheLongEdgeWhenWidthEqualsHeight() {
saveTestBitmap(3000, 3000)
imageCompressor.execute(testImagePath, 2000)

val image = ImageFileUtils.getBitmap(testImagePath, BitmapFactory.Options())!!

assertThat(2000, equalTo(image.width))
assertThat(2000, equalTo(image.height))
}

@Test
fun keepExifAfterScaling() {
val attributes = mutableMapOf(
// supported exif tags
ExifInterface.TAG_DATETIME to "2014:01:23 14:57:18",
ExifInterface.TAG_DATETIME_ORIGINAL to "2014:01:23 14:57:18",
ExifInterface.TAG_DATETIME_DIGITIZED to "2014:01:23 14:57:18",
ExifInterface.TAG_OFFSET_TIME to "+1:00",
ExifInterface.TAG_OFFSET_TIME_ORIGINAL to "+1:00",
ExifInterface.TAG_OFFSET_TIME_DIGITIZED to "+1:00",
ExifInterface.TAG_SUBSEC_TIME to "First photo",
ExifInterface.TAG_SUBSEC_TIME_ORIGINAL to "0",
ExifInterface.TAG_SUBSEC_TIME_DIGITIZED to "0",
ExifInterface.TAG_IMAGE_DESCRIPTION to "Photo from Poland",
ExifInterface.TAG_MAKE to "OLYMPUS IMAGING CORP",
ExifInterface.TAG_MODEL to "STYLUS1",
ExifInterface.TAG_SOFTWARE to "Version 1.0",
ExifInterface.TAG_ARTIST to "Grzegorz",
ExifInterface.TAG_COPYRIGHT to "G",
ExifInterface.TAG_MAKER_NOTE to "OLYMPUS",
ExifInterface.TAG_USER_COMMENT to "First photo",
ExifInterface.TAG_IMAGE_UNIQUE_ID to "123456789",
ExifInterface.TAG_CAMERA_OWNER_NAME to "John",
ExifInterface.TAG_BODY_SERIAL_NUMBER to "987654321",
ExifInterface.TAG_GPS_ALTITUDE to "41/1",
ExifInterface.TAG_GPS_ALTITUDE_REF to "0",
ExifInterface.TAG_GPS_DATESTAMP to "2014:01:23",
ExifInterface.TAG_GPS_TIMESTAMP to "14:57:18",
ExifInterface.TAG_GPS_LATITUDE to "50/1,49/1,8592/1000",
ExifInterface.TAG_GPS_LATITUDE_REF to "N",
ExifInterface.TAG_GPS_LONGITUDE to "0/1,8/1,12450/1000",
ExifInterface.TAG_GPS_LONGITUDE_REF to "W",
ExifInterface.TAG_GPS_SATELLITES to "8",
ExifInterface.TAG_GPS_STATUS to "A",
ExifInterface.TAG_ORIENTATION to "1",

// unsupported exif tags
ExifInterface.TAG_THUMBNAIL_IMAGE_LENGTH to "5",
ExifInterface.TAG_DNG_VERSION to "100",
)

saveTestBitmap(3000, 4000, attributes)
imageCompressor.execute(testImagePath, 2000)

val exifData = ExifInterface(testImagePath)
for (attributeName in attributes.keys) {
if (attributeName == ExifInterface.TAG_THUMBNAIL_IMAGE_LENGTH ||
attributeName == ExifInterface.TAG_DNG_VERSION
) {
assertThat(exifData.getAttribute(attributeName), equalTo(null))
} else {
assertThat(exifData.getAttribute(attributeName), equalTo(attributes[attributeName]))
}
}
}

@Test
fun verifyNoRotationAppliedForExifRotation() {
val attributes = mapOf(ExifInterface.TAG_ORIENTATION to ExifInterface.ORIENTATION_ROTATE_90.toString())
saveTestBitmap(3000, 4000, attributes)
imageCompressor.execute(testImagePath, 4000)

val image = ImageFileUtils.getBitmap(testImagePath, BitmapFactory.Options())!!

assertThat(3000, equalTo(image.width))
assertThat(4000, equalTo(image.height))
}

private fun saveTestBitmap(width: Int, height: Int, attributes: Map<String, String> = emptyMap()) {
testImagePath = File.createTempFile("test", ".jpg").absolutePath

val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
ImageFileUtils.saveBitmapToFile(bitmap, testImagePath)
val exifInterface = ExifInterface(testImagePath)
for ((key, value) in attributes) {
exifInterface.setAttribute(key, value)
}
exifInterface.saveAttributes()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.odk.collect.android.instrumented.utilities
package org.odk.collect.androidshared.bitmap

import android.content.Context
import android.graphics.Bitmap
Expand All @@ -26,7 +26,6 @@ import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.odk.collect.android.utilities.ImageFileUtils
import timber.log.Timber
import java.io.File
import java.io.IOException
Expand All @@ -50,7 +49,10 @@ class ImageFileUtilsTest {
attributes[ExifInterface.TAG_ORIENTATION] = ExifInterface.ORIENTATION_ROTATE_90.toString()
saveTestBitmapToFile(sourceFile.absolutePath, attributes)
ImageFileUtils.copyImageAndApplyExifRotation(sourceFile, destinationFile)
val image = ImageFileUtils.getBitmap(destinationFile.absolutePath, BitmapFactory.Options())!!
val image = ImageFileUtils.getBitmap(
destinationFile.absolutePath,
BitmapFactory.Options()
)!!

assertEquals(2, image.width)
assertEquals(1, image.height)
Expand All @@ -64,7 +66,10 @@ class ImageFileUtilsTest {
attributes[ExifInterface.TAG_ORIENTATION] = ExifInterface.ORIENTATION_ROTATE_270.toString()
saveTestBitmapToFile(sourceFile.absolutePath, attributes)
ImageFileUtils.copyImageAndApplyExifRotation(sourceFile, destinationFile)
val image = ImageFileUtils.getBitmap(destinationFile.absolutePath, BitmapFactory.Options())!!
val image = ImageFileUtils.getBitmap(
destinationFile.absolutePath,
BitmapFactory.Options()
)!!

assertEquals(2, image.width)
assertEquals(1, image.height)
Expand All @@ -78,7 +83,10 @@ class ImageFileUtilsTest {
attributes[ExifInterface.TAG_ORIENTATION] = ExifInterface.ORIENTATION_ROTATE_180.toString()
saveTestBitmapToFile(sourceFile.absolutePath, attributes)
ImageFileUtils.copyImageAndApplyExifRotation(sourceFile, destinationFile)
val image = ImageFileUtils.getBitmap(destinationFile.absolutePath, BitmapFactory.Options())!!
val image = ImageFileUtils.getBitmap(
destinationFile.absolutePath,
BitmapFactory.Options()
)!!

assertEquals(1, image.width)
assertEquals(2, image.height)
Expand All @@ -92,7 +100,10 @@ class ImageFileUtilsTest {
attributes[ExifInterface.TAG_ORIENTATION] = ExifInterface.ORIENTATION_UNDEFINED.toString()
saveTestBitmapToFile(sourceFile.absolutePath, attributes)
ImageFileUtils.copyImageAndApplyExifRotation(sourceFile, destinationFile)
val image = ImageFileUtils.getBitmap(destinationFile.absolutePath, BitmapFactory.Options())!!
val image = ImageFileUtils.getBitmap(
destinationFile.absolutePath,
BitmapFactory.Options()
)!!

assertEquals(1, image.width)
assertEquals(2, image.height)
Expand All @@ -105,7 +116,10 @@ class ImageFileUtilsTest {
fun copyAndRotateImageNoExif() {
saveTestBitmapToFile(sourceFile.absolutePath, null)
ImageFileUtils.copyImageAndApplyExifRotation(sourceFile, destinationFile)
val image = ImageFileUtils.getBitmap(destinationFile.absolutePath, BitmapFactory.Options())!!
val image = ImageFileUtils.getBitmap(
destinationFile.absolutePath,
BitmapFactory.Options()
)!!

assertEquals(1, image.width)
assertEquals(2, image.height)
Expand Down
Loading

0 comments on commit 34a0b91

Please sign in to comment.