1
//
//  main.c
//  cbp
//
//  Created by Zhan on 16/4/13.
//  Copyright © 2016年 Zhan. All rights reserved.
//
#include <stdio.h>
#include <stdlib.h>
#include<math.h>

#pragma pack(2)

typedef unsigned short int WORD;
typedef unsigned int DWORD;

typedef struct BMP_FILE_HEADER
{
    WORD bType;
    DWORD bSize;
    WORD bReserved1;
    WORD bReserved2;
    DWORD bOffset;
} BMPFILEHEADER;

typedef struct BMP_INFO
{
    DWORD bInfoSize;
    DWORD bWidth;
    DWORD bHeight;
    WORD bPlanes;
    WORD bBitCount;
    DWORD bCompression;
    DWORD bmpImageSize;
    DWORD bXPelsPerMeter;
    DWORD bYPelsPerMeter;
    DWORD bClrUsed;
    DWORD bClrImportant;
} BMPINF;

/*彩色表*/
typedef struct RGB_QUAD
{
    WORD rgbBlue;
    WORD rgbGreen;
    WORD rgbRed;
    WORD rgbReversed;
} RGBQUAD;

int main()
{
    FILE *fp,*fpout;
    BMPFILEHEADER fileHeader;
    BMPINF infoHeader;
    int width, height;
    //WORD c;
    int s;
    float s1,s2;
    unsigned char **image;

    if((fp = fopen("XG.bmp", "rb")) == NULL)
    {
        printf("Cann't open the file!\n");
    }


    fseek(fp, 0, 0);
    fread(&fileHeader, sizeof(fileHeader), 1, fp);
    fread(&infoHeader, sizeof(infoHeader), 1, fp);

    printf("size fileHeader == %ld\n",sizeof(fileHeader));
    printf("size infoHader == %ld\n",sizeof(infoHeader));

    width = infoHeader.bWidth;
    height = abs(infoHeader.bHeight);

    printf("infoHeader.bWidth == %d\n",width);
    printf("infoHeader.bheight == %d\n",height);

    image = (unsigned char **)malloc(sizeof(unsigned char  *) * width);
    image[0] = (unsigned char *)malloc(sizeof(unsigned char ) * width * height);

    //    unsigned char **image1 =(unsigned char**) malloc (width*sizeof(int*));
    //    for(int i=0;i<width;i++)
    //        *image1++=(unsigned char*) malloc (height*sizeof(int));

    fseek(fp,(sizeof(fileHeader)+sizeof(infoHeader)),SEEK_SET);
    for(int i=0;i<width;i++)
    {
        for(int j=0;j<height;j++){
            fread(&image[i][j],1,1,fp); }}      //Memory leak ?
    for(int i=1;i<width;i++){
        for(int j=1;j<height;j++)
        {
            s1=image[i-1][j+1]+2*image[i][j+1]+image[i+1][j+1];
            s1=s1-image[i-1][j-1]-2*image[i][j-1]-image[i+1][j-1];
            s2=image[i-1][j-1]+2*image[i-1][j]+image[i-1][j+1];
            s2=s2-image[i+1][j-1]-2*image[i+1][j]-image[i+1][j+1];
            s=fabs(s1)+fabs(s2);
            if(s>80)
                image[i][j]=255;
            else
                image[i][j]=0;
        }
    }
    if((fpout=fopen("za.bmp","wb"))==NULL){
        printf("cannot open outfile!\n");
        free(image[0]);
        free(image);
        return 0;
    }
    printf("intoWrite\n");
    fwrite(&fileHeader,sizeof(fileHeader),1,fpout);
    fwrite(&infoHeader,sizeof(infoHeader),1,fpout);
    for(int i=0;i<width;i++)
    {
        for(int j=0;j<height;j++){
            printf("forWrite\n");
            fwrite(&image[i][j],1,1,fpout);}}
    //    c = fgetc(fp);
    //    int mi=0,mj=0;
    //    while (!feof(fp))
    //    {
    //        fwrite(&c,1,1,fpout);
    //        mi++;mj++;
    //    c = fgetc(fp);
    //    }
    free(image[0]);
    free(image);
    printf("OK!\n");
    fclose(fp);
    fclose(fpout);
    return 0;
}

This is my code for bmp edge detection.I use Xcode to run this code,it always prompts "Thread 1:EXC_BAD_ACCESS(code=1,address = 0x0)" or "Function call argument is an uninitialized value" at "fread(&image[i][j],1,1,fp)".Why I used Static two-dimensional arrays there is no error,but dynamic two-dimensional array is error?

3 Answers3

1

This will allocate height to each width and you should now be able to reference image[i][j]

int each = 0;
image = malloc(sizeof(unsigned char  *) * width);
for ( each = 0; each < width; each++) {
    image[each] = malloc(sizeof(unsigned char ) * height);
}

freeing will be similar.

for ( each = 0; each < width; each++) {
    free ( image[each]);
}
free ( image);
user3121023
  • 8,181
  • 5
  • 18
  • 16
  • Note that even though this solves the bug, there is no use to allocate a fragmented lookup table in the first place. – Lundin Apr 13 '16 at 10:49
  • I used this way on Visual Studio,and got this: IntelliSense: expression must contain a pointer to an object type – Michael Zhan Apr 13 '16 at 14:18
0
image[0] = (unsigned char *)malloc(sizeof(unsigned char ) * width * height);

You only allocate room for one array, instead of a whole lookup table, where every pointer points at an allocated array.

But there is absolutely no need to use some obscure lookup table here in the first place. Instead, use a 2D array:

width = ...;
height = ....;
unsigned char (*image)[][height];
image = malloc( sizeof(unsigned char[width][height]) );

...

free(image);

And now, since you have a real 2D array instead of some fragmented thing, you can read the whole array at once if you wish:

fread(image, sizeof(unsigned[width][height]), 1, fp);

Meaning: into my 2D array, read one 2D array from fp. You can skip the loop.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • I used this way on Visual Studio,and got this: IntelliSense: expression must be a pointer to point to the complete object type – Michael Zhan Apr 13 '16 at 14:16
  • @MichaelZhan You have to use a modern standard C compiler to compile this. The Visual Studio "2015" compiler is completely outdated crap, it contains year 1989 technology mixed with a bit of year 1999 technology. – Lundin Apr 14 '16 at 07:45
  • HAHA.Finally I have used calloc function.And actually,I like Xcode to write the code. – Michael Zhan Apr 14 '16 at 08:32
0
image=(WORD **)calloc(width,sizeof(WORD*));
        if (NULL==image) return 1;
            for (a=0;a<width;a++) {
                image[a]=(WORD*)calloc(height,sizeof(WORD));
                if (NULL==image[a]){
                    printf("free image\n");
                    free(image);
                    return 2;}
            }

I used calloc function,Of this function is to allocate memory and initialize.