本文旨在探究js压缩图片的两种方式: 改变图片长宽 , 改变图片质量 ,和结合了以上两者的 最终方案 。
首先,阅读本文需要知道canvas的两个方法
这两个方法具体的说明可以在MDN上查看,关于图片压缩,也有很多现成的博客可以直接用。但是那些博客都有个问题,并没有关心之后图片的压缩质量。
我试着用一个现成的例子去跑了一下,一个1.7M的图片压缩到了23k,堪称像素级毁灭性破坏。
假如一张大图可能包含着很多文字等关键信息,必须上传之后使用方能清晰辨认。所以要压缩之后质量尽可能接近500k的。500k像素以内,就是若一张图宽度为1024,则高度不能超过500。因为图片有其他的信息,也是要占大小的。即不得大于 1024*500 。
所以,根据需求,上传图片不能超过500k的情况下尽可能保留图片的清晰度。当然如果可以的情况下用上面提到的 canvas.toDataURL 设置压缩程度为0.9,0.8试试看,图片质量可以接受,大小会有大幅度的缩小。
如果不压缩,靠调整图片长宽去控制上传大小呢?
原理很简单,就是靠不断地缩小限定的最大宽高,直到最终长宽的积小于规定的大小。
这种方法有可能最后得出的图片的大小会略大于规定大小,原因上文也提到过了,如果想使用这种方法,可自行再调整一下。
上面的方法有个问题,就是改变了图片的原始长宽。如果一个图的长宽足够大,压缩图片质量,糊一点但是内容看得清也是ok的嘛。所以,跟上面同理,我们可以不断调整图片的质量设定直到大小合适,那么,如何在图片上传之前知道图片的大小呢?
首先,需要知道的一点是,压缩之后拿到的base64字符串会转成blob对象,然后传给服务端。
可以查阅文档,blob对象有个属性是size
这个size就是上传之后实际的文件大小。
参照上面的思路,可以每次改变 canvas.toDataURL('image/' + fileType, level)level的值,去调整压缩图片质量,然后用blob对象的size去验证是否满足500k以内的需求。
关于 canvas.toDataURL 的level到底是怎么计算的,MDN文档里也没说,写了个循环一次减少0.1的level压缩了几个图片
用加减乘除算了一下,没找到规律,数学不好放弃了(这个东西好像也不是能观察出来的,看结果跟初始大小没啥关系)。
这里要注意的是,有可能遇到超大图片,0.1的level可能不足以压缩到500k,所以小于0.1的时候,改变level递减的差值继续压缩下去
在开始接收到图片的时候给一个loading增加用户的耐心好了,loading万岁~
其实单纯的压缩质量遇到稍大的图片,会导致页面高频计算,然后页面基本就用不了了- -。有尝试过用iphone的一个屏幕截图(10M左右),压的时候稍过一会,整个手机都在发烫,只能杀进程。
所以,若对长度没有特殊的限制,可以做一个缩放,去加快压缩的进度,提高能压缩的图片大小上限。
页面到了ios上还是不行- -,可以看到最后图片level为0.001,最长边为764。
问题还是循环次数还是过多,计算频率太高。从图中可看出,对于大图来说,初始设定的level和图片尺寸过于宽松,可以优化一下初始level和尺寸。
有的时候还会遇到一张图片无论如何也压不到500k,就是上一次和这次的压缩后大小没有变化,这种情况需要抛错,不让循环继续。
大图片的等待时间稍长,可以给用户先预览一个base64的图片增加等待耐心,方法名为 getImgBase64 ,这里都一并给出了
解决的隐患:上面这个方案会出现我需要一个500k的照片,压到了520k之后,再压了一次。有时候这最后的一次会特别夸张,直接将图片弄到了几十k。
参考了: https://github.com/WangYuLue/image-conversion
这个库里面有个方法 compressAccurately ,这个方法可以比较精准地压缩。偷偷翻了一下源码。
其实上一个方案的痛点就在于,如何在每一个压缩循环里处理尺寸和压缩比例。
总结
如有纰漏,欢迎指正
解:加上7后能被3整除的整数的一般形式是:
3N-7(N是整数)
如果是三位数加上7后能被3整除
则有:
100≤3N-7≤1000
解得
36≤N≤335
36至335的整数共有:
335-36+1=300(个)
所以有300个三位数加上7后能被3整除
N=36时,3N-7=101
M=335时,3N-7=998
所以第一个符合条件的数是101,最后一个是998,
全部三位数分别是:
101
104
107
110
113
116
119
122
125
128
131
134
137
140
143
146
149
152
155
158
161
164
167
170
173
176
179
182
185
188
191
194
197
200
203
206
209
212
215
218
221
224
227
230
233
236
239
242
245
248
251
254
257
260
263
266
269
272
275
278
281
284
287
290
293
296
299
302
305
308
311
314
317
320
323
326
329
332
335
338
341
344
347
350
353
356
359
362
365
368
371
374
377
380
383
386
389
392
395
398
401
404
407
410
413
416
419
422
425
428
431
434
437
440
443
446
449
452
455
458
461
464
467
470
473
476
479
482
485
488
491
494
497
500
503
506
509
512
515
518
521
524
527
530
533
536
539
542
545
548
551
554
557
560
563
566
569
572
575
578
581
584
587
590
593
596
599
602
605
608
611
614
617
620
623
626
629
632
635
638
641
644
647
650
653
656
659
662
665
668
671
674
677
680
683
686
689
692
695
698
701
704
707
710
713
716
719
722
725
728
731
734
737
740
743
746
749
752
755
758
761
764
767
770
773
776
779
782
785
788
791
794
797
800
803
806
809
812
815
818
821
824
827
830
833
836
839
842
845
848
851
854
857
860
863
866
869
872
875
878
881
884
887
890
893
896
899
902
905
908
911
914
917
920
923
926
929
932
935
938
941
944
947
950
953
956
959
962
965
968
971
974
977
980
983
986
989
992
995
998
共300个
如果学习过等差数列求和公式,
它们的和=(101+998)*300/2=164850
如果没有学习过等差数列求和公式
可以用下列方法求和:
将上述数据从大到小排列后再与原数据对应相加
即:
101 + 998 = 1099
104 + 995 = 1099
107 + 992 = 1099
110 + 989 = 1099
113 + 986 = 1099
116 + 983 = 1099
119 + 980 = 1099
122 + 977 = 1099
125 + 974 = 1099
128 + 971 = 1099
131 + 968 = 1099
134 + 965 = 1099
137 + 962 = 1099
140 + 959 = 1099
143 + 956 = 1099
146 + 953 = 1099
149 + 950 = 1099
152 + 947 = 1099
155 + 944 = 1099
158 + 941 = 1099
161 + 938 = 1099
164 + 935 = 1099
167 + 932 = 1099
170 + 929 = 1099
173 + 926 = 1099
176 + 923 = 1099
179 + 920 = 1099
182 + 917 = 1099
185 + 914 = 1099
188 + 911 = 1099
191 + 908 = 1099
194 + 905 = 1099
197 + 902 = 1099
200 + 899 = 1099
203 + 896 = 1099
206 + 893 = 1099
209 + 890 = 1099
212 + 887 = 1099
215 + 884 = 1099
218 + 881 = 1099
221 + 878 = 1099
224 + 875 = 1099
227 + 872 = 1099
230 + 869 = 1099
233 + 866 = 1099
236 + 863 = 1099
239 + 860 = 1099
242 + 857 = 1099
245 + 854 = 1099
248 + 851 = 1099
251 + 848 = 1099
254 + 845 = 1099
257 + 842 = 1099
260 + 839 = 1099
263 + 836 = 1099
266 + 833 = 1099
269 + 830 = 1099
272 + 827 = 1099
275 + 824 = 1099
278 + 821 = 1099
281 + 818 = 1099
284 + 815 = 1099
287 + 812 = 1099
290 + 809 = 1099
293 + 806 = 1099
296 + 803 = 1099
299 + 800 = 1099
302 + 797 = 1099
305 + 794 = 1099
308 + 791 = 1099
311 + 788 = 1099
314 + 785 = 1099
317 + 782 = 1099
320 + 779 = 1099
323 + 776 = 1099
326 + 773 = 1099
329 + 770 = 1099
332 + 767 = 1099
335 + 764 = 1099
338 + 761 = 1099
341 + 758 = 1099
344 + 755 = 1099
347 + 752 = 1099
350 + 749 = 1099
353 + 746 = 1099
356 + 743 = 1099
359 + 740 = 1099
362 + 737 = 1099
365 + 734 = 1099
368 + 731 = 1099
371 + 728 = 1099
374 + 725 = 1099
377 + 722 = 1099
380 + 719 = 1099
383 + 716 = 1099
386 + 713 = 1099
389 + 710 = 1099
392 + 707 = 1099
395 + 704 = 1099
398 + 701 = 1099
401 + 698 = 1099
404 + 695 = 1099
407 + 692 = 1099
410 + 689 = 1099
413 + 686 = 1099
416 + 683 = 1099
419 + 680 = 1099
422 + 677 = 1099
425 + 674 = 1099
428 + 671 = 1099
431 + 668 = 1099
434 + 665 = 1099
437 + 662 = 1099
440 + 659 = 1099
443 + 656 = 1099
446 + 653 = 1099
449 + 650 = 1099
452 + 647 = 1099
455 + 644 = 1099
458 + 641 = 1099
461 + 638 = 1099
464 + 635 = 1099
467 + 632 = 1099
470 + 629 = 1099
473 + 626 = 1099
476 + 623 = 1099
479 + 620 = 1099
482 + 617 = 1099
485 + 614 = 1099
488 + 611 = 1099
491 + 608 = 1099
494 + 605 = 1099
497 + 602 = 1099
500 + 599 = 1099
503 + 596 = 1099
506 + 593 = 1099
509 + 590 = 1099
512 + 587 = 1099
515 + 584 = 1099
518 + 581 = 1099
521 + 578 = 1099
524 + 575 = 1099
527 + 572 = 1099
530 + 569 = 1099
533 + 566 = 1099
536 + 563 = 1099
539 + 560 = 1099
542 + 557 = 1099
545 + 554 = 1099
548 + 551 = 1099
551 + 548 = 1099
554 + 545 = 1099
557 + 542 = 1099
560 + 539 = 1099
563 + 536 = 1099
566 + 533 = 1099
569 + 530 = 1099
572 + 527 = 1099
575 + 524 = 1099
578 + 521 = 1099
581 + 518 = 1099
584 + 515 = 1099
587 + 512 = 1099
590 + 509 = 1099
593 + 506 = 1099
596 + 503 = 1099
599 + 500 = 1099
602 + 497 = 1099
605 + 494 = 1099
608 + 491 = 1099
611 + 488 = 1099
614 + 485 = 1099
617 + 482 = 1099
620 + 479 = 1099
623 + 476 = 1099
626 + 473 = 1099
629 + 470 = 1099
632 + 467 = 1099
635 + 464 = 1099
638 + 461 = 1099
641 + 458 = 1099
644 + 455 = 1099
647 + 452 = 1099
650 + 449 = 1099
653 + 446 = 1099
656 + 443 = 1099
659 + 440 = 1099
662 + 437 = 1099
665 + 434 = 1099
668 + 431 = 1099
671 + 428 = 1099
674 + 425 = 1099
677 + 422 = 1099
680 + 419 = 1099
683 + 416 = 1099
686 + 413 = 1099
689 + 410 = 1099
692 + 407 = 1099
695 + 404 = 1099
698 + 401 = 1099
701 + 398 = 1099
704 + 395 = 1099
707 + 392 = 1099
710 + 389 = 1099
713 + 386 = 1099
716 + 383 = 1099
719 + 380 = 1099
722 + 377 = 1099
725 + 374 = 1099
728 + 371 = 1099
731 + 368 = 1099
734 + 365 = 1099
737 + 362 = 1099
740 + 359 = 1099
743 + 356 = 1099
746 + 353 = 1099
749 + 350 = 1099
752 + 347 = 1099
755 + 344 = 1099
758 + 341 = 1099
761 + 338 = 1099
764 + 335 = 1099
767 + 332 = 1099
770 + 329 = 1099
773 + 326 = 1099
776 + 323 = 1099
779 + 320 = 1099
782 + 317 = 1099
785 + 314 = 1099
788 + 311 = 1099
791 + 308 = 1099
794 + 305 = 1099
797 + 302 = 1099
800 + 299 = 1099
803 + 296 = 1099
806 + 293 = 1099
809 + 290 = 1099
812 + 287 = 1099
815 + 284 = 1099
818 + 281 = 1099
821 + 278 = 1099
824 + 275 = 1099
827 + 272 = 1099
830 + 269 = 1099
833 + 266 = 1099
836 + 263 = 1099
839 + 260 = 1099
842 + 257 = 1099
845 + 254 = 1099
848 + 251 = 1099
851 + 248 = 1099
854 + 245 = 1099
857 + 242 = 1099
860 + 239 = 1099
863 + 236 = 1099
866 + 233 = 1099
869 + 230 = 1099
872 + 227 = 1099
875 + 224 = 1099
878 + 221 = 1099
881 + 218 = 1099
884 + 215 = 1099
887 + 212 = 1099
890 + 209 = 1099
893 + 206 = 1099
896 + 203 = 1099
899 + 200 = 1099
902 + 197 = 1099
905 + 194 = 1099
908 + 191 = 1099
911 + 188 = 1099
914 + 185 = 1099
917 + 182 = 1099
920 + 179 = 1099
923 + 176 = 1099
926 + 173 = 1099
929 + 170 = 1099
932 + 167 = 1099
935 + 164 = 1099
938 + 161 = 1099
941 + 158 = 1099
944 + 155 = 1099
947 + 152 = 1099
950 + 149 = 1099
953 + 146 = 1099
956 + 143 = 1099
959 + 140 = 1099
962 + 137 = 1099
965 + 134 = 1099
968 + 131 = 1099
971 + 128 = 1099
974 + 125 = 1099
977 + 122 = 1099
980 + 119 = 1099
983 + 116 = 1099
986 + 113 = 1099
989 + 110 = 1099
992 + 107 = 1099
995 + 104 = 1099
998 + 101 = 1099
所以要计算的和=1099*300/2=164850
(上述数据是在电子表格中自动产生的,如果手工打出这么多数据来就太烦了,呵呵)
供参考!JSWYC