SkBitmap.cpp revision 03dd6d5208a6e3d92190e7020300e4399178ae4b
1/*
2 * Copyright 2008 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkAtomics.h"
9#include "SkBitmap.h"
10#include "SkColorPriv.h"
11#include "SkConfig8888.h"
12#include "SkData.h"
13#include "SkFilterQuality.h"
14#include "SkHalf.h"
15#include "SkImageInfoPriv.h"
16#include "SkMallocPixelRef.h"
17#include "SkMask.h"
18#include "SkMath.h"
19#include "SkPixelRef.h"
20#include "SkReadBuffer.h"
21#include "SkRect.h"
22#include "SkScalar.h"
23#include "SkTemplates.h"
24#include "SkUnPreMultiply.h"
25#include "SkWriteBuffer.h"
26#include "SkWritePixelsRec.h"
27
28#include <string.h>
29
30static bool reset_return_false(SkBitmap* bm) {
31    bm->reset();
32    return false;
33}
34
35SkBitmap::SkBitmap()
36    : fPixelLockCount(0)
37    , fPixels        (nullptr)
38    , fColorTable    (nullptr)
39    , fPixelRefOrigin{0, 0}
40    , fRowBytes      (0)
41    , fFlags         (0) {}
42
43// copy pixelref, but don't copy lock.
44SkBitmap::SkBitmap(const SkBitmap& src)
45    : fPixelRef      (src.fPixelRef)
46    , fPixelLockCount(0)
47    , fPixels        (nullptr)
48    , fColorTable    (nullptr)
49    , fPixelRefOrigin(src.fPixelRefOrigin)
50    , fInfo          (src.fInfo)
51    , fRowBytes      (src.fRowBytes)
52    , fFlags         (src.fFlags)
53{
54    SkDEBUGCODE(src.validate();)
55    SkDEBUGCODE(this->validate();)
56}
57
58// take lock and lockcount from other.
59SkBitmap::SkBitmap(SkBitmap&& other)
60    : fPixelRef      (std::move(other.fPixelRef))
61    , fPixelLockCount          (other.fPixelLockCount)
62    , fPixels                  (other.fPixels)
63    , fColorTable              (other.fColorTable)
64    , fPixelRefOrigin          (other.fPixelRefOrigin)
65    , fInfo          (std::move(other.fInfo))
66    , fRowBytes                (other.fRowBytes)
67    , fFlags                   (other.fFlags) {
68    SkASSERT(!other.fPixelRef);
69    other.fInfo.reset();
70    other.fPixelLockCount = 0;
71    other.fPixels         = nullptr;
72    other.fColorTable     = nullptr;
73    other.fPixelRefOrigin = SkIPoint{0, 0};
74    other.fRowBytes       = 0;
75    other.fFlags          = 0;
76}
77
78SkBitmap::~SkBitmap() {
79    SkDEBUGCODE(this->validate();)
80    this->freePixels();
81}
82
83SkBitmap& SkBitmap::operator=(const SkBitmap& src) {
84    if (this != &src) {
85        this->freePixels();
86        SkASSERT(!fPixels);
87        SkASSERT(!fColorTable);
88        SkASSERT(!fPixelLockCount);
89        fPixelRef       = src.fPixelRef;
90        fPixelRefOrigin = src.fPixelRefOrigin;
91        fInfo           = src.fInfo;
92        fRowBytes       = src.fRowBytes;
93        fFlags          = src.fFlags;
94    }
95    SkDEBUGCODE(this->validate();)
96    return *this;
97}
98
99SkBitmap& SkBitmap::operator=(SkBitmap&& other) {
100    if (this != &other) {
101        this->freePixels();
102        SkASSERT(!fPixels);
103        SkASSERT(!fColorTable);
104        SkASSERT(!fPixelLockCount);
105        fPixelRef       = std::move(other.fPixelRef);
106        fInfo           = std::move(other.fInfo);
107        fPixelLockCount = other.fPixelLockCount;
108        fPixels         = other.fPixels;
109        fColorTable     = other.fColorTable;
110        fPixelRefOrigin = other.fPixelRefOrigin;
111        fRowBytes       = other.fRowBytes;
112        fFlags          = other.fFlags;
113        SkASSERT(!other.fPixelRef);
114        other.fInfo.reset();
115        other.fPixelLockCount = 0;
116        other.fPixels         = nullptr;
117        other.fColorTable     = nullptr;
118        other.fPixelRefOrigin = SkIPoint{0, 0};
119        other.fRowBytes       = 0;
120        other.fFlags          = 0;
121    }
122    return *this;
123}
124
125void SkBitmap::swap(SkBitmap& other) {
126    SkTSwap(*this, other);
127    SkDEBUGCODE(this->validate();)
128}
129
130void SkBitmap::reset() {
131    this->freePixels();
132    this->fInfo.reset();
133    sk_bzero(this, sizeof(*this));
134}
135
136void SkBitmap::getBounds(SkRect* bounds) const {
137    SkASSERT(bounds);
138    bounds->set(0, 0,
139                SkIntToScalar(fInfo.width()), SkIntToScalar(fInfo.height()));
140}
141
142void SkBitmap::getBounds(SkIRect* bounds) const {
143    SkASSERT(bounds);
144    bounds->set(0, 0, fInfo.width(), fInfo.height());
145}
146
147///////////////////////////////////////////////////////////////////////////////
148
149bool SkBitmap::setInfo(const SkImageInfo& info, size_t rowBytes) {
150    SkAlphaType newAT = info.alphaType();
151    if (!SkColorTypeValidateAlphaType(info.colorType(), info.alphaType(), &newAT)) {
152        return reset_return_false(this);
153    }
154    // don't look at info.alphaType(), since newAT is the real value...
155
156    // require that rowBytes fit in 31bits
157    int64_t mrb = info.minRowBytes64();
158    if ((int32_t)mrb != mrb) {
159        return reset_return_false(this);
160    }
161    if ((int64_t)rowBytes != (int32_t)rowBytes) {
162        return reset_return_false(this);
163    }
164
165    if (info.width() < 0 || info.height() < 0) {
166        return reset_return_false(this);
167    }
168
169    if (kUnknown_SkColorType == info.colorType()) {
170        rowBytes = 0;
171    } else if (0 == rowBytes) {
172        rowBytes = (size_t)mrb;
173    } else if (!info.validRowBytes(rowBytes)) {
174        return reset_return_false(this);
175    }
176
177    this->freePixels();
178
179    fInfo = info.makeAlphaType(newAT);
180    fRowBytes = SkToU32(rowBytes);
181    return true;
182}
183
184bool SkBitmap::setAlphaType(SkAlphaType newAlphaType) {
185    if (!SkColorTypeValidateAlphaType(fInfo.colorType(), newAlphaType, &newAlphaType)) {
186        return false;
187    }
188    if (fInfo.alphaType() != newAlphaType) {
189        fInfo = fInfo.makeAlphaType(newAlphaType);
190        if (fPixelRef) {
191            fPixelRef->changeAlphaType(newAlphaType);
192        }
193    }
194    return true;
195}
196
197void SkBitmap::updatePixelsFromRef() const {
198    if (fPixelRef) {
199        if (fPixelLockCount > 0) {
200            SkASSERT(fPixelRef->isLocked());
201
202            void* p = fPixelRef->pixels();
203            if (p) {
204                p = (char*)p
205                    + fPixelRefOrigin.fY * fRowBytes
206                    + fPixelRefOrigin.fX * fInfo.bytesPerPixel();
207            }
208            fPixels = p;
209            fColorTable = fPixelRef->colorTable();
210        } else {
211            SkASSERT(0 == fPixelLockCount);
212            fPixels = nullptr;
213            fColorTable = nullptr;
214        }
215    }
216}
217
218#ifdef SK_SUPPORT_LEGACY_BITMAP_SETPIXELREF
219SkPixelRef* SkBitmap::setPixelRef(SkPixelRef* pr, int dx, int dy) {
220    this->setPixelRef(sk_ref_sp(pr), dx, dy);
221    return pr;
222}
223#endif
224
225void SkBitmap::setPixelRef(sk_sp<SkPixelRef> pr, int dx, int dy) {
226#ifdef SK_DEBUG
227    if (pr) {
228        if (kUnknown_SkColorType != fInfo.colorType()) {
229            const SkImageInfo& prInfo = pr->info();
230            SkASSERT(fInfo.width() <= prInfo.width());
231            SkASSERT(fInfo.height() <= prInfo.height());
232            SkASSERT(fInfo.colorType() == prInfo.colorType());
233            switch (prInfo.alphaType()) {
234                case kUnknown_SkAlphaType:
235                    SkASSERT(fInfo.alphaType() == kUnknown_SkAlphaType);
236                    break;
237                case kOpaque_SkAlphaType:
238                case kPremul_SkAlphaType:
239                    SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType ||
240                             fInfo.alphaType() == kPremul_SkAlphaType);
241                    break;
242                case kUnpremul_SkAlphaType:
243                    SkASSERT(fInfo.alphaType() == kOpaque_SkAlphaType ||
244                             fInfo.alphaType() == kUnpremul_SkAlphaType);
245                    break;
246            }
247        }
248    }
249#endif
250
251    if (pr) {
252        const SkImageInfo& info = pr->info();
253        fPixelRefOrigin.set(SkTPin(dx, 0, info.width()), SkTPin(dy, 0, info.height()));
254    } else {
255        // ignore dx,dy if there is no pixelref
256        fPixelRefOrigin.setZero();
257    }
258
259    if (fPixelRef != pr) {
260        this->freePixels();
261        SkASSERT(!fPixelRef);
262
263        fPixelRef = std::move(pr);
264        this->updatePixelsFromRef();
265    }
266
267    SkDEBUGCODE(this->validate();)
268}
269
270void SkBitmap::lockPixels() const {
271    if (fPixelRef && 0 == sk_atomic_inc(&fPixelLockCount)) {
272        fPixelRef->lockPixels();
273        this->updatePixelsFromRef();
274    }
275    SkDEBUGCODE(this->validate();)
276}
277
278void SkBitmap::unlockPixels() const {
279    SkASSERT(!fPixelRef || fPixelLockCount > 0);
280
281    if (fPixelRef && 1 == sk_atomic_dec(&fPixelLockCount)) {
282        fPixelRef->unlockPixels();
283        this->updatePixelsFromRef();
284    }
285    SkDEBUGCODE(this->validate();)
286}
287
288bool SkBitmap::lockPixelsAreWritable() const {
289    return fPixelRef ? fPixelRef->lockPixelsAreWritable() : false;
290}
291
292void SkBitmap::setPixels(void* p, SkColorTable* ctable) {
293    if (nullptr == p) {
294        this->setPixelRef(nullptr, 0, 0);
295        return;
296    }
297
298    if (kUnknown_SkColorType == fInfo.colorType()) {
299        this->setPixelRef(nullptr, 0, 0);
300        return;
301    }
302
303    sk_sp<SkPixelRef> pr(SkMallocPixelRef::NewDirect(fInfo, p, fRowBytes, ctable));
304    this->setPixelRef(std::move(pr), 0, 0);
305    if (!fPixelRef) {
306        return;
307    }
308    // since we're already allocated, we lockPixels right away
309    this->lockPixels();
310    SkDEBUGCODE(this->validate();)
311}
312
313bool SkBitmap::tryAllocPixels(Allocator* allocator, SkColorTable* ctable) {
314    HeapAllocator stdalloc;
315
316    if (nullptr == allocator) {
317        allocator = &stdalloc;
318    }
319    return allocator->allocPixelRef(this, ctable);
320}
321
322///////////////////////////////////////////////////////////////////////////////
323
324bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, size_t rowBytes) {
325    if (kIndex_8_SkColorType == requestedInfo.colorType()) {
326        return reset_return_false(this);
327    }
328    if (!this->setInfo(requestedInfo, rowBytes)) {
329        return reset_return_false(this);
330    }
331
332    // setInfo may have corrected info (e.g. 565 is always opaque).
333    const SkImageInfo& correctedInfo = this->info();
334    // setInfo may have computed a valid rowbytes if 0 were passed in
335    rowBytes = this->rowBytes();
336
337    SkMallocPixelRef::PRFactory defaultFactory;
338
339    sk_sp<SkPixelRef> pr(defaultFactory.create(correctedInfo, rowBytes, nullptr));
340    if (!pr) {
341        return reset_return_false(this);
342    }
343    this->setPixelRef(std::move(pr), 0, 0);
344
345    // TODO: lockPixels could/should return bool or void*/nullptr
346    this->lockPixels();
347    if (nullptr == this->getPixels()) {
348        return reset_return_false(this);
349    }
350    return true;
351}
352
353bool SkBitmap::tryAllocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactory* factory,
354                                SkColorTable* ctable) {
355    if (kIndex_8_SkColorType == requestedInfo.colorType() && nullptr == ctable) {
356        return reset_return_false(this);
357    }
358    if (!this->setInfo(requestedInfo)) {
359        return reset_return_false(this);
360    }
361
362    // setInfo may have corrected info (e.g. 565 is always opaque).
363    const SkImageInfo& correctedInfo = this->info();
364
365    SkMallocPixelRef::PRFactory defaultFactory;
366    if (nullptr == factory) {
367        factory = &defaultFactory;
368    }
369
370    sk_sp<SkPixelRef> pr(factory->create(correctedInfo, correctedInfo.minRowBytes(), ctable));
371    if (!pr) {
372        return reset_return_false(this);
373    }
374    this->setPixelRef(std::move(pr), 0, 0);
375
376    // TODO: lockPixels could/should return bool or void*/nullptr
377    this->lockPixels();
378    if (nullptr == this->getPixels()) {
379        return reset_return_false(this);
380    }
381    return true;
382}
383
384static void invoke_release_proc(void (*proc)(void* pixels, void* ctx), void* pixels, void* ctx) {
385    if (proc) {
386        proc(pixels, ctx);
387    }
388}
389
390bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, size_t rb,
391                             SkColorTable* ct, void (*releaseProc)(void* addr, void* context),
392                             void* context) {
393    if (!this->setInfo(requestedInfo, rb)) {
394        invoke_release_proc(releaseProc, pixels, context);
395        this->reset();
396        return false;
397    }
398    if (nullptr == pixels) {
399        invoke_release_proc(releaseProc, pixels, context);
400        return true;    // we behaved as if they called setInfo()
401    }
402
403    // setInfo may have corrected info (e.g. 565 is always opaque).
404    const SkImageInfo& correctedInfo = this->info();
405
406    sk_sp<SkPixelRef> pr(SkMallocPixelRef::NewWithProc(correctedInfo, rb, ct, pixels, releaseProc,
407                                                       context));
408    if (!pr) {
409        this->reset();
410        return false;
411    }
412
413    this->setPixelRef(std::move(pr), 0, 0);
414
415    // since we're already allocated, we lockPixels right away
416    this->lockPixels();
417    SkDEBUGCODE(this->validate();)
418    return true;
419}
420
421bool SkBitmap::installPixels(const SkPixmap& pixmap) {
422    return this->installPixels(pixmap.info(), pixmap.writable_addr(),
423                               pixmap.rowBytes(), pixmap.ctable(),
424                               nullptr, nullptr);
425}
426
427bool SkBitmap::installMaskPixels(const SkMask& mask) {
428    if (SkMask::kA8_Format != mask.fFormat) {
429        this->reset();
430        return false;
431    }
432    return this->installPixels(SkImageInfo::MakeA8(mask.fBounds.width(),
433                                                   mask.fBounds.height()),
434                               mask.fImage, mask.fRowBytes);
435}
436
437///////////////////////////////////////////////////////////////////////////////
438
439void SkBitmap::freePixels() {
440    if (fPixelRef) {
441        if (fPixelLockCount > 0) {
442            fPixelRef->unlockPixels();
443        }
444        fPixelRef = nullptr;
445        fPixelRefOrigin.setZero();
446    }
447    fPixelLockCount = 0;
448    fPixels = nullptr;
449    fColorTable = nullptr;
450}
451
452uint32_t SkBitmap::getGenerationID() const {
453    return fPixelRef ? fPixelRef->getGenerationID() : 0;
454}
455
456void SkBitmap::notifyPixelsChanged() const {
457    SkASSERT(!this->isImmutable());
458    if (fPixelRef) {
459        fPixelRef->notifyPixelsChanged();
460    }
461}
462
463///////////////////////////////////////////////////////////////////////////////
464
465/** We explicitly use the same allocator for our pixels that SkMask does,
466 so that we can freely assign memory allocated by one class to the other.
467 */
468bool SkBitmap::HeapAllocator::allocPixelRef(SkBitmap* dst,
469                                            SkColorTable* ctable) {
470    const SkImageInfo info = dst->info();
471    if (kUnknown_SkColorType == info.colorType()) {
472//        SkDebugf("unsupported config for info %d\n", dst->config());
473        return false;
474    }
475
476    sk_sp<SkPixelRef> pr(SkMallocPixelRef::NewAllocate(info, dst->rowBytes(), ctable));
477    if (!pr) {
478        return false;
479    }
480
481    dst->setPixelRef(std::move(pr), 0, 0);
482    // since we're already allocated, we lockPixels right away
483    dst->lockPixels();
484    return true;
485}
486
487///////////////////////////////////////////////////////////////////////////////
488
489static bool copy_pixels_to(const SkPixmap& src, void* const dst, size_t dstSize,
490                           size_t dstRowBytes, bool preserveDstPad) {
491    const SkImageInfo& info = src.info();
492
493    if (0 == dstRowBytes) {
494        dstRowBytes = src.rowBytes();
495    }
496    if (dstRowBytes < info.minRowBytes()) {
497        return false;
498    }
499
500    if (!preserveDstPad && static_cast<uint32_t>(dstRowBytes) == src.rowBytes()) {
501        size_t safeSize = src.getSafeSize();
502        if (safeSize > dstSize || safeSize == 0)
503            return false;
504        else {
505            // This implementation will write bytes beyond the end of each row,
506            // excluding the last row, if the bitmap's stride is greater than
507            // strictly required by the current config.
508            memcpy(dst, src.addr(), safeSize);
509            return true;
510        }
511    } else {
512        // If destination has different stride than us, then copy line by line.
513        if (info.getSafeSize(dstRowBytes) > dstSize) {
514            return false;
515        } else {
516            // Just copy what we need on each line.
517            size_t rowBytes = info.minRowBytes();
518            const uint8_t* srcP = reinterpret_cast<const uint8_t*>(src.addr());
519            uint8_t* dstP = reinterpret_cast<uint8_t*>(dst);
520            for (int row = 0; row < info.height(); ++row) {
521                memcpy(dstP, srcP, rowBytes);
522                srcP += src.rowBytes();
523                dstP += dstRowBytes;
524            }
525
526            return true;
527        }
528    }
529}
530
531bool SkBitmap::copyPixelsTo(void* dst, size_t dstSize, size_t dstRB, bool preserveDstPad) const {
532    if (nullptr == dst) {
533        return false;
534    }
535    SkAutoPixmapUnlock result;
536    if (!this->requestLock(&result)) {
537        return false;
538    }
539    return copy_pixels_to(result.pixmap(), dst, dstSize, dstRB, preserveDstPad);
540}
541
542///////////////////////////////////////////////////////////////////////////////
543
544bool SkBitmap::isImmutable() const {
545    return fPixelRef ? fPixelRef->isImmutable() : false;
546}
547
548void SkBitmap::setImmutable() {
549    if (fPixelRef) {
550        fPixelRef->setImmutable();
551    }
552}
553
554bool SkBitmap::isVolatile() const {
555    return (fFlags & kImageIsVolatile_Flag) != 0;
556}
557
558void SkBitmap::setIsVolatile(bool isVolatile) {
559    if (isVolatile) {
560        fFlags |= kImageIsVolatile_Flag;
561    } else {
562        fFlags &= ~kImageIsVolatile_Flag;
563    }
564}
565
566void* SkBitmap::getAddr(int x, int y) const {
567    SkASSERT((unsigned)x < (unsigned)this->width());
568    SkASSERT((unsigned)y < (unsigned)this->height());
569
570    char* base = (char*)this->getPixels();
571    if (base) {
572        base += y * this->rowBytes();
573        switch (this->colorType()) {
574            case kRGBA_F16_SkColorType:
575                base += x << 3;
576                break;
577            case kRGBA_8888_SkColorType:
578            case kBGRA_8888_SkColorType:
579                base += x << 2;
580                break;
581            case kARGB_4444_SkColorType:
582            case kRGB_565_SkColorType:
583                base += x << 1;
584                break;
585            case kAlpha_8_SkColorType:
586            case kIndex_8_SkColorType:
587            case kGray_8_SkColorType:
588                base += x;
589                break;
590            default:
591                SkDEBUGFAIL("Can't return addr for config");
592                base = nullptr;
593                break;
594        }
595    }
596    return base;
597}
598
599///////////////////////////////////////////////////////////////////////////////
600///////////////////////////////////////////////////////////////////////////////
601
602void SkBitmap::erase(SkColor c, const SkIRect& area) const {
603    SkDEBUGCODE(this->validate();)
604
605    switch (fInfo.colorType()) {
606        case kUnknown_SkColorType:
607        case kIndex_8_SkColorType:
608            // TODO: can we ASSERT that we never get here?
609            return; // can't erase. Should we bzero so the memory is not uninitialized?
610        default:
611            break;
612    }
613
614    SkAutoPixmapUnlock result;
615    if (!this->requestLock(&result)) {
616        return;
617    }
618
619    if (result.pixmap().erase(c, area)) {
620        this->notifyPixelsChanged();
621    }
622}
623
624void SkBitmap::eraseColor(SkColor c) const {
625    this->erase(c, SkIRect::MakeWH(this->width(), this->height()));
626}
627
628//////////////////////////////////////////////////////////////////////////////////////
629//////////////////////////////////////////////////////////////////////////////////////
630
631bool SkBitmap::extractSubset(SkBitmap* result, const SkIRect& subset) const {
632    SkDEBUGCODE(this->validate();)
633
634    if (nullptr == result || !fPixelRef) {
635        return false;   // no src pixels
636    }
637
638    SkIRect srcRect, r;
639    srcRect.set(0, 0, this->width(), this->height());
640    if (!r.intersect(srcRect, subset)) {
641        return false;   // r is empty (i.e. no intersection)
642    }
643
644    // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have
645    // exited above.
646    SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width()));
647    SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height()));
648
649    SkBitmap dst;
650    dst.setInfo(this->info().makeWH(r.width(), r.height()), this->rowBytes());
651    dst.setIsVolatile(this->isVolatile());
652
653    if (fPixelRef) {
654        SkIPoint origin = fPixelRefOrigin;
655        origin.fX += r.fLeft;
656        origin.fY += r.fTop;
657        // share the pixelref with a custom offset
658        dst.setPixelRef(fPixelRef, origin.x(), origin.y());
659    }
660    SkDEBUGCODE(dst.validate();)
661
662    // we know we're good, so commit to result
663    result->swap(dst);
664    return true;
665}
666
667///////////////////////////////////////////////////////////////////////////////
668
669bool SkBitmap::canCopyTo(SkColorType dstCT) const {
670    const SkColorType srcCT = this->colorType();
671
672    if (srcCT == kUnknown_SkColorType) {
673        return false;
674    }
675    if (srcCT == kAlpha_8_SkColorType && dstCT != kAlpha_8_SkColorType) {
676        return false;   // can't convert from alpha to non-alpha
677    }
678
679    bool sameConfigs = (srcCT == dstCT);
680    switch (dstCT) {
681        case kAlpha_8_SkColorType:
682        case kRGB_565_SkColorType:
683        case kRGBA_8888_SkColorType:
684        case kBGRA_8888_SkColorType:
685            break;
686        case kGray_8_SkColorType:
687            if (!sameConfigs) {
688                return false;
689            }
690            break;
691        case kARGB_4444_SkColorType:
692            return sameConfigs || kN32_SkColorType == srcCT || kIndex_8_SkColorType == srcCT;
693        default:
694            return false;
695    }
696    return true;
697}
698
699bool SkBitmap::readPixels(const SkImageInfo& requestedDstInfo, void* dstPixels, size_t dstRB,
700                          int x, int y) const {
701    SkAutoPixmapUnlock src;
702    if (!this->requestLock(&src)) {
703        return false;
704    }
705    return src.pixmap().readPixels(requestedDstInfo, dstPixels, dstRB, x, y);
706}
707
708bool SkBitmap::readPixels(const SkPixmap& dst, int srcX, int srcY) const {
709    return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
710}
711
712bool SkBitmap::writePixels(const SkPixmap& src, int dstX, int dstY) {
713    SkAutoPixmapUnlock dst;
714    if (!this->requestLock(&dst)) {
715        return false;
716    }
717
718    if (!SkImageInfoValidConversion(fInfo, src.info())) {
719        return false;
720    }
721
722    SkWritePixelsRec rec(src.info(), src.addr(), src.rowBytes(), dstX, dstY);
723    if (!rec.trim(fInfo.width(), fInfo.height())) {
724        return false;
725    }
726
727    void* dstPixels = this->getAddr(rec.fX, rec.fY);
728    const SkImageInfo dstInfo = fInfo.makeWH(rec.fInfo.width(), rec.fInfo.height());
729    return SkPixelInfo::CopyPixels(dstInfo, dstPixels, this->rowBytes(),
730                                   rec.fInfo, rec.fPixels, rec.fRowBytes, src.ctable());
731}
732
733bool SkBitmap::copyTo(SkBitmap* dst, SkColorType dstColorType, Allocator* alloc) const {
734    if (!this->canCopyTo(dstColorType)) {
735        return false;
736    }
737
738    // if we have a texture, first get those pixels
739    SkBitmap tmpSrc;
740    const SkBitmap* src = this;
741
742    if (fPixelRef) {
743        SkIRect subset;
744        subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY,
745                       fInfo.width(), fInfo.height());
746        if (fPixelRef->readPixels(&tmpSrc, dstColorType, &subset)) {
747            if (fPixelRef->info().alphaType() == kUnpremul_SkAlphaType) {
748                // FIXME: The only meaningful implementation of readPixels
749                // (GrPixelRef) assumes premultiplied pixels.
750                return false;
751            }
752            SkASSERT(tmpSrc.width() == this->width());
753            SkASSERT(tmpSrc.height() == this->height());
754
755            // did we get lucky and we can just return tmpSrc?
756            if (tmpSrc.colorType() == dstColorType && nullptr == alloc) {
757                dst->swap(tmpSrc);
758                // If the result is an exact copy, clone the gen ID.
759                SkPixelRef* dstPixelRef = dst->pixelRef();
760                if (!dstPixelRef && dstPixelRef->info() == fPixelRef->info()) {
761                    dstPixelRef->cloneGenID(*fPixelRef);
762                }
763                return true;
764            }
765
766            // fall through to the raster case
767            src = &tmpSrc;
768        }
769    }
770
771    SkAutoPixmapUnlock srcUnlocker;
772    if (!src->requestLock(&srcUnlocker)) {
773        return false;
774    }
775    SkPixmap srcPM = srcUnlocker.pixmap();
776    if (kRGB_565_SkColorType == dstColorType && kOpaque_SkAlphaType != srcPM.alphaType()) {
777        // copyTo() is not strict on alpha type.  Here we set the src to opaque to allow
778        // the call to readPixels() to succeed and preserve this lenient behavior.
779        srcPM = SkPixmap(srcPM.info().makeAlphaType(kOpaque_SkAlphaType), srcPM.addr(),
780                         srcPM.rowBytes(), srcPM.ctable());
781    }
782
783    const SkImageInfo dstInfo = srcPM.info().makeColorType(dstColorType);
784    SkBitmap tmpDst;
785    if (!tmpDst.setInfo(dstInfo)) {
786        return false;
787    }
788
789    // allocate colortable if srcConfig == kIndex8_Config
790    sk_sp<SkColorTable> ctable;
791    if (dstColorType == kIndex_8_SkColorType) {
792        ctable.reset(SkRef(srcPM.ctable()));
793    }
794    if (!tmpDst.tryAllocPixels(alloc, ctable.get())) {
795        return false;
796    }
797
798    SkAutoPixmapUnlock dstUnlocker;
799    if (!tmpDst.requestLock(&dstUnlocker)) {
800        return false;
801    }
802
803    if (!srcPM.readPixels(dstUnlocker.pixmap())) {
804        return false;
805    }
806
807    //  (for BitmapHeap) Clone the pixelref genID even though we have a new pixelref.
808    //  The old copyTo impl did this, so we continue it for now.
809    //
810    //  TODO: should we ignore rowbytes (i.e. getSize)? Then it could just be
811    //      if (src_pixelref->info == dst_pixelref->info)
812    //
813    if (srcPM.colorType() == dstColorType && tmpDst.getSize() == srcPM.getSize64()) {
814        SkPixelRef* dstPixelRef = tmpDst.pixelRef();
815        if (dstPixelRef->info() == fPixelRef->info()) {
816            dstPixelRef->cloneGenID(*fPixelRef);
817        }
818    }
819
820    dst->swap(tmpDst);
821    return true;
822}
823
824// TODO: can we merge this with copyTo?
825bool SkBitmap::deepCopyTo(SkBitmap* dst) const {
826    const SkColorType dstCT = this->colorType();
827
828    if (!this->canCopyTo(dstCT)) {
829        return false;
830    }
831    return this->copyTo(dst, dstCT, nullptr);
832}
833
834///////////////////////////////////////////////////////////////////////////////
835
836static bool GetBitmapAlpha(const SkBitmap& src, uint8_t* SK_RESTRICT alpha, int alphaRowBytes) {
837    SkASSERT(alpha != nullptr);
838    SkASSERT(alphaRowBytes >= src.width());
839
840    SkAutoPixmapUnlock apl;
841    if (!src.requestLock(&apl)) {
842        for (int y = 0; y < src.height(); ++y) {
843            memset(alpha, 0, src.width());
844            alpha += alphaRowBytes;
845        }
846        return false;
847    }
848    const SkPixmap& pmap = apl.pixmap();
849    SkPixelInfo::CopyPixels(SkImageInfo::MakeA8(pmap.width(), pmap.height()), alpha, alphaRowBytes,
850                            pmap.info(), pmap.addr(), pmap.rowBytes(), pmap.ctable());
851    return true;
852}
853
854#include "SkPaint.h"
855#include "SkMaskFilter.h"
856#include "SkMatrix.h"
857
858bool SkBitmap::extractAlpha(SkBitmap* dst, const SkPaint* paint,
859                            Allocator *allocator, SkIPoint* offset) const {
860    SkDEBUGCODE(this->validate();)
861
862    SkBitmap    tmpBitmap;
863    SkMatrix    identity;
864    SkMask      srcM, dstM;
865
866    srcM.fBounds.set(0, 0, this->width(), this->height());
867    srcM.fRowBytes = SkAlign4(this->width());
868    srcM.fFormat = SkMask::kA8_Format;
869
870    SkMaskFilter* filter = paint ? paint->getMaskFilter() : nullptr;
871
872    // compute our (larger?) dst bounds if we have a filter
873    if (filter) {
874        identity.reset();
875        if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
876            goto NO_FILTER_CASE;
877        }
878        dstM.fRowBytes = SkAlign4(dstM.fBounds.width());
879    } else {
880    NO_FILTER_CASE:
881        tmpBitmap.setInfo(SkImageInfo::MakeA8(this->width(), this->height()), srcM.fRowBytes);
882        if (!tmpBitmap.tryAllocPixels(allocator, nullptr)) {
883            // Allocation of pixels for alpha bitmap failed.
884            SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
885                    tmpBitmap.width(), tmpBitmap.height());
886            return false;
887        }
888        GetBitmapAlpha(*this, tmpBitmap.getAddr8(0, 0), srcM.fRowBytes);
889        if (offset) {
890            offset->set(0, 0);
891        }
892        tmpBitmap.swap(*dst);
893        return true;
894    }
895    srcM.fImage = SkMask::AllocImage(srcM.computeImageSize());
896    SkAutoMaskFreeImage srcCleanup(srcM.fImage);
897
898    GetBitmapAlpha(*this, srcM.fImage, srcM.fRowBytes);
899    if (!filter->filterMask(&dstM, srcM, identity, nullptr)) {
900        goto NO_FILTER_CASE;
901    }
902    SkAutoMaskFreeImage dstCleanup(dstM.fImage);
903
904    tmpBitmap.setInfo(SkImageInfo::MakeA8(dstM.fBounds.width(), dstM.fBounds.height()),
905                      dstM.fRowBytes);
906    if (!tmpBitmap.tryAllocPixels(allocator, nullptr)) {
907        // Allocation of pixels for alpha bitmap failed.
908        SkDebugf("extractAlpha failed to allocate (%d,%d) alpha bitmap\n",
909                tmpBitmap.width(), tmpBitmap.height());
910        return false;
911    }
912    memcpy(tmpBitmap.getPixels(), dstM.fImage, dstM.computeImageSize());
913    if (offset) {
914        offset->set(dstM.fBounds.fLeft, dstM.fBounds.fTop);
915    }
916    SkDEBUGCODE(tmpBitmap.validate();)
917
918    tmpBitmap.swap(*dst);
919    return true;
920}
921
922///////////////////////////////////////////////////////////////////////////////
923
924static void write_raw_pixels(SkWriteBuffer* buffer, const SkPixmap& pmap) {
925    const SkImageInfo& info = pmap.info();
926    const size_t snugRB = info.width() * info.bytesPerPixel();
927    const char* src = (const char*)pmap.addr();
928    const size_t ramRB = pmap.rowBytes();
929
930    buffer->write32(SkToU32(snugRB));
931    info.flatten(*buffer);
932
933    const size_t size = snugRB * info.height();
934    SkAutoTMalloc<char> storage(size);
935    char* dst = storage.get();
936    for (int y = 0; y < info.height(); ++y) {
937        memcpy(dst, src, snugRB);
938        dst += snugRB;
939        src += ramRB;
940    }
941    buffer->writeByteArray(storage.get(), size);
942
943    const SkColorTable* ct = pmap.ctable();
944    if (kIndex_8_SkColorType == info.colorType() && ct) {
945        buffer->writeBool(true);
946        ct->writeToBuffer(*buffer);
947    } else {
948        buffer->writeBool(false);
949    }
950}
951
952void SkBitmap::WriteRawPixels(SkWriteBuffer* buffer, const SkBitmap& bitmap) {
953    const SkImageInfo info = bitmap.info();
954    if (0 == info.width() || 0 == info.height() || bitmap.isNull()) {
955        buffer->writeUInt(0); // instead of snugRB, signaling no pixels
956        return;
957    }
958
959    SkAutoPixmapUnlock result;
960    if (!bitmap.requestLock(&result)) {
961        buffer->writeUInt(0); // instead of snugRB, signaling no pixels
962        return;
963    }
964
965    write_raw_pixels(buffer, result.pixmap());
966}
967
968bool SkBitmap::ReadRawPixels(SkReadBuffer* buffer, SkBitmap* bitmap) {
969    const size_t snugRB = buffer->readUInt();
970    if (0 == snugRB) {  // no pixels
971        return false;
972    }
973
974    SkImageInfo info;
975    info.unflatten(*buffer);
976
977    if (info.width() < 0 || info.height() < 0) {
978        return false;
979    }
980
981    // If there was an error reading "info" or if it is bogus,
982    // don't use it to compute minRowBytes()
983    if (!buffer->validate(SkColorTypeValidateAlphaType(info.colorType(),
984                                                       info.alphaType()))) {
985        return false;
986    }
987
988    const size_t ramRB = info.minRowBytes();
989    const int height = SkMax32(info.height(), 0);
990    const uint64_t snugSize = sk_64_mul(snugRB, height);
991    const uint64_t ramSize = sk_64_mul(ramRB, height);
992    static const uint64_t max_size_t = (size_t)(-1);
993    if (!buffer->validate((snugSize <= ramSize) && (ramSize <= max_size_t))) {
994        return false;
995    }
996
997    sk_sp<SkData> data(SkData::MakeUninitialized(SkToSizeT(ramSize)));
998    unsigned char* dst = (unsigned char*)data->writable_data();
999    buffer->readByteArray(dst, SkToSizeT(snugSize));
1000
1001    if (snugSize != ramSize) {
1002        const unsigned char* srcRow = dst + snugRB * (height - 1);
1003        unsigned char* dstRow = dst + ramRB * (height - 1);
1004        for (int y = height - 1; y >= 1; --y) {
1005            memmove(dstRow, srcRow, snugRB);
1006            srcRow -= snugRB;
1007            dstRow -= ramRB;
1008        }
1009        SkASSERT(srcRow == dstRow); // first row does not need to be moved
1010    }
1011
1012    sk_sp<SkColorTable> ctable;
1013    if (buffer->readBool()) {
1014        ctable.reset(SkColorTable::Create(*buffer));
1015        if (!ctable) {
1016            return false;
1017        }
1018
1019        if (info.isEmpty()) {
1020            // require an empty ctable
1021            if (ctable->count() != 0) {
1022                buffer->validate(false);
1023                return false;
1024            }
1025        } else {
1026            // require a non-empty ctable
1027            if (ctable->count() == 0) {
1028                buffer->validate(false);
1029                return false;
1030            }
1031            unsigned char maxIndex = ctable->count() - 1;
1032            for (uint64_t i = 0; i < ramSize; ++i) {
1033                dst[i] = SkTMin(dst[i], maxIndex);
1034            }
1035        }
1036    }
1037
1038    sk_sp<SkPixelRef> pr(SkMallocPixelRef::NewWithData(info, info.minRowBytes(),
1039                                                       ctable.get(), data.get()));
1040    if (!pr.get()) {
1041        return false;
1042    }
1043    bitmap->setInfo(pr->info());
1044    bitmap->setPixelRef(std::move(pr), 0, 0);
1045    return true;
1046}
1047
1048enum {
1049    SERIALIZE_PIXELTYPE_NONE,
1050    SERIALIZE_PIXELTYPE_REF_DATA
1051};
1052
1053///////////////////////////////////////////////////////////////////////////////
1054
1055SkBitmap::RLEPixels::RLEPixels(int width, int height) {
1056    fHeight = height;
1057    fYPtrs = (uint8_t**)sk_calloc_throw(height * sizeof(uint8_t*));
1058}
1059
1060SkBitmap::RLEPixels::~RLEPixels() {
1061    sk_free(fYPtrs);
1062}
1063
1064///////////////////////////////////////////////////////////////////////////////
1065
1066#ifdef SK_DEBUG
1067void SkBitmap::validate() const {
1068    fInfo.validate();
1069
1070    // ImageInfo may not require this, but Bitmap ensures that opaque-only
1071    // colorTypes report opaque for their alphatype
1072    if (kRGB_565_SkColorType == fInfo.colorType()) {
1073        SkASSERT(kOpaque_SkAlphaType == fInfo.alphaType());
1074    }
1075
1076    SkASSERT(fInfo.validRowBytes(fRowBytes));
1077    uint8_t allFlags = kImageIsVolatile_Flag;
1078#ifdef SK_BUILD_FOR_ANDROID
1079    allFlags |= kHasHardwareMipMap_Flag;
1080#endif
1081    SkASSERT((~allFlags & fFlags) == 0);
1082    SkASSERT(fPixelLockCount >= 0);
1083
1084    if (fPixels) {
1085        SkASSERT(fPixelRef);
1086        SkASSERT(fPixelLockCount > 0);
1087        SkASSERT(fPixelRef->isLocked());
1088        SkASSERT(fPixelRef->rowBytes() == fRowBytes);
1089        SkASSERT(fPixelRefOrigin.fX >= 0);
1090        SkASSERT(fPixelRefOrigin.fY >= 0);
1091        SkASSERT(fPixelRef->info().width() >= (int)this->width() + fPixelRefOrigin.fX);
1092        SkASSERT(fPixelRef->info().height() >= (int)this->height() + fPixelRefOrigin.fY);
1093        SkASSERT(fPixelRef->rowBytes() >= fInfo.minRowBytes());
1094    } else {
1095        SkASSERT(nullptr == fColorTable);
1096    }
1097}
1098#endif
1099
1100#ifndef SK_IGNORE_TO_STRING
1101#include "SkString.h"
1102void SkBitmap::toString(SkString* str) const {
1103
1104    static const char* gColorTypeNames[kLastEnum_SkColorType + 1] = {
1105        "UNKNOWN", "A8", "565", "4444", "RGBA", "BGRA", "INDEX8",
1106    };
1107
1108    str->appendf("bitmap: ((%d, %d) %s", this->width(), this->height(),
1109                 gColorTypeNames[this->colorType()]);
1110
1111    str->append(" (");
1112    if (this->isOpaque()) {
1113        str->append("opaque");
1114    } else {
1115        str->append("transparent");
1116    }
1117    if (this->isImmutable()) {
1118        str->append(", immutable");
1119    } else {
1120        str->append(", not-immutable");
1121    }
1122    str->append(")");
1123
1124    SkPixelRef* pr = this->pixelRef();
1125    if (nullptr == pr) {
1126        // show null or the explicit pixel address (rare)
1127        str->appendf(" pixels:%p", this->getPixels());
1128    } else {
1129        const char* uri = pr->getURI();
1130        if (uri) {
1131            str->appendf(" uri:\"%s\"", uri);
1132        } else {
1133            str->appendf(" pixelref:%p", pr);
1134        }
1135    }
1136
1137    str->append(")");
1138}
1139#endif
1140
1141///////////////////////////////////////////////////////////////////////////////
1142
1143bool SkBitmap::requestLock(SkAutoPixmapUnlock* result) const {
1144    SkASSERT(result);
1145
1146    SkPixelRef* pr = fPixelRef.get();
1147    if (nullptr == pr) {
1148        return false;
1149    }
1150
1151    // We have to lock the whole thing (using the pixelref's dimensions) until the api supports
1152    // a partial lock (with offset/origin). Hence we can't use our fInfo.
1153    SkPixelRef::LockRequest req = { pr->info().dimensions(), kNone_SkFilterQuality };
1154    SkPixelRef::LockResult res;
1155    if (pr->requestLock(req, &res)) {
1156        SkASSERT(res.fPixels);
1157        // The bitmap may be a subset of the pixelref's dimensions
1158        SkASSERT(fPixelRefOrigin.x() + fInfo.width()  <= res.fSize.width());
1159        SkASSERT(fPixelRefOrigin.y() + fInfo.height() <= res.fSize.height());
1160        const void* addr = (const char*)res.fPixels + SkColorTypeComputeOffset(fInfo.colorType(),
1161                                                                               fPixelRefOrigin.x(),
1162                                                                               fPixelRefOrigin.y(),
1163                                                                               res.fRowBytes);
1164
1165        result->reset(SkPixmap(this->info(), addr, res.fRowBytes, res.fCTable),
1166                      res.fUnlockProc, res.fUnlockContext);
1167        return true;
1168    }
1169    return false;
1170}
1171
1172bool SkBitmap::peekPixels(SkPixmap* pmap) const {
1173    if (fPixels) {
1174        if (pmap) {
1175            pmap->reset(fInfo, fPixels, fRowBytes, fColorTable);
1176        }
1177        return true;
1178    }
1179    return false;
1180}
1181
1182///////////////////////////////////////////////////////////////////////////////
1183
1184#ifdef SK_DEBUG
1185void SkImageInfo::validate() const {
1186    SkASSERT(fWidth >= 0);
1187    SkASSERT(fHeight >= 0);
1188    SkASSERT(SkColorTypeIsValid(fColorType));
1189    SkASSERT(SkAlphaTypeIsValid(fAlphaType));
1190}
1191#endif
1192