1868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// found in the LICENSE file. 4868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/thumbnails/content_based_thumbnailing_algorithm.h" 6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/metrics/histogram.h" 8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/thumbnails/content_analysis.h" 10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/thumbnails/simple_thumbnail_crop.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/scrollbar_size.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/size_conversions.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/skbitmap_operations.h" 16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "ui/gfx/skia_util.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace { 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kThumbnailHistogramName[] = "Thumbnail.RetargetMS"; 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kFailureHistogramName[] = "Thumbnail.FailedRetargetMS"; 22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const float kScoreBoostFromSuccessfulRetargeting = 1.1f; 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 24868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void CallbackInvocationAdapter( 25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const thumbnails::ThumbnailingAlgorithm::ConsumerCallback& callback, 26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_refptr<thumbnails::ThumbnailingContext> context, 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const SkBitmap& source_bitmap) { 287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) callback.Run(*context.get(), source_bitmap); 29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace 32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace thumbnails { 34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)using content::BrowserThread; 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ContentBasedThumbnailingAlgorithm::ContentBasedThumbnailingAlgorithm( 38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::Size& target_size) 39868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : target_size_(target_size) { 40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!target_size.IsEmpty()); 41868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ClipResult ContentBasedThumbnailingAlgorithm::GetCanvasCopyInfo( 44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::Size& source_size, 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ui::ScaleFactor scale_factor, 46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect* clipping_rect, 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size* target_size) const { 48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(!source_size.IsEmpty()); 49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size target_thumbnail_size = 50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SimpleThumbnailCrop::GetCopySizeForThumbnail(scale_factor, target_size_); 51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ClipResult clipping_method = thumbnails::CLIP_RESULT_NOT_CLIPPED; 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *clipping_rect = GetClippingRect( 54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) source_size, target_thumbnail_size, target_size, &clipping_method); 55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return clipping_method; 56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ContentBasedThumbnailingAlgorithm::ProcessBitmap( 59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_refptr<ThumbnailingContext> context, 60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const ConsumerCallback& callback, 61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const SkBitmap& bitmap) { 62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(context.get()); 64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (bitmap.isNull() || bitmap.empty()) 65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size target_thumbnail_size = 68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SimpleThumbnailCrop::ComputeTargetSizeAtMaximumScale(target_size_); 69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SkBitmap source_bitmap = 717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) PrepareSourceBitmap(bitmap, target_thumbnail_size, context.get()); 72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // If the source is same (or smaller) than the target, just return it as 74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // the final result. Otherwise, send the shrinking task to the blocking 75868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // thread pool. 76868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (source_bitmap.width() <= target_thumbnail_size.width() || 77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) source_bitmap.height() <= target_thumbnail_size.height()) { 78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->score.boring_score = 79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SimpleThumbnailCrop::CalculateBoringScore(source_bitmap); 80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->score.good_clipping = 81868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (context->clip_result == CLIP_RESULT_WIDER_THAN_TALL || 82868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->clip_result == CLIP_RESULT_TALLER_THAN_WIDE || 83868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->clip_result == CLIP_RESULT_NOT_CLIPPED || 84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->clip_result == CLIP_RESULT_SOURCE_SAME_AS_TARGET); 85868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) callback.Run(*context.get(), source_bitmap); 87868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior( 91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FROM_HERE, 92868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&CreateRetargetedThumbnail, 93868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) source_bitmap, 94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) target_thumbnail_size, 95868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context, 96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) callback), 97868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)) { 98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(WARNING) << "PostSequencedWorkerTask failed. The thumbnail for " 99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << context->url << " will not be created."; 100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static 104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)SkBitmap ContentBasedThumbnailingAlgorithm::PrepareSourceBitmap( 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const SkBitmap& received_bitmap, 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::Size& thumbnail_size, 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ThumbnailingContext* context) { 108868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size resize_target; 109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SkBitmap clipped_bitmap; 110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (context->clip_result == CLIP_RESULT_UNPROCESSED) { 111868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // This case will require extracting a fragment from the retrieved bitmap. 112868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int scrollbar_size = gfx::scrollbar_size(); 113868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size scrollbarless( 114868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::max(1, received_bitmap.width() - scrollbar_size), 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) std::max(1, received_bitmap.height() - scrollbar_size)); 116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect clipping_rect = GetClippingRect( 118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scrollbarless, 119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) thumbnail_size, 120868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &resize_target, 121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &context->clip_result); 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) received_bitmap.extractSubset(&clipped_bitmap, 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::RectToSkIRect(clipping_rect)); 125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // This means that the source bitmap has been requested and at least 127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // clipped. Upstream code in same cases seems opportunistic and it may 128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // not perform actual resizing if copying with resize is not supported. 129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // In this case we will resize to the orignally requested copy size. 130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) resize_target = context->requested_copy_size; 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) clipped_bitmap = received_bitmap; 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SkBitmap result_bitmap = SkBitmapOperations::DownsampleByTwoUntilSize( 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) clipped_bitmap, resize_target.width(), resize_target.height()); 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#if !defined(USE_AURA) 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // If the bitmap has not been indeed resized, it has to be copied. In that 138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // case resampler simply returns a reference to the original bitmap, sitting 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // in PlatformCanvas. One does not simply assign these 'magic' bitmaps to 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // SkBitmap. They cannot be refcounted. 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // With Aura, this does not happen since PlatformCanvas is platform 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // idependent. 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (clipped_bitmap.width() == result_bitmap.width() && 145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) clipped_bitmap.height() == result_bitmap.height()) { 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch clipped_bitmap.copyTo(&result_bitmap, kN32_SkColorType); 147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif 149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return result_bitmap; 151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ContentBasedThumbnailingAlgorithm::CreateRetargetedThumbnail( 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const SkBitmap& source_bitmap, 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::Size& thumbnail_size, 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) scoped_refptr<ThumbnailingContext> context, 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const ConsumerCallback& callback) { 159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::TimeTicks begin_compute_thumbnail = base::TimeTicks::Now(); 160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) float kernel_sigma = 161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->clip_result == CLIP_RESULT_SOURCE_SAME_AS_TARGET ? 5.0f : 2.5f; 162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SkBitmap thumbnail = thumbnailing_utils::CreateRetargetedThumbnailImage( 163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) source_bitmap, thumbnail_size, kernel_sigma); 164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool processing_failed = thumbnail.empty(); 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (processing_failed) { 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Log and apply the method very much like in SimpleThumbnailCrop (except 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // that some clipping and copying is not required). 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(WARNING) << "CreateRetargetedThumbnailImage failed. " 169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << "The thumbnail for " << context->url 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) << " will be created the old-fashioned way."; 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ClipResult clip_result; 173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect clipping_rect = SimpleThumbnailCrop::GetClippingRect( 174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size(source_bitmap.width(), source_bitmap.height()), 175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) thumbnail_size, 176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) &clip_result); 177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) source_bitmap.extractSubset(&thumbnail, gfx::RectToSkIRect(clipping_rect)); 178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) thumbnail = SkBitmapOperations::DownsampleByTwoUntilSize( 179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) thumbnail, thumbnail_size.width(), thumbnail_size.height()); 180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (processing_failed) { 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LOCAL_HISTOGRAM_TIMES(kFailureHistogramName, 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::TimeTicks::Now() - begin_compute_thumbnail); 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci LOCAL_HISTOGRAM_TIMES(kThumbnailHistogramName, 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::TimeTicks::Now() - begin_compute_thumbnail); 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->score.boring_score = 190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SimpleThumbnailCrop::CalculateBoringScore(source_bitmap); 191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!processing_failed) 192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->score.boring_score *= kScoreBoostFromSuccessfulRetargeting; 193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->score.good_clipping = 194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) (context->clip_result == CLIP_RESULT_WIDER_THAN_TALL || 195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->clip_result == CLIP_RESULT_TALLER_THAN_WIDE || 196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->clip_result == CLIP_RESULT_NOT_CLIPPED || 197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) context->clip_result == CLIP_RESULT_SOURCE_SAME_AS_TARGET); 198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Post the result (the bitmap) back to the callback. 199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BrowserThread::PostTask( 200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) BrowserThread::UI, 201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) FROM_HERE, 202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::Bind(&CallbackInvocationAdapter, callback, context, thumbnail)); 203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ContentBasedThumbnailingAlgorithm::~ContentBasedThumbnailingAlgorithm() { 206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// static 209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)gfx::Rect ContentBasedThumbnailingAlgorithm::GetClippingRect( 210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::Size& source_size, 211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const gfx::Size& thumbnail_size, 212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Size* target_size, 213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ClipResult* clip_result) { 214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Compute and return the clipping rectagle of the source image and the 215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // size of the target bitmap which will be used for the further processing. 216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // This function in 'general case' is trivial (don't clip, halve the source) 217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // but it is needed for handling edge cases (source smaller than the target 218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // thumbnail size). 219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(target_size); 220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(clip_result); 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) gfx::Rect clipping_rect; 222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (source_size.width() < thumbnail_size.width() || 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) source_size.height() < thumbnail_size.height()) { 224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) clipping_rect = gfx::Rect(thumbnail_size); 225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *target_size = thumbnail_size; 226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *clip_result = CLIP_RESULT_SOURCE_IS_SMALLER; 227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (source_size.width() < thumbnail_size.width() * 4 || 228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) source_size.height() < thumbnail_size.height() * 4) { 229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) clipping_rect = gfx::Rect(source_size); 230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *target_size = source_size; 231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *clip_result = CLIP_RESULT_SOURCE_SAME_AS_TARGET; 232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) clipping_rect = gfx::Rect(source_size); 234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) target_size->SetSize(source_size.width() / 2, source_size.height() / 2); 235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *clip_result = CLIP_RESULT_NOT_CLIPPED; 236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return clipping_rect; 239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace thumbnails 242