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