How can I fix the use too memory problem

Discussion in 'Mac Programming' started by DeathscytheSeph, Dec 5, 2008.

  1. DeathscytheSeph macrumors newbie

    Joined:
    Jul 9, 2007
    #1
    I wrote the program about the image

    when i run with the small image like 160x120px it run properly but when i run with the bigger image like 800x600px it “EXC_BAD_ACCESS” T_T.

    the problem is occur at the array because I create the array that keep the data of the pixel of the image so i have 2 array
    1: colorValue[height][width][4];
    2: labelValue[height * width];
    that 2 array is the problem

    Anyone help please

    PS. I try to change it to pointer but it still have the problem when use memcpy T_T after i pass the array to the function

    Thank you
     
  2. sanPietro98 macrumors 6502a

    sanPietro98

    Joined:
    May 30, 2008
    Location:
    28.416834,-81.581214
    #2
    There is not enough information here for us to diagnose the problem or offer advice. Can you provide code snippets?

    How are you computing 'width' and 'height'?
     
  3. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #3
    This seems like a LOT of memory to put on the stack. I don't know the types of your arrays, but assuming they're ints, the colorValue array is 7,680,000 bytes wide, and labelValue is 1,920,000, for a total of 9,600,000 bytes on the stack. Most of the time this will be much larger than will be allowed for the stack, leading to your problem. This much data should be placed on the heap. You could do this in various ways, but the most common would be to allocate:
    Code:
    height*width*sizeof(int)
    or
    Code:
    height*width*4*sizeof(int)
    bytes on the heap using malloc. The (void *) returned could be cast to an (int *), and assigned to an int * variable you have on the stack (using a nice, trim 4 or 8 bytes (sizeof(void *)) depending on your platform). It would take a lot more work to be able to handily treat this as a 3-dimensional array, because you would need a lot more pointers at each dimension. You could use multiple "indicies" into this memory that you invent and track, but to actually be able to say myArr[x][y][z] would take a herculean effort.

    In the last thread I suggested this, but I will again... why not use the dynamic data structures already available for this purpose? You could easily make a class that is a simple int wrapper (instead of using NSNumber), and build a:
    Code:
    NSMutableArray of
      NSMutableArray of
        NSMutableArray of
          intWrapper which contains an
            int
    
    (That's not code, not sure if quote maintains formatting)

    You would access it as:
    Code:
    rPart = [[[[colorValue objectAtIndex:x] objectAtIndex:y] objectAtIndex:0] intValue];
    gPart = [[[[colorValue objectAtIndex:x] objectAtIndex:y] objectAtIndex:1] intValue];
    bPart = [[[[colorValue objectAtIndex:x] objectAtIndex:y] objectAtIndex:2] intValue];
    alphaPart = [[[[colorValue objectAtIndex:x] objectAtIndex:y] objectAtIndex:3] intValue];
    
    Though this would give you 96-bit colorspace, which is probably overkill, but it's just for example's sake. You could also have a method that does all of that for you:
    Code:
    -(int) valueFrom:(NSArray *)valList Xpos:(int)x Ypos:(int)y Zpos:(int)z {
      return [[[[valList objectAtIndex:x] objectAtIndex: y] objectAtIndex:z] intValue];
    }
    then you could call it as:

    Code:
    int rValue = [self valueFrom:colorList Xpos:x YPos:y Zpos:0];
    The setup of this would require a bit of work, but it wouldn't be too bad (not as bad as a C-means of trying to make something you can get to with [][][]):
    Code:
    NSMutableArray *colorList = [[NSMutableArray alloc] init];
    for(int x=0;x<height;x++){
      [colorList addObject:[[NSMutableArray alloc] init]];
      for(int y=0;y<width;y++) {
        [[colorList objectAtIndex:x] addObject:[[NSMutableArray alloc] init]];
        for(int z=0;z<4;z++) {
          [[[colorList objectAtIndex:x] objectAtIndex:y] addObject:[NSNumber initWithInt:0]];
        }
      }
    }
    
    This should be treated as pseduocode, even though i tried to write correct Objective-C. I am not at a mac, and don't have an objective-C environment set up here.

    -Lee
     
  4. MacRumors Guy macrumors member

    Joined:
    Sep 17, 2008
    #4
    0.0 are you sure it isn't nicer just to use [][][] to index the malloc'ed array?
     
  5. DeathscytheSeph thread starter macrumors newbie

    Joined:
    Jul 9, 2007
    #5
    Width and Height is the size of the input image

    this is the code snippet
    NSLog(@"Begin Labeling image");
    NSSize mySize = [self size];
    int
    row, column, widthInPixels = mySize.width, heightInPixels = mySize.height;
    int colorValue[heightInPixels][widthInPixels][4],
    labelValue[heightInPixels * widthInPixels];
    // int*** colorValue;
    //
    // colorValue = (int***) malloc(sizeof(int***) * heightInPixels);
    // for(int i = 0; i < heightInPixels;i++)
    // {
    // colorValue = (int**)malloc(widthInPixels * sizeof(int*));
    // for(int j=0; j < widthInPixels;j++)
    // {
    // colorValue[j] = (int*)malloc(4 * sizeof(int));
    // for(int k=0;k < 4;k++)
    // {
    // colorValue[j][k] = 0;
    // }
    // }
    // }
    //
    // int * labelValue = (int*) malloc(sizeof(int) * heightInPixels * widthInPixels);
    for (int i = 0; i < heightInPixels * widthInPixels; i++)
    labelValue = 0;


    //Read Pixel Data
    [self lockFocus]; // necessary for NSReadPixel() to work.
    for (row = 0; row < heightInPixels; row++)
    for (column = 0; column < widthInPixels; column++)
    {
    NSColor
    *pixelColor = NSReadPixel(NSMakePoint(column, heightInPixels - (row +1)));
    colorValue[row][column][0] = [pixelColor redComponent] * 255;
    colorValue[row][column][1] = [pixelColor greenComponent] * 255;
    colorValue[row][column][2] = [pixelColor blueComponent] * 255;
    colorValue[row][column][3] = [pixelColor alphaComponent] * 255;
    }
    [self unlockFocus];

    int numLabel = 0;
    if (![NSImage isBackGroundOfImage:self atX:0 atY:0])
    labelValue[0 * widthInPixels + 0] = ++numLabel;

    //label first row
    for (column = 1; column < widthInPixels; column++)
    {
    if (![NSImage isBackGroundOfImage:self atX:column atY:0] &&
    ![NSImage isValueInRangeOfFirstValue:colorValue[0][column]
    compareWith:colorValue[0][column - 1]]) {
    labelValue[0 * widthInPixels + column] = ++numLabel;
    } else {

    labelValue[0 * widthInPixels + column] = numLabel;
    }
    }

    //label entire row
    for (row = 1; row < heightInPixels; row++)
    for (column = 0; column < widthInPixels; column++)
    if (![NSImage isBackGroundOfImage:self atX:column atY:row]) {
    if ([NSImage isValueInRangeOfFirstValue:colorValue[row][column]
    compareWith:colorValue[row][column - 1]]) {
    labelValue[row * widthInPixels + column] = labelValue[row * widthInPixels + column - 1];
    } else if ([NSImage isValueInRangeOfFirstValue:colorValue[row][column]
    compareWith:colorValue[row - 1][column]]) {
    labelValue[row * widthInPixels + column] = labelValue[(row - 1) * widthInPixels + column];
    } else if ([NSImage isValueInRangeOfFirstValue:colorValue[row][column]
    compareWith:colorValue[row - 1][column - 1]]) {
    labelValue[row * widthInPixels + column] = labelValue[(row - 1) * widthInPixels + column - 1];
    } else if ([NSImage isValueInRangeOfFirstValue:colorValue[row][column]
    compareWith:colorValue[row - 1][column + 1]]) {
    labelValue[row * widthInPixels + column] = labelValue[(row - 1) * widthInPixels + column + 1];
    } else {
    labelValue[row * widthInPixels + column] = ++numLabel;
    }
    }


    //second pass
    for (row = 1; row < heightInPixels; row++)
    for (column = 0; column < widthInPixels; column++) {
    if(column + 1 < widthInPixels && labelValue[row * widthInPixels + column] != labelValue[row * widthInPixels + column+1] &&
    [NSImage isValueInRangeOfFirstValue:colorValue[row][column]
    compareWith:colorValue[row][column + 1]]){
    if(labelValue[row * widthInPixels + column]<labelValue[row * widthInPixels + column+1])
    [NSImage reValueInArray:labelValue arrayHeight: heightInPixels widthOfRow:widthInPixels replaceValue:labelValue[row * widthInPixels + column + 1] withValue:labelValue[row * widthInPixels + column]];
    else
    [NSImage reValueInArray:labelValue arrayHeight: heightInPixels widthOfRow:widthInPixels replaceValue:labelValue[row * widthInPixels + column] withValue:labelValue[row * widthInPixels + column + 1]];
    }
    else if(column - 1 >= 0 && row+1<heightInPixels && labelValue[row * widthInPixels + column]!=labelValue[(row+1) * widthInPixels + column-1] &&
    [NSImage isValueInRangeOfFirstValue:colorValue[row][column]
    compareWith:colorValue[row - 1][column + 1]]){
    if(labelValue[row * widthInPixels + column] < labelValue[(row+1) * widthInPixels + column-1])
    [NSImage reValueInArray:labelValue arrayHeight: heightInPixels widthOfRow:widthInPixels replaceValue:labelValue[(row + 1) * widthInPixels + column - 1] withValue:labelValue[row * widthInPixels + column]];
    else
    [NSImage reValueInArray:labelValue arrayHeight: heightInPixels widthOfRow:widthInPixels replaceValue:labelValue[row * widthInPixels + column] withValue:labelValue[(row + 1) * widthInPixels + column - 1]];
    }
    else if(row+1<heightInPixels && labelValue[row * widthInPixels + column] != labelValue[(row+1) * widthInPixels + column]
    && [NSImage isValueInRangeOfFirstValue:colorValue[row][column]
    compareWith:colorValue[row + 1][column]]){
    if(labelValue[row * widthInPixels + column]<labelValue[(row+1) * widthInPixels + column])
    [NSImage reValueInArray:labelValue arrayHeight: heightInPixels widthOfRow:widthInPixels replaceValue:labelValue[(row + 1) * widthInPixels + column] withValue:labelValue[row * widthInPixels + column]];
    else
    [NSImage reValueInArray:labelValue arrayHeight: heightInPixels widthOfRow:widthInPixels replaceValue:labelValue[row * widthInPixels + column] withValue:labelValue[(row + 1) * widthInPixels + column]];
    }
    else if(column+1<widthInPixels && row+1<heightInPixels && labelValue[row * widthInPixels + column]!=labelValue[(row+1) * widthInPixels + column+1]
    && [NSImage isValueInRangeOfFirstValue:colorValue[row][column]
    compareWith:colorValue[row + 1][column + 1]]){
    if(labelValue[row * widthInPixels + column]<labelValue[(row+1) * widthInPixels + column+1])
    [NSImage reValueInArray:labelValue arrayHeight: heightInPixels widthOfRow:widthInPixels replaceValue:labelValue[(row + 1) * widthInPixels + column + 1] withValue:labelValue[row * widthInPixels + column]];
    else
    [NSImage reValueInArray:labelValue arrayHeight: heightInPixels widthOfRow:widthInPixels replaceValue:labelValue[row * widthInPixels + column] withValue:labelValue[(row + 1) * widthInPixels + column + 1]];
    }


    }


    NSLog(@"End of Labeling Begin check how many of label");

    bool checkInt[numLabel + 1];

    for(int i = 0; i < numLabel + 1; i++)
    checkInt = NO;

    for(int i = 0; i < heightInPixels * widthInPixels; i++) {
    checkInt[labelValue] = YES;
    }

    int numCheck = 0;
    for (int i = 0; i < 23; i++)
    if (checkInt)
    numCheck++;


    NSLog(@"%d", numCheck);


    // Create the represent image
    NSImage
    *labeledImage = [[[self class] alloc] initWithSize:mySize];


    // Need a place to put the monochrome pixels.
    NSBitmapImageRep *blackAndWhiteRep =
    [[NSBitmapImageRep alloc]
    initWithBitmapDataPlanes: nil // Nil pointer tells the kit to allocate the pixel buffer for us.
    pixelsWide: widthInPixels
    pixelsHigh: heightInPixels
    bitsPerSample: 8
    samplesPerPixel: 2
    hasAlpha: YES
    isPlanar: NO
    colorSpaceName: NSCalibratedWhiteColorSpace // 0 = black, 1 = white in this color space.
    bytesPerRow: 0 // Passing zero means "you figure it out."
    bitsPerPixel: 16]; // This must agree with bitsPerSample and samplesPerPixel.

    monochromePixel
    *pixels = (monochromePixel *)[blackAndWhiteRep bitmapData]; // -bitmapData returns a void*, not an NSData object ;-)

    [self lockFocus]; // necessary for NSReadPixel() to work.
    for (row = 0; row < heightInPixels; row++)
    for (column = 0; column < widthInPixels; column++) {
    monochromePixel
    *thisPixel = &(pixels[((widthInPixels * row) + column)]);


    // thisPixel->grayValue = 1.0 - rint(255 * // use this line for negative..
    thisPixel->grayValue = (1.0 - (labelValue[(widthInPixels * row) + column] / (numCheck + 1.0))) * 255;

    thisPixel->alpha = 255; // handle the transparency, too
    }
    [self unlockFocus];

    [labeledImage addRepresentation:blackAndWhiteRep];
    [blackAndWhiteRep release];

    //return [labeledImage autorelease];
    return labeledImage;
     

Share This Page