Read and display gray scale images in C language.

半世苍凉 提交于 2019-12-13 02:25:56

问题


I want to load gray scale images in C, pre process it and then display the modified image. My question is:

What is the right way to import gray scale images(jpeg,png formats)in C language ?

My own search before asking this question.

1- fread or with file management, we can read image but data will be encrypted(compressed), I want gray scale values(0-255) of each pixel.

2- There is one API ImageMagick which can be helpful but it is having installation problem with Mac OS X.

I have done image processing in python and matlab but have no idea about C language.

Thanks


回答1:


This answer is an attempt to demonstrate how to develop with ImageMagick's MagickWand API with Xcode, and is based on the comments from the OP.

After installing ImageMagick, start a new Xcode command-line C project. Before writing any code, you need to tell llvm about the ImageMagick resources/libraries/etc.

There are many, many, ways to achieve this, but here's the quickest I can think of.

  • Navigate to top-level project's "Build Settings"
  • Under "All" (not "Basic") search for "Other Linker Flags"
  • Outside of Xcode, open up Terminal.app and enter the following
    • MagickWand-config --ldflags
  • Enter the output from Terminal.app as the value for "Other Linker Flags"

  • Back in the settings search; enter "Other C Flags"
  • Back in Terminal.app run the following
    • MagickWand-config --cflags
  • Enter the resulting output as the value for "Other C Flags"

Over in file main.c, you should notice Xcode picking-up MagickWand commands right away.

Try the following (needs X11 installed) ...

#include <stdio.h>
#include <wand/MagickWand.h>

int main(int argc, const char * argv[]) {
    MagickWandGenesis();
    MagickWand * wand;
    wand = NewMagickWand();
    MagickReadImage(wand, "wizard:");
    MagickQuantizeImage(wand, 255, GRAYColorspace, 0, MagickFalse, MagickTrue);
    MagickDisplayImage(wand, ":0");
    wand = DestroyMagickWand(wand);
    MagickWandTerminus();
    return 0;
}

... and build + run to verify.

edit

To get the gray scale (0-255) value for each pixel, you can invoke a pixel iterator (see second example here), or export the values. Here is an example of dynamically populating a list of gray values by exporting...

    // Get image size from wand instance
    size_t width = MagickGetImageWidth(wand);
    size_t height = MagickGetImageHeight(wand);
    size_t total_gray_pixels =  width * height;

    // Allocate memory to hold values (total pixels * size of data type)
    unsigned char * blob = malloc(total_gray_pixels);

    MagickExportImagePixels(wand,      // Image instance
                            0,         // Start X
                            0,         // Start Y
                            width,     // End X
                            height,    // End Y
                            "I",       // Value where "I" = intensity = gray value
                            CharPixel, // Storage type where "unsigned char == (0 ~ 255)
                            blob);     // Destination pointer

    // Dump to stdout
    for (int i = 0; i < total_gray_pixels; i++ ) {
        printf("Gray value @ %lux%lu = %d\n", i % width, i / height, (int)blob[i]);
    }
    /** Example output...
     * Gray value @ 0x0 = 226
     * Gray value @ 1x0 = 189
     * Gray value @ 2x0 = 153
     * Gray value @ 3x0 = 116
     * Gray value @ 4x0 = 80
     * ... etc
     */



回答2:


You have a number of options, but I will go through them starting with the easiest and least integrated with OSX, and getting progressively more integrated with OSX.

Easiest Option

Personally, if I was intent on processing greyscale images, I would write my software to use NetPBM's Portable Greymap (PGM) format as that is the very simplest to read and write and readily interchangeable with other formats. There is no compression, DCT, quantisation, colorspaces, EXIF data - just your data with a simple header. The documentation is here.

Basically a PGM file looks like this:

P2
# Shows the word "FEEP" (example from Netpbm man page on PGM)
24 7
15
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
0  3  3  3  3  0  0  7  7  7  7  0  0 11 11 11 11  0  0 15 15 15 15  0
0  3  0  0  0  0  0  7  0  0  0  0  0 11  0  0  0  0  0 15  0  0 15  0
0  3  3  3  0  0  0  7  7  7  0  0  0 11 11 11  0  0  0 15 15 15 15  0
0  3  0  0  0  0  0  7  0  0  0  0  0 11  0  0  0  0  0 15  0  0  0  0
0  3  0  0  0  0  0  7  7  7  7  0  0 11 11 11 11  0  0 15  0  0  0  0
0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0

You can see the P2 says it is in ASCII (easy to read) and a greymap. Then the next line says it is 24 pixels wide by 7 tall and that the brightest pixel is 15. Very simple to read and write. You can change the P2 to P5 and write everything after the MAXVAL in binary to save space.

Now you can just use ImageMagick outside your program to convert JPEG, PNG, GIF, TIFF files to PGM like this - without needing any linking or libraries or compiler switches:

convert input.png output.pgm

convert input.jpg output.pgm

Likewise, when you have finished processing and created your resulting output file in PGM format you can convert it to JPEG or TIFF by simply reversing the parameters:

convert result.pgm result.jpg

Personally, I would install ImageMagick using homebrew. You go to the homebrew website and copy the one-liner and paste it into a terminal to install homebrew. Then you can install ImageMagick with:

brew install imagemagick

and, by the way, if you want to try out the other suggestion here, using OpenCV, then that is as easy as

brew search opencv
brew install homebrew/science/opencv

If you want a small, self-contained example of a little OpenCV project, have a look at my answer to another question here - you can also see how a project like that is possible from the command line with ImageMagick in my other answer to the same question.

Magick++

If you choose to install ImageMagick using homebrew you will get Magick++ which will allow you to write your algorithms in C and C++. It is pretty easy to use and can run on any platforms, including OSX and Windows and Linux so it is attractive from that point of view. It also has many, many image-processing functions built right in. There is a good tutorial here, and documentation here.

Your code will look something like this:

// Read an image from URL
Image url_image("http://www.serverName.com/image.gif");

// Read image from local filesystem
Image local_file_image("my_image.gif"); 

// Modify image
Pixels my_pixel_cache(my_image);
PixelPacket* pixels;
// define the view area that will be accessed via the image pixel cache
int start_x = 10, start_y = 20, size_x = 200, size_y = 100;
// return a pointer to the pixels of the defined pixel cache
pixels = my_pixel_cache.get(start_x, start_y, size_x, size_y);

// set the color of the first pixel from the pixel cache to black (x=10, y=20 on my_image) 
*pixels = Color("black");

// set to green the pixel 200 from the pixel cache:
// this pixel is located at x=0, y=1 in the pixel cache (x=10, y=21 on my_image) 
*(pixels+200) = Color("green");

// now that the operations on my_pixel_cache have been finalized
// ensure that the pixel cache is transferred back to my_image
my_pixel_cache.sync();

// Save results as BMP file
image.write(“result.bmp”);

Apple OSX Option

The other ENTIRELY SEPARATE option would be to use the tools that Apple provides for manipulating images - they are fast and easy to use, but are not going to work on Linux or Windows. So, for example, if you want to

a) load a PNG file (or a TIFF or JPEG, just change the extension)

b) save it as a JPEG file

c) process the individual pixels

// Load a PNG file
NSImage * strImage = [[NSImage alloc]initWithContentsOfFile:@"/Users/mark/Desktop/input.png"];

// Save NSImage as JPG
NSData *imageData = [strImage TIFFRepresentation];
NSBitmapImageRep *imageRep = [NSBitmapImageRep imageRepWithData:imageData];
NSDictionary *imageProps = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:1.0] forKey:NSImageCompressionFactor];
imageData = [imageRep representationUsingType:NSJPEGFileType properties:imageProps];
[imageData writeToFile:@"/Users/Mark/Desktop/result.jpg" atomically:YES];

// Access individual pixels
int w=imageRep.pixelsWide;
int h=imageRep.pixelsHigh;
int bps=imageRep.bitsPerSample;

printf("Dimensions: %dx%d\n",w,h);
printf("bps: %d\n",bps);

// Get a pointer to the uncompressed, unencoded pixel data
unsigned char *pixelData = [imageRep bitmapData];

for(int j=0;j<10;j++){
    printf("Pixel %d: %d\n",j,pixelData[j]);
}

Of course, you could take the code above and easily make a little utility that converts any file format to PGM and then you could go with my first suggestion of using PGM format and wouldn't need to install ImageMagick - although it is actually dead simple with homebrew.

Bear in mind that you can mix Objective-C (as in the last example) with C++ and C in a single project using clang (Apple's compiler), so you can go ahead in C as you indicate in your question with any of the examples I have given above.

If you are new to developing on OSX, you need to go to the AppStore and download, for free, Apple's Xcode to get the compiler and libraries. Then you must do

xcode-select --install 

to install the command-line tools if you wish to do traditional development using Makefiles and command-line compilation/linking.




回答3:


You can install ImageMagick on OS/X with this command:

sudo port install ImageMagick

You can get the macports package from https://www.macports.org




回答4:


Don't have much experience with Mac's but I have quite a lot with OpenCV. Now granted a lot of OpenCV is in C++ (which may or may not be a problem) however it definitely supports everything you want to do and more. It's very easy to work with has lot's of helpful wiki's and a very good community.

Link to installing on Mac: http://blogs.wcode.org/2014/10/howto-install-build-and-use-opencv-macosx-10-10/

Link to some OpenCV wikis: http://opencv.org/documentation.html

EDIT: I should also mention that older versions of OpenCV are in C and a lot of the functions are still supported if you chose to go the C route.



来源:https://stackoverflow.com/questions/33769797/read-and-display-gray-scale-images-in-c-language

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!