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