• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 #include "SkChunkAlloc.h"
9 #include "SkPackBits.h"
10 #include "SkBitmap.h"
11 #include "SkPixelRef.h"
12 
13 class RLEPixelRef : public SkPixelRef {
14 public:
15     RLEPixelRef(SkBitmap::RLEPixels* rlep, SkColorTable* ctable);
16     virtual ~RLEPixelRef();
17 
18 protected:
19     // overrides from SkPixelRef
20     virtual void* onLockPixels(SkColorTable**);
21     virtual void onUnlockPixels();
22 
23 private:
24     SkBitmap::RLEPixels* fRLEPixels;
25     SkColorTable*        fCTable;
26 };
27 
RLEPixelRef(SkBitmap::RLEPixels * rlep,SkColorTable * ctable)28 RLEPixelRef::RLEPixelRef(SkBitmap::RLEPixels* rlep, SkColorTable* ctable)
29         : SkPixelRef(NULL) {
30     fRLEPixels = rlep;  // we now own this ptr
31     fCTable = ctable;
32     SkSafeRef(ctable);
33 }
34 
~RLEPixelRef()35 RLEPixelRef::~RLEPixelRef() {
36     SkDELETE(fRLEPixels);
37     SkSafeUnref(fCTable);
38 }
39 
onLockPixels(SkColorTable ** ct)40 void* RLEPixelRef::onLockPixels(SkColorTable** ct) {
41     *ct = fCTable;
42     return fRLEPixels;
43 }
44 
onUnlockPixels()45 void RLEPixelRef::onUnlockPixels() {
46     // nothing to do
47 }
48 
49 /////////////////////////////////////////////////////////////////////////////
50 
51 class ChunkRLEPixels : public SkBitmap::RLEPixels {
52 public:
ChunkRLEPixels(int width,int height,size_t chunkSize)53     ChunkRLEPixels(int width, int height, size_t chunkSize)
54         : SkBitmap::RLEPixels(width, height), fStorage(chunkSize) {
55     }
56 
57     SkChunkAlloc fStorage;
58 };
59 
60 SkPixelRef* SkCreateRLEPixelRef(const SkBitmap& src);
SkCreateRLEPixelRef(const SkBitmap & src)61 SkPixelRef* SkCreateRLEPixelRef(const SkBitmap& src) {
62 
63     if (SkBitmap::kIndex8_Config != src.config() &&
64             SkBitmap::kA8_Config != src.config()) {
65         return NULL;
66     }
67 
68     size_t maxPacked = SkPackBits::ComputeMaxSize8(src.width());
69 
70     // estimate the rle size based on the original size
71     size_t size = src.getSize() >> 3;
72     if (size < maxPacked) {
73         size = maxPacked;
74     }
75 
76     ChunkRLEPixels* rlePixels = SkNEW_ARGS(ChunkRLEPixels,
77                                            (src.width(), src.height(), size));
78 
79     uint8_t* dstRow = NULL;
80     size_t free = 0;
81     size_t totalPacked = 0;
82 
83     for (int y = 0; y < src.height(); y++) {
84         const uint8_t* srcRow = src.getAddr8(0, y);
85 
86         if (free < maxPacked) {
87             dstRow = (uint8_t*)rlePixels->fStorage.allocThrow(size);
88             free = size;
89         }
90         size_t packedSize = SkPackBits::Pack8(srcRow, src.width(), dstRow);
91         SkASSERT(packedSize <= free);
92         rlePixels->setPackedAtY(y, dstRow);
93 
94         dstRow += packedSize;
95         free -= packedSize;
96 
97         totalPacked += packedSize;
98     }
99 
100 //#ifdef SK_DEBUG
101 #if 0
102     // test
103     uint8_t* buffer = new uint8_t[src.width()];
104     for (int y = 0; y < src.height(); y++) {
105         const uint8_t* srcRow = src.getAddr8(0, y);
106         SkPackBits::Unpack8(buffer, 0, src.width(), rlePixels->packedAtY(y));
107         int n = memcmp(buffer, srcRow, src.width());
108         if (n) {
109             SkDebugf("----- memcmp returned %d on line %d\n", n, y);
110         }
111         SkASSERT(n == 0);
112     }
113     delete[] buffer;
114 
115     size_t totalAlloc = src.height() * sizeof(uint8_t*) + totalPacked;
116 
117     SkDebugf("--- RLE: orig [%d %d] %d, rle %d %d savings %g\n",
118              src.width(), src.height(), src.getSize(),
119              src.height() * sizeof(uint8_t*), totalPacked,
120              (float)totalAlloc / src.getSize());
121 
122 #endif
123 
124     // transfer ownership of rlePixels to our pixelref
125     return SkNEW_ARGS(RLEPixelRef, (rlePixels, src.getColorTable()));
126 }
127 
128