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