OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/android/thumbnail/thumbnail_cache.h" | 5 #include "chrome/browser/android/thumbnail/thumbnail_cache.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cmath> | 8 #include <cmath> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 if (!WriteBigEndianToFile(file, kCompressedKey)) | 495 if (!WriteBigEndianToFile(file, kCompressedKey)) |
496 return false; | 496 return false; |
497 | 497 |
498 if (!WriteBigEndianToFile(file, content_size.width())) | 498 if (!WriteBigEndianToFile(file, content_size.width())) |
499 return false; | 499 return false; |
500 | 500 |
501 if (!WriteBigEndianToFile(file, content_size.height())) | 501 if (!WriteBigEndianToFile(file, content_size.height())) |
502 return false; | 502 return false; |
503 | 503 |
504 // Write ETC1 header. | 504 // Write ETC1 header. |
505 compressed_data->lockPixels(); | |
506 | |
507 unsigned char etc1_buffer[ETC_PKM_HEADER_SIZE]; | 505 unsigned char etc1_buffer[ETC_PKM_HEADER_SIZE]; |
508 etc1_pkm_format_header(etc1_buffer, | 506 etc1_pkm_format_header(etc1_buffer, |
509 compressed_data->info().width(), | 507 compressed_data->info().width(), |
510 compressed_data->info().height()); | 508 compressed_data->info().height()); |
511 | 509 |
512 int header_bytes_written = file.WriteAtCurrentPos( | 510 int header_bytes_written = file.WriteAtCurrentPos( |
513 reinterpret_cast<char*>(etc1_buffer), ETC_PKM_HEADER_SIZE); | 511 reinterpret_cast<char*>(etc1_buffer), ETC_PKM_HEADER_SIZE); |
514 if (header_bytes_written != ETC_PKM_HEADER_SIZE) | 512 if (header_bytes_written != ETC_PKM_HEADER_SIZE) |
515 return false; | 513 return false; |
516 | 514 |
517 int data_size = etc1_get_encoded_data_size( | 515 int data_size = etc1_get_encoded_data_size( |
518 compressed_data->info().width(), | 516 compressed_data->info().width(), |
519 compressed_data->info().height()); | 517 compressed_data->info().height()); |
520 int pixel_bytes_written = file.WriteAtCurrentPos( | 518 int pixel_bytes_written = file.WriteAtCurrentPos( |
521 reinterpret_cast<char*>(compressed_data->pixels()), | 519 reinterpret_cast<char*>(compressed_data->pixels()), |
522 data_size); | 520 data_size); |
523 if (pixel_bytes_written != data_size) | 521 if (pixel_bytes_written != data_size) |
524 return false; | 522 return false; |
525 | 523 |
526 compressed_data->unlockPixels(); | |
527 | |
528 if (!WriteBigEndianToFile(file, kCurrentExtraVersion)) | 524 if (!WriteBigEndianToFile(file, kCurrentExtraVersion)) |
529 return false; | 525 return false; |
530 | 526 |
531 if (!WriteBigEndianFloatToFile(file, 1.f / scale)) | 527 if (!WriteBigEndianFloatToFile(file, 1.f / scale)) |
532 return false; | 528 return false; |
533 | 529 |
534 return true; | 530 return true; |
535 } | 531 } |
536 | 532 |
537 } // anonymous namespace | 533 } // anonymous namespace |
(...skipping 30 matching lines...) Expand all Loading... |
568 | 564 |
569 void ThumbnailCache::CompressionTask( | 565 void ThumbnailCache::CompressionTask( |
570 SkBitmap raw_data, | 566 SkBitmap raw_data, |
571 gfx::Size encoded_size, | 567 gfx::Size encoded_size, |
572 const base::Callback<void(sk_sp<SkPixelRef>, const gfx::Size&)>& | 568 const base::Callback<void(sk_sp<SkPixelRef>, const gfx::Size&)>& |
573 post_compression_task) { | 569 post_compression_task) { |
574 sk_sp<SkPixelRef> compressed_data; | 570 sk_sp<SkPixelRef> compressed_data; |
575 gfx::Size content_size; | 571 gfx::Size content_size; |
576 | 572 |
577 if (!raw_data.empty()) { | 573 if (!raw_data.empty()) { |
578 SkAutoLockPixels raw_data_lock(raw_data); | |
579 gfx::Size raw_data_size(raw_data.width(), raw_data.height()); | 574 gfx::Size raw_data_size(raw_data.width(), raw_data.height()); |
580 size_t pixel_size = 4; // Pixel size is 4 bytes for kARGB_8888_Config. | 575 size_t pixel_size = 4; // Pixel size is 4 bytes for kARGB_8888_Config. |
581 size_t stride = pixel_size * raw_data_size.width(); | 576 size_t stride = pixel_size * raw_data_size.width(); |
582 | 577 |
583 size_t encoded_bytes = | 578 size_t encoded_bytes = |
584 etc1_get_encoded_data_size(encoded_size.width(), encoded_size.height()); | 579 etc1_get_encoded_data_size(encoded_size.width(), encoded_size.height()); |
585 SkImageInfo info = SkImageInfo::Make(encoded_size.width(), | 580 SkImageInfo info = SkImageInfo::Make(encoded_size.width(), |
586 encoded_size.height(), | 581 encoded_size.height(), |
587 kUnknown_SkColorType, | 582 kUnknown_SkColorType, |
588 kUnpremul_SkAlphaType); | 583 kUnpremul_SkAlphaType); |
589 sk_sp<SkData> etc1_pixel_data(SkData::MakeUninitialized(encoded_bytes)); | 584 sk_sp<SkData> etc1_pixel_data(SkData::MakeUninitialized(encoded_bytes)); |
590 sk_sp<SkPixelRef> etc1_pixel_ref(SkMallocPixelRef::MakeWithData( | 585 sk_sp<SkPixelRef> etc1_pixel_ref(SkMallocPixelRef::MakeWithData( |
591 info, 0, NULL, std::move(etc1_pixel_data))); | 586 info, 0, NULL, std::move(etc1_pixel_data))); |
592 | 587 |
593 etc1_pixel_ref->lockPixels(); | |
594 bool success = etc1_encode_image( | 588 bool success = etc1_encode_image( |
595 reinterpret_cast<unsigned char*>(raw_data.getPixels()), | 589 reinterpret_cast<unsigned char*>(raw_data.getPixels()), |
596 raw_data_size.width(), | 590 raw_data_size.width(), |
597 raw_data_size.height(), | 591 raw_data_size.height(), |
598 pixel_size, | 592 pixel_size, |
599 stride, | 593 stride, |
600 reinterpret_cast<unsigned char*>(etc1_pixel_ref->pixels()), | 594 reinterpret_cast<unsigned char*>(etc1_pixel_ref->pixels()), |
601 encoded_size.width(), | 595 encoded_size.width(), |
602 encoded_size.height()); | 596 encoded_size.height()); |
603 etc1_pixel_ref->setImmutable(); | 597 etc1_pixel_ref->setImmutable(); |
604 etc1_pixel_ref->unlockPixels(); | |
605 | 598 |
606 if (success) { | 599 if (success) { |
607 compressed_data = std::move(etc1_pixel_ref); | 600 compressed_data = std::move(etc1_pixel_ref); |
608 content_size = raw_data_size; | 601 content_size = raw_data_size; |
609 } | 602 } |
610 } | 603 } |
611 | 604 |
612 content::BrowserThread::PostTask( | 605 content::BrowserThread::PostTask( |
613 content::BrowserThread::UI, | 606 content::BrowserThread::UI, |
614 FROM_HERE, | 607 FROM_HERE, |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
853 | 846 |
854 if (compressed_data.get()) { | 847 if (compressed_data.get()) { |
855 gfx::Size buffer_size = gfx::Size(compressed_data->info().width(), | 848 gfx::Size buffer_size = gfx::Size(compressed_data->info().width(), |
856 compressed_data->info().height()); | 849 compressed_data->info().height()); |
857 | 850 |
858 SkBitmap raw_data; | 851 SkBitmap raw_data; |
859 raw_data.allocPixels(SkImageInfo::Make(buffer_size.width(), | 852 raw_data.allocPixels(SkImageInfo::Make(buffer_size.width(), |
860 buffer_size.height(), | 853 buffer_size.height(), |
861 kRGBA_8888_SkColorType, | 854 kRGBA_8888_SkColorType, |
862 kOpaque_SkAlphaType)); | 855 kOpaque_SkAlphaType)); |
863 SkAutoLockPixels raw_data_lock(raw_data); | |
864 compressed_data->lockPixels(); | |
865 success = etc1_decode_image( | 856 success = etc1_decode_image( |
866 reinterpret_cast<unsigned char*>(compressed_data->pixels()), | 857 reinterpret_cast<unsigned char*>(compressed_data->pixels()), |
867 reinterpret_cast<unsigned char*>(raw_data.getPixels()), | 858 reinterpret_cast<unsigned char*>(raw_data.getPixels()), |
868 buffer_size.width(), | 859 buffer_size.width(), |
869 buffer_size.height(), | 860 buffer_size.height(), |
870 raw_data.bytesPerPixel(), | 861 raw_data.bytesPerPixel(), |
871 raw_data.rowBytes()); | 862 raw_data.rowBytes()); |
872 compressed_data->unlockPixels(); | |
873 raw_data.setImmutable(); | 863 raw_data.setImmutable(); |
874 | 864 |
875 if (!success) { | 865 if (!success) { |
876 // Leave raw_data_small empty for consistency with other failure modes. | 866 // Leave raw_data_small empty for consistency with other failure modes. |
877 } else if (content_size == buffer_size) { | 867 } else if (content_size == buffer_size) { |
878 // Shallow copy the pixel reference. | 868 // Shallow copy the pixel reference. |
879 raw_data_small = raw_data; | 869 raw_data_small = raw_data; |
880 } else { | 870 } else { |
881 // The content size is smaller than the buffer size (likely because of | 871 // The content size is smaller than the buffer size (likely because of |
882 // a power-of-two rounding), so deep copy the bitmap. | 872 // a power-of-two rounding), so deep copy the bitmap. |
883 raw_data_small.allocPixels(SkImageInfo::Make(content_size.width(), | 873 raw_data_small.allocPixels(SkImageInfo::Make(content_size.width(), |
884 content_size.height(), | 874 content_size.height(), |
885 kRGBA_8888_SkColorType, | 875 kRGBA_8888_SkColorType, |
886 kOpaque_SkAlphaType)); | 876 kOpaque_SkAlphaType)); |
887 SkAutoLockPixels raw_data_small_lock(raw_data_small); | |
888 SkCanvas small_canvas(raw_data_small); | 877 SkCanvas small_canvas(raw_data_small); |
889 small_canvas.drawBitmap(raw_data, 0, 0); | 878 small_canvas.drawBitmap(raw_data, 0, 0); |
890 raw_data_small.setImmutable(); | 879 raw_data_small.setImmutable(); |
891 } | 880 } |
892 } | 881 } |
893 | 882 |
894 content::BrowserThread::PostTask( | 883 content::BrowserThread::PostTask( |
895 content::BrowserThread::UI, | 884 content::BrowserThread::UI, |
896 FROM_HERE, | 885 FROM_HERE, |
897 base::Bind(post_decompression_callback, success, raw_data_small)); | 886 base::Bind(post_decompression_callback, success, raw_data_small)); |
898 } | 887 } |
899 | 888 |
900 ThumbnailCache::ThumbnailMetaData::ThumbnailMetaData() { | 889 ThumbnailCache::ThumbnailMetaData::ThumbnailMetaData() { |
901 } | 890 } |
902 | 891 |
903 ThumbnailCache::ThumbnailMetaData::ThumbnailMetaData( | 892 ThumbnailCache::ThumbnailMetaData::ThumbnailMetaData( |
904 const base::Time& current_time, | 893 const base::Time& current_time, |
905 const GURL& url) | 894 const GURL& url) |
906 : capture_time_(current_time), url_(url) { | 895 : capture_time_(current_time), url_(url) { |
907 } | 896 } |
908 | 897 |
909 std::pair<SkBitmap, float> ThumbnailCache::CreateApproximation( | 898 std::pair<SkBitmap, float> ThumbnailCache::CreateApproximation( |
910 const SkBitmap& bitmap, | 899 const SkBitmap& bitmap, |
911 float scale) { | 900 float scale) { |
912 DCHECK(!bitmap.empty()); | 901 DCHECK(!bitmap.empty()); |
913 DCHECK_GT(scale, 0); | 902 DCHECK_GT(scale, 0); |
914 SkAutoLockPixels bitmap_lock(bitmap); | |
915 float new_scale = 1.f / kApproximationScaleFactor; | 903 float new_scale = 1.f / kApproximationScaleFactor; |
916 | 904 |
917 gfx::Size dst_size = gfx::ScaleToFlooredSize( | 905 gfx::Size dst_size = gfx::ScaleToFlooredSize( |
918 gfx::Size(bitmap.width(), bitmap.height()), new_scale); | 906 gfx::Size(bitmap.width(), bitmap.height()), new_scale); |
919 SkBitmap dst_bitmap; | 907 SkBitmap dst_bitmap; |
920 dst_bitmap.allocPixels(SkImageInfo::Make(dst_size.width(), | 908 dst_bitmap.allocPixels(SkImageInfo::Make(dst_size.width(), |
921 dst_size.height(), | 909 dst_size.height(), |
922 bitmap.info().colorType(), | 910 bitmap.info().colorType(), |
923 bitmap.info().alphaType())); | 911 bitmap.info().alphaType())); |
924 dst_bitmap.eraseColor(0); | 912 dst_bitmap.eraseColor(0); |
925 SkAutoLockPixels dst_bitmap_lock(dst_bitmap); | |
926 | |
927 SkCanvas canvas(dst_bitmap); | 913 SkCanvas canvas(dst_bitmap); |
928 canvas.scale(new_scale, new_scale); | 914 canvas.scale(new_scale, new_scale); |
929 canvas.drawBitmap(bitmap, 0, 0, NULL); | 915 canvas.drawBitmap(bitmap, 0, 0, NULL); |
930 dst_bitmap.setImmutable(); | 916 dst_bitmap.setImmutable(); |
931 | 917 |
932 return std::make_pair(dst_bitmap, new_scale * scale); | 918 return std::make_pair(dst_bitmap, new_scale * scale); |
933 } | 919 } |
934 | 920 |
935 void ThumbnailCache::OnMemoryPressure( | 921 void ThumbnailCache::OnMemoryPressure( |
936 base::MemoryPressureListener::MemoryPressureLevel level) { | 922 base::MemoryPressureListener::MemoryPressureLevel level) { |
937 if (level == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { | 923 if (level == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { |
938 cache_.Clear(); | 924 cache_.Clear(); |
939 approximation_cache_.Clear(); | 925 approximation_cache_.Clear(); |
940 } | 926 } |
941 } | 927 } |
OLD | NEW |