Skip to content

Commit fc411b0

Browse files
committed
Decouple export from preview ViewInfo
1 parent 62db7b2 commit fc411b0

4 files changed

Lines changed: 13 additions & 139 deletions

File tree

app/src/main/java/me/rosuh/easywatermark/ui/ComposeMainActivity.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ import androidx.navigation.compose.rememberNavController
6060
import me.rosuh.easywatermark.R
6161

6262
import me.rosuh.easywatermark.data.model.FuncTitleModel
63-
import me.rosuh.easywatermark.data.model.ViewInfo
6463
import android.widget.Toast
6564
import me.rosuh.easywatermark.BuildConfig
6665
import me.rosuh.easywatermark.ui.about.AboutScreen
@@ -234,7 +233,6 @@ class ComposeMainActivity : ComponentActivity() {
234233
val userPreferences by viewModel.userPreferences.collectAsStateWithLifecycle()
235234
val state by viewModel.launchScreenUiStateFlow.collectAsStateWithLifecycle()
236235
val context = LocalContext.current
237-
val viewInfo by viewModel.viewInfoStateFlow.collectAsStateWithLifecycle()
238236
val templates by viewModel.templateListFlow.collectAsStateWithLifecycle()
239237

240238
// [DEBUG] temporary export instrumentation — remove after diagnosing
@@ -244,10 +242,9 @@ class ComposeMainActivity : ComponentActivity() {
244242
}
245243

246244
val doExport: () -> Unit = {
247-
Log.d("EXPORT", "doExport called imageList=${state.selectedImageList.size} viewInfo=$viewInfo")
245+
Log.d("EXPORT", "doExport called imageList=${state.selectedImageList.size}")
248246
viewModel.saveImage(
249247
context.contentResolver,
250-
viewInfo,
251248
state.selectedImageList
252249
)
253250
}
@@ -413,8 +410,8 @@ class ComposeMainActivity : ComponentActivity() {
413410
viewModel.saveOutput(level = q)
414411
},
415412
onExportClick = {
416-
Log.d("EXPORT", "click viewInfo=$viewInfo isEmpty=${viewInfo == ViewInfo.Empty} sdk=${Build.VERSION.SDK_INT}")
417-
if (viewInfo == ViewInfo.Empty) {
413+
Log.d("EXPORT", "click selectedImages=${state.selectedImageList.size} sdk=${Build.VERSION.SDK_INT}")
414+
if (state.selectedImageList.isEmpty()) {
418415
return@SaveExportSheet
419416
}
420417
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {

app/src/main/java/me/rosuh/easywatermark/ui/MainViewModel.kt

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import android.content.Context
99
import android.content.Intent
1010
import android.graphics.Bitmap
1111
import android.graphics.Canvas
12-
import android.graphics.Matrix
1312
import android.graphics.Paint
1413
import android.net.Uri
1514
import android.os.Build
@@ -59,9 +58,7 @@ import me.rosuh.easywatermark.data.repo.MemorySettingRepo
5958
import me.rosuh.easywatermark.data.repo.TemplateRepository
6059
import me.rosuh.easywatermark.data.repo.UserConfigRepository
6160
import me.rosuh.easywatermark.data.repo.WaterMarkRepository
62-
import me.rosuh.easywatermark.ui.widget.WaterMarkImageView
6361
import me.rosuh.easywatermark.utils.FileUtils.Companion.outPutFolderName
64-
import me.rosuh.easywatermark.utils.bitmap.calculateInSampleSize
6562
import me.rosuh.easywatermark.utils.bitmap.decodeBitmapFromUri
6663
import me.rosuh.easywatermark.utils.bitmap.decodeSampledBitmapFromResource
6764
import me.rosuh.easywatermark.utils.ktx.applyConfig
@@ -137,7 +134,6 @@ class MainViewModel (
137134

138135
val colorPalette: MutableLiveData<Palette> = MutableLiveData()
139136

140-
private var matrixValues = FloatArray(9)
141137

142138
private var _viewInfoStateFlow: MutableStateFlow<ViewInfo> = MutableStateFlow(ViewInfo.Empty)
143139

@@ -216,7 +212,6 @@ class MainViewModel (
216212

217213
fun saveImage(
218214
contentResolver: ContentResolver,
219-
viewInfo: ViewInfo,
220215
imageList: List<ImageInfo>,
221216
) {
222217
viewModelScope.launch {
@@ -226,7 +221,7 @@ class MainViewModel (
226221
}
227222
saveResult.value =
228223
Result.success(null, code = TYPE_SAVING)
229-
val result = generateList(contentResolver, viewInfo, imageList)
224+
val result = generateList(contentResolver, imageList)
230225
if (result.isFailure()) {
231226
saveResult.value = Result.failure(null, code = TYPE_ERROR_FILE_NOT_FOUND)
232227
return@launch
@@ -238,7 +233,6 @@ class MainViewModel (
238233

239234
private suspend fun generateList(
240235
contentResolver: ContentResolver,
241-
viewInfo: ViewInfo,
242236
infoList: List<ImageInfo>?,
243237
): Result<List<ImageInfo>> =
244238
withContext(Dispatchers.Default) {
@@ -249,7 +243,7 @@ class MainViewModel (
249243
try {
250244
info.jobState = JobState.Ing
251245
launch(Dispatchers.Main) { saveProcess.value = info }
252-
info.result = generateImage(contentResolver, viewInfo, info)
246+
info.result = generateImage(contentResolver, info)
253247
info.jobState = JobState.Success(info.result!!)
254248
launch(Dispatchers.Main) { saveProcess.value = info }
255249
} catch (fne: FileNotFoundException) {
@@ -271,7 +265,6 @@ class MainViewModel (
271265

272266
private suspend fun generateImage(
273267
contentResolver: ContentResolver,
274-
viewInfo: ViewInfo,
275268
imageInfo: ImageInfo,
276269
): Result<Uri> =
277270
withContext(Dispatchers.IO) {
@@ -286,46 +279,15 @@ class MainViewModel (
286279
message = "Copy bitmap from uri failed."
287280
)
288281

289-
val inSample = calculateInSampleSize(
290-
mutableBitmap.width,
291-
mutableBitmap.height,
292-
WaterMarkImageView.calculateDrawLimitWidth(viewInfo.width, viewInfo.paddingLeft),
293-
WaterMarkImageView.calculateDrawLimitHeight(viewInfo.height, viewInfo.paddingRight),
294-
)
295282
imageInfo.width = mutableBitmap.width
296283
imageInfo.height = mutableBitmap.height
297284
val tmpConfig = waterMark.value ?: return@withContext Result.failure(
298285
null,
299286
code = "-1",
300287
message = "config.value == null"
301288
)
302-
imageInfo.inSample = inSample
303289
val canvas = Canvas(mutableBitmap)
304-
// generate matrix of drawable
305-
val imageMatrix = WaterMarkImageView.adjustMatrix(
306-
Matrix(),
307-
viewInfo.width,
308-
viewInfo.height,
309-
viewInfo.paddingLeft,
310-
viewInfo.paddingTop,
311-
imageInfo.width,
312-
imageInfo.height
313-
)
314-
Log.i(
315-
"generateImage",
316-
"""
317-
imageMatrix = $imageMatrix,
318-
inSample = $inSample,
319-
imageInfo = $imageInfo
320-
viewInfo = $viewInfo,
321-
bitmapW = ${mutableBitmap.width}
322-
bitmapH = ${mutableBitmap.height},
323-
""".trimIndent()
324-
)
325-
// calculate the scale factor
326-
imageMatrix.getValues(matrixValues)
327-
imageInfo.scaleX = 1 / matrixValues[Matrix.MSCALE_X]
328-
imageInfo.scaleY = 1 / matrixValues[Matrix.MSCALE_X]
290+
// Export sizing is image-space; preview matrix values are not needed here.
329291
val bitmapPaint = TextPaint().applyConfig(imageInfo, tmpConfig, isScale = false)
330292
val layoutPaint = Paint()
331293
// S2a: build the cell shader through the Android renderer seam (same seam the preview
@@ -342,11 +304,12 @@ class MainViewModel (
342304
}
343305

344306
WaterMarkRepository.MarkMode.Image -> {
307+
// Decode the icon against source-image bounds so export is independent of preview size.
345308
val iconBitmapRect = decodeSampledBitmapFromResource(
346309
contentResolver,
347310
tmpConfig.iconUri,
348-
viewInfo.width,
349-
viewInfo.height
311+
imageInfo.width,
312+
imageInfo.height
350313
)
351314
if (iconBitmapRect.isFailure() || iconBitmapRect.data == null) {
352315
return@withContext Result.failure(

app/src/main/java/me/rosuh/easywatermark/utils/bitmap/BitmapUtils.kt

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import android.graphics.Bitmap
88
import android.graphics.BitmapFactory
99
import android.graphics.Matrix
1010
import android.graphics.Matrix.ScaleToFit
11-
import android.graphics.Rect
12-
import android.graphics.RectF
1311
import android.net.Uri
1412
import android.provider.MediaStore
1513
import android.util.Log
@@ -20,7 +18,6 @@ import kotlinx.coroutines.Dispatchers
2018
import kotlinx.coroutines.withContext
2119
import me.rosuh.easywatermark.MyApp
2220
import me.rosuh.easywatermark.data.model.Result
23-
import me.rosuh.easywatermark.data.model.ViewInfo
2421
import java.io.FileNotFoundException
2522
import java.io.InputStream
2623
import java.lang.ref.SoftReference
@@ -319,90 +316,6 @@ private fun getBytesInPixel(config: Bitmap.Config): Int {
319316
}
320317
}
321318

322-
/**
323-
* @author hi@rosuh.me
324-
* @date 2021/10/16
325-
* Copy from [ImageView]
326-
*/
327-
fun generateMatrix(
328-
viewInfo: ViewInfo,
329-
drawableWidth: Int,
330-
drawableHeight: Int,
331-
bounds: Rect,
332-
tempSrc: RectF,
333-
tempDst: RectF,
334-
): Matrix {
335-
val dwidth: Int = drawableWidth
336-
val dheight: Int = drawableHeight
337-
val vwidth: Int = viewInfo.width - viewInfo.paddingLeft - viewInfo.paddingRight
338-
val vheight: Int = viewInfo.height - viewInfo.paddingTop - viewInfo.paddingBottom
339-
val fits = ((dwidth < 0 || vwidth == dwidth)
340-
&& (dheight < 0 || vheight == dheight))
341-
var mDrawMatrix = Matrix()
342-
if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == viewInfo.scaleType) {
343-
/* If the drawable has no intrinsic size, or we're told to
344-
scaletofit, then we just fill our entire view.
345-
*/
346-
bounds.set(0, 0, vwidth, vheight)
347-
} else {
348-
// We need to do the scaling ourself, so have the drawable
349-
// use its native size.
350-
bounds.set(0, 0, dwidth, dheight)
351-
if (ScaleType.MATRIX == viewInfo.scaleType) {
352-
// Use the specified matrix as-is.
353-
if (!viewInfo.matrix.isIdentity) {
354-
mDrawMatrix = viewInfo.matrix
355-
}
356-
} else if (fits) {
357-
// The bitmap fits exactly, no transform needed.
358-
} else if (ScaleType.CENTER == viewInfo.scaleType) {
359-
// Center bitmap in view, no scaling.
360-
mDrawMatrix = viewInfo.matrix
361-
mDrawMatrix.setTranslate(
362-
((vwidth - dwidth) * 0.5f).roundToInt().toFloat(),
363-
((vheight - dheight) * 0.5f).roundToInt().toFloat()
364-
)
365-
} else if (ScaleType.CENTER_CROP == viewInfo.scaleType) {
366-
mDrawMatrix = viewInfo.matrix
367-
val scale: Float
368-
var dx = 0f
369-
var dy = 0f
370-
if (dwidth * vheight > vwidth * dheight) {
371-
scale = vheight.toFloat() / dheight.toFloat()
372-
dx = (vwidth - dwidth * scale) * 0.5f
373-
} else {
374-
scale = vwidth.toFloat() / dwidth.toFloat()
375-
dy = (vheight - dheight * scale) * 0.5f
376-
}
377-
mDrawMatrix.setScale(scale, scale)
378-
mDrawMatrix.postTranslate(Math.round(dx).toFloat(), Math.round(dy).toFloat())
379-
} else if (ScaleType.CENTER_INSIDE == viewInfo.scaleType) {
380-
mDrawMatrix = viewInfo.matrix
381-
val dx: Float
382-
val dy: Float
383-
val scale: Float = if (dwidth <= vwidth && dheight <= vheight) {
384-
1.0f
385-
} else {
386-
(vwidth.toFloat() / dwidth.toFloat()).coerceAtMost(vheight.toFloat() / dheight.toFloat())
387-
}
388-
dx = ((vwidth - dwidth * scale) * 0.5f).roundToInt().toFloat()
389-
dy = ((vheight - dheight * scale) * 0.5f).roundToInt().toFloat()
390-
mDrawMatrix.setScale(scale, scale)
391-
mDrawMatrix.postTranslate(dx, dy)
392-
} else {
393-
// Generate the required transform.
394-
tempSrc.set(0f, 0f, dwidth.toFloat(), dheight.toFloat())
395-
tempDst.set(0f, 0f, vwidth.toFloat(), vheight.toFloat())
396-
mDrawMatrix = viewInfo.matrix
397-
mDrawMatrix.setRectToRect(
398-
tempSrc,
399-
tempDst,
400-
scaleTypeToScaleToFit(viewInfo.scaleType)
401-
)
402-
}
403-
}
404-
return mDrawMatrix
405-
}
406319

407320

408321
fun scaleTypeToScaleToFit(st: ScaleType): ScaleToFit {

app/src/main/java/me/rosuh/easywatermark/utils/ktx/IntExtension.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import android.content.res.Resources
77
import android.graphics.Shader
88
import android.os.Build
99
import android.util.TypedValue
10-
import me.rosuh.easywatermark.ui.widget.WaterMarkImageView
10+
11+
private const val DEFAULT_BG_ANIM_DURATION = 450L
1112

1213
val Int.dp
1314
get() = TypedValue.applyDimension(
@@ -26,7 +27,7 @@ val Float.dp
2627
fun Int.toColor(
2728
toColor: Int,
2829
autoStart: Boolean = true,
29-
duration: Long = WaterMarkImageView.ANIMATION_DURATION,
30+
duration: Long = DEFAULT_BG_ANIM_DURATION,
3031
doOnUpdate: (it: ValueAnimator) -> Unit = {},
3132
): ObjectAnimator? {
3233
return ObjectAnimator.ofInt(
@@ -54,4 +55,4 @@ fun Int?.toTileMode(): Shader.TileMode {
5455
}
5556
else -> Shader.TileMode.REPEAT
5657
}
57-
}
58+
}

0 commit comments

Comments
 (0)