I was recently trying to update my game to store graphics in compressed formats (JPEG and PNG).
Whilst I ended up settling on a different library, my initial attempt was to incorporate ijg to do JPEG decompression. However, I was unable to get even the simplest console application to work and am wondering if anyone might be able to shed some light on the reasons why.
Here is my code, which is linked to the jpeg.lib that is part of the ijg packages:
#include "stdafx.h"
#include <stdio.h>
#include <assert.h>
#include <jpeglib.h>
int _tmain(int argc, _TCHAR* argv[])
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPARRAY buffer;
int row_stride;
//initialize error handling
cinfo.err = jpeg_std_error(&jerr);
//initialize the decompression
jpeg_create_decompress(&cinfo);
FILE* infile;
errno_t err = fopen_s(&infile, "..\\Sample.jpg", "rb");
assert(err == 0);
//specify the input
jpeg_stdio_src(&cinfo, infile);
//read headers
(void) jpeg_read_header(&cinfo, TRUE);
return 0;
}
The problem is that the call to jpeg_read_header() fails with an access violation:
Unhandled exception at 0x7c91b1fa
(ntdll.dll) in JPEGTest.exe:
0xC0000005: Access violation writing
location 0x00000010.
Does anyone have any ideas what I might be doing wrong?
I've just encountered the same problem (although I was trying to encode an image).
Apparently, FILE* are not portable between DLLs so you can't use any libjpeg API that takes a FILE* as a parameter.
There are several solutions, but they all come down to having to rebuild the library:
Build the library as a static lib, and link it to your application. This is what I did, and it solved my problem.
Move the source/destination handlers out of libjpeg and into your application. Then you could build libjpeg as either a static lib or a DLL, whichever suits you. I'm not sure whether this would work, but it is the suggested solution in the "install.doc" file distributed with the source code.
I agree with HernĂ¡n. This is not a good interface (I think the internal code itself is probably good), unless you really need to work low-level (and maybe not even then). I think ImageMagick is probably better. They have a "MagickWand" C interface that is more high level, not to mention that it supports many more formats.
However, I was curious about libjpeg's interface, so I got a test program working to my satisfaction, based on your example program as well as libjpeg.doc, the IJG example, and USING THE IJG JPEG LIBRARY. Anyway, here's the code. It just prints out the dimensions, and the RGB of the first pixel of every row.
I am very surprised you get an error with my code. It works fine for me, and compiles without any warnings. Can someone else test it?
#include <stdio.h>
#include <assert.h>
#include <jpeglib.h>
int main(int argc, char* argv[])
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPARRAY buffer;
int row_stride;
//initialize error handling
cinfo.err = jpeg_std_error(&jerr);
FILE* infile;
infile = fopen("Sample.jpg", "rb");
assert(infile != NULL);
//initialize the decompression
jpeg_create_decompress(&cinfo);
//specify the input
jpeg_stdio_src(&cinfo, infile);
//read headers
(void) jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
printf("width: %d, height: %d\n", cinfo.output_width, cinfo.output_height);
row_stride = cinfo.output_width * cinfo.output_components;
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
JSAMPLE firstRed, firstGreen, firstBlue; // first pixel of each row, recycled
while (cinfo.output_scanline < cinfo.output_height)
{
(void)jpeg_read_scanlines(&cinfo, buffer, 1);
firstRed = buffer[0][0];
firstBlue = buffer[0][1];
firstGreen = buffer[0][2];
printf("R: %d, G: %d, B: %d\n", firstRed, firstBlue, firstGreen);
}
jpeg_finish_decompress(&cinfo);
return 0;
}
Here is a workaround without having to rebuild the library: Make replacement I/O functions, as André Caron stated, but have nothing in them but the standard stdio functions.
The code below I made in the past might help.
It is written for libpng, but I believe it is easy to do the same in libjpeg.
I added this to the code:
png_set_write_fn (png_ptr,file,replwrite,replflush);
Then created the replacement functions:
void replwrite (png_structp png_ptr, png_bytep data, png_size_t length)
{
fwrite (data,1,length,(FILE*) png_get_io_ptr(png_ptr));
}
void replflush (png_structp png_ptr)
{
fflush ((FILE*) png_get_io_ptr(png_ptr));
}
It always works for me. What I'm actually doing is telling libpng, "Hey, don't use the write functions from the MSVCR that your .dll points to, use these ones, that come from the MSVCR I use in my program, fwrite and fflush". You see it's basically a compatibility issue.
I hope this or something like this will solve the problem.
It's difficult to see the cause of the access violation from the code sample given. If you can include a stack trace (with symbols) that would help identify the issue.
One thing to verify is that the alignment settings for the .LIB and .EXE projects are consistent, this will often lead to nasty problems as struct/class members are not where the compiler expects them to be.
To work with images in multiple formats, let me recommend you DevIL as a library http://openil.sourceforge.net/. It's an excellent choice, as I've used it many times with excellent results. Beware that it's syntax is OpenGL-like.
The list of features:
Supports loading of:
.bmp
.cut
.dcx
.dds
.exr
.ico
.icns
.gif
.jpg
.jp2
.lbm
.lif
.mdl
.pcd
.pcx
.pic
.png
.pnm
.psd
.psp
.raw
.sgi
.tga
.tif
.wal
.act
.pal
.hdr
Doom graphics
Supports saving of:
.bmp
.dds
.jpg
.pcx
.png
.pnm
.raw
.sgi
.tga
.tif
.pal
Library Features
Portable, supports Windows, Mac OS X and *nix.
OpenGL-style syntax.
Use of image names instead of ugly pointers.
Loading from files, file streams or memory "lumps".
Direct access to data through ilGetData() and ilSetData().
Support for luminance, rgb(a), bgr(a) and colour-indexed images.
Support for 3 different numbers of bits per channel.
Conversion between all formats and datatypes (including palettes).
User-defined automatic conversions if desired when loading images.
Automatic conversion when saving images if needed.
Automatic conversion of colour-indexed images to truecolour images if desired.
Controllable compression when saving.
Maintains a state stack that can be pushed and popped.
Full support for 3d texture volumes (3d images).
Validation of images.
Support for layers.
Support for mipmaps.
Support for animations.
User-specified clear colour.
Can load a default image if loading fails.
User-specified hints.
Use of key colours.
Support for overlaying an image on top of another.
Allows the user to specify their own loading and saving callbacks, even overriding the default ones.
Support for user-specified read and write functions.
Delphi support.
Visual Basic support.
Linux support.
Can pick and choose which features will be used to create smaller dlls.
Choose whether to use the Intel Jpeg Library or libjpeg.
A whole host of effects and filters to apply to images, such as embossing and edge detection.
Images can be resized or even be put on a larger background (enlarged canvas).
OpenGL, Allegro, Windows GDI and DirectX API support.
here is a tested function
void test(char FileName[])
{
unsigned long x, y;
struct jpeg_decompress_struct info; //for our jpeg info
struct jpeg_error_mgr err; //the error handler
JSAMPARRAY buffer;
FILE* infile;
//initialize error handling
info.err = jpeg_std_error(& err);
infile = fopen(FileName, "rb"); //open the file
//if the jpeg file doesn't load
if(!infile) {
fprintf(stderr, "Error reading JPEG file %s!", FileName);
// printf("Error reading JPEG file %s!", FileName);
//return 0;
}
//initialize the decompression
jpeg_create_decompress(&info);
//specify the input
jpeg_stdio_src(&info, infile);
//read headers
jpeg_read_header(&info, TRUE); // read jpeg file header
jpeg_start_decompress(&info); // decompress the file
//set width and height
x = info.output_width;
y = info.output_height;
printf("x value is %ul", x);
printf("x value is %ul", y);
}
This question is almost 10 years now, but exactly the same what author posted happened to me today (I'm using Visual Studio 2013).
Initially I tried to use the libjpeg library from GnuWin32: http://gnuwin32.sourceforge.net/packages/jpeg.htm and was getting the same error.
Then noticed this is a "version 6b" of libJpeg, which is quite old now (2005)
What worked for me was installing libJpeg through nuget pacakge manager:
Install-Package libjpeg -Version 9.2.0.1
Related
One main question, several underwritten questions (sorry).
I'm trying to read GSUB infos (and other tables) in a ttf font. How to do that? Which lib could I use?
GSUB is a substitution table telling how glyphs used in the same neighborhood must morph to another glyph. Is is very common in many languages, and in english, it is more rare, but the best example is ligature.
It is good documented for OpenType fonts (otf) and I know it exists in Truetype fonts (ttf).
But how can I access it? Is there a library such as Freetype + Harfbuzz?
It seems Freetype gives only access to OTF tables, not TTF, am I right?
FT_OpenType_Validate: This function only works with OpenType fonts
And is Harfbuzz optional or mandatory for such needs?
Documentations are poor (at my pov), so I'm searching for experiences, working examples.
It also seems to be hard to make freetype + harfbuzz working toghether on windows, is it really needed? How to?
Sources:
mactype
official poor example
My test code, not working, because GSUB is an "Unimplemented Feature" says Freetype:
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OPENTYPE_VALIDATE_H
#include <stdexcept>
int main(int argc, char* argv[])
{
FT_Library ftLibrary;
FT_Error errorLib = FT_Init_FreeType(&ftLibrary);
if (errorLib)
throw std::runtime_error("Couldn't initialize the library: FT_Init_FreeType() failed");
FT_Face ftFace;
FT_Error errorFace = FT_New_Face(ftLibrary, argv[1], 0, &ftFace); //getting first face
if (errorFace)
throw std::runtime_error("Couldn't load the font file: FT_New_Face() failed");
FT_Bytes BASE = NULL;
FT_Bytes GDEF = NULL;
FT_Bytes GPOS = NULL;
FT_Bytes GSUB = NULL;
FT_Bytes JSTF = NULL;
FT_Error errorValidate = FT_OpenType_Validate(ftFace, FT_VALIDATE_GSUB, &BASE, &GDEF, &GPOS, &GSUB, &JSTF);
if (errorValidate)
throw std::runtime_error("Couldn't validate opentype datas");
//7=Unimplemented_Feature
FT_OpenType_Free(ftFace, BASE);
FT_OpenType_Free(ftFace, GDEF);
FT_OpenType_Free(ftFace, GPOS);
FT_OpenType_Free(ftFace, GSUB);
FT_OpenType_Free(ftFace, JSTF);
FT_Done_Face(ftFace);
FT_Done_FreeType(ftLibrary);
return 0;
}
On Windows you have to enable OpenType Validation Module. If you're using Visual Studio to build FreeType then follow steps below.
In freetype/config/ftmodule.h add this:
FT_USE_MODULE( FT_Module_Class, otv_module_class )
Then in Solution Explorer add src/otvalid/otvalid.c to the project.
You are ready to build library. Don't forget to update your project with new library or object files.
Using this I was able to get access to GPOS table. But don't be very optimistic. OpenType's tables support in FreeType is super limited. So, what you really get is raw pointer to bytes. In order to get some useful data there you have to parse these bytes according to OpenType spec. And I would say that this is not a trivial task taking into account complexity of the OpenType spec. I would even say that it's overcomplicated, but still possible.
If you decide to do it remember that you have to reverse byte order for data that you read from any table.
I'm using OpenCV and am reading gigabytes of images -- too much to fit into memory at a single time. However, I need to initialize some basic structures which require the image dimensions. At the moment I'm using imread and then freeing the image right away, and this is really inefficient.
Is there a way to get the image dimensions without reading the entire file, using opencv? If not could you suggest another library (preferably lightweight, seeing as that's all it'll be used for) that can parse the headers? Ideally it would support at least as many formats as OpenCV.
I don't think this is possible in opencv directly.
Although it isn't specified in the docs, Java's ImageReader.getHight (and getWidth) only parse the image header, not the whole image.
Alternatively here is a reasonable looking lightweight library that definitely only checks the headers, and supports a good amount of image formats.
Finally, if you're on Linux the 'identify ' terminal command will also give you the dimensions, which you could then read in programmatically.
You could use boost gil:
#include <boost/gil/extension/io/jpeg_io.hpp>
int main(int argc, char *argv[])
{
//set/get file_path
auto dims = boost::gil::jpeg_read_dimensions(file_path);
int width = dims.x;
int height = dims.y;
}
You will have to link against libjpeg, by adding -ljpeg flag to the linker. You can get some more information here.
I need to save a multipage TIFF from my program, but it seems Qt doesn't support multipage TIFF. Still, I need to do it. What would be the best way to go about doing it from my program?
So far, I'm thinking about using ImageMagick's command line utility to create the multipage TIFF from many JPEG files I create, or adding libtiff to my project and trying to use it, or using GDI+ (on Windows at least) to generate the TIFF.
Any other ideas I might have missed?
I'd like to avoid using external EXEs or DLLs if possible, i.e. if I can add a library directly to my project's source code it would be best.
Also, if you know of a project where it's already done, please post a link to it, I'd rather not reinvent the wheel.
Just wanted to add my info on a similar topic. I ended up just building libTiff from the latest (4.0.3) source. My project is all in x64, but it was pretty easy:
Download and unzip libTIFF source
Open the VS2010 (or whatever) for x64 (or x32) cmd
cd to your unzipped folder from step 1
type: nmake /f makefile.vc
Fetch the files from /libtiff folder and add to your project
Here's an example of reading 16-bit TIFF data:
TIFF *MultiPageTiff = TIFFOpen("C:\\MultiPageTiff.tif", "r");
std::vector<unsigned short*> SimulatedQueue;
//Read First TIFF to setup the Buffers and init
//everything
int Width, Height;
//Bit depth, in bits
unsigned short depth;
TIFFGetField(MultiPageTiff, TIFFTAG_IMAGEWIDTH, &Width);
TIFFGetField(MultiPageTiff, TIFFTAG_IMAGELENGTH, &Height);
TIFFGetField(MultiPageTiff, TIFFTAG_BITSPERSAMPLE, &depth);
//This should be Width*(depth / sizeof(char))
tsize_t ScanlineSizeBytes = TIFFScanlineSize(MultiPageTiff);
if(MultiPageTiff){
int dircount = 0;
do{
dircount++;
//I'm going to be QQueue'ing these up, so a buffer needs to be
//allocated per new TIFF page
unsigned short *Buffer = new unsigned short[Width*Height];
//Copy all the scan lines
for(int Row = 0; Row < Height; Row++){
TIFFReadScanline(MultiPageTiff, &Buffer[Row*Width], Row, 0);
}
SimulatedQueue.push_back(Buffer);
}while(TIFFReadDirectory(MultiPageTiff));
TIFFClose(MultiPageTiff);
}
Sources:
Building libTIFF from VS - http://www.remotesensing.org/libtiff/build.html#PC
Example MultiPage TIFF - http://www.remotesensing.org/libtiff/libtiff.html
Misc. Tiff Manuals - http://www.remotesensing.org/libtiff/man/
Qt uses libtiff to read and write TIFF. So I would use the same library, just less headache. Secondly: look at http://qt.gitorious.org/qt/qt/blobs/4.8/src/gui/image/qtiffhandler.cpp to get a clue of how Qt writes one QImage. To support multiple pages I think you need to use TIFFSetField() (see here, TIFFTAG_PAGENAME and TIFFTAG_PAGENUMBER). I would start to either expand the write() function or write something similar, where you:
TIFFClientOpen();
iterate over a list of QImages
set the page per QImage
do the things QTiffHandler::write() does
TIFFClose();
see also: http://code.google.com/p/multiphoton/source/browse/MatroxImagingLibrary.cpp?#1628
I have two problems, the first has been solved.
Current problem
If I embed a file that requires a library to load it, such as a jpeg image or a mp3 music, I will need to use the file as input to the library. However, each library is different and uses a way to get a file as input, the input may be the file name or a FILE* pointer (from libc's file interface).
I would like to know how to access an embedded file with a name. It will be inefficient if I create a temporary file, is there another way? Can I map a file name to memory? My platforms are Windows and Linux.
If show_file(const char* name) is a function from a library, I will need a string to open the file.
I have seen these questions:
How to get file descriptor of buffer in memory?
Getting Filename from file descriptor in C
and the following code is my solution. Is it a good solution? Is it inefficient?
# include <stdio.h>
# include <unistd.h>
extern char _binary_data_txt_start;
extern const void* _binary_data_txt_size;
const size_t len = (size_t)&_binary_data_txt_size;
void show_file(const char* name){
FILE* file = fopen(name, "r");
if (file == NULL){
printf("Error (show_file): %s\n", name);
return;
}
while (true){
char ch = fgetc(file);
if (feof(file) )
break;
putchar( ch );
}
printf("\n");
fclose(file);
}
int main(){
int fpipe[2];
pipe(fpipe);
if( !fork() ){
for( int buffsize = len, done = 0; buffsize>done; ){
done += write( fpipe[1], &_binary_data_txt_start + done, buffsize-done );
}
_exit(0);
}
close(fpipe[1]);
char name[200];
sprintf(name, "/proc/self/fd/%d", fpipe[0] );
show_file(name);
close(fpipe[0]);
}
The other problem (solved)
I tried to embed a file on Linux, with GCC, and it worked. However, I tried to do the same thing on Windows, with Mingw, and it did not compile.
The code is:
# include <stdio.h>
extern char _binary_data_txt_start;
extern char _binary_data_txt_end;
int main(){
for (char* my_file = &_binary_data_txt_start; my_file <= &_binary_data_txt_end; my_file++)
putchar(*my_file);
printf("\n");
}
The compilation commands are:
objcopy --input-target binary --output-target elf32-i386 --binary-architecture i386 data.txt data.o
g++ main.cpp data.o -o test.exe
On Windows, I get the following compiler error:
undefined reference to `_binary_data_txt_start'
undefined reference to `_binary_data_txt_end'
I tried to replace elf32-i386 with i386-pc-mingw32, but I still get the same error.
I think that for this to work with MinGW you'll need to remove the leading underscore from the names in the .c file. See Embedding binary blobs using gcc mingw for some details.
See if using the following helps:
extern char binary_data_txt_start;
extern char binary_data_txt_end;
If you need the same source to work for Linux or MinGW builds, you might need to use the preprocessor to have the right name used in the different environments.
If you're using a library that requires a FILE* for reading data, then you can use fmemopen(3) to create a pseudofile out of a memory blob. This will avoid creating a temporary file on disk. Unfortunately, it's a GNU extension, so I don't know if it's available with MinGW (likely not).
However, most well-written libraries (such as libpng and the IJG's JPEG library) provide routines for opening a file from memory as opposed to from disk. libpng, in particular, even offers a streaming interface, where you can incrementally decode a PNG file before it's been completely read into memory. This is useful if, say, you're streaming an interlaced PNG from the network and you want to display the interlaced data as it loads for a better user experience.
On Windows, you can embed custom resource into executable file. You would need a .RC file and a resource compiler. With Visual Studio IDE you can do it without hassle.
In your code, you would use FindResource, LoadResource and LockResource functions to load the contents into memory at runtime. A sample code that reads the resource as long string:
void GetResourceAsString(int nResourceID, CStringA &strResourceString)
{
HRSRC hResource = FindResource(NULL, MAKEINTRESOURCE(nResourceID), L"DATA");
HGLOBAL hResHandle = LoadResource(NULL, hResource);
const char* lpData = static_cast<char*> ( LockResource(hResHandle) );
strResourceString.SetString(lpData, SizeofResource(NULL, hResource));
FreeResource(hResource);
}
Where nResourceID is the ID of resource under custom resource type DATA. DATA is just a name, you may choose another name. Other in-built resources are cursors, dialogs, string-tables etc.
I've created a small library called elfdataembed which provides a simple interface for extracting/referencing sections embedded using objcopy. This allows you to pass the offset/size to another tool, or reference it directly from the runtime using file descriptors. Hopefully this will help someone in the future.
It's worth mentioning this approach is more efficient than compiling to a symbol, as it allows external tools to reference the data without needing to be extracted, and it also doesn't require the entire binary to be loaded into memory in order to extract/reference it.
Use nm data.o to see what it named the symbols. It may be something as simple as the filesystem differences causing the filename-derived symbols to be different (eg filename capitalized).
Edit: Just saw your second question. If you are using threads you can make a pipe and pass that to the library (first using fdopen() if it wants a FILE *). If you are more specific about the API you need to talk to I can add more specific advice.
I will try to be clear ....
My project idea is as follow :
I took several compression algorithms which I implemented using C++, after that I took a text file and applied to it the compression algorithms which I implemented, then applied several encryption algorithms on the compressed files, now I am left with final step which is converting these encrypted files to any format of image ( am thinking about png since its the clearest one ).
MY QUESTION IS :
How could I transform a binary stream into a png format ?
I know the image will look rubbish.
I want the binary stream to be converted to a an png format so I can view it as an image
I am using C++, hope some one out there can help me
( my previous thread which was closed )
https://stackoverflow.com/questions/5773638/converting-a-text-file-to-any-format-of-images-png-etc-c
thanx in advance
Help19
If you really really must store your data inside a PNG, it's better to use a 3rd party library like OpenCV to do the work for you. OpenCV will let you store your data and save it on the disk as PNG or any other format that it supports.
The code to do this would look something like this:
#include <cv.h>
#include <highgui.h>
IplImage* out_image = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, bits_pr_pixel);
char* buff = new char[width * height * bpp];
// then copy your data to this buff
out_image->imageData = buff;
if (!cvSaveImage("fake_picture.png", out_image))
{
std::cout << "ERROR: Failed cvSaveImage" << std::endl;
}
cvReleaseImage(&out_image);
The code above it's just to give you an idea on how to do what you need using OpenCV.
I think you're better served with a bi-dimensional bar code instead of converting your blob of data into a png image.
One of the codes that you could use is the QR code.
To do what you have in mind (storing data in an image), you'll need a lossless image format. PNG is a good choice for this. libpng is the official PNG encoding library. It's written in C, so you should be able to easily interface it with your C++ code. The homepage I linked you to contains links to both the source code so you can compile libpng into your project as well as a manual on how to use it. A few quick notes on using libpng:
It uses setjmp and longjmp for error handling. It's a little weird if you haven't worked with C's long jump functionality before, but the manual provides a few good examples.
It uses zlib for compression, so you'll also have to compile that into your project.