Skip to content

Commit aa86615

Browse files
authored
feat: Additional options for saveArtwork (#9)
- New `format` option which allows us to specify the format of the saved file (defaults to `jpeg`). - Changed `compress` option to expect a number between `0.0` & `1.0` which represents the quality of the saved image (defaults to `1`).
1 parent db2d5d4 commit aa86615

9 files changed

Lines changed: 99 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ and this project attempts to adhere to [Semantic Versioning](https://semver.org/
77

88
## [Unreleased]
99

10+
### ❗ Breaking Changes
11+
12+
- Revised "compression" option for `saveArtwork`.
13+
- Changed `ArtworkOptions` type.
14+
- `compress` is now a number between `0.0` & `1.0` specifying the quality of the saved image (defaults to `1`).
15+
- New `format` option specifying the file format the image will be saved as (defaults to `jpeg`).
16+
1017
## [2.0.0-beta.1] - 2025-09-02
1118

1219
### ❗ Breaking Changes

README.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ const MetadataPresets: Record<string, MediaMetadataPublicFields>;
4545

4646
An object containing several metadata presets we can use to retrieve metadata.
4747

48+
### SaveFormat
49+
50+
```ts
51+
const SaveFormat = {
52+
JPEG: 'jpeg',
53+
PNG: 'png',
54+
WEBP: 'webp',
55+
};
56+
```
57+
58+
Formats that we can save the image as.
59+
4860
## Functions
4961

5062
### getArtwork
@@ -108,10 +120,18 @@ Update internal configuration options such as the max size of the returned base6
108120

109121
```ts
110122
type ArtworkOptions = {
123+
/**
124+
* A value in the range `0.0` - `1.0` specifying the quality of the resulting image.
125+
* - Defaults to `1`.
126+
*/
127+
compress?: number;
128+
/**
129+
* Specifies the format the image will be saved in.
130+
* - Defaults to `SaveFormat.JPEG`.
131+
*/
132+
format?: SaveFormat;
111133
/** Uri we want to save the artwork to instead of the cache directory. */
112134
saveUri?: string;
113-
/** Whether we should compress the saved image to 80% image quality. */
114-
compress?: boolean;
115135
};
116136
```
117137

android/src/main/java/com/cyanchill/missingcore/metadataretriever/models/ArtworkOptions.kt

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,59 @@ package com.cyanchill.missingcore.metadataretriever.models
33
import com.facebook.react.bridge.Arguments
44
import com.facebook.react.bridge.ReadableMap
55

6+
import android.graphics.Bitmap
67
import android.net.Uri
78
import android.os.Bundle
89

910
class ArtworkOptions(options: ReadableMap) {
1011
/** If we want to return the artwork as a base64 string. */
1112
val asBase64: Boolean
1213

14+
/** A value in the range `0.0` - `1.0` specifying the quality of the resulting image. */
15+
val compress: Double
16+
/** Specifies the format the image will be saved in. */
17+
val format: ImageFormat
1318
/** Location where we want to save the image. */
1419
val saveUri: String?
15-
/** Save the image at 80% quality. */
16-
val compress: Boolean
1720

1821
init {
1922
val optionsBundle = Arguments.toBundle(options) as Bundle
2023
asBase64 = optionsBundle.getBoolean("base64")
21-
compress = optionsBundle.getBoolean("compress")
24+
25+
compress = if (optionsBundle.containsKey("compress")) optionsBundle.getDouble("compress") else 1.0
26+
// Default format to JPEG if it's not provided.
27+
format = ImageFormat.fromCode(optionsBundle.getString("format")) ?: ImageFormat.JPEG
2228

2329
// Remove `file://` in `saveUri` if provided.
2430
val uri = optionsBundle.getString("saveUri")
2531
saveUri = if (uri != null) Uri.parse(uri).path else null
2632
}
2733
}
34+
35+
enum class ImageFormat(val code: String) {
36+
JPEG("jpeg"),
37+
JPG("jpg"),
38+
PNG("png"),
39+
WEBP("webp");
40+
41+
val fileExtension: String
42+
get() = when (this) {
43+
JPEG, JPG -> ".jpg"
44+
PNG -> ".png"
45+
WEBP -> ".webp"
46+
}
47+
48+
val compressFormat: Bitmap.CompressFormat
49+
get() = when (this) {
50+
JPEG, JPG -> Bitmap.CompressFormat.JPEG
51+
PNG -> Bitmap.CompressFormat.PNG
52+
WEBP -> Bitmap.CompressFormat.WEBP
53+
}
54+
55+
companion object {
56+
fun fromCode(code: String?): ImageFormat? {
57+
if (code == null) return null
58+
return entries.find { it.code == code }
59+
}
60+
}
61+
}

android/src/main/java/com/cyanchill/missingcore/metadataretriever/modules/MetadataReader.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,12 @@ class MetadataReader(reactContext: ReactApplicationContext): APIConfigs() {
179179
fun saveImage(bytes: ByteArray, options: ArtworkOptions): String? {
180180
try {
181181
// Generate path to save image if we didn't provide one.
182-
val imgUri = options.saveUri ?: "$saveDirectory${File.separator}${UUID.randomUUID()}.jpeg"
182+
val imgUri = options.saveUri ?: "$saveDirectory${File.separator}${UUID.randomUUID()}${options.format.fileExtension}"
183183
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
184184
FileOutputStream(imgUri).use { fos ->
185185
bitmap.compress(
186-
Bitmap.CompressFormat.JPEG,
187-
if (options.compress) 80 else 100,
186+
options.format.compressFormat,
187+
(options.compress * 100).toInt(),
188188
fos,
189189
)
190190
fos.flush()

examples/benchmarking-demo/data/useTracksWithSavedArtwork.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ async function getTracksWithSavedArtwork() {
3838
const tracksMetadata = await Promise.allSettled(
3939
results.results.map(async ({ uri, data }) => {
4040
const { id, filename } = assetURIMap[uri]!;
41-
const imgUri = await saveArtwork(uri, { compress: true });
41+
const imgUri = await saveArtwork(uri, { compress: 0.8 });
4242
return { id, filename, artworkData: imgUri, ...data };
4343
})
4444
);

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import MetadataRetriever from './MetadataRetriever';
33
import { MetadataPresets } from './constants';
44

55
import type { ArtworkOptions } from './types/ArtworkOptions';
6+
import { SaveFormat } from './types/ArtworkOptions';
67
import type { ConfigOptions } from './types/ConfigOptions';
78
import type { BulkMetadata, MediaMetadataExcerpt } from './types/GetMetadata';
89
import type { MediaMetadata } from './types/MediaMetadata';
@@ -65,4 +66,5 @@ export {
6566
type MediaMetadataExcerpt,
6667
type MediaMetadataPublicField,
6768
MetadataPresets,
69+
SaveFormat,
6870
};

src/types.utils.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@
22
export type Prettify<T> = {
33
[K in keyof T]: T[K];
44
} & unknown;
5+
6+
export type ObjectValues<T> = T[keyof T];

src/types/ArtworkOptions.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
1+
import type { ObjectValues } from 'src/types.utils';
2+
3+
export const SaveFormat = {
4+
JPEG: 'jpeg',
5+
PNG: 'png',
6+
WEBP: 'webp',
7+
} as const;
8+
9+
export type SaveFormat = ObjectValues<typeof SaveFormat>;
10+
111
/** Extra options for when using `getArtwork`. */
212
export type ArtworkOptions = {
13+
/**
14+
* A value in the range `0.0` - `1.0` specifying the quality of the resulting image.
15+
* - Defaults to `1`.
16+
*/
17+
compress?: number;
18+
/**
19+
* Specifies the format the image will be saved in.
20+
* - Defaults to `SaveFormat.JPEG`.
21+
*/
22+
format?: SaveFormat;
323
/** Uri we want to save the artwork to instead of the cache directory. */
424
saveUri?: string;
5-
/** Whether we should compress the saved image to 80% image quality. */
6-
compress?: boolean;
725
};

src/types/MediaMetadataPublicField.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { ObjectValues } from 'src/types.utils';
2+
13
/**
24
* Fields that can be extracted from media file.
35
*
@@ -47,7 +49,8 @@ const MediaMetadataPublicFields = [
4749
'year',
4850
] as const;
4951

50-
export type MediaMetadataPublicField =
51-
(typeof MediaMetadataPublicFields)[number];
52+
export type MediaMetadataPublicField = ObjectValues<
53+
typeof MediaMetadataPublicFields
54+
>;
5255

5356
export type MediaMetadataPublicFields = ReadonlyArray<MediaMetadataPublicField>;

0 commit comments

Comments
 (0)