I am working in c trying to create an image and save it to a given directory. I don't care what type of image file it is (PNG, jpeg, bitmap, etc.), I just want it to be viewable in Windows 10. The data stream is in the following form: std::vector<unsigned char>
.
I would like to do this natively in c , but I am not against using a library if it is straightforward to implement and lightweight.
I have this working in C# using the following code, but I don't know if there is a direct translation into c
// C# code to translate into c ?
var image = new BitmapImage();
using (var ms = new MemoryStream(message.ImageData))
{
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = ms;
image.EndInit();
image.Freeze();
}
CodePudding user response:
C# implementations have image routines in the language's standard library. C does not. So there is no equivalent code in standard C : you need to use a third party library. On Windows you could use Win32.
Below I use stb_image_write.h
, which can be found here; the stb libraries are barebones 1-file or 2-file libraries typically used in independent game development where having a dependency on libPNG et. al. would be overkill.
#include <vector>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
std::vector<unsigned char> generate_some_image(int wd, int hgt)
{
// this is just an example for tutorial purposes ... generate a red circle
// in a white field.
std::vector<unsigned char> data(wd * hgt * 4);
int c_x = wd / 2;
int c_y = hgt / 2;
int radius = c_x;
int i = 0;
for (int y = 0; y < hgt; y ) {
for (int x = 0; x < wd; x ) {
if ((x - c_x) * (x - c_x) (y - c_y) * (y - c_y) <= radius * radius) {
data[i ] = 255;
data[i ] = 0;
data[i ] = 0;
data[i ] = 255;
} else {
data[i ] = 255;
data[i ] = 255;
data[i ] = 255;
data[i ] = 255;
}
}
}
return data;
}
int main()
{
const int wd = 128;
const int hgt = 128;
std::vector<unsigned char> data = generate_some_image(wd, hgt);
return stbi_write_png( "c:\\test\\foo.png", wd, hgt, 4, &(data[0]), 4*wd);
}
CodePudding user response:
There is no default standard C library for creating an image file with a specific format (PNG, Bitmap ... etc). However, there are tricks to create an image and make it viewable if this is all that you need. The ways are discussed below:
- Use a library as jwezorek! mentioned in his answer. There are tons of libraries that can help: OpenCV, STB ... etc
- Create a function that creates a file and streams the pixels data to that file in a specific format (Can be fun for some and a headache for others).
- Save the image data as raw data (pixels data only) in a file, and use a simpler programming language to read the file data and view the image. For instance, let's assume that you will use "python" as the simpler language to create a simple image viewer on windows 10, the code will look as follows:
import NumPy as np
import scipy.misc as smp
from PIL import Image
w = 1066
h = 600
with open('rgb.raw', 'r') as file:
data = file.read().replace('\n', ' ') # Replacing new lines with spaces
rgbs = data.split(' ') # Get a 1D array of all the numbers (pixels) in file
rgbs = [ int(x) for x in rgbs if x != ''] # Change the data into integers
nprgbs = np.array(rgbs, dtype=np.uint8) # Define a numpy array
arr = np.reshape(nprgbs, (h,w,3)) # Reorder the 1D array to 3D matrix (width, height, channels)
img = Image.fromarray(arr) # Create an Image from the pixels.
img.show() # View the image in a window (It uses the default viewer of the OS)
The above code will read a file containing the RGB channels of an image and view it on the default viewer.
As you can see, you can do it in a variety of ways, choose the simplest and the most suitable for you. In conclusion, the answer to your question is "No" unless you use a custom library, create your own functions, or use simpler programming languages to read the stream of data and use them to create the file.