Skip to content

Commit d1a2b7f

Browse files
authored
Update predominant color (#247)
* Update predominant color
1 parent c620adb commit d1a2b7f

File tree

4 files changed

+48
-89
lines changed

4 files changed

+48
-89
lines changed

src/cloudinary-image.component.spec.ts

Lines changed: 25 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -770,10 +770,10 @@ describe('CloudinaryImage', () => {
770770
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/c_fit,w_30/e_pixelate,f_auto,q_1/bear'));
771771
}));
772772
});
773-
describe('placeholder type solid', () => {
773+
describe('placeholder type predominant-color with exact dimensions', () => {
774774
@Component({
775-
template: `<cl-image public-id="bear" width="300" crop="fit">
776-
<cl-placeholder type="solid"></cl-placeholder>
775+
template: `<cl-image public-id="bear" width="300" height="300" crop="fit">
776+
<cl-placeholder type="predominant-color"></cl-placeholder>
777777
</cl-image>`
778778
})
779779
class TestComponent {}
@@ -791,18 +791,18 @@ describe('CloudinaryImage', () => {
791791
fixture.detectChanges(); // initial binding
792792
des = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
793793
});
794-
it('creates an img element with placeholder', fakeAsync(() => {
794+
it('creates an img element with placeholder size 1 pxl', fakeAsync(() => {
795795
tick();
796796
fixture.detectChanges();
797797
const img = des[0].children[0].nativeElement as HTMLImageElement;
798-
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/c_fit,w_30/ar_1,b_auto,' +
799-
'c_pad,w_iw_div_2/c_crop,g_north_east,h_10,w_10/c_fill,h_ih,w_iw/f_auto,q_auto/bear'));
798+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/c_fit,h_30,w_30/ar_1,b_auto,' +
799+
'c_pad,w_iw_div_2/c_crop,g_north_east,h_1,w_1/f_auto,q_auto/bear'));
800800
}));
801801
});
802-
describe('placeholder type vectorize', () => {
802+
describe('placeholder type predominant-color', () => {
803803
@Component({
804804
template: `<cl-image public-id="bear" width="300" crop="fit">
805-
<cl-placeholder type="vectorize"></cl-placeholder>
805+
<cl-placeholder type="predominant-color"></cl-placeholder>
806806
</cl-image>`
807807
})
808808
class TestComponent {}
@@ -824,14 +824,14 @@ describe('CloudinaryImage', () => {
824824
tick();
825825
fixture.detectChanges();
826826
const img = des[0].children[0].nativeElement as HTMLImageElement;
827-
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/c_fit,w_30/e_vectorize,q_1/bear'));
827+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/c_fit,w_30/ar_1,b_auto,' +
828+
'c_pad,w_iw_div_2/c_crop,g_north_east,h_10,w_10/c_fill,h_ih,w_iw/f_auto,q_auto/bear'));
828829
}));
829830
});
830-
describe('placeholder with cl-transformation', () => {
831+
describe('placeholder type vectorize', () => {
831832
@Component({
832833
template: `<cl-image public-id="bear" width="300" crop="fit">
833-
<cl-transformation effect="sepia"></cl-transformation>
834-
<cl-placeholder type="blur"></cl-placeholder>
834+
<cl-placeholder type="vectorize"></cl-placeholder>
835835
</cl-image>`
836836
})
837837
class TestComponent {}
@@ -845,58 +845,22 @@ describe('CloudinaryImage', () => {
845845
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent, CloudinaryPlaceHolder],
846846
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
847847
}).createComponent(TestComponent);
848+
848849
fixture.detectChanges(); // initial binding
849850
des = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
850851
});
851-
it('creates an img element with placeholder and cl-transformations', fakeAsync(() => {
852+
it('creates an img element with placeholder', fakeAsync(() => {
852853
tick();
853854
fixture.detectChanges();
854855
const img = des[0].children[0].nativeElement as HTMLImageElement;
855-
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_sepia/c_fit,w_30/e_blur:2000,f_auto,q_1/bear'));
856-
}));
857-
});
858-
describe('cl-image with acessibility modes', () => {
859-
@Component({
860-
template: `<cl-image public-id="bear" accessibility="darkmode"></cl-image>
861-
<cl-image public-id="bear" accessibility="monochrome"></cl-image>
862-
<cl-image public-id="bear" accessibility="brightmode"></cl-image>
863-
<cl-image public-id="bear" accessibility="colorblind"></cl-image>`
864-
})
865-
class TestComponent {}
866-
867-
let fixture: ComponentFixture<TestComponent>;
868-
let des: DebugElement[]; // the elements w/ the directive
869-
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
870-
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
871-
beforeEach(() => {
872-
fixture = TestBed.configureTestingModule({
873-
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent],
874-
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
875-
}).createComponent(TestComponent);
876-
fixture.detectChanges(); // initial binding
877-
des = fixture.debugElement.queryAll(By.directive(CloudinaryImage));
878-
});
879-
it('creates an img element with accessibility darkmode', fakeAsync(() => {
880-
const img = des[0].children[0].nativeElement as HTMLImageElement;
881-
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_tint:75:black/bear'));
882-
}));
883-
it('creates an img element with accessibility monochrome', fakeAsync(() => {
884-
const img = des[1].children[0].nativeElement as HTMLImageElement;
885-
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_grayscale/bear'));
886-
}));
887-
it('creates an img element with accessibility brightmode', fakeAsync(() => {
888-
const img = des[2].children[0].nativeElement as HTMLImageElement;
889-
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_tint:50:white/bear'));
890-
}));
891-
it('creates an img element with accessibility colorblind', fakeAsync(() => {
892-
const img = des[3].children[0].nativeElement as HTMLImageElement;
893-
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_assist_colorblind/bear'));
856+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/c_fit,w_30/e_vectorize,q_1/bear'));
894857
}));
895858
});
896-
describe('cl-image with acessibility modes and transformation', () => {
859+
describe('placeholder with cl-transformation', () => {
897860
@Component({
898-
template: `<cl-image public-id="bear" accessibility="darkmode" effect="grayscale" overlay="sample">
899-
<cl-transformation effect="sepia"></cl-transformation>
861+
template: `<cl-image public-id="bear" width="300" crop="fit">
862+
<cl-transformation effect="sepia"></cl-transformation>
863+
<cl-placeholder type="blur"></cl-placeholder>
900864
</cl-image>`
901865
})
902866
class TestComponent {}
@@ -907,15 +871,17 @@ describe('CloudinaryImage', () => {
907871
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
908872
beforeEach(() => {
909873
fixture = TestBed.configureTestingModule({
910-
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent],
874+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent, CloudinaryPlaceHolder],
911875
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
912876
}).createComponent(TestComponent);
913877
fixture.detectChanges(); // initial binding
914-
des = fixture.debugElement.queryAll(By.directive(CloudinaryImage));
878+
des = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
915879
});
916-
it('creates an img element with accessibility darkmode without overwriting effect', fakeAsync(() => {
880+
it('creates an img element with placeholder and cl-transformations', fakeAsync(() => {
881+
tick();
882+
fixture.detectChanges();
917883
const img = des[0].children[0].nativeElement as HTMLImageElement;
918-
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_sepia/e_grayscale,l_sample/e_tint:75:black/bear'));
884+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_sepia/c_fit,w_30/e_blur:2000,f_auto,q_1/bear'));
919885
}));
920886
});
921887
});

src/cloudinary-image.component.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { Cloudinary } from './cloudinary.service';
1717
import { CloudinaryTransformationDirective } from './cloudinary-transformation.directive';
1818
import { CloudinaryPlaceHolder } from './cloudinary-placeholder.component';
1919
import { isBrowser } from './cloudinary.service';
20-
import { accessibilityEffect } from './constants';
2120

2221
@Component({
2322
selector: 'cl-image',
@@ -34,7 +33,6 @@ export class CloudinaryImage
3433
@Input('loading') loading: string;
3534
@Input('width') width?: string;
3635
@Input('height') height?: string;
37-
@Input('accessibility') accessibility?: string;
3836

3937
@ContentChildren(CloudinaryTransformationDirective)
4038
transformations: QueryList<CloudinaryTransformationDirective>;
@@ -45,7 +43,6 @@ export class CloudinaryImage
4543

4644
observer: MutationObserver;
4745
shouldShowPlaceHolder: boolean = true;
48-
options: object = {};
4946

5047
constructor(private el: ElementRef, private cloudinary: Cloudinary) {}
5148

@@ -125,10 +122,6 @@ export class CloudinaryImage
125122
if (this.placeholderComponent) {
126123
this.placeholderHandler(options);
127124
}
128-
if (this.accessibility) {
129-
this.options = options;
130-
options.src = this.accessibilityModeHandler();
131-
}
132125
const imageTag = this.cloudinary.imageTag(this.publicId, options);
133126

134127
this.setElementAttributes(image, imageTag.attributes());
@@ -149,13 +142,9 @@ export class CloudinaryImage
149142
const placeholderOptions = {};
150143

151144
Object.keys(options).forEach(name => {
152-
placeholderOptions[name] = (name === 'width' && !options[name].startsWith('auto') || name === 'height') ? Math.floor(parseInt(options[name], 10) * 0.1) : options[name];
145+
placeholderOptions[name] = (name === 'width' && !options[name].startsWith('auto') || name === 'height') ? Math.ceil(parseInt(options[name], 10) * 0.1) : options[name];
153146
})
154147
this.placeholderComponent.options = placeholderOptions;
155148
}
156-
157-
accessibilityModeHandler() {
158-
return this.cloudinary.url(this.publicId, {transformation: [this.options, accessibilityEffect[this.accessibility]]});
159-
}
160149
}
161150

src/cloudinary-placeholder.component.ts

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
Input,
66
} from '@angular/core';
77
import {Cloudinary} from './cloudinary.service';
8-
8+
import { placeholderImageOptions, predominantColorTransformPxl } from './constants';
99

1010
@Component({
1111
selector: 'cl-placeholder',
@@ -40,17 +40,10 @@ export class CloudinaryPlaceHolder implements AfterContentChecked {
4040
}
4141

4242
getPlaceholderImage() {
43-
const placeholderImageOptions = {
44-
'vectorize': {effect: 'vectorize', quality: 1},
45-
'pixelate': {effect: 'pixelate', quality: 1, fetch_format: 'auto'},
46-
'blur': {effect: 'blur:2000', quality: 1, fetch_format: 'auto'},
47-
'solid': [
48-
{width: 'iw_div_2', aspect_ratio: 1, crop: 'pad', background: 'auto'},
49-
{crop: 'crop', width: 10, height: 10, gravity: 'north_east'},
50-
{width: 'iw', height: 'ih', crop: 'fill'},
51-
{fetch_format: 'auto', quality: 'auto'}]
43+
if (this.type === 'predominant-color' && this.itemHeight && this.itemWidth) {
44+
return this.cloudinary.url(this.publicId, {transformation: [this.options, ...predominantColorTransformPxl]});
45+
} else {
46+
return this.cloudinary.url(this.publicId, {transformation: [this.options, ...placeholderImageOptions[this.type] || placeholderImageOptions['blur']]})
5247
}
53-
let transformation = [].concat.apply([], [this.options, placeholderImageOptions[this.type] || placeholderImageOptions['blur']]);
54-
return this.cloudinary.url(this.publicId, {transformation: transformation});
5548
}
5649
}

src/constants.ts

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
1-
export const accessibilityEffect = {
2-
'darkmode': {effect: 'tint:75:black'},
3-
'brightmode': {effect: 'tint:50:white'},
4-
'monochrome': {effect: 'grayscale'},
5-
'colorblind': {effect: 'assist_colorblind'}
6-
}
1+
export const predominantColorTransformPxl = [
2+
{width: 'iw_div_2', aspect_ratio: 1, crop: 'pad', background: 'auto'},
3+
{crop: 'crop', width: 1, height: 1, gravity: 'north_east'},
4+
{fetch_format: 'auto', quality: 'auto'}];
5+
6+
export const predominantColorTransform = [
7+
{width: 'iw_div_2', aspect_ratio: 1, crop: 'pad', background: 'auto'},
8+
{crop: 'crop', width: 10, height: 10, gravity: 'north_east'},
9+
{width: 'iw', height: 'ih', crop: 'fill'},
10+
{fetch_format: 'auto', quality: 'auto'}];
11+
12+
export const placeholderImageOptions = {
13+
'vectorize': {effect: 'vectorize', quality: 1},
14+
'pixelate': {effect: 'pixelate', quality: 1, fetch_format: 'auto'},
15+
'blur': {effect: 'blur:2000', quality: 1, fetch_format: 'auto'},
16+
'predominant-color': predominantColorTransform
17+
};

0 commit comments

Comments
 (0)