Qt multipage TIFF - c++

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

Related

list file extensions supported by OpenCV

In OpenCV, I see imread() and VideoCapture() both take a string to a file path of multiple extensions. Is there a way to get a list of extensions that are supported by them? For example, getting a list of "jpg", "png", "mov", "mpg", etc.? I assume this is system dependent and others have needed to query this at runtime.
Furthermore, how is support determined? If have something like the below code and the Mat I get back always seems partially corrupted (I can see a bit of the image). It doesn't seem to change regardless of the frame number I ask for. I can play this video in my video player "totem", but I'm not even sure if totem and OpenCV are even using the same codec for this file.
Mat fromVideo(std::string _videoPath, int frame) {
VideoCapture capture(_videoPath);
Mat f;
for (int i = 0; i < frame; i++) {
capture >> f;
}
return f;
}
For imread() (more info here):
Windows bitmaps - *.bmp, *.dib (always supported)
JPEG files - *.jpeg, *.jpg, *.jpe (see the Notes section)
JPEG 2000 files - *.jp2 (see the Notes section)
Portable Network Graphics - *.png (see the Notes section)
Portable image format - *.pbm, *.pgm, *.ppm (always supported)
Sun rasters - *.sr, *.ras (always supported)
TIFF files - *.tiff, *.tif (see the Notes section)
For VideoCapture():
AVI files - *.avi
It seems that AVI is the only format with decent cross-platform support. See here for more info.
Use the method cv::VideoCapture::isOpened() to make sure that the constructor was successful in initializing the VideoCapture object.
Note that even if it was possible to get a list of supported container formats from OpenCV (AVI, MKV for instance) with their typical filename extensions, you would still need to know the exact list of supported codecs (and even then the exact file you want to open might be corrupted, etc...). So a list of filename extensions is not enough to accurately describe what is internally supported by OpenCV, and the simplest solution at the OpenCV API level is this isOpened() method.
Just update:
cv::VideoCapture cap("D:\\test.mp4")
works for me.

SDL embed image inside program executable

Is it possible to embed an image within a program using SDL which can be used at run time.
For example, I have a program which brings up a splash screen on startup containing the logo and copyright information. Rather than having this image in a bitmap file and using SDL_LoadBMP to load it to a SDL_Surface. I would like to have the image embedded in the program binary, to stop someone potentially changing the splash image and copyright name.
Does anyone have any suggestions on ways to do this? Example code would be great.
Embedding a file in an executable is easy but there are some gotchas, there are several ways to do it including some portable and non-portable ways.
Using #embed
This will reportedly be part of C23. It may be on track to appear in C++26 as well. Check whether your compiler supports this feature. In the future, this may be the most portable and straightforward way to embed binary data.
static const unsigned char IMAGE_DATA[] = {
#embed "myimage.bmp
};
See WG14 n2592 for the feature proposal.
Advantages: simplest, easiest
Disadvantages: your compiler probably doesn’t support this yet
Convert the image to C code
Write a script to convert the image to a constant array in C. The script would look something like this in Python:
#!/usr/bin/env python3
print("static const unsigned char IMAGE_DATA[] = {{{}}};".format(
",".join(str(b) for b in open("myimage.bmp", "rb").read())))
Just pipe the output to a *.h file and include that file from one other file. You can get the size of the file with sizeof(IMAGE_DATA).
Advantages: portable
Disadvantages: requires Python to be installed, does not work if array is too large for compiler, requires adding a custom step to the build system
Convert the image to an object file
This is more platform-dependent. On platforms with GNU binutils toolchains (e.g. Linux) you can use objcopy, I think bin2obj works on Microsoft toolchains.
Advantages: works everywhere
Disadvantages: non-portable, requires adding a custom step to the build system, the custom step might be tricky to get right
On GNU binutils toolchains, with objcopy
The objcopy program lets you specify binary as the input format, but then you need to specify the architecture explicitly... so you will have to modify the command for i386 and x64 versions of your executable.
$ objcopy --input binary --output elf32-i386 --binary-architecture i386 \
myimage.bmp myimage.o
You can get the data from C by using the following declarations:
// Ignore the fact that these are char...
extern char _binary_myimage_bmp_start, _binary_myimage_bmp_end;
#define MYIMAGE_DATA ((void *) &_binary_myimage_bmp_start)
#define MYIMAGE_SIZE \
((size_t) (&_binary_myimage_bmp_end - &_binary_myimage_bmp_start))
Use an assembler directive
Paradoxically, embedding a static file is fairly easy in assembler. Assemblers often have directives like .incbin (which works with GAS and YASM).
Advantages: works everywhere
Disadvantages: non-portable, assembler syntax is different between platforms
(Windows) Embed the file as a resource
On Windows, you can embed resources in an EXE and then get the resources using library calls.
Advantages: probably easiest if you are on Windows
Disadvantages: only works on Windows
You can export the image as .xpm format (in gimp) and include it to your code. But you will need SDL_Image.h to load it as SDL_Surface.
As it is in this doc, is really simple:
//To create a surface from an XPM image included in C source, use:
SDL_Surface *IMG_ReadXPMFromArray(char **xpm);
A example in C/C++:
#include <SDL/SDL.h>
#include "test.xpm"
#include <SDL/SDL_image.h>
SDL_Surface *image;
SDL_Surface *screen;
int main(int argc, char **argv)
{
SDL_Init(SDL_INIT_EVERYTHING);
screen = SDL_SetVideoMode(800,600,32,SDL_SWSURFACE);
image = IMG_ReadXPMFromArray(test_xpm); //the .xpm image is a char array. "test_xpm" is the name of the char array
SDL_Rect offset;
offset.x = 0;
offset.y = 0;
SDL_BlitSurface(image,NULL,screen,&offset);
SDL_Flip(screen);
SDL_Delay(5000);
return 0;
}
I hope this helps.
With gimp you can save a image as c code.

Can anyone clearify how to get tiff rating metadata in C++ or just the file rating the way Win Explore reads it?

Hey I'm completely lost when it comes to reading the tiff metadata in C++, I've looked over google and can't find any examples. All i want to do is read the rating property and output that to console i should be able to take it from there.
thanks in advance.
UPDATE
thanks folks I'll look more into the libtiff library
Looking into the libtiff folder it seems a bit overkill for what I'm trying to accomplish. Is it possible to read the "properties/details" tab of a file verse setting up the library or am I asking something extremely retarded. Again all i'm looking to find is a if there is a rating on he file or not.
Well, libtiff exposes all of this functionality, you just need to read the docs.
To set metadata, you have TIFFSetField
int
TIFFSetField(TIFF* tif, ttag_t tag, ...)
Likewise, to retrieve metadata you have TIFFGetField
int
TIFFGetField(TIFF* tif, ttag_t tag, ...)
One thing to note here is if you are reading standard TIFF tags or proprietary tags. If they are proprietary and not in the libtiff library then someone has added them on their own, in which case you need their tag declarations to incorporate into your version of libtiff (or just get theirs). You can follow this guide if it comes to that (I've had to do it).
There is ImageMagick which does handle TIFF images: http://www.imagemagick.org/script/formats.php you can pull the metadata using the framework it uses libTiff underneath, using this you should be able to pull the metadata tags using calls to TIFFGetField like Ed S. suggests
This is the sample usage leached from the libTiff page:
TIFF* tif = TIFFOpen("myfile.tif", "r");
if (tif) {
uint32 imageWidth, imageLength;
uint32 tileWidth, tileLength;
uint32 x, y;
tdata_t buf;
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &imageLength);
TIFFGetField(tif, TIFFTAG_TILEWIDTH, &tileWidth);
TIFFGetField(tif, TIFFTAG_TILELENGTH, &tileLength);
buf = _TIFFmalloc(TIFFTileSize(tif));
for (y = 0; y < imageLength; y += tileLength)
for (x = 0; x < imageWidth; x += tileWidth)
TIFFReadTile(tif, buf, x, y, 0);
_TIFFfree(buf);
TIFFClose(tif);
}
there is also a list of tags that are handled by the library: http://www.libtiff.org/support.html

converting a binary stream into a png format

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.

JPEG support with ijg - getting access violation

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