示例#1
0
// static
bool SkBitmapScaler::Resize(SkBitmap* resultPtr,
                            const SkBitmap& source,
                            ResizeMethod method,
                            float destWidth, float destHeight,
                            SkBitmap::Allocator* allocator) {

  SkConvolutionProcs convolveProcs= { 0, NULL, NULL, NULL, NULL };
  PlatformConvolutionProcs(&convolveProcs);

  SkRect destSubset = { 0, 0, destWidth, destHeight };

  // 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)));

    SkRect dest = { 0, 0, destWidth, destHeight };
    if (!dest.contains(destSubset)) {
        SkErrorInternals::SetError( kInvalidArgument_SkError,
                                    "Sorry, the destination bitmap scale subset "
                                    "falls outside the full destination bitmap." );
        return false;
    }

    // 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 ||
        destWidth < 1 || destHeight < 1) {
        // todo: seems like we could handle negative dstWidth/Height, since that
        // is just a negative scale (flip)
        return false;
    }

    method = ResizeMethodToAlgorithmMethod(method);

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

    SkAutoLockPixels locker(source);
    if (!source.readyToDraw() ||
        source.colorType() != kN32_SkColorType) {
        return false;
    }

    SkResizeFilter filter(method, source.width(), source.height(),
                          destWidth, destHeight, destSubset, convolveProcs);

    // 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 unsigned char* sourceSubset =
        reinterpret_cast<const unsigned char*>(source.getPixels());

    // Convolve into the result.
    SkBitmap result;
    result.setInfo(SkImageInfo::MakeN32(SkScalarCeilToInt(destSubset.width()),
                                        SkScalarCeilToInt(destSubset.height()),
                                        source.alphaType()));
    result.allocPixels(allocator, NULL);
    if (!result.readyToDraw()) {
        return false;
    }

    BGRAConvolve2D(sourceSubset, static_cast<int>(source.rowBytes()),
        !source.isOpaque(), filter.xFilter(), filter.yFilter(),
        static_cast<int>(result.rowBytes()),
        static_cast<unsigned char*>(result.getPixels()),
        convolveProcs, true);

    *resultPtr = result;
    resultPtr->lockPixels();
    SkASSERT(resultPtr->getPixels());
    return true;
}
示例#2
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;
}
    // 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;
    }