Compressing a bitmap in memory with C++ - c++

I have a program that grabs an image using BitBlt() and is stored in a variable unsigned char* image. Ideally before uploading it to my server I would like to compress it since it's somewhat large uncompressed. I've tried a couple different ways with zlib, writing my own run length encoding method, and more but no luck. I chalk it up to me not having a strong understanding compression.
I searched and found some examples using zlib but my image appears to stay the same size after attempting to compress it. Here is that code:
unsigned char* compressBitmap(size_t inImgSize, unsigned char* inImage)
{
uLongf srcLen = inImgSize;
uLongf destLen = compressBound(srcLen);
unsigned char* outImage = new unsigned char[destLen];
int res = compress((Bytef*)outImage, &destLen, (Bytef*)inImage, srcLen);
return outImage;
}
I checked and confirmed it is not returning an error. Everything is executed and the image makes it to the server fine, just not compressed at all. I am probably making a bunch of dumb mistakes so any help is appreciated.

Lossless compression on image data doesn't usually lend itself to reduced file sizes (especially photos, simple icons maybe). If you want to know whether the compression is actually working, try uploading an entirely black image and see if the size reduces. If you can see a reduction in file size on a black image, but not the images you are using, you may have to consider using a lossy format instead (e.g. jpeg, png, etc).

Related

Writing image data to the disk as fast as possible

I am writing an application that generates a huge amount of images. Each frame is 1280x800 pixels large and has 1 byte per pixel for color information (greyscale). Each of the frames must be written to disk.
Currently I simply dump the raw pixel data to a binary file on the disk. The file can then be viewed with a special viewer I also created.
This is a very unsatisfactory solution, since the images can't be viewed/processed directly. They always have to run through my custom viewer/converter.
Is there an image format I could use to write my images to disk that:
Is fast to be written (no compression etc.)
Does not increase the final file's size much
Supports dumping my raw pixel buffer in there (no alignemnt changes etc.)
Can be read by common applications (Windows Explorer, Paint, Photoshop etc.)
I already tried to use .png, but the file generation takes much too long due to the compression.
Have a look at the binary Portable GrayMap (P5) format. It consists of an extremely simple header followed by raw image data (without any alignment requirements), and is widely supported by image viewers.
Both bmp and tiff can be used to save raw data. Bmp has the oddity of having image upside down, unless height is negative. And tiff has plenty of encoding options. It should be anyway feasible to reverse engineer the format to be used as a template, where the image data is copy pasted. So no need to use a library: just a header, image data and an optional footer concatenated.

SDL2 C++ Capturing Video of Renderer Animation/Sprite

I have an animation/sprite created using SDL2. The animation works fine when it is being rendered to a screen. But now I also want it to be recorded into a video file (locally stored). For this, I am planning on using FFmpeg APIs, to which I'll be sending a raw RGB pixel data array.
My problem is with fetching the data from SDL2 APIs.
What I've tried is:
// From http://stackoverflow.com/questions/30157164/sdl-saving-window-as-bmp
SDL_Surface *sshot = SDL_CreateRGBSurface(0, 750, 750, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
SDL_RenderReadPixels(gRenderer, NULL, SDL_PIXELFORMAT_ARGB8888, sshot->pixels, sshot->pitch);
// From https://wiki.libsdl.org/SDL_RWFromMem
char fName[50];
sprintf(fName, "/tmp/a/ss%03d.bmp", fileCnt);
char bitmap[310000];
SDL_RWops *rw = SDL_RWFromMem(bitmap, sizeof(bitmap));
SDL_SaveBMP_RW(sshot, rw, 1);
Above does not work. But dumping a single frame into a file with following code works:
SDL_SaveBMP(sshot, "/tmp/alok1/ss.bmp")
This obviously is not an acceptable solution - Writing to thousands of BMPs and then using FFmpeg from command-line to create a video.
What am I doing wrong? How do you extract data from SDL_RWops? Is the use of SDL_RWFromMem the right approach to my problem statement?
Your buffer is too small to fit specified image, hence it cannot be saved here. Increase buffer size to at least actual image size + BMP header (width*height*bpp + 54, but padding needs to be counted too (what SDL_Surface refers as pitch)).
Note that taking 3Mb from stack may get you dangerously close to overflow (but could still be fine, depends on what happened in functions prior to the one in question). Chain-calling several functions that takes big chunk of stack may very quickly deplete it. It is likely you don't really need any extra space or BMP conversion at all - like creating AVImage and copying pixels directly to it from SDL_Surface.
Also in terms of performance this kind of readback would not be great (but probably compression itself is much heavier anyway).

How to store images in c++ with Ximea

I have a superSpeed usb 3.0 Ximea camera and I'm trying to code an application with a Ximea camera that consists on computer vision and machine learning.
I've been able to alocate the frames captured by the camera in it's buffer but I can find the way to save those images or frames as an JPEG or BMP file. I don't know if it's just a command line in my script or I need some kind of libraries to do it.
The images are aquired using these commands:
#define EXPECTED_IMAGES 10
for (int images=0;images < EXPECTED_IMAGES;images++)
{
// getting image from camera
stat = xiGetImage(xiH, 5000, &image);
HandleResult(stat,"xiGetImage");
printf("Image %d (%dx%d) received from camera\n", images, (int)image.width, (int)image.height);
}
As I can extract the data from the images, I suppose that the frame is still in the buffer, but I can't figure out the way to save it as a JPEG or BMP file in the computer.
I would appreciate any help with the code.
Thank you!
Aha, saving the image. I think you might have gotten the answer by now.
But here is mine, and I hope this will be useful for anyone working with machine vision cameras.
I have been working with XIMEA for quite a while now. XIMEA API does not include any functions to save images from the buffer to hard drive. So, you need to write your own function or use some library to save out images. And I think, essentially it all comes down to whether it's RAW or compressed image and what kind of image format you want to save out. ie. BMP, JPEG, PNG, PGM, EXR ......
Let's make couple assumptions first.
Here I assume you want to save out 8bit per pixel RAW image having a resolution of 1024*1024. The size of the image will be 8bit * 1024 * 1024 = 8388608bit = 1048576btye ~= 1MB
By looking at your code, you are using XIMEA API in C++.
Okay...... Here are two ways I used most often to save out images from XIMEA.
Writing all the image pixels to a binary file with a proper header according to the format you want to save out. Here is an example saving a data to a PGM format image.
FILE *file;
char fileName = "example.pgm";
char *image;
int width = 1024;
int height = 1024;
int byte_per_pixel = 1;
int max_pixel_value = 255;
file = fopen (fileName , "w+bx");
if(file == NULL){
fprintf(stderr, "Cannot open %s\n", fileName);
return -1;
}
size_t n = 0;
n += fprintf(file, "P5\n# Comment goes here!\n%d %d\n%d\n", width, height, max_pixel_value);
n += fwrite(image, 1, width * height * byte_per_pixel, file);
fclose (fileToSave);
Saving image to PGM may seem easy but when you need to save an image having pixel depth higher than 8bit, you need to deal with endianness issue, since PGM big-endian format. Here is a link to Netpbm formats if you want to read more about it. https://en.wikipedia.org/wiki/Netpbm_format
And also, other formats may have way more complicated data structure then you cannot just simply put down a header. So, using an image library or OpenCV will be a lot less cumbersome.
The handy OpenCV imwrite. Since you are gonna deal with pixels, OpenCV is a good library to have. OpenCV is a powerful library helps you with manipulating matrixes easier than ever. And it comes with a lot of useful stuff like GPU accelerated OpenCV functions. Back to the topic, imwrite can save images to many formats. Here is an example I wrote to save RAW data to PNG format.
string fileName = "example.png";
char *image;
int width = 1024;
int height = 1024;
int byte_per_pixel = 1;
int max_pixel_value = 255;
cv::Mat img_raw = cv::Mat(height, width, CV_8UC1, image);
vector compression_params;
compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
compression_params.push_back(0);
cv::imwrite(PNGFileName, img_raw, compression_params);
imwirte will determine what kind of format you want to save out based on the filename extension. And just a couple lines of code. OpenCV saves out the image for you effortlessly. Here is a link to OpenCV documentation of imwirte, http://docs.opencv.org/2.4/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imwrite
I hope my answer can help you and others are wondering how to save out images.
to store images from XIMEA cameras I would recommend to use the OpenCV library
as it provides tools for storing both JPEG and BMP image formats. Please download
a short example that demonstrates the storing of several different data formats
from the camera to JPEG and BMP images. Download the archive with MSVC 2013 project and OpenCV3.0 binaries from here and use password SHWJGRAIHFLG for
extraction.
If you should have any other questions concerning XIMEA products, please visit
and register directly on the XIMEA customer support. Thank you.
Best regards,
XIMEA team

Simple frame by frame video decoder library

I'm looking for a simple c/c++ lib that would allow to extract the first frame of a video as a uchar array. And have a simple fonction to access the next one.
I know of FFMPEG but it requiere to play with packet and things like that, and i'm surprised that nowhere on the net i can find a lib that allow something like :
Video v = openVideo("path");
uchar* data = v.getFrame();
v.nextFrame();
I just need to extract frames of a video to use it as a texture...no need for reencoding after or anything...
of course something that would read the most format than possible would be great, something built upon libavcodec for example ;p
And i'm using Windows 7
Thanks!
Here's an example with OpenCV:
#include <cv.h>
#include <highgui.h>
int
main(int argc, char **argv)
{
cv::VideoCapture capture(argv[1]);
if (capture.grab())
{
cv::Mat_<char> frame;
capture.retrieve(frame);
//
// Convert to your byte array here
//
}
return 0;
}
It's untested, but I cannibalized it from some existing working code, so it shouldn't take you long to get it working.
The cv::Mat_<unsigned char> is essentially a byte array. If you really need something that's explicitly of type unsigned char *, then you can malloc space of the appropriate size and iterate over the matrix using
You can convert a cv::Mat to a byte array using pixel positions(cv::Mat_::at()) or iterators (cv::Mat_::begin() and friends).
There are many reasons why libraries rarely expose image data as a simple pointer, such as:
It implies the entire image must occupy a contiguous space in memory. This is a big deal when dealing with large images
It requires committing a certain ordering of the data (pixel vs non-planar -- are the RGB planes stored interspersed or separately?) and reduces flexibility
Dereferencing pointers is a cause for bugs (buffer overruns, etc).
So if you want your pointer, you have to do a bit of work for it.
You can use OpenCV it is very simple and they have a useful manual on their site http://opencv.willowgarage.com/wiki/
Use DirectShow. Here's an article: http://www.codeproject.com/KB/audio-video/framegrabber.aspx
There are DirectShow 'add-ons' to decode different video formats. Here's one of the sites where you can grab free DirectShow filter packs to decode some common formats that are not directly supported by DirectShow: http://www.free-codecs.com/download/DirectShow_FilterPack.htm

Convert image into useable byte array in C?

Does anyone know how to open an image, specifically a jpg, to a byte array in C or C++? Any form of help is appreciated.
Thanks!
The ImageMagick library can do this too, although often it provides enough image manipulation functions that you can do many things without needing to convert the image to a byte array and handle it yourself.
You could try the DevIL Image Library I've only used it in relation to OpenGL related things, but it also functions as just a plain image loading library.
Check out the source code for wxImage in the wxWidgets GUI Framework. You will most likely be interested in the *nix distribution.
Another alternative is the GNU Jpeg library.
Here is how I would do it using GDIPlus Bitmap.LockBits method defined in the header GdiPlusBitmap.h:
Gdiplus::BitmapData bitmapData;
Gdiplus::Rect rect(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
//get the bitmap data
if(Gdiplus::Ok == bitmap.LockBits(
&rect, //A rectangle structure that specifies the portion of the Bitmap to lock.
Gdiplus::ImageLockModeRead | Gdiplus::ImageLockModeWrite, //ImageLockMode values that specifies the access level (read/write) for the Bitmap.
bitmap.GetPixelFormat(),// PixelFormat values that specifies the data format of the Bitmap.
&bitmapData //BitmapData that will contain the information about the lock operation.
))
{
//get the lenght of the bitmap data in bytes
int len = bitmapData.Height * std::abs(bitmapData.Stride);
BYTE* buffer = new BYTE[len];
memcpy(bitmapData.Scan0, buffer, len);//copy it to an array of BYTEs
//...
//cleanup
pBitmapImageRot.UnlockBits(&bitmapData);
delete []buffer;
}
I have my students use netpbm to represent images because it comes with a handy C library, but you can also put images into text form, create them by hand, and so on. The nice thing here is that you can convert all sorts of images, not just JPEGs, into PBM format, using command-line tools the Unix way. The djpeg tool is available a number of places including the JPEG Club. Students with relatively little experience can write some fairly sophisticated programs using this format.
OpenCV can also do this.
http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/index.html
search for: "Accessing image elements"