 Chromium Code Reviews
 Chromium Code Reviews Issue 377303002:
  add readPixels() to SkBitmap  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@master
    
  
    Issue 377303002:
  add readPixels() to SkBitmap  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@master| OLD | NEW | 
|---|---|
| 1 | 1 | 
| 2 /* | 2 /* | 
| 3 * Copyright 2008 The Android Open Source Project | 3 * Copyright 2008 The Android Open Source Project | 
| 4 * | 4 * | 
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be | 
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. | 
| 7 */ | 7 */ | 
| 8 | 8 | 
| 9 | 9 | 
| 10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" | 
| (...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 814 result->swap(dst); | 814 result->swap(dst); | 
| 815 return true; | 815 return true; | 
| 816 } | 816 } | 
| 817 | 817 | 
| 818 /////////////////////////////////////////////////////////////////////////////// | 818 /////////////////////////////////////////////////////////////////////////////// | 
| 819 | 819 | 
| 820 #include "SkCanvas.h" | 820 #include "SkCanvas.h" | 
| 821 #include "SkPaint.h" | 821 #include "SkPaint.h" | 
| 822 | 822 | 
| 823 bool SkBitmap::canCopyTo(SkColorType dstColorType) const { | 823 bool SkBitmap::canCopyTo(SkColorType dstColorType) const { | 
| 824 if (this->colorType() == kUnknown_SkColorType) { | 824 const SkColorType srcCT = this->colorType(); | 
| 825 | |
| 826 if (srcCT == kUnknown_SkColorType) { | |
| 825 return false; | 827 return false; | 
| 826 } | 828 } | 
| 827 | 829 | 
| 828 bool sameConfigs = (this->colorType() == dstColorType); | 830 bool sameConfigs = (srcCT == dstColorType); | 
| 829 switch (dstColorType) { | 831 switch (dstColorType) { | 
| 830 case kAlpha_8_SkColorType: | 832 case kAlpha_8_SkColorType: | 
| 831 case kRGB_565_SkColorType: | 833 case kRGB_565_SkColorType: | 
| 832 case kRGBA_8888_SkColorType: | 834 case kRGBA_8888_SkColorType: | 
| 833 case kBGRA_8888_SkColorType: | 835 case kBGRA_8888_SkColorType: | 
| 834 break; | 836 break; | 
| 835 case kIndex_8_SkColorType: | 837 case kIndex_8_SkColorType: | 
| 836 if (!sameConfigs) { | 838 if (!sameConfigs) { | 
| 837 return false; | 839 return false; | 
| 838 } | 840 } | 
| 839 break; | 841 break; | 
| 840 case kARGB_4444_SkColorType: | 842 case kARGB_4444_SkColorType: | 
| 841 return sameConfigs || kN32_SkColorType == this->colorType(); | 843 return sameConfigs || kN32_SkColorType == srcCT || kIndex_8_SkColorT ype == srcCT; | 
| 842 default: | 844 default: | 
| 843 return false; | 845 return false; | 
| 844 } | 846 } | 
| 845 return true; | 847 return true; | 
| 846 } | 848 } | 
| 847 | 849 | 
| 850 #include "SkConfig8888.h" | |
| 851 | |
| 852 bool SkBitmap::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t ds tRB, | |
| 853 int x, int y) const { | |
| 854 if (kUnknown_SkColorType == dstInfo.colorType()) { | |
| 855 return false; | |
| 856 } | |
| 857 if (NULL == dstPixels || dstRB < dstInfo.minRowBytes()) { | |
| 858 return false; | |
| 859 } | |
| 860 if (0 == dstInfo.width() || 0 == dstInfo.height()) { | |
| 
scroggo
2014/07/10 15:09:48
Arguably this could return true.
 
reed1
2014/07/10 15:32:16
Possibly. Below we return false if the srcR doesn'
 | |
| 861 return false; | |
| 862 } | |
| 863 | |
| 864 SkIRect srcR = SkIRect::MakeXYWH(x, y, dstInfo.width(), dstInfo.height()); | |
| 865 if (!srcR.intersect(0, 0, this->width(), this->height())) { | |
| 866 return false; | |
| 867 } | |
| 868 | |
| 869 SkImageInfo info = dstInfo; | |
| 870 // the intersect may have shrunk info's logical size | |
| 871 info.fWidth = srcR.width(); | |
| 872 info.fHeight = srcR.height(); | |
| 
scroggo
2014/07/10 15:09:48
You never use info after this (except to check byt
 
reed1
2014/07/10 15:32:16
Good catch.
 | |
| 873 | |
| 874 // if x or y are negative, then we have to adjust pixels | |
| 875 if (x > 0) { | |
| 876 x = 0; | |
| 877 } | |
| 878 if (y > 0) { | |
| 879 y = 0; | |
| 880 } | |
| 881 // here x,y are either 0 or negative | |
| 882 dstPixels = ((char*)dstPixels - y * dstRB - x * info.bytesPerPixel()); | |
| 883 | |
| 884 ////////////// | |
| 885 | |
| 886 SkAutoLockPixels alp(*this); | |
| 887 | |
| 888 // since we don't stop creating un-pixeled devices yet, check for no pixels here | |
| 889 if (NULL == this->getPixels()) { | |
| 890 return false; | |
| 891 } | |
| 892 | |
| 893 SkImageInfo srcInfo = this->info(); | |
| 894 srcInfo.fWidth = dstInfo.width(); | |
| 
scroggo
2014/07/10 15:09:48
shouldn't this be:
    srcInfo.fWidth = info.widt
 
reed1
2014/07/10 15:32:15
Agreed. I will make the suggested change above, an
 | |
| 895 srcInfo.fHeight = dstInfo.height(); | |
| 896 | |
| 897 const void* srcPixels = this->getAddr(srcR.x(), srcR.y()); | |
| 898 return SkPixelInfo::CopyPixels(dstInfo, dstPixels, dstRB, srcInfo, srcPixels , this->rowBytes(), | |
| 899 this->getColorTable()); | |
| 900 } | |
| 901 | |
| 848 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, | 902 bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, | 
| 849 Allocator* alloc) const { | 903 Allocator* alloc) const { | 
| 850 if (!this->canCopyTo(dstColorType)) { | 904 if (!this->canCopyTo(dstColorType)) { | 
| 851 return false; | 905 return false; | 
| 852 } | 906 } | 
| 853 | 907 | 
| 854 // if we have a texture, first get those pixels | 908 // if we have a texture, first get those pixels | 
| 855 SkBitmap tmpSrc; | 909 SkBitmap tmpSrc; | 
| 856 const SkBitmap* src = this; | 910 const SkBitmap* src = this; | 
| 857 | 911 | 
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 912 | 966 | 
| 913 if (!tmpDst.readyToDraw()) { | 967 if (!tmpDst.readyToDraw()) { | 
| 914 // allocator/lock failed | 968 // allocator/lock failed | 
| 915 return false; | 969 return false; | 
| 916 } | 970 } | 
| 917 | 971 | 
| 918 // pixelRef must be non NULL or tmpDst.readyToDraw() would have | 972 // pixelRef must be non NULL or tmpDst.readyToDraw() would have | 
| 919 // returned false. | 973 // returned false. | 
| 920 SkASSERT(tmpDst.pixelRef() != NULL); | 974 SkASSERT(tmpDst.pixelRef() != NULL); | 
| 921 | 975 | 
| 922 /* do memcpy for the same configs cases, else use drawing | 976 if (!src->readPixels(tmpDst.info(), tmpDst.getPixels(), tmpDst.rowBytes(), 0 , 0)) { | 
| 923 */ | 977 return false; | 
| 924 if (src->colorType() == dstColorType) { | 978 } | 
| 925 if (tmpDst.getSize() == src->getSize()) { | |
| 926 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); | |
| 927 | 979 | 
| 928 SkPixelRef* dstPixelRef = tmpDst.pixelRef(); | 980 // Hack (for BitmapHeap) -- clone the pixelref genID even though we have a new pixelref. | 
| 929 if (dstPixelRef->info() == fPixelRef->info()) { | 981 // The old copyTo impl did this, so we continue it for now. | 
| 
scroggo
2014/07/10 15:09:48
I don't agree that this is a hack. The point of th
 
reed1
2014/07/10 15:32:16
I don't agree with the hack either, but BitmapHeap
 | |
| 930 dstPixelRef->cloneGenID(*fPixelRef); | 982 // | 
| 931 } | 983 if (src->colorType() == dstColorType && tmpDst.getSize() == src->getSize()) { | 
| 932 } else { | 984 SkPixelRef* dstPixelRef = tmpDst.pixelRef(); | 
| 933 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); | 985 if (dstPixelRef->info() == fPixelRef->info()) { | 
| 934 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); | 986 dstPixelRef->cloneGenID(*fPixelRef); | 
| 935 // to be sure we don't read too much, only copy our logical pixels | |
| 936 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); | |
| 937 for (int y = 0; y < tmpDst.height(); y++) { | |
| 938 memcpy(dstP, srcP, bytesToCopy); | |
| 939 srcP += src->rowBytes(); | |
| 940 dstP += tmpDst.rowBytes(); | |
| 941 } | |
| 942 } | 987 } | 
| 943 } else if (kARGB_4444_SkColorType == dstColorType | |
| 944 && kN32_SkColorType == src->colorType()) { | |
| 945 if (src->alphaType() == kUnpremul_SkAlphaType) { | |
| 946 // Our method for converting to 4444 assumes premultiplied. | |
| 947 return false; | |
| 948 } | |
| 949 SkASSERT(src->height() == tmpDst.height()); | |
| 950 SkASSERT(src->width() == tmpDst.width()); | |
| 951 for (int y = 0; y < src->height(); ++y) { | |
| 952 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0, y); | |
| 953 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); | |
| 954 DITHER_4444_SCAN(y); | |
| 955 for (int x = 0; x < src->width(); ++x) { | |
| 956 dstRow[x] = SkDitherARGB32To4444(srcRow[x], | |
| 957 DITHER_VALUE(x)); | |
| 958 } | |
| 959 } | |
| 960 } else { | |
| 961 if (tmpDst.alphaType() == kUnpremul_SkAlphaType) { | |
| 962 // We do not support drawing to unpremultiplied bitmaps. | |
| 963 return false; | |
| 964 } | |
| 965 | |
| 966 // Always clear the dest in case one of the blitters accesses it | |
| 967 // TODO: switch the allocation of tmpDst to call sk_calloc_throw | |
| 968 tmpDst.eraseColor(SK_ColorTRANSPARENT); | |
| 969 | |
| 970 SkCanvas canvas(tmpDst); | |
| 971 SkPaint paint; | |
| 972 | |
| 973 paint.setDither(true); | |
| 974 canvas.drawBitmap(*src, 0, 0, &paint); | |
| 975 } | 988 } | 
| 976 | 989 | 
| 977 dst->swap(tmpDst); | 990 dst->swap(tmpDst); | 
| 978 return true; | 991 return true; | 
| 979 } | 992 } | 
| 980 | 993 | 
| 981 bool SkBitmap::deepCopyTo(SkBitmap* dst) const { | 994 bool SkBitmap::deepCopyTo(SkBitmap* dst) const { | 
| 982 const SkColorType dstCT = this->colorType(); | 995 const SkColorType dstCT = this->colorType(); | 
| 983 | 996 | 
| 984 if (!this->canCopyTo(dstCT)) { | 997 if (!this->canCopyTo(dstCT)) { | 
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1383 /////////////////////////////////////////////////////////////////////////////// | 1396 /////////////////////////////////////////////////////////////////////////////// | 
| 1384 | 1397 | 
| 1385 #ifdef SK_DEBUG | 1398 #ifdef SK_DEBUG | 
| 1386 void SkImageInfo::validate() const { | 1399 void SkImageInfo::validate() const { | 
| 1387 SkASSERT(fWidth >= 0); | 1400 SkASSERT(fWidth >= 0); | 
| 1388 SkASSERT(fHeight >= 0); | 1401 SkASSERT(fHeight >= 0); | 
| 1389 SkASSERT(SkColorTypeIsValid(fColorType)); | 1402 SkASSERT(SkColorTypeIsValid(fColorType)); | 
| 1390 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); | 1403 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); | 
| 1391 } | 1404 } | 
| 1392 #endif | 1405 #endif | 
| OLD | NEW |