How to specify little endian in Jasper JPEG2000 - c++

I am encoding raw byte to JPEG2000 using jasper library. The image produced is big endian whereas I need the output in little endian. How to specify the endianness in jasper? Here is the code snippet:
EncodeAsJPEG2000(array<Byte> ^inputImage, array<Byte> ^outputImage, uint32 width, uint32 height, uint32 size)
{
jas_init();
jas_image_t *pImage;
pImage = jas_image_create0();
pin_ptr<Byte> pInput = &inputImage[0];
int totalCopied = 0;
if (pImage)
{
tsize_t bytesperline = 2;
int iCmp = 0;
jas_stream_t *pStream;
jas_image_cmptparm_t cmptparm;
cmptparm.tlx = 0;
cmptparm.tly = 0;
cmptparm.hstep = 1;
cmptparm.vstep = 1;
cmptparm.width = width;
cmptparm.height = height;
cmptparm.prec = 16;
cmptparm.sgnd = false;
jas_image_addcmpt(pImage, iCmp, &cmptparm);
//jas_image_setcmpttype(pImage, 0, JAS_IMAGE_CT_GRAY_Y);
pImage->clrspc_ = JAS_CLRSPC_SGRAY; /* grayscale Image */
pImage->cmprof_ = 0;
jas_stream_seek(pImage->cmpts_[iCmp]->stream_, 0, SEEK_SET);
jas_stream_write(pImage->cmpts_[iCmp]->stream_, pInput, size);
pStream = jas_stream_fopen("C:\\jaspimage.jp2" , "w+b");
int copied = 0;
if (pStream)
{
char optionsString[128];
optionsString[0] = '\0';
int format = jas_image_strtofmt("jp2");
jas_image_encode(pImage, pStream, format, "rate=1.0");
jas_stream_close(pStream);
}
jas_image_destroy(pImage);
}
}
I verified the endian using ImageJ. It says little endian false.

How to specify the endianness in jasper?
You cannot.
Neither its documentation mentions anything on that, nor its src contains anything related.
You can switch the endianness manually, which may come with an additional performance overhead (which even if the library supported that feature, you would have to cope with it anyway).
However, as #MatthewPope mentioned, you could try flipping only the Exif data (read more in How can I change the endianness of my file with exiftool?), like this for example:
exiftool -all= -tagsfromfile test.jpg -all:all -unsafe -exifbyteorder=little-endian test.jpg
This approach will be significantly faster than the above mentioned, since the size of the Exif data is at least one order of magnitude smaller than the whole file most of the times.
Wikipedia states that Exif metadata are restricted in size to 64 kB in JPEG images, which, if true, is ~812 times less than the image sizes you are handling.
ExifTool can be used for editing meta information in an image. Read this interesting question too: How does JPEG endianness matter on coding?

Related

OpenCV vs byte array

I am working on a simple C++ image processing application and deciding whether to use OpenCV for loading the image and accessing individual pixels.
My current approach is to simply load the image using fopen, reading the 54 byte header and load the rest of the bytes in a char* array.
To access a specific pixel I use
long q = (long*)(bmpData + x*3 + (bmpSize.height - y - 1) * bmpSize.stride);
To perform a simple color check, for ex. "is blue?"
if (((long*)q | 0xFF000000) == 0xFFFF0000) //for some reason RGB is reversed to BGR
//do something here
Is OpenCV any faster considering all the function calls, parsing, etc.?
Bitmap file header is actually 54 bytes and you can't skip it. You have to read it to find the width, height, bitcount... calculate padding if necessary... and other information.
Depending on how the file is opened, OpenCV will read the header and reads the pixels directly in to a buffer. The only change is that the rows are flipped so the image is right side up.
cv::Mat mat = cv::imread("filename.bmp", CV_LOAD_IMAGE_COLOR);
uint8_t* data = (uint8_t*)mat.data;
The header checks and the small changes made by OpenCV will not significantly affect performance. The bottle neck is mainly in reading the file from the disk. The change in performance will be difficult to measure, unless you are doing a very specific task, for example you want only 3 bytes in a very large file, and you don't want to read the entire file.
OpenCV is overkill for this task, so you may choose other libraries for example CImg as suggested in comments. If you use smaller libraries they load faster, it might be noticeable when your program starts.
The following code is a test run on Windows.
For a large 16MB bitmap file, the result is almost identical for opencv versus plain c++.
For a small 200kb bitmap file, the result is 0.00013 seconds to read in plain C++, and 0.00040 seconds for opencv. Note the plain c++ is not doing much beside reading the bytes.
class stopwatch
{
std::chrono::time_point<std::chrono::system_clock> time_start, time_end;
public:
stopwatch() { reset();}
void reset(){ time_start = std::chrono::system_clock::now(); }
void print(const char* title)
{
time_end = std::chrono::system_clock::now();
std::chrono::duration<double> diff = time_end - time_start;
if(title) std::cout << title;
std::cout << diff.count() << "\n";
}
};
int main()
{
const char* filename = "filename.bmp";
//I use `fake` to prevent the compiler from over-optimization
//and skipping the whole loop. But it may not be necessary here
int fake = 0;
//open the file 100 times
int count = 100;
stopwatch sw;
for(int i = 0; i < count; i++)
{
//plain c++
std::ifstream fin(filename, std::ios::binary);
fin.seekg(0, std::ios::end);
int filesize = (int)fin.tellg();
fin.seekg(0, std::ios::beg);
std::vector<uint8_t> pixels(filesize - 54);
BITMAPFILEHEADER hd;
BITMAPINFOHEADER bi;
fin.read((char*)&hd, sizeof(hd));
fin.read((char*)&bi, sizeof(bi));
fin.read((char*)pixels.data(), pixels.size());
fake += pixels[i];
}
sw.print("time fstream: ");
sw.reset();
for(int i = 0; i < count; i++)
{
//opencv:
cv::Mat mat = cv::imread(filename, CV_LOAD_IMAGE_COLOR);
uint8_t* pixels = (uint8_t*)mat.data;
fake += pixels[i];
}
sw.print("time opencv: ");
printf("show some fake calculation: %d\n", fake);
return 0;
}

Read bmp file header size

I am trying to find file size, file header size width, and height of a bmp file. I have studied the format of bmp file and the arrangement of bytes in file.
When I try this code it shows wrong width and height for different files.
I have tried this for three images so far. This one image results the right measurement.
This one did not:
I don't understand where I went wrong, but the bit depth showed the right value for all three images.
Here is my code:
#include<iostream>
#include<fstream>
#include<math.h>
using namespace std;
int main() {
ifstream inputfile("bmp.bmp",ios::binary);
char c; int imageheader[1024];
double filesize=0; int width=0; int height=0;int bitCount = 0;
for(int i=0; i<1024; i++) {
inputfile.get(c); imageheader[i]=int(c);
}
filesize=filesize+(imageheader[2])*pow(2,0)+(imageheader[3])*pow(2,8)+(imageheader[4])*pow(2,16)+(imageheader[5])*pow(2,24);
cout<<endl<<endl<<"File Size: "<<(filesize/1024)<<" Kilo Bytes"<<endl;
width=width+(imageheader[18])*pow(2,0)+(imageheader[19])*pow(2,8)+(imageheader[20])*pow(2,16)+(imageheader[21])*pow(2,24);
cout<<endl<<"Width: "<<endl<<(width)<<endl;
height=height+(imageheader[22])*pow(2,0)+(imageheader[23])*pow(2,8)+(imageheader[24])*pow(2,16)+(imageheader[25])*pow(2,24);
cout<<endl<<"Height: "<<endl<<(height)<<endl;
bitCount=bitCount+(imageheader[28])*pow(2,0)+(imageheader[29])*pow(2,8);
cout<<endl<<"Bit Depth: "<<endl<<(bitCount)<<endl;
}
Let's start by reading the BMP header in as a series of bytes, not integers. To make this code truly portable, we'll use <stdint> types.
#include <fstream>
#include <stdint.h>
int main()
{
ifstream inputfile("D:/test.bmp", ios::binary);
uint8_t headerbytes[54] = {};
inputfile.read((char*)headerbytes, sizeof(headerbytes));
Now that we've got the header in memory as an array of bytes, we can simply cast the memory address of each header field back into a integer. Referencing the wikipedia page for bmp and the layout diagram.
uint32_t filesize = *(uint32_t*)(headerbytes+2);
uint32_t dibheadersize = *(uint32_t*)(headerbytes + 14);
uint32_t width = *(uint32_t*)(headerbytes + 18);
uint32_t height = *(uint32_t*)(headerbytes + 22);
uint16_t planes = *(uint16_t*)(headerbytes + 26);
uint16_t bitcount = *(uint16_t*)(headerbytes + 28);
Now an astute reader of the code will recognize that the individual fieds of a a BMP headers are stored in little endian format. And that the code above relies on you to have an x86 processor or any other architecture in which the byte layout is Little Endian. On a big endian machine, you'll have to apply a workaround to convert from LE to BE for each of the variables above.
The bug is reading into signed char. This should fix it:
for(int i = 0; i < 1024; i++)
{
//inputfile.get(c); imageheader[i] = int(c);
// This version of get returns int, where -1 means EOF. Should be checking for errors...
imageheader[i] = inputfile.get();
}
Others have commented on improvements to the code so I won't bother.

GL Screenshot Breaks on viewport resize…sometimes

I’m developing a plugin for SIMDIS (basically military google earth), written in c++ using VS 2012. It’s a pretty nifty little thing to auto plot points, and one of its functions is to take a series of screenshot of the view-port and save the images off so it can be used/processed somewhere else. This works fine too… until you re-size the view-port one too many times. Re-size is done by clicking the corner of the window and dragging it bigger and smaller, and the program may launch full screen or windowed mode; either way it works fine the first few sets… or as long as the window is not re-sized.
When it breaks, the program will still march happily along, create the files, and filling them with data at what seems to be an appropriate size for whatever resolution image I’m trying to generate… but the format becomes no-good. It will still be a *.bmp, but windows stops being able to understand it. No errors are thrown though, (I think, I’m not catching any GL errors?[if that’s possible?]).
I can’t get it to consistently happen with a specific number of actions, but it seems to start failing after 3-7 view-port re-sizes. I don’t know if this is a problem with my screenshot code, an issue with the SIMDIS program or plugin, a GL issue, or what. I’ve tested it on multiple machines.
Has anyone run into this problem before? Is there something specific I should be doing that I’m not? Is this a problem native to the parent program (SIMDIS), or something I can work with/around with GL commands I don’t know about?
Screenshot code follows:
#include "TakeScreenshot.h" //has "#include <gl/GL.h>" etc...
TakeScreenshot::TakeScreenshot()
{
}
std::vector<int> * TakeScreenshot::TakeAScreenshotBMP(const char* filename)
{
//std::cout << "Screenshot! ";
std::vector<int> * returnVec = new std::vector<int>();
int VPort[4] = {0,0,0,0};
int FSize = 0;
int PackStore = 0;
//get GL viewport dimensions, x,y,w,h into vport
glGetIntegerv(GL_VIEWPORT,VPort);
//make a framebuffer, RGB
FSize = VPort[2]*VPort[3]*3;
unsigned char PStore[8294400];// 4k sized buffer
//store settings
glGetIntegerv(GL_PACK_ALIGNMENT, &PackStore);
//unpack to byte order
glPixelStorei(GL_PACK_ALIGNMENT, 1);
//read the gl buffer into our buffer
glReadPixels(VPort[0],VPort[1],VPort[2],VPort[3],GL_RGB,GL_UNSIGNED_BYTE,&PStore);
//Pass back settings
glPixelStorei(GL_PACK_ALIGNMENT, PackStore);
///
//set up file info
///
BITMAPINFOHEADER BMIH; //info header
BMIH.biSize = sizeof(BITMAPINFOHEADER);
BMIH.biSizeImage= VPort[2] * VPort[3] * 3;
BMIH.biWidth = VPort[2];
BMIH.biHeight = VPort[3];
BMIH.biPlanes = 1;
BMIH.biBitCount = 24;
BMIH.biCompression = BI_RGB;
BITMAPFILEHEADER bmfh;//file header
int nBitsOffset = sizeof(BITMAPFILEHEADER) + BMIH.biSize;
LONG lImageSize = BMIH.biSizeImage;
LONG lFileSize = nBitsOffset + lImageSize;
bmfh.bfType = 'B' + ('M'<<8);
bmfh.bfOffBits = nBitsOffset;
bmfh.bfSize = lFileSize;
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
// swap r and b values because GL has them backwards for BMP format.
unsigned char SwapByte;
for(int loop = 0; loop<FSize; loop+=3)
{
SwapByte = PStore[loop];
PStore[loop] = PStore[loop+2];
PStore[loop +2] = SwapByte;
}
///
// File writing section
///
FILE *pFile;
pFile = fopen(filename, "wb");
//if something borked
if(pFile == NULL)
{
std::cout << "TakeScreenshot::TakeAScreenshotBMP>> Error; was not able to create file (Permisions?)" << std::endl;
returnVec->push_back(-1);
returnVec->push_back(-1);
return returnVec; //exit
}
UINT nWrittenFileHeaderSize = fwrite(&bmfh,1,sizeof(BITMAPFILEHEADER), pFile);
UINT nWrittenInfoHeaderSize = fwrite(&BMIH,1,sizeof(BITMAPINFOHEADER), pFile);
UINT nWrittenDIBDataSize = fwrite(&PStore, 1, lImageSize, pFile);
fclose(pFile);
//some return data for processing later
returnVec->push_back(VPort[2]);
returnVec->push_back(VPort[3]);
return returnVec;
}
TakeScreenshot::~TakeScreenshot(void)
{
}

exchanging 2 memory positions

I am working with OpenCV and Qt, Opencv use BGR while Qt uses RGB , so I have to swap those 2 bytes for very big images.
There is a better way of doing the following?
I can not think of anything faster but looks so simple and lame...
int width = iplImage->width;
int height = iplImage->height;
uchar *iplImagePtr = (uchar *) iplImage->imageData;
uchar buf;
int limit = height * width;
for (int y = 0; y < limit; ++y) {
buf = iplImagePtr[2];
iplImagePtr[2] = iplImagePtr[0];
iplImagePtr[0] = buf;
iplImagePtr += 3;
}
QImage img((uchar *) iplImage->imageData, width, height,
QImage::Format_RGB888);
We are currently dealing with this issue in a Qt application. We've found that the Intel Performance Primitives to be be fastest way to do this. They have extremely optimized code. In the html help files at Intel ippiSwapChannels Documentation they have an example of exactly what you are looking for.
There are couple of downsides
Is the size of the library, but you can link static link just the library routines you need.
Running on AMD cpus. Intel libs run VERY slow by default on AMD. Check out www.agner.org/optimize/asmlib.zip for details on how do a work around.
I think this looks absolutely fine. That the code is simple is not something negative. If you want to make it shorter you could use std::swap:
std::swap(iplImagePtr[0], iplImagePtr[2]);
You could also do the following:
uchar* end = iplImagePtr + height * width * 3;
for ( ; iplImagePtr != end; iplImagePtr += 3) {
std::swap(iplImagePtr[0], iplImagePtr[2]);
}
There's cvConvertImage to do the whole thing in one line, but I doubt it's any faster either.
Couldn't you use one of the following methods ?
void QImage::invertPixels ( InvertMode mode = InvertRgb )
or
QImage QImage::rgbSwapped () const
Hope this helps a bit !
I would be inclined to do something like the following, working on the basis of that RGB data being in three byte blocks.
int i = 0;
int limit = (width * height); // / 3;
while(i != limit)
{
buf = iplImagePtr[i]; // should be blue colour byte
iplImagePtr[i] = iplImagaePtr[i + 2]; // save the red colour byte in the blue space
iplImagePtr[i + 2] = buf; // save the blue color byte into what was the red slot
// i++;
i += 3;
}
I doubt it is any 'faster' but at end of day, you just have to go through the entire image, pixel by pixel.
You could always do this:
int width = iplImage->width;
int height = iplImage->height;
uchar *start = (uchar *) iplImage->imageData;
uchar *end = start + width * height;
for (uchar *p = start ; p < end ; p += 3)
{
uchar buf = *p;
*p = *(p+2);
*(p+2) = buf;
}
but a decent compiler would do this anyway.
Your biggest overhead in these sorts of operations is going to be memory bandwidth.
If you're using Windows then you can probably do this conversion using the BitBlt and two appropriately set up DIBs. If you're really lucky then this could be done in the graphics hardware.
I hate to ruin anyone's day, but if you don't want to go the IPP route (see photo_tom) or pull in an optimized library, you might get better performance from the following (modifying Andreas answer):
uchar *iplImagePtr = (uchar *) iplImage->imageData;
uchar buf;
size_t limit = height * width;
for (size_t y = 0; y < limit; ++y) {
std::swap(iplImagePtr[y * 3], iplImagePtr[y * 3 + 2]);
}
Now hold on, folks, I hear you yelling "but all those extra multiplies and adds!" The thing is, this form of the loop is far easier for a compiler to optimize, especially if they get smart enough to multithread this sort of algorithm, because each pass through the loop is independent of those before or after. In the other form, the value of iplImagePtr was dependent on the value in previous pass. In this form, it is constant throughout the whole loop; only y changes, and that is in a very, very common "count from 0 to N-1" loop construct, so it's easier for an optimizer to digest.
Or maybe it doesn't make a difference these days because optimizers are insanely smart (are they?). I wonder what a benchmark would say...
P.S. If you actually benchmark this, I'd also like to see how well the following performs:
uchar *iplImagePtr = (uchar *) iplImage->imageData;
uchar buf;
size_t limit = height * width;
for (size_t y = 0; y < limit; ++y) {
uchar *pixel = iplImagePtr + y * 3;
std::swap(pix[0], pix[2]);
}
Again, pixel is defined in the loop to limit its scope and keep the optimizer from thinking there's a cycle-to-cycle dependency. If the compiler increments and decrements the stack pointer each time through the loop to "create" and "destroy" pixel, well, it's stupid and I'll apologize for wasting your time.
cvCvtColor(iplImage, iplImage, CV_BGR2RGB);

How do I read JPEG and PNG pixels in C++ on Linux?

I'm doing some image processing, and I'd like to individually read each pixel value in a JPEG and PNG images.
In my deployment scenario, it would be awkward for me to use a 3rd party library (as I have restricted access on the target computer), but I'm assuming that there's no standard C or C++ library for reading JPEG/PNG...
So, if you know of a way of not using a library then great, if not then answers are still welcome!
There is no standard library in the C-standard to read the file-formats.
However, most programs, especially on the linux platform use the same library to decode the image-formats:
For jpeg it's libjpeg, for png it's libpng.
The chances that the libs are already installed is very high.
http://www.libpng.org
http://www.ijg.org
This is a small routine I digged from 10 year old source code (using libjpeg):
#include <jpeglib.h>
int loadJpg(const char* Name) {
unsigned char a, r, g, b;
int width, height;
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * infile; /* source file */
JSAMPARRAY pJpegBuffer; /* Output row buffer */
int row_stride; /* physical row width in output buffer */
if ((infile = fopen(Name, "rb")) == NULL) {
fprintf(stderr, "can't open %s\n", Name);
return 0;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, infile);
(void) jpeg_read_header(&cinfo, TRUE);
(void) jpeg_start_decompress(&cinfo);
width = cinfo.output_width;
height = cinfo.output_height;
unsigned char * pDummy = new unsigned char [width*height*4];
unsigned char * pTest = pDummy;
if (!pDummy) {
printf("NO MEM FOR JPEG CONVERT!\n");
return 0;
}
row_stride = width * cinfo.output_components;
pJpegBuffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
while (cinfo.output_scanline < cinfo.output_height) {
(void) jpeg_read_scanlines(&cinfo, pJpegBuffer, 1);
for (int x = 0; x < width; x++) {
a = 0; // alpha value is not supported on jpg
r = pJpegBuffer[0][cinfo.output_components * x];
if (cinfo.output_components > 2) {
g = pJpegBuffer[0][cinfo.output_components * x + 1];
b = pJpegBuffer[0][cinfo.output_components * x + 2];
} else {
g = r;
b = r;
}
*(pDummy++) = b;
*(pDummy++) = g;
*(pDummy++) = r;
*(pDummy++) = a;
}
}
fclose(infile);
(void) jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
BMap = (int*)pTest;
Height = height;
Width = width;
Depth = 32;
}
For jpeg, there is already a library called libjpeg, and there is libpng for png. The good news is that they compile right in and so target machines will not need dll files or anything. The bad news is they are in C :(
Also, don't even think of trying to read the files yourself. If you want an easy-to-read format, use PPM instead.
Unfortunately, jpeg format is compressed, so you would have to decompress it before reading individual pixels. This is a non-trivial task. If you can't use a library, you may want to refer to one to see how it's decompressing the image. There is an open-source library on sourceforge: CImg on sourceforge.
Since it could use the exposure, I'll mention one other library to investigate: The IM Toolkit, which is hosted at Sourceforge. It is cross platform, and abstracts the file format completely away from the user, allowing an image to be loaded and processed without worrying about most of the details. It does support both PNG and JPEG out of the box, and can be extended with other import filters if needed.
It comes with a large collection of image processing operators as well...
It also has a good quality binding to Lua.
As Nils pointed, there is no such thing as a C or C++ standard library for JPEG compression and image manipulation.
In case you'd be able to use a third party library, you may want to try GDAL which supports JPEG, PNG and tens of other formats, compressions and mediums.
Here is simple example that presents how to read pixel data from JPEG file using GDAL C++ API:
#include <gdal_priv.h>
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
int main()
{
GDALAllRegister(); // once per application
// Assume 3-band image with 8-bit per pixel per channel (24-bit depth)
std::string const file("/home/mloskot/test.jpg");
// Open file with image data
GDALDataset* ds = static_cast<GDALDataset*>(GDALOpen(file.c_str(), GA_ReadOnly));
assert(0 != ds);
// Example 1 - Read multiple bands at once, assume 8-bit depth per band
{
int const ncols = ds->GetRasterXSize();
int const nrows = ds->GetRasterYSize();
int const nbands = ds->GetRasterCount();
int const nbpp = GDALGetDataTypeSize(GDT_Byte) / 8;
std::vector<unsigned char> data(ncols * nrows * nbands * nbpp);
CPLErr err = ds->RasterIO(GF_Read, 0, 0, ncols, nrows, &data[0], ncols, nrows, GDT_Byte, nbands, 0, 0, 0, 0);
assert(CE_None == err);
// ... use data
}
// Example 2 - Read first scanline by scanline of 1 band only, assume 8-bit depth per band
{
GDALRasterBand* band1 = ds->GetRasterBand(1);
assert(0 != band1);
int const ncols = band1->GetXSize();
int const nrows = band1->GetYSize();
int const nbpp = GDALGetDataTypeSize(GDT_Byte) / 8;
std::vector<unsigned char> scanline(ncols * nbpp);
for (int i = 0; i < nrows; ++i)
{
CPLErr err = band1->RasterIO(GF_Read, 0, 0, ncols, 1, &scanline[0], ncols, 1, GDT_Byte, 0, 0);
assert(CE_None == err);
// ... use scanline
}
}
return 0;
}
There is more complete GDAL API tutorial available.
I've had good experiences with the DevIL library. It supports a wide range of image formats and follows a function-style very similar to OpenGL.
Granted, it is a library, but it's definitely worth a try.
Since the other answers already mention that you will most likely need to use a library, take a look at ImageMagick and see if it is possible to do what you need it to do. It comes with a variety of different ways to interface with the core functionality of ImageMagick, including libraries for almost every single programming language available.
Homepage: ImageMagick
If speed is not a problem you can try LodePNG that take a very minimalist approach to PNG loading and saving.
Or even go with picoPNG from the same author that is a self-contained png loader in a function.