Пример #1
0
// static
SkBitmap ImageOperations::ResizeBasic(const SkBitmap& source,
                                      ResizeMethod method,
                                      int dest_width, int dest_height,
                                      const SkIRect& dest_subset,
                                      void* dest_pixels /* = nullptr */) {
  // Ensure that the ResizeMethod enumeration is sound.
  SkASSERT(((RESIZE_FIRST_QUALITY_METHOD <= method) &&
            (method <= RESIZE_LAST_QUALITY_METHOD)) ||
           ((RESIZE_FIRST_ALGORITHM_METHOD <= method) &&
            (method <= RESIZE_LAST_ALGORITHM_METHOD)));

  // If the size of source or destination is 0, i.e. 0x0, 0xN or Nx0, just
  // return empty.
  if (source.width() < 1 || source.height() < 1 ||
      dest_width < 1 || dest_height < 1)
    return SkBitmap();

  method = ResizeMethodToAlgorithmMethod(method);
  // Check that we deal with an "algorithm methods" from this point onward.
  SkASSERT((ImageOperations::RESIZE_FIRST_ALGORITHM_METHOD <= method) &&
           (method <= ImageOperations::RESIZE_LAST_ALGORITHM_METHOD));

  SkAutoLockPixels locker(source);
  if (!source.readyToDraw())
      return SkBitmap();

  ConvolutionFilter1D x_filter;
  ConvolutionFilter1D y_filter;

  resize::ComputeFilters(method, source.width(), dest_width, dest_subset.fLeft, dest_subset.width(), &x_filter);
  resize::ComputeFilters(method, source.height(), dest_height, dest_subset.fTop, dest_subset.height(), &y_filter);

  // Get a source bitmap encompassing this touched area. We construct the
  // offsets and row strides such that it looks like a new bitmap, while
  // referring to the old data.
  const uint8_t* source_subset =
      reinterpret_cast<const uint8_t*>(source.getPixels());

  // Convolve into the result.
  SkBitmap result;
  SkImageInfo info = SkImageInfo::Make(dest_subset.width(),
                                       dest_subset.height(),
                                       kBGRA_8888_SkColorType,
                                       kPremul_SkAlphaType);

  if (dest_pixels) {
    result.installPixels(info, dest_pixels, info.minRowBytes());
  } else {
    result.allocPixels(info);
  }

  if (!result.readyToDraw())
    return SkBitmap();

  BGRAConvolve2D(source_subset, static_cast<int>(source.rowBytes()),
                 !source.isOpaque(), x_filter, y_filter,
                 static_cast<int>(result.rowBytes()),
                 static_cast<unsigned char*>(result.getPixels()));

  // Preserve the "opaque" flag for use as an optimization later.
  result.setAlphaType(source.alphaType());

  return result;
}
Пример #2
0
SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_t index)
{
    TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "index", static_cast<int>(index));

    ImageDecoder* decoder = 0;
    const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder);
    ASSERT(!resumeDecoding || decoder);

    SkBitmap fullSizeImage;
    bool complete = decode(index, &decoder, &fullSizeImage);

    if (!decoder)
        return SkBitmap();
    if (index >= m_frameComplete.size())
        m_frameComplete.resize(index + 1);
    m_frameComplete[index] = complete;

    // If we are not resuming decoding that means the decoder is freshly
    // created and we have ownership. If we are resuming decoding then
    // the decoder is owned by ImageDecodingStore.
    OwnPtr<ImageDecoder> decoderContainer;
    if (!resumeDecoding)
        decoderContainer = adoptPtr(decoder);

    if (fullSizeImage.isNull()) {
        // If decode has failed and resulted an empty image we can save work
        // in the future by returning early.
        m_decodeFailedAndEmpty = !m_isMultiFrame && decoder->failed();

        if (resumeDecoding)
            ImageDecodingStore::instance().unlockDecoder(this, decoder);
        return SkBitmap();
    }

    // If the image generated is complete then there is no need to keep
    // the decoder. For multi-frame images, if all frames in the image are
    // decoded, we remove the decoder.
    bool removeDecoder;

    if (m_isMultiFrame) {
        size_t decodedFrameCount = 0;
        for (Vector<bool>::iterator it = m_frameComplete.begin(); it != m_frameComplete.end(); ++it) {
            if (*it)
                decodedFrameCount++;
        }
        removeDecoder = m_frameCount && (decodedFrameCount == m_frameCount);
    } else {
        removeDecoder = complete;
    }

    if (resumeDecoding) {
        if (removeDecoder) {
            ImageDecodingStore::instance().removeDecoder(this, decoder);
            m_frameComplete.clear();
        } else {
            ImageDecodingStore::instance().unlockDecoder(this, decoder);
        }
    } else if (!removeDecoder) {
        ImageDecodingStore::instance().insertDecoder(this, decoderContainer.release());
    }
    return fullSizeImage;
}
Пример #3
0
// static
SkBitmap ImageOperations::ResizeSubpixel(const SkBitmap& source,
                                         int dest_width, int dest_height,
                                         const SkIRect& dest_subset) {
  // Currently only works on Linux/BSD because these are the only platforms
  // where SkFontHost::GetSubpixelOrder is defined.
#if defined(XP_UNIX)
  // Understand the display.
  const SkFontHost::LCDOrder order = SkFontHost::GetSubpixelOrder();
  const SkFontHost::LCDOrientation orientation =
      SkFontHost::GetSubpixelOrientation();

  // Decide on which dimension, if any, to deploy subpixel rendering.
  int w = 1;
  int h = 1;
  switch (orientation) {
    case SkFontHost::kHorizontal_LCDOrientation:
      w = dest_width < source.width() ? 3 : 1;
      break;
    case SkFontHost::kVertical_LCDOrientation:
      h = dest_height < source.height() ? 3 : 1;
      break;
  }

  // Resize the image.
  const int width = dest_width * w;
  const int height = dest_height * h;
  SkIRect subset = { dest_subset.fLeft, dest_subset.fTop,
                     dest_subset.fLeft + dest_subset.width() * w,
                     dest_subset.fTop + dest_subset.height() * h };
  SkBitmap img = ResizeBasic(source, ImageOperations::RESIZE_LANCZOS3, width,
                             height, subset);
  const int row_words = img.rowBytes() / 4;
  if (w == 1 && h == 1)
    return img;

  // Render into subpixels.
  SkBitmap result;
  SkImageInfo info = SkImageInfo::Make(dest_subset.width(),
                                       dest_subset.height(),
                                       kBGRA_8888_SkColorType,
                                       kPremul_SkAlphaType);


  result.allocPixels(info);
  if (!result.readyToDraw())
    return img;

  SkAutoLockPixels locker(img);
  if (!img.readyToDraw())
    return img;

  uint32_t* src_row = img.getAddr32(0, 0);
  uint32_t* dst_row = result.getAddr32(0, 0);
  for (int y = 0; y < dest_subset.height(); y++) {
    uint32_t* src = src_row;
    uint32_t* dst = dst_row;
    for (int x = 0; x < dest_subset.width(); x++, src += w, dst++) {
      uint8_t r = 0, g = 0, b = 0, a = 0;
      switch (order) {
        case SkFontHost::kRGB_LCDOrder:
          switch (orientation) {
            case SkFontHost::kHorizontal_LCDOrientation:
              r = SkGetPackedR32(src[0]);
              g = SkGetPackedG32(src[1]);
              b = SkGetPackedB32(src[2]);
              a = SkGetPackedA32(src[1]);
              break;
            case SkFontHost::kVertical_LCDOrientation:
              r = SkGetPackedR32(src[0 * row_words]);
              g = SkGetPackedG32(src[1 * row_words]);
              b = SkGetPackedB32(src[2 * row_words]);
              a = SkGetPackedA32(src[1 * row_words]);
              break;
          }
          break;
        case SkFontHost::kBGR_LCDOrder:
          switch (orientation) {
            case SkFontHost::kHorizontal_LCDOrientation:
              b = SkGetPackedB32(src[0]);
              g = SkGetPackedG32(src[1]);
              r = SkGetPackedR32(src[2]);
              a = SkGetPackedA32(src[1]);
              break;
            case SkFontHost::kVertical_LCDOrientation:
              b = SkGetPackedB32(src[0 * row_words]);
              g = SkGetPackedG32(src[1 * row_words]);
              r = SkGetPackedR32(src[2 * row_words]);
              a = SkGetPackedA32(src[1 * row_words]);
              break;
          }
          break;
        case SkFontHost::kNONE_LCDOrder:
          break;
      }
      // Premultiplied alpha is very fragile.
      a = a > r ? a : r;
      a = a > g ? a : g;
      a = a > b ? a : b;
      *dst = SkPackARGB32(a, r, g, b);
    }
    src_row += h * row_words;
    dst_row += result.rowBytes() / 4;
  }
  result.setAlphaType(img.alphaType());
  return result;
#else
  return SkBitmap();
#endif  // OS_POSIX && !OS_MACOSX && !defined(OS_ANDROID)
}
Пример #4
0
 // Returns the icon to be displayed in the window.
 SkBitmap WidgetDelegate::GetWindowIcon()
 {
     return SkBitmap();
 }
Пример #5
0
 void ImageButton::SetImage(ButtonState aState, const SkBitmap* anImage)
 {
     images_[aState] = anImage ? *anImage : SkBitmap();
     PreferredSizeChanged();
 }
Пример #6
0
 Menu* Menu::AddSubMenu(int index, int item_id, const std::wstring& label)
 {
     return AddSubMenuWithIcon(index, item_id, label, SkBitmap());
 }
Пример #7
0
    // static
    SkBitmap ImageOperations::ResizeBasic(const SkBitmap& source,
        ResizeMethod method,
        int dest_width, int dest_height,
        const SkIRect& dest_subset)
    {
        // 确保枚举值合法.
        SkASSERT(((RESIZE_FIRST_QUALITY_METHOD<=method) &&
            (method<=RESIZE_LAST_QUALITY_METHOD)) ||
            ((RESIZE_FIRST_ALGORITHM_METHOD<=method) &&
            (method<=RESIZE_LAST_ALGORITHM_METHOD)));

        // 用于计算函数执行时间, 方便查看是否有问题.
        base::TimeTicks resize_start = base::TimeTicks::Now();

        SkIRect dest = { 0, 0, dest_width, dest_height };
        DCHECK(dest.contains(dest_subset)) <<
            "The supplied subset does not fall within the destination image.";

        // 如果源和目的大小都是0(0*0 0*N N*0), 返回一个空位图.
        if(source.width()<1 || source.height()<1 ||
            dest_width<1 || dest_height<1)
        {
            return SkBitmap();
        }

        method = ResizeMethodToAlgorithmMethod(method);
        // Check that we deal with an "algorithm methods" from this point onward.
        SkASSERT((ImageOperations::RESIZE_FIRST_ALGORITHM_METHOD<=method) &&
            (method<=ImageOperations::RESIZE_LAST_ALGORITHM_METHOD));

        SkAutoLockPixels locker(source);

        ResizeFilter filter(method, source.width(), source.height(),
            dest_width, dest_height, dest_subset);

        // Get a source bitmap encompassing this touched area. We construct the
        // offsets and row strides such that it looks like a new bitmap, while
        // referring to the old data.
        const uint8* source_subset =
            reinterpret_cast<const uint8*>(source.getPixels());

        // Convolve into the result.
        base::CPU cpu;
        SkBitmap result;
        result.setConfig(SkBitmap::kARGB_8888_Config,
            dest_subset.width(), dest_subset.height());
        result.allocPixels();
        BGRAConvolve2D(source_subset, static_cast<int>(source.rowBytes()),
            !source.isOpaque(), filter.x_filter(), filter.y_filter(),
            static_cast<int>(result.rowBytes()),
            static_cast<unsigned char*>(result.getPixels()),
            cpu.has_sse2());

        // Preserve the "opaque" flag for use as an optimization later.
        result.setIsOpaque(source.isOpaque());

        base::TimeDelta delta = base::TimeTicks::Now() - resize_start;
        UMA_HISTOGRAM_TIMES("Image.ResampleMS", delta);

        return result;
    }