Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 236 lines (211 sloc) 8.029 kb
dc5be1c0 » uli
2009-07-04 Initial check-in.
1 //
2 // NSImage+IconRef.m
3 // testapp
4 //
5 // Created by Uli Kusterer on 09.02.05.
720b0e7b »
2010-03-04 Added licensing information to the source files.
6 // Copyright 2005 M. Uli Kusterer.
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 // claim that you wrote the original software. If you use this software
18 // in a product, an acknowledgment in the product documentation would be
19 // appreciated but is not required.
20 //
21 // 2. Altered source versions must be plainly marked as such, and must not be
22 // misrepresented as being the original software.
23 //
24 // 3. This notice may not be removed or altered from any source
25 // distribution.
dc5be1c0 » uli
2009-07-04 Initial check-in.
26 //
27
28 #import "NSImage+IconRef.h"
29
30
31 // -----------------------------------------------------------------------------
32 // Expatriates from Troy Stephens' IconFamily class:
33 // -----------------------------------------------------------------------------
34
35 @implementation NSImage (UKIconRef)
36
37 -(IconRef) iconRefRepresentation
38 {
39 static int gIKitCounter = 0;
40 IconRef iconRef = NULL;
41 IconFamilyHandle fam = (IconFamilyHandle) NewHandle( sizeof(OSType) + sizeof(Size) );
42 (**fam).resourceType = 'icns';
43 (**fam).resourceSize = sizeof(OSType) + sizeof(Size);
44
45 Handle myPict = [self get32BitDataAtPixelSize: 128];
46 SetIconFamilyData( fam, kThumbnail32BitData, myPict );
47 DisposeHandle( myPict );
48 myPict = [self get8BitMaskAtPixelSize: 128];
49 SetIconFamilyData( fam, kThumbnail8BitMask, myPict );
50 DisposeHandle( myPict );
51
52 RegisterIconRefFromIconFamily( 'IKit', ++gIKitCounter, fam, &iconRef );
53 DisposeHandle( (Handle) fam );
54
55 return iconRef;
56 }
57
58 -(Handle) get8BitMaskAtPixelSize: (int)requiredPixelSize
59 {
60 NSBitmapImageRep* bitmapImageRep = [NSBitmapImageRep imageRepWithData: [self TIFFRepresentation]];
61 Handle hRawData;
62 unsigned char* pRawData;
63 Size rawDataSize;
64 unsigned char* pSrc;
65 unsigned char* pDest;
66 int x, y;
67
68 // Get information about the bitmapImageRep.
69 int pixelsWide = [bitmapImageRep pixelsWide];
70 int pixelsHigh = [bitmapImageRep pixelsHigh];
71 int bitsPerSample = [bitmapImageRep bitsPerSample];
72 int samplesPerPixel = [bitmapImageRep samplesPerPixel];
73 int bitsPerPixel = [bitmapImageRep bitsPerPixel];
74 // BOOL hasAlpha = [bitmapImageRep hasAlpha];
75 BOOL isPlanar = [bitmapImageRep isPlanar];
76 // int numberOfPlanes = [bitmapImageRep numberOfPlanes];
77 int bytesPerRow = [bitmapImageRep bytesPerRow];
78 // int bytesPerPlane = [bitmapImageRep bytesPerPlane];
79 unsigned char* bitmapData = [bitmapImageRep bitmapData];
80
81 // Make sure bitmap has the required dimensions.
82 if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize)
83 return NULL;
84
85 // So far, this code only handles non-planar 32-bit RGBA, 24-bit RGB and 8-bit grayscale source bitmaps.
86 // This could be made more flexible with some additional programming...
87 if (isPlanar)
88 {
89 NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to isPlanar == YES");
90 return NULL;
91 }
92 if (bitsPerSample != 8)
93 {
94 NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to bitsPerSample == %d", bitsPerSample);
95 return NULL;
96 }
97
98 if (((samplesPerPixel == 1) && (bitsPerPixel == 8)) || ((samplesPerPixel == 3) && (bitsPerPixel == 24)) || ((samplesPerPixel == 4) && (bitsPerPixel == 32)))
99 {
100 rawDataSize = pixelsWide * pixelsHigh;
101 hRawData = NewHandle( rawDataSize );
102 if (hRawData == NULL)
103 return NULL;
104 pRawData = (unsigned char*) *hRawData;
105
106 pSrc = bitmapData;
107 pDest = pRawData;
108
109 if (bitsPerPixel == 32) {
110 for (y = 0; y < pixelsHigh; y++) {
111 pSrc = bitmapData + y * bytesPerRow;
112 for (x = 0; x < pixelsWide; x++) {
113 pSrc += 3;
114 *pDest++ = *pSrc++;
115 }
116 }
117 }
118 else if (bitsPerPixel == 24) {
119 memset( pDest, 255, rawDataSize );
120 }
121 else if (bitsPerPixel == 8) {
122 for (y = 0; y < pixelsHigh; y++) {
123 memcpy( pDest, pSrc, pixelsWide );
124 pSrc += bytesPerRow;
125 pDest += pixelsWide;
126 }
127 }
128 }
129 else
130 {
131 NSLog(@"get8BitMaskFromBitmapImageRep:requiredPixelSize: returning NULL due to samplesPerPixel == %d, bitsPerPixel == %", samplesPerPixel, bitsPerPixel);
132 return NULL;
133 }
134
135 return hRawData;
136 }
137
138 -(Handle) get32BitDataAtPixelSize:(int)requiredPixelSize
139 {
140 Handle hRawData;
141 unsigned char* pRawData;
142 Size rawDataSize;
143 unsigned char* pSrc;
144 unsigned char* pDest;
145 int x, y;
146 unsigned char alphaByte;
147 float oneOverAlpha;
148 NSBitmapImageRep* bitmapImageRep = [NSBitmapImageRep imageRepWithData: [self TIFFRepresentation]];
149
150 // Get information about the bitmapImageRep.
151 int pixelsWide = [bitmapImageRep pixelsWide];
152 int pixelsHigh = [bitmapImageRep pixelsHigh];
153 int bitsPerSample = [bitmapImageRep bitsPerSample];
154 int samplesPerPixel = [bitmapImageRep samplesPerPixel];
155 int bitsPerPixel = [bitmapImageRep bitsPerPixel];
156 // BOOL hasAlpha = [bitmapImageRep hasAlpha];
157 BOOL isPlanar = [bitmapImageRep isPlanar];
158 // int numberOfPlanes = [bitmapImageRep numberOfPlanes];
159 int bytesPerRow = [bitmapImageRep bytesPerRow];
160 // int bytesPerPlane = [bitmapImageRep bytesPerPlane];
161 unsigned char* bitmapData = [bitmapImageRep bitmapData];
162
163 // Make sure bitmap has the required dimensions.
164 if (pixelsWide != requiredPixelSize || pixelsHigh != requiredPixelSize)
165 return NULL;
166
167 // So far, this code only handles non-planar 32-bit RGBA and 24-bit RGB source bitmaps.
168 // This could be made more flexible with some additional programming to accommodate other possible
169 // formats...
170 if (isPlanar)
171 {
172 NSLog(@"get32BitDataAtPixelSize: returning NULL due to isPlanar == YES");
173 return NULL;
174 }
175 if (bitsPerSample != 8)
176 {
177 NSLog(@"get32BitDataAtPixelSize: returning NULL due to bitsPerSample == %d", bitsPerSample);
178 return NULL;
179 }
180
181 if (((samplesPerPixel == 3) && (bitsPerPixel == 24)) || ((samplesPerPixel == 4) && (bitsPerPixel == 32)))
182 {
183 rawDataSize = pixelsWide * pixelsHigh * 4;
184 hRawData = NewHandle( rawDataSize );
185 if (hRawData == NULL)
186 return NULL;
187 pRawData = (unsigned char*)*hRawData;
188
189 pSrc = bitmapData;
190 pDest = pRawData;
191
192 if (bitsPerPixel == 32) {
193 for (y = 0; y < pixelsHigh; y++) {
194 pSrc = bitmapData + y * bytesPerRow;
195 for (x = 0; x < pixelsWide; x++) {
196 // Each pixel is 3 bytes of RGB data, followed by 1 byte of
197 // alpha. The RGB values are premultiplied by the alpha (so
198 // that Quartz can save time when compositing the bitmap to a
199 // destination), and we undo this premultiplication (with some
200 // lossiness unfortunately) when retrieving the bitmap data.
201 *pDest++ = alphaByte = *(pSrc+3);
202 if (alphaByte) {
203 oneOverAlpha = 255.0f / (float)alphaByte;
204 *pDest++ = *(pSrc+0) * oneOverAlpha;
205 *pDest++ = *(pSrc+1) * oneOverAlpha;
206 *pDest++ = *(pSrc+2) * oneOverAlpha;
207 } else {
208 *pDest++ = 0;
209 *pDest++ = 0;
210 *pDest++ = 0;
211 }
212 pSrc+=4;
213 }
214 }
215 } else if (bitsPerPixel == 24) {
216 for (y = 0; y < pixelsHigh; y++) {
217 pSrc = bitmapData + y * bytesPerRow;
218 for (x = 0; x < pixelsWide; x++) {
219 *pDest++ = 0;
220 *pDest++ = *pSrc++;
221 *pDest++ = *pSrc++;
222 *pDest++ = *pSrc++;
223 }
224 }
225 }
226 }
227 else
228 {
229 NSLog(@"get32BitDataAtPixelSize: returning NULL due to samplesPerPixel == %d, bitsPerPixel == %", samplesPerPixel, bitsPerPixel);
230 return NULL;
231 }
232
233 return hRawData;
234 }
235
236 @end
Something went wrong with that request. Please try again.