Skip to content

Commit

Permalink
feat(caa upload): retain source format for Apple Music images
Browse files Browse the repository at this point in the history
When the source image on Apple Music is JPEG, return the maximised
image as JPEG. If it's not JPEG, always use PNG. See #80 for
discussion.
  • Loading branch information
ROpdebee committed Oct 20, 2021
1 parent 6af1e8d commit c830f6e
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/mb_enhanced_cover_art_uploads/maximise.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ async function maximiseExceptions(smallurl: URL): Promise<MaximisedImage[] | und
return maximiseDiscogs(smallurl);
}

if (smallurl.hostname.endsWith('.mzstatic.com')) {
return maximiseAppleMusic(smallurl);
}

return;
}

Expand All @@ -79,3 +83,31 @@ async function maximiseDiscogs(smallurl: URL): Promise<MaximisedImage[]> {
headers: {},
}];
}

async function maximiseAppleMusic(smallurl: URL): Promise<MaximisedImage[]> {
// For Apple Music, IMU always returns a PNG, regardless of whether the
// original source image was PNG or JPEG. When the original image is a JPEG,
// we want to fetch a JPEG version. Although the PNG is of slightly better
// quality due to generational loss when a JPEG is re-encoded, the quality
// loss is so minor that the additional costs of downloading, uploading,
// and storing the PNG are unjustifiable. See #80.

const results: MaximisedImage[] = [];
for await (const imgGeneric of maximiseGeneric(smallurl)) {
// Assume original file name is penultimate component of pathname, e.g.
// https://is5-ssl.mzstatic.com/image/thumb/Music124/v4/58/34/98/58349857-55bb-62ae-81d4-4a2726e33528/5060786561909.png/999999999x0w-999.png
// We're still conservative though, if it's not a JPEG, we won't
// return the JPEG version
if (/\.jpe?g$/i.test(imgGeneric.url.pathname.split('/').at(-2))) {
results.push({
...imgGeneric,
url: new URL(imgGeneric.url.href.replace(/\.png$/i, '.jpg'))
});
}

// Always return the original maximised URL as a backup
results.push(imgGeneric);
}

return results;
}
95 changes: 95 additions & 0 deletions tests/mb_enhanced_cover_art_uploads/maximise.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ beforeAll(() => {
__set__('maxurl', fakeImu);
});

beforeEach(() => {
fakeImu.mockClear();
});

describe('maximising images', () => {
it('yields the maximised image', async () => {
fakeImu.mockImplementation((_url, options) => options.cb?.([{ url: 'https://example.com/max' } as unknown as maxurlResult]));
Expand Down Expand Up @@ -83,3 +87,94 @@ describe('maximising Discogs images', () => {
expect(result.done).toBeTrue();
});
});

describe('maximising Apple Music images', () => {
beforeAll(() => {
fakeImu.mockImplementation((url, options) => {
options.cb?.([{ url } as unknown as maxurlResult]);
});
});

it('retains PNG format if original is PNG', async () => {
const it = getMaximisedCandidates(new URL('https://is5-ssl.mzstatic.com/image/thumb/Music124/v4/58/34/98/58349857-55bb-62ae-81d4-4a2726e33528/5060786561909.png/999999999x0w-999.png'));
let result = await it.next();

// expect(result.done).toBeFalse();
expect(result.value.url.href).toBe('https://is5-ssl.mzstatic.com/image/thumb/Music124/v4/58/34/98/58349857-55bb-62ae-81d4-4a2726e33528/5060786561909.png/999999999x0w-999.png');

result = await it.next();

expect(result.done).toBeTrue();
});

it('uses JPEG format if original is JPEG', async () => {
const it = getMaximisedCandidates(new URL('https://is3-ssl.mzstatic.com/image/thumb/Music124/v4/73/bd/c8/73bdc8dc-9ab2-ce6e-e581-4bb3d9e559fc/190295474089.jpg/999999999x0w-999.png'));
const result = await it.next();

expect(result.done).toBeFalse();
expect(result.value.url.href).toBe('https://is3-ssl.mzstatic.com/image/thumb/Music124/v4/73/bd/c8/73bdc8dc-9ab2-ce6e-e581-4bb3d9e559fc/190295474089.jpg/999999999x0w-999.jpg');
});

it('uses PNG format as backup for JPEG', async () => {
const it = getMaximisedCandidates(new URL('https://is3-ssl.mzstatic.com/image/thumb/Music124/v4/73/bd/c8/73bdc8dc-9ab2-ce6e-e581-4bb3d9e559fc/190295474089.jpg/999999999x0w-999.png'));
let result = await it.next();

expect(result.done).toBeFalse();
expect(result.value.url.href).toBe('https://is3-ssl.mzstatic.com/image/thumb/Music124/v4/73/bd/c8/73bdc8dc-9ab2-ce6e-e581-4bb3d9e559fc/190295474089.jpg/999999999x0w-999.jpg');

result = await it.next();

expect(result.done).toBeFalse();
expect(result.value.url.href).toBe('https://is3-ssl.mzstatic.com/image/thumb/Music124/v4/73/bd/c8/73bdc8dc-9ab2-ce6e-e581-4bb3d9e559fc/190295474089.jpg/999999999x0w-999.png');

result = await it.next();

expect(result.done).toBeTrue();
});

it('keeps original maximised URL if format is unknown', async () => {
const it = getMaximisedCandidates(new URL('https://is3-ssl.mzstatic.com/image/thumb/Music124/v4/73/bd/c8/73bdc8dc-9ab2-ce6e-e581-4bb3d9e559fc/190295474089.webp/999999999x0w-999.png'));
let result = await it.next();

expect(result.done).toBeFalse();
expect(result.value.url.href).toBe('https://is3-ssl.mzstatic.com/image/thumb/Music124/v4/73/bd/c8/73bdc8dc-9ab2-ce6e-e581-4bb3d9e559fc/190295474089.webp/999999999x0w-999.png');

result = await it.next();

expect(result.done).toBeTrue();
});

it('maximises images', async () => {
fakeImu.mockImplementationOnce((_url, options) => {
options.cb?.([{ url: 'https://is4-ssl.mzstatic.com/image/thumb/Music115/v4/f1/e6/ad/f1e6adf1-fce1-a7fa-2f9c-e37e32738306/075679767103.jpg/999999999x0w-999.png' } as unknown as maxurlResult]);
});

const it = getMaximisedCandidates(new URL('https://is4-ssl.mzstatic.com/image/thumb/Music115/v4/f1/e6/ad/f1e6adf1-fce1-a7fa-2f9c-e37e32738306/075679767103.jpg/160x160bb-60.jpg'));
let result = await it.next();

expect(result.done).toBeFalse();
expect(result.value.url.href).toBe('https://is4-ssl.mzstatic.com/image/thumb/Music115/v4/f1/e6/ad/f1e6adf1-fce1-a7fa-2f9c-e37e32738306/075679767103.jpg/999999999x0w-999.jpg');

result = await it.next();

expect(result.done).toBeFalse();
expect(result.value.url.href).toBe('https://is4-ssl.mzstatic.com/image/thumb/Music115/v4/f1/e6/ad/f1e6adf1-fce1-a7fa-2f9c-e37e32738306/075679767103.jpg/999999999x0w-999.png');

result = await it.next();

expect(result.done).toBeTrue();
expect(fakeImu).toHaveBeenCalledOnce();
});

it('retains PNG for old-style iTunes URLs', async () => {
const it = getMaximisedCandidates(new URL('https://is2-ssl.mzstatic.com/image/thumb/Music114/v4/61/67/d4/6167d478-a353-28be-75fa-0ebbc74808e2/source/999999999x0w-999.png'));
let result = await it.next();

expect(result.done).toBeFalse();
expect(result.value.url.href).toBe('https://is2-ssl.mzstatic.com/image/thumb/Music114/v4/61/67/d4/6167d478-a353-28be-75fa-0ebbc74808e2/source/999999999x0w-999.png');

result = await it.next();

expect(result.done).toBeTrue();
});
});

0 comments on commit c830f6e

Please sign in to comment.