I have a data array of pixel intensity (e.g. unsigned char pixel_intensity[4] = {0, 255, 255, 0}) and I need to create image in C code on Linux (Raspberry Pi).
What is the easiest way to do it?
I would suggest using the netpbm format as it is very easy to program. It is documented here and here.
I have written a little demonstration of how to write a simple greyscale ramp to a 100x256 image below.
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *imageFile;
int x,y,pixel,height=100,width=256;
imageFile=fopen("image.pgm","wb");
if(imageFile==NULL){
perror("ERROR: Cannot open output file");
exit(EXIT_FAILURE);
}
fprintf(imageFile,"P5\n"); // P5 filetype
fprintf(imageFile,"%d %d\n",width,height); // dimensions
fprintf(imageFile,"255\n"); // Max pixel
/* Now write a greyscale ramp */
for(x=0;x<height;x++){
for(y=0;y<width;y++){
pixel=y;
fputc(pixel,imageFile);
}
}
fclose(imageFile);
}
The header of the image looks like this:
P5
256 100
255
<binary data of pixels>
And the image looks like this (I have made it into a JPEG for rendering on here)
Once you have an image, you can use the superb ImageMagick (here) tools to convert the image to anything else you like, e.g. if you want the greyscale created by the above converted into a JPEG, just use ImageMagick like this:
convert image.pgm image.jpg
Or, if you want a PNG
convert image.pgm image.png
You can actually use the PGM format images directly on the web, by convention, the MIME type is image/x-portable-graymap
Related
In the main part, I rotated the image. Then I wrote a code for writing my image to in project file as a jpeg file. I couldn't do it.
Here is my code:
They are some definitions and libraries I used. (I also added standard libraries.)
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#define CHANNEL_NUM 3
int main() {
.
.
.
write(&out_image); // calling by reference
}
After this part, I want to write my image as a jpg file. So this is the writing part:
int write(unsigned char *rgb_image)
{
int width =400;
int height = 400;
rgb_image = malloc(width*height*CHANNEL_NUM);
stbi_write_jpg("rotated_image", width, height, CHANNEL_NUM, rgb_image, width*CHANNEL_NUM);
return 0;
}
I am not sure about the second part so I share it with you. By the way, I don't get any errors in both functions. (main and write)
If you want the full code, let me know in the comment section. I can share my main function too.
I'm beginning with openCV, I have to use it for a project at school. I'm using CodeBlocks on windows.
I am trying to write a very simple function that convert a image in RGB format to an HSV format, then display the Hue channel.
long traiter_image(IplImage* Image)
{
IplImage* ImHSV = 0;
IplImage* chans[3];
cvCvtColor(Image, ImHSV, CV_BGR2HSV); // BGR to HSV
// split channels
cvSplit (ImHSV, chans[0], chans[1], chans[2], NULL);
Afficher("Teinte",chans[0]); // Display Hue
return 0;
}
I don't have any building errors, but when I execute the code, a windows appears, telling me that "null array pointer is passed in function cvgetmat". The problem comes from the cvCvtColor function, but I don't know how to fix it...
Before calling cvCvtColor(), you should create the memory for the output image, which should be of the same size and depth as the input image.
For your case, it should be:
IplImage* ImHSV = cvCreateImage(cvGetSize(Image), IPL_DEPTH_8U, 3);
cvCvtColor(Image, ImHSV, CV_BGR2HSV); // BGR to HSV
I have a very simple function that saves a PPM image:
void WriteCImage(CImage *cimg, char *filename)
{
FILE *fp;
int i,n;
fp = fopen(filename,"w");
fprintf(fp,"P6\n");
fprintf(fp,"%d %d\n",cimg->C[0]->ncols,cimg->C[0]->nrows);
fprintf(fp,"255\n");
n = cimg->C[0]->ncols*cimg->C[0]->nrows;
for (i=0; i < n; i++)
{
fputc(cimg->C[0]->val[i],fp);
fputc(cimg->C[1]->val[i],fp);
fputc(cimg->C[2]->val[i],fp);
}
fclose(fp);
}
as you can see, this function receives a matrix (in CImage format) and writes the image data in the ASCII file. It seems correct, but every time I copy a grayscale image to a PPM image I have problems. Look at the code:
//that's a PGM grayscale image
gt = ReadImage(argv[1]);
//creating an RGB image with same dimensions of the PGM image
nwcimg = CreateCImage(gt->nrows,gt->ncols);
n=gt->nrows*gt->ncols;
//iterate through the PGM image
for(index=0;index<n;index++)
{
// just a copy of the grayscale image value to all 3 layeres
//of the PPM (RGB) image
nwcimg->C[0]->val[index]=gt->val[index];
nwcimg->C[1]->val[index]=gt->val[index];
nwcimg->C[2]->val[index]=gt->val[index];
}
WriteCImage(nwcimg,"gt-copied.ppm");
DestroyCImage(&nwcimg);
DestroyImage(>);
what problem i have? well, the code seems correct and simple. But when the cimage matrix/vector is written as a file, i can see that the two pictures are not the same. Seems like the pixels of the PGM image are 'shifted' or 'mirrored' in the copied image.
You can see the Image File and The RGB copy
Shouldn't
for(index=0;index<n;index++) {
nwcimg->C[0]->val[index]=gt->val[index];
nwcimg->C[1]->val[index]=gt->val[index];
nwcimg->C[2]->val[index]=gt->val[index];
be
for(index=0;index<n;index) {
nwcimg->C[0]->val[index]=gt->val[index++];
nwcimg->C[1]->val[index]=gt->val[index++];
nwcimg->C[2]->val[index]=gt->val[index++];
? The for loop in your file writer writes 3 bytes per loop. The loop in your reader consumes only 1 byte per loop then copies it into three separate arrays.
I want to implement a simple command line based image editor. The program will
provide a text based menu, which provides several functions for user to manipulate a windows
bitmap (.bmp) image file. The menu will include load image, rotate image, mirror image, save image
and quit options. The load image option will be used to open and read pixel values from a given
bitmap file. This option will also print out the basic properties, such as dimensions and total size, of the given file. The rotate and mirror options will manipulate previously read pixel values. An image
must be loaded before applying these options. The save option will save the pixel values in the
memory to a bitmap file with a given filename.
Which approach do you recommend for me about this project and about bitmap file structure?
It would be very appreciated if you give me advice even about one particular topic for example load the file.
libbmp will make your program all but trivial to implement.
If you really want to use C then try the libbmp library http://code.google.com/p/libbmp/
However, I'd recommend using C#, then the task would be trivial with the System.Drawing namespace.
This function is used for loading a bmp file to memory.
you have to declare first a header file with bmp structure
BMP* load_BMP(char *filename);
BMP *bmp; // local integer for file loaded
FILE *in; // pointer for file opening
int rowsize;
int row, col, color, i;
unsigned char b;
in=fopen(filename,"rb"); // open binary file
if (in==NULL)
{
printf("Problem in opening file %s.\n",filename);
return NULL;
}
bmp=(BMP*) malloc(sizeof(BMP)); //memory allocation
if (bmp==NULL)
{
printf("Not enough memory to load the image.\n");
return NULL;
}
fread(bmp->BM,2,1,in);
if (bmp->BM[0]!='B' || bmp->BM[1]!='M')
{
printf("Bad BMP image file.\n");
free(bmp);
return NULL;
}
fread(&bmp->fileSize,4,1,in);
fread(&bmp->Reserved1,2,1,in);
fread(&bmp->Reserved2,2,1,in);
fread(&bmp->imageOffset,4,1,in);
fread(&bmp->imageHeaderSize,4,1,in);
fread(&bmp->imageWidth,4,1,in);
rowsize=4*((3*bmp->imageWidth+3)/4); //calculate rowsize because of padding
fread(&bmp->imageHeight,4,1,in);
fread(&bmp->colorPlanes,2,1,in);
fread(&bmp->compressionMethod,4,1,in);
fread(&bmp->imageSize,4,1,in);
fread(&bmp->hPPM,4,1,in);
fread(&bmp->vPPM,4,1,in);
fread(&bmp->paletteColors,4,1,in);
fread(&bmp->paletteImportantColors,4,1,in);
bmp->data=(unsigned char*) malloc(bmp->imageSize); //allocate memory for image data array
if (bmp->data==NULL)
{
printf("There is not enough memory to load the image\n");
free(bmp);
return NULL;
}
for(row=0;row<bmp->imageHeight;row++) //read picture data
{
for(col=0;col<bmp->imageWidth;col++)
for(color=0;color<=2;color++)
fread(&bmp->data[row*rowsize+3*col+color],
sizeof(unsigned char),1,in);
//read extra bytes for end of row padding
for(i=0;i<rowsize-3*bmp->imageWidth;i++)
fread(&b,1,1,in);
}
fclose(in);
return bmp;
}
I am writing an improved Perlin noise (I don't really understand simplex noise) terrain generator for C, and I am practically finished with the alpha build. However, there is one thing holding me back: actually saving the stupid image. I recruited MagickWand to help me solve the problem of PNG creation, and it looks like a nice implementation on the whole, with tons of useful features etc., but there is very little documentation on the whole thing. No tutorials, really, just a bunch of lists of functions and some example programs. Here is my code so far, based on this:
EDIT: Cut out a bunch of irrelevant code.
#include <stdio.h>
#include <stdlib.h>
#include "mt.h"
#include "diamondsquare.h"
#include "/Library/Frameworks/libWand.framework/Versions/6.3.0/Headers/wand/MagickWand.h"
int main () {
unsigned long seed = 0, x = 0, y = 0, initial = 0, range = 0;
int smooth = 0, fail = 1, index1 = 0, index2 = 0, exception = 0;
char flagchar1 = 'n';
// Some imperative code. Not relevant.
image *ConstituteImage(x, y, "I", IntegerPixel, grid, &exception);
write("image.png", image);
}
At the very least, I know that this is linked wrong (compiling returns an error inside wand.h that it can't find one of the headers). What's the proper way to go about creating an image from an array within a program using MagickWand for C?
Too much code, it could be summarized with:
image *ConstituteImage(x, y, "I", IntegerPixel, grid, &exception);
write("image.png", image);
But reading the MagickWand link you provided:
MagickWriteImageFile
MagickWriteImageFile() writes an image to an open file descriptor. The
format of the MagickWriteImageFile method is:
MagickBooleanType MagickWriteImageFile ( MagickWand *wand, FILE *file
); A description of each parameter follows:
wand: The magick wand. file: The file descriptor.
So it is clear you have to call:
MagickBooleanType MagickWriteImageFile ( MagickWand *wand, FILE *file );
that header almost definitely tries to include other headers so you need something like:
gcc -I"/Library/Frameworks/libWand.framework/Versions/6.3.0/Headers"
or
gcc -I"/Library/Frameworks/libWand.framework/Versions/6.3.0/Headers/wand"