diff options
author | 2016-02-01 13:16:14 -0800 | |
---|---|---|
committer | 2016-02-01 13:16:14 -0800 | |
commit | f267c1efe7de7a8e71404afde6cbf93c3808d267 (patch) | |
tree | 3ca07e8c6e5526ccfe4166953631006dd8b71845 /gm | |
parent | 9d02b264b72be64702e43cb797b7899a8a6926ca (diff) |
Add ability to extract YUV planes from SkImage
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1513393002
Review URL: https://codereview.chromium.org/1513393002
Diffstat (limited to 'gm')
-rw-r--r-- | gm/imagetoyuvplanes.cpp | 111 | ||||
-rw-r--r-- | gm/yuvtorgbeffect.cpp | 14 |
2 files changed, 118 insertions, 7 deletions
diff --git a/gm/imagetoyuvplanes.cpp b/gm/imagetoyuvplanes.cpp new file mode 100644 index 0000000000..4883a682f8 --- /dev/null +++ b/gm/imagetoyuvplanes.cpp @@ -0,0 +1,111 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#include <SkSurface.h> +#include "gm.h" +#include "SkBitmap.h" +#include "SkGradientShader.h" +#include "SkImage.h" + +static SkImage* create_image(GrContext* context, int width, int height) { + SkAutoTUnref<SkSurface> surface; + SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); + if (context) { + surface.reset(SkSurface::NewRenderTarget(context, SkSurface::kYes_Budgeted, info, 0)); + } else { + surface.reset(SkSurface::NewRaster(info)); + } + if (!surface) { + return nullptr; + } + // Create an RGB image from which we will extract planes + SkPaint paint; + static const SkColor kColors[] = + { SK_ColorBLUE, SK_ColorYELLOW, SK_ColorGREEN, SK_ColorWHITE }; + SkScalar r = (width + height) / 4.f; + paint.setShader(SkGradientShader::CreateRadial(SkPoint::Make(0,0), r, kColors, + nullptr, SK_ARRAY_COUNT(kColors), + SkShader::kMirror_TileMode))->unref(); + + surface->getCanvas()->drawPaint(paint); + return surface->newImageSnapshot(); +} + +DEF_SIMPLE_GM(image_to_yuv_planes, canvas, 120, 525) { + static const SkScalar kPad = 5.f; + static const int kImageSize = 32; + + GrContext *context = canvas->getGrContext(); + SkAutoTUnref<SkImage> rgbImage(create_image(context, kImageSize, kImageSize)); + if (!rgbImage) { + return; + } + + canvas->drawImage(rgbImage, kPad, kPad); + // Test cases where all three planes are the same size, where just u and v are the same size, + // and where all differ. + static const SkISize kSizes[][3] = { + {{kImageSize, kImageSize}, {kImageSize , kImageSize }, {kImageSize, kImageSize }}, + {{kImageSize, kImageSize}, {kImageSize/2, kImageSize/2}, {kImageSize/2, kImageSize/2}}, + {{kImageSize, kImageSize}, {kImageSize/2, kImageSize/2}, {kImageSize/3, kImageSize/3}} + }; + + // A mix of rowbytes triples to go with the above sizes. + static const size_t kRowBytes[][3] { + {0, 0, 0}, + {kImageSize, kImageSize/2 + 1, kImageSize}, + {kImageSize + 13, kImageSize, kImageSize/3 + 8} + }; + + + SkScalar x = kPad; + for (size_t s = 0; s < SK_ARRAY_COUNT(kSizes); ++s) { + SkScalar y = rgbImage->height() + 2 * kPad; + + const SkISize *sizes = kSizes[s]; + size_t realRowBytes[3]; + for (int i = 0; i < 3; ++i) { + realRowBytes[i] = kRowBytes[s][i] ? kRowBytes[s][i] : kSizes[s][i].fWidth; + } + SkAutoTDeleteArray<uint8_t> yPlane(new uint8_t[realRowBytes[0] * sizes[0].fHeight]); + SkAutoTDeleteArray<uint8_t> uPlane(new uint8_t[realRowBytes[1] * sizes[1].fHeight]); + SkAutoTDeleteArray<uint8_t> vPlane(new uint8_t[realRowBytes[2] * sizes[2].fHeight]); + + void *planes[3] = {yPlane.get(), uPlane.get(), vPlane.get()}; + + // Convert the RGB image to YUV planes using each YUV color space and draw the YUV planes + // to the canvas. + SkBitmap yuvBmps[3]; + yuvBmps[0].setInfo(SkImageInfo::MakeA8(sizes[0].fWidth, sizes[0].fHeight), kRowBytes[s][0]); + yuvBmps[1].setInfo(SkImageInfo::MakeA8(sizes[1].fWidth, sizes[1].fHeight), kRowBytes[s][1]); + yuvBmps[2].setInfo(SkImageInfo::MakeA8(sizes[2].fWidth, sizes[2].fHeight), kRowBytes[s][2]); + yuvBmps[0].setPixels(yPlane.get()); + yuvBmps[1].setPixels(uPlane.get()); + yuvBmps[2].setPixels(vPlane.get()); + + for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace; ++space) { + // Clear the planes so we don't accidentally see the old values if there is a bug in + // readYUV8Planes(). + memset(yPlane.get(), 0, realRowBytes[0] * sizes[0].fHeight); + memset(uPlane.get(), 0, realRowBytes[1] * sizes[1].fHeight); + memset(vPlane.get(), 0, realRowBytes[2] * sizes[2].fHeight); + if (rgbImage->readYUV8Planes(sizes, planes, kRowBytes[s], + static_cast<SkYUVColorSpace>(space))) { + yuvBmps[0].notifyPixelsChanged(); + yuvBmps[1].notifyPixelsChanged(); + yuvBmps[2].notifyPixelsChanged(); + for (int i = 0; i < 3; ++i) { + canvas->drawBitmap(yuvBmps[i], x, y); + y += kPad + yuvBmps[i].height(); + } + } + } + + x += rgbImage->width() + kPad; + } +} diff --git a/gm/yuvtorgbeffect.cpp b/gm/yuvtorgbeffect.cpp index 18d799c3f7..bf4094cf4f 100644 --- a/gm/yuvtorgbeffect.cpp +++ b/gm/yuvtorgbeffect.cpp @@ -20,7 +20,7 @@ #include "SkGradientShader.h" #include "batches/GrDrawBatch.h" #include "batches/GrRectBatchFactory.h" -#include "effects/GrYUVtoRGBEffect.h" +#include "effects/GrYUVEffect.h" #define YSIZE 8 #define USIZE 4 @@ -118,12 +118,12 @@ protected: GrPipelineBuilder pipelineBuilder; pipelineBuilder.setXPFactory( GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref(); - SkAutoTUnref<GrFragmentProcessor> fp( - GrYUVtoRGBEffect::Create(texture[indices[i][0]], - texture[indices[i][1]], - texture[indices[i][2]], - sizes, - static_cast<SkYUVColorSpace>(space))); + SkAutoTUnref<const GrFragmentProcessor> fp( + GrYUVEffect::CreateYUVToRGB(texture[indices[i][0]], + texture[indices[i][1]], + texture[indices[i][2]], + sizes, + static_cast<SkYUVColorSpace>(space))); if (fp) { SkMatrix viewMatrix; viewMatrix.setTranslate(x, y); |