Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

altivec 2003

macrumors regular
Original poster
Feb 8, 2003
135
0
Texas
I'm starting a small cocoa application that will convert an image file into a 1-bit text format that is compatible with my z80 assembler (for TI-83+ programs). I already wrote one in Real Basic about a year ago (ay, the shame!), but for various reasons I no longer have it. My problem with the cocoa version is figuring out how to access the pixels/data of a NSImage directly. Does anybody know how this works? Do you have to create and add a bitmap representation to the NSImage, or is there some other way?
In the Real Basic version, I just looped through all of the pixels performing pixel tests. It wasn't the most efficient method, but it worked well. A quick look at NSImage's documentation, however, provided no equivalent to Real Basic's pixel tests.

My next question deals with monitoring cpu usage. Is there any way to figure out the current level of cpu activity other than making a NSTask that runs the unix "top" command?

Finally, is there a way to monitor the audio output of the built in audio controller? I'm thinking of some pointless program that draws a sound-analysis similar to that of iTunes. I wrote the graphing code, but I need data!

In short, I know nearly nothing about cocoa :eek:
Thanks
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
Moderator! Move this to Mac Programming please :)

NSImage does not actually contain the pixels itself. If you are working with bitmap images then the NSBitmapImageRep contains the pixel data so you need to work with that if you are doing pixel by pixel manipulation. Once you have your bitmap rep you have getPixel:atX:y: and setPixel:atX:y: to work with (although you may find you don't need to do pixel by pixel work: if you are just compositing your bitmaps then use the standard NSImage methods).

Getting the CPU usage: do not run top in an NSTask! top uses quite a bit of CPU on it's own. There are system calls (not pure Cocoa) to get this data. I'm not sure what they are though...

You need to find out what sysctl is using:
sysctl vm.loadavg
vm.loadavg: 0.10 0.29 0.48


Audio Stuff: no idea. I think it's possible (Audio Hijack seems to be able to do all sorts of stuff with the audio subsystems).
 

HiRez

macrumors 603
Jan 6, 2004
6,265
2,629
Western US
You can use [NSBitmapImageRep imageRepWithData:[myImage TIFFRepresentation]] to get a bitmap rep (assuming myImage is your NSImage).

As far as the audio goes, you can use CoreAudio or QuickTime to get that data. I assume you mean level/frequency metering capabilities. It's not easy if you're used to Cocoa, though. Both APIs are fairly complex and use procedural C and Carbon calls and variable types. QuickTime is probably a bit easier, see the documentation for functions such as SetMovieAudioVolumeMeteringEnabled(), GetMovieAudioFrequencyMeteringBandFrequencies(), and GetMovieAudioVolumeLevels().
 

altivec 2003

macrumors regular
Original poster
Feb 8, 2003
135
0
Texas
robbieduncan said:
Moderator! Move this to Mac Programming please :)

Ah, I forgot there was a dedicated Mac Programming forum. Thanks for taking the time to move it, whoever did!

Ok, this looks as though it is what I need for the image problem. I have no idea how I managed to miss that in the documentation, but thanks to you both I now have a starting point here. When I get it done (probably today) I might post a link to show you how much I managed to screw up even with your excellent advice :rolleyes:

I already looked at CoreAudio and Quicktime a little, but I guess I should just stop being lazy! HiRez, the routines you list look really promising, but do they only work on a movie? Don't worry about me being too used to cocoa, though; I moved from procedural c to objective c/cocoa just a little bit ago.
 

altivec 2003

macrumors regular
Original poster
Feb 8, 2003
135
0
Texas
robbieduncan said:
I think that in QuickTime anything it can open is a "Movie" so an mp3 would be a Movie to the QuickTime API.
True. But what I wanted to do is monitor the system audio out, not the audio in a file.

But back to the image question. I've finally figured out that the getPixel: atX: y: method is only present in Tiger! I'm on Panther, darn it!
So It looks like I'll have to get the bitmap data pointer from NSBitmapImageRep and do everything myself. Oh well, it shouldn't be THAT hard... NSBitmapImageRep tells me what the width and height are, which makes things easier.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
What are you trying to do with the images that you need pixel by pixel access? It's possible that Cocoa would allow you to do what you want without it using built in methods (which may well be faster).
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
Are you sure you don't have
Code:
-(void)getPixel:(unsigned int[])pixelData atX:(int)x y:(int)y
? My documentation says that
Code:
- (NSColor *)colorAtX:(int)x y:(int)y
was added in 10.4 but does not say that about getPixel:...
 

altivec 2003

macrumors regular
Original poster
Feb 8, 2003
135
0
Texas
robbieduncan said:
What are you trying to do with the images that you need pixel by pixel access? It's possible that Cocoa would allow you to do what you want without it using built in methods (which may well be faster).
This is what I thought I needed pixel access for :). That .tar includes two sample bitmap images from a calculator game project of mine. I'm sorry if my refusal to follow apple's interface guidelines offended you... I just like brushed metal :cool:

I wrote the thing by invoking my bitmap rep's bitmapData method. That returns a pointer to the data, which I looped through and reformatted. This is probably a hundred times faster than doing pixel tests anyway (not that speed would be an issue). On my 266 mhz laptop, it converts almost instantly... I was happily surprised. If you have any reason to see the (probably horribly written) source, I can upload it.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
Well, I'm glad you got it to do what you wanted but the App in the .tar you posted does not start for me. I assume you have posted a Development build (ZeroLink) which will not start on anyones machine but yours! Not to worry, I'm not that bothered. I just thought if I knew what you were doing I might be able to suggest a way to do it via the APIs available.
 

altivec 2003

macrumors regular
Original poster
Feb 8, 2003
135
0
Texas
robbieduncan said:
Well, I'm glad you got it to do what you wanted but the App in the .tar you posted does not start for me. I assume you have posted a Development build (ZeroLink) which will not start on anyones machine but yours! Not to worry, I'm not that bothered. I just thought if I knew what you were doing I might be able to suggest a way to do it via the APIs available.
Yikes, this really shows how little I have done with cocoa...
Umm, exactly HOW do you change to deployment build mode? Is it in the target settings? :eek:
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
There is a drop down on the toolbar of the build window (Shift-Command-B). Once switched to Deployment you need to do a Clean then a Build.
 

HiRez

macrumors 603
Jan 6, 2004
6,265
2,629
Western US
altivec 2003 said:
I already looked at CoreAudio and Quicktime a little, but I guess I should just stop being lazy! HiRez, the routines you list look really promising, but do they only work on a movie? Don't worry about me being too used to cocoa, though; I moved from procedural c to objective c/cocoa just a little bit ago.
Eh...you might be right about that, I thought I saw somewhere you could tell it to monitor an output, but it looks like they all operate on a specific movie. Still, I think there must be some way to do that using QuickTime, though I don't know what yet as I've ony recently started dabbling in QuickTime audio. There is a new QTAudioContext type introduced in QuickTime 7, but I can't find any documentation about what it is or what I can do with it. Now I'm sure CoreAudio must be able to do what you ask, but I don't know anything about that and I found the CoreAudio API to be a bear to work with, at least for playing compressed sound data (.MP3, etc.). One thing I did discover is that apparently CoreAudio cannot play back protected AAC files (iTMS), or at least it's not easy to do it, while in QuickTime they open like any other audio file. Anyone know what the deal is there?

BTW, I got bitten by that "ZeroLink Development builds only run on your own machine" thingy too. Distributed the first alpha of my app and was all excited, only to find that no one could even launch it. It's a good lesson to learn early!
 

gekko513

macrumors 603
Oct 16, 2003
6,301
1
I have also "released" Development builds for public testing :eek: , twice :eek: :eek:

For pixel access on an NSBitmapImageRep, it's most efficient to get the bitmap data as a pointer and work directly by dereferencing. I think it would go something like this ...
Code:
- (BOOL) manipulateImageRep:(NSBitmapImageRep*)rep {
    int Bpr, spp;
    unsigned byte *data;
    int x, y, w, h;

    if ([rep bitsPerSample] != 8) {
        // usually each color component is stored
        // using 8 bits, but recently 16 bits is occasionally
        // also used ... you might want to handle that here
        return NO;
    }
    
    Bpr = [rep bytesPerRow];
    spp = [rep samplesPerPixel];
    data = [rep bitmapData];
    w = [rep pixelsWide];
    h = [rep pixelsHigh];

    for (y=0; y<h; y++) {
        unsigned byte *p = data + Bpr*y;
        for (x=0; x<w; x++) {
            // do your thing
            // p[0] is red, p[1] is green, p[2] is blue, p[3] can be alpha if spp==4
            p += spp;
        }
    }
    return YES;
}
 

HiRez

macrumors 603
Jan 6, 2004
6,265
2,629
Western US
gekko513 said:
For pixel access on an NSBitmapImageRep, it's most efficient to get the bitmap data as a pointer and work directly by dereferencing. I think it would go something like this ...
That's the way I do it, but I wonder how efficient the getPixel: method is, perhaps they have optimized it well. Would be simpler.
 

altivec 2003

macrumors regular
Original poster
Feb 8, 2003
135
0
Texas
gekko513 said:
I have also "released" Development builds for public testing :eek: , twice :eek: :eek:
Well, that makes me feel a little better, as long as this second attempt works ;)

*Crosses fingers*

Your code is actually quite similar to what I came up with, except I used *pointer instead of pointer[0]. Just a habit, I guess. I only needed to deal with one sample per pixel, because I am dealing with black and white bitmaps (unfortunately, my graphing calculator does not have a color screen...).

Thanks, everyone. I don't like to think what would've happened if I never learned that zerolink-ed builds don't work on other computers!
 

gekko513

macrumors 603
Oct 16, 2003
6,301
1
HiRez said:
That's the way I do it, but I wonder how efficient the getPixel: method is, perhaps they have optimized it well. Would be simpler.
We should test it ...
 

HiRez

macrumors 603
Jan 6, 2004
6,265
2,629
Western US
altivec 2003 said:
I don't like to think what would've happened if I never learned that zerolink-ed builds don't work on other computers!
It took me a few days to figure it out, I was tearing my hair out trying to find what would cause that. Xcode should pop up a warning dialog the first time you try that. :cool:
 

caveman_uk

Guest
Feb 17, 2003
2,390
1
Hitchin, Herts, UK
gekko513 said:
I have also "released" Development builds for public testing :eek: , twice :eek: :eek:
I've nearly been caught out but I'm lucky enough to have two macs which means I spotted that before I released anything. Handy for checking that you've got all your frameworks built in properly too :D
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.