I have a task to edit exif tags and add to them application specific values.
if the exif tags exist libexif is more than happy to edit them .
but if the exif tags don't exist, i will have to create them and append them to file.
libexif uses the C fopen so i don't think there is going to be an easy way without some IO manipulation.
I am thinking to read the raw image data put them in memory , fopen(newfile, 'w')
add the exif data
and then append the image data.
only if someone knows an easier way , ( i am restricted with libexif, libexiv2 might create a liscence conflict) .
for the common good i am going to answer my own question, exif application has a modified libjpeg that enable the manipulation of the jpeg raw data.
it has functions like
jpeg_data_load_data (JPEGData *data, const unsigned char *d,unsigned int size);
and
jpeg_data_set_exif_data(myJPEGImage,exif); jpeg_data_save_file(myJPEGImage,"gangrene1.jpg");
That can be used, also free available programs like imagemagick have their own libjpeg , libexif implementation to do manipulate exif and jpeg data.
Hopes this helps
I have just gone down the same road as you with choosing between libexif and libexiv2. I went with libexif due to the licensing.
Back to the question at hand,
libexif doesn't support directly loading JPG's in. You'll need another package to read in the JPG and extract the EXIF header (or you could write something yourself).
There is an excellent Github project called exifyay that uses libexif and has two extra libs that handle reading in JPGS. It is a python project but the sources for the libraries are C. You can find exifyay here (note I am not involved in any way with exifyay or libexif)
I have just recently compiled libexif and merged sources from exifyay into a VS2010 project here. There is an example in the folder 'contrib\examples\LibexifExample'. If you don't like downloading random links here is a sample of the code I got working:
/*
* write-exif.c
*
* Placed into the public domain by Daniel Fandrich
*
* Create a new EXIF data block and write it into a JPEG image file.
*
* The JPEG image data used in this example is fixed and is guaranteed not
* to contain an EXIF tag block already, so it is easy to precompute where
* in the file the EXIF data should be. In real life, a library like
* libjpeg (included with the exif command-line tool source code) would
* be used to write to an existing JPEG file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <libexif/exif-data.h>
#include <libjpeg/jpeg-data.h>
#include <JpegEncoderEXIF/JpegEncoderEXIF.h>
/* byte order to use in the EXIF block */
#define FILE_BYTE_ORDER EXIF_BYTE_ORDER_INTEL
/* comment to write into the EXIF block */
#define FILE_COMMENT "libexif demonstration image"
/* special header required for EXIF_TAG_USER_COMMENT */
#define ASCII_COMMENT "ASCII\0\0\0"
static ExifEntry *create_tag(ExifData *exif, ExifIfd ifd, ExifTag tag, size_t len)
{
void *buf;
ExifEntry *entry;
/* Create a memory allocator to manage this ExifEntry */
ExifMem *mem = exif_mem_new_default();
assert(mem != NULL); /* catch an out of memory condition */
/* Create a new ExifEntry using our allocator */
entry = exif_entry_new_mem (mem);
assert(entry != NULL);
/* Allocate memory to use for holding the tag data */
buf = exif_mem_alloc(mem, len);
assert(buf != NULL);
/* Fill in the entry */
entry->data = (unsigned char*)buf;
entry->size = len;
entry->tag = tag;
entry->components = len;
entry->format = EXIF_FORMAT_UNDEFINED;
/* Attach the ExifEntry to an IFD */
exif_content_add_entry (exif->ifd[ifd], entry);
/* The ExifMem and ExifEntry are now owned elsewhere */
exif_mem_unref(mem);
exif_entry_unref(entry);
return entry;
}
int main(int argc, char **argv)
{
ExifEntry *entry;
//Input JPG
char mInputFilename[]="example.jpg";
//Load JPG
JPEGData * mJpegData = jpeg_data_new_from_file(mInputFilename);
//Load Exif data from JPG
ExifData * mExifData = jpeg_data_get_exif_data(mJpegData);
//Set some Exif options
exif_data_set_option(mExifData, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
exif_data_set_data_type(mExifData, EXIF_DATA_TYPE_COMPRESSED);
exif_data_set_byte_order(mExifData, FILE_BYTE_ORDER);
entry = create_tag(mExifData, EXIF_IFD_EXIF, EXIF_TAG_USER_COMMENT,
sizeof(ASCII_COMMENT) + sizeof(FILE_COMMENT) - 2);
/* Write the special header needed for a comment tag */
memcpy(entry->data, ASCII_COMMENT, sizeof(ASCII_COMMENT)-1);
/* Write the actual comment text, without the trailing NUL character */
memcpy(entry->data+8, FILE_COMMENT, sizeof(FILE_COMMENT)-1);
/* create_tag() happens to set the format and components correctly for
* EXIF_TAG_USER_COMMENT, so there is nothing more to do. */
/* Create a EXIF_TAG_SUBJECT_AREA tag */
entry = create_tag(mExifData, EXIF_IFD_EXIF, EXIF_TAG_SUBJECT_AREA,
4 * exif_format_get_size(EXIF_FORMAT_SHORT));
entry->format = EXIF_FORMAT_SHORT;
entry->components = 4;
//Write back exif data
jpeg_data_set_exif_data(mJpegData,mExifData);
//Save to JPG
jpeg_data_save_file(mJpegData,"test.jpg");
return 0;
}
Related
I have a char array (char* dataToInflate) obtained from a .gz file I would like to inflate into another char array.
I don't know the original decompressed size, so I believe this means I can't use the uncompress function that is within the zlib library, since per the manual:
The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.
I have looked at the zpipe.C example (https://zlib.net/zpipe.c), and the inf function here looks suitable but I'm not sure how to adapt it from FILEs to char arrays.
Does anyone know how or have any other ideas for inflating a char array into another char array?
Update:
I read here: Uncompress() of 'zlib' returns Z_DATA_ERROR
that for arrays obtained through gzip files, uncompress isn't suitable.
I found that I could decompress the file in full using gzopen, gzread and gzclose like so:
gzFile in_file_gz = gzopen(gz_char_array, "rb");
char unzip_buffer[8192];
int unzipped_bytes;
std::vector<char> unzipped_data;
while (true) {
unzipped_bytes = gzread(in_file_gz, unzip_buffer, 8192);
if (unzipped_bytes > 0) {
unzipped_data.insert(unzipped_data.end(), unzip_buffer, unzip_buffer + unzipped_bytes);
} else {
break;
}
}
gzclose(in_file_gz)
but I would also like to be able to decompress the char array. I tried with the following method:
void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr, uLong *uncomprLen) {
int err;
z_stream d_stream; /* decompression stream */
d_stream.zalloc = NULL;
d_stream.zfree = NULL;
d_stream.opaque = NULL;
d_stream.next_in = compr;
d_stream.avail_in = 0;
d_stream.next_out = uncompr;
err = inflateInit2(&d_stream, MAX_WBITS + 16);
CHECK_ERR(err, "inflateInit");
while (d_stream.total_out < *uncomprLen && d_stream.total_in < comprLen) {
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
err = inflate(&d_stream, Z_NO_FLUSH);
if (err == Z_STREAM_END)
break;
CHECK_ERR(err, "inflate");
}
err = inflateEnd(&d_stream);
*uncomprLen = d_stream.total_out;
}
but in the while loop, the inflate method returns Z_STREAM_END before the file has decompressed in full.
The method returns successfully, but only a partial buffer has been written.
I put a minimum working example here:
https://github.com/alanjtaylor/zlibExample
if anyone has time to look.
Thanks a lot!
The example you have on github, "zippedFile.gz" is a concatenation of seven independent gzip members. This is permitted by the gzip standard (RFC 1952), and the zlib gz* file functions automatically process all of the members.
pigz will show all of the members:
% pigz -lvt zippedFile.gz
method check timestamp compressed original reduced name
gzip 8 e323586d ------ ----- 616431 1543643 60.1% zippedFile
gzip 8 7efd928a ------ ----- 369231 921600 59.9% <...>
gzip 8 7ebd8b2a ------ ----- 919565 2319970 60.4% <...>
gzip 8 3dd6e2ba ------ ----- 619670 1549236 60.0% <...>
gzip 8 c1cb922e ------ ----- 600367 1533151 60.8% <...>
gzip 8 a9fef06c ------ ----- 620250 1541785 59.8% <...>
gzip 8 43b57506 ------ ----- 623081 1555203 59.9% <...>
The inflate* functions will only process one member at a time, in order to let you know with Z_STREAM_END that the member decompressed successfully and that the CRC checked out ok.
All you need to do is put your inflator in a loop and run it until the input is exhausted, or you run into an error. (This is noted in the documentation for inflateInit2 in zlib.h.)
There are a few issues with your inflator, but I understand that it is just an initial attempt to get things working, so I won't comment.
uncompress is indeed designed for where you have all that information ready. It's a utility function.
It probably wraps inflate, which is what you want to use. You have to run it in a loop and manage the "stream" parameters yourself by repeatedly pointing to the next chunk of buffered data until it's all been eaten.
There's an annotated example in the documentation.
In my C program I would like to use libexif along with libjpeg to set exif tags on an existing jpeg file present at a given path inputFilePath, and save the resulting jpeg to output path outputFilePath.
The input jpeg file is large (40000 X 40000 pixels) so loading the whole image in memory isn't preferable and shouldn't be needed.
I don't care about other existing Exif tags in the Jpeg, they may be removed.
I have read and tried the example provided with libexif which uses a fixed JPEG, but just can't figure out how to do the same for any JPEG.
Btw, I did get the following code which sets exif tags by loading the jpeg in-memory to work. It uses the libjpeg implementation provided in exif utility that comes along with libexif.
ExifEntry *entry;
ExifData *exif = exif_data_new();
if (!exif) {
//Out of memory
}
/* Set the image options */
exif_data_set_option(exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
exif_data_set_data_type(exif, EXIF_DATA_TYPE_COMPRESSED);
exif_data_set_byte_order(exif, FILE_BYTE_ORDER);
/* Create the mandatory EXIF fields with default data */
exif_data_fix(exif);
/* All these tags are created with default values by exif_data_fix() */
/* Change the data to the correct values for this image. */
entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION);
exif_set_long(entry->data, FILE_BYTE_ORDER, w);
entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION);
exif_set_long(entry->data, FILE_BYTE_ORDER, h);
entry = init_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_COLOR_SPACE);
exif_set_short(entry->data, FILE_BYTE_ORDER, 1);
/* Create a EXIF_TAG_USER_COMMENT tag. This one must be handled
* differently because that tag isn't automatically created and
* allocated by exif_data_fix(), nor can it be created using
* exif_entry_initialize() so it must be explicitly allocated here.
*/
entry = create_tag(exif, EXIF_IFD_EXIF, EXIF_TAG_USER_COMMENT,
sizeof(ASCII_COMMENT) + sizeof(FILE_COMMENT) - 2);
/* Write the special header needed for a comment tag */
memcpy(entry->data, ASCII_COMMENT, sizeof(ASCII_COMMENT) - 1);
/* Write the actual comment text, without the trailing NUL character */
memcpy(entry->data + 8, FILE_COMMENT, sizeof(FILE_COMMENT) - 1);
/* create_tag() happens to set the format and components correctly for
* EXIF_TAG_USER_COMMENT, so there is nothing more to do. */
JPEGData *jdata;
unsigned char *d = NULL;
unsigned int ds;
ExifLog *log = NULL;
/* Parse the JPEG file. */
jdata = jpeg_data_new();
jpeg_data_log(jdata, log);
jpeg_data_load_file(jdata, inputFilePath);
/* Make sure the EXIF data is not too big. */
exif_data_save_data(exif, &d, &ds);
if (ds) {
free(d);
if (ds > 0xffff)
//Too much EXIF data
};
jpeg_data_set_exif_data(jdata, exif);
/* Save the modified image. */
jpeg_data_save_file(jdata, outputFilePath);
jpeg_data_unref(jdata);
If you aren't re-compressing or editing the image, then you won't need libjpeg. It can be done with fopen and fputc.
There's a good description of the JPEG file structure and metadata from exiv2. Most jpeg files will start with 0xFFD8 (start of image), then an APP0 block for JFIF data (0xFF E0 <length> <data>). If there is an EXIF header, it's in the APP1 block (0xFF E1 <length> <data>).
The blocks in a JPEG file are formatted as
Marker (0xFF xx) where xx is En for APPn blocks
Content
2 bytes - length of content in bytes including these 2 bytes
data
So, an outline of your program would be
Copy the file until the APP1 block
Write your APP1 block instead
Copy the rest of the file
The EXIF header contents can be created with exif_data_save_data() in libexif.
I am doing my assignment to read a .rgb video file and display it in the window. I have only known how to read and display an image in C++. What should I do when reading the video and display it frame by frame. I don't want to use third party libraries, just pure C++ and windows programming.
My idea is: firstly load the whole video file into the program using fopen and allocate the buffer for it. Then just like display an image, I wanna treat the whole video as an array of frames, so after rendering the first frame, I will go to the next frame. In addition, how to keep the video display at a constant fps? If you have any learning resources or coding pieces, it would be very helpful!
Thanks
Since you haven't mentioned platform you are using.
But this snippet will help you to read file frame by frame.
#include <stdio.h>
int main()
{
FILE * fp = NULL;
int size = 800 * 600 * 2;
unsigned char * rawData = NULL;
fp = fopen("raw.rgb", "r+b");
rawData = (unsigned char *)malloc(size);
if (NULL == rawData)
return -1;
if (fp)
{
while(!feof(fp))
{
fread(rawData, size, 1, fp);
// GOT FRAME
}
fclose(fp);
fp = NULL;
}
}
Doing this without using any third-party library will be a lot of lot of works!
You may use the OpenCV library to do the work. Check http://opencv.org/
I'm developing a linux-program, that is supposed to parse a file downloaded from another computer or the internet, and collect information from that file. The program also has to re-download the file by routine, every n days/hours/minutes/whatever, and parse it again to keep updated in case the file has changed.
However, the process of parsing the file could require a lot of resources. Thus, I would like a function to check if the file has changed since last time it was downloaded. I imagine something like this example:
int get_checksum(char *filename) {
// New prototype, if no such function already exists in standard C-libraries
int result; // Or char/float/whatever
// ...
return result;
}
int main(void) {
char filename[] = { "foo.dat" };
char file_url[] = { "http://example.com/foo.dat" }
int old_checksum; // Or char/float/whatever
int new_checksum; // Or char/float/whatever
// ...
// Now assume that old_checksum has a value from before:
dl_file(filename, file_url); // Some prototype for downloading the file
if ((new_checksum = get_checksum(filename)) == -1) {
// Badness
}
else {
if (new_checksum != old_checksum) {
old_checksum = new_checksum;
// Parse the file
}
else {
// Do nothing
}
}
// ...
}
Q1: Is there such a function as get_checksum (from the example above) available in standard C/C++ libraries?
Q2: If not: What is the best way to achieve this purpose?
There is no need for:
- a very advanced function
- encrypted or secured checksums
- the ability to compare a new file against files older than the last one, since the new downloaded file will always overwrite the older one
You can use the stat() function. It can give you access to the file parameters like last access time, time of last modification, file size etc:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
But you need to have execute permission on the file you would be using it on.
man page
There was nothing built in the C++ language until std::hash<> in C++11 which is very simple, but may be appropriate for your needs.
Last I checked there is nothing at all in Boost (the most common C++ library extension). The reasoning is talked about here, but may be dated:
http://www.gamedev.net/topic/528553-why-doesnt-boost-have-a-cryptographic-hash-library/
So, you're best bet is:
std::hash with the file contents.
Or something like the following could be of use saved into a simple header and linked:
http://www.zedwood.com/article/cpp-md5-function
Or you could get a library such as OpenSSL or Crypto++.
You could do an XOR hash, in which you just xor successive blocks of unsigned ints/longs, but this has problems with collisions. For example, if the file is mostly chars, then the majority of the bytes will be in the ranges of normal ASCII/Unicode chars, so there will be a lot of unused key space.
For a standard implementation, you could read the file into a string and use std::hash from C++11. http://en.cppreference.com/w/cpp/utility/hash
The following is an example of the first method:
unsigned int hash(vector<char> file){
unsigned int result;
int *arr = (int*)file.data();
for(int i = 0;i < file.size() / sizeof(unsigned int);i++)
result ^= arr[i];
return result;
}
You just have to read the file into the vector.
The two functions in openCV cvLoadImage and cvSaveImage accept file path's as arguments.
For example, when saving a image it's cvSaveImage("/tmp/output.jpg", dstIpl) and it writes on the disk.
Is there any way to feed this a buffer already in memory? So instead of a disk write, the output image will be in memory.
I would also like to know this for both cvSaveImage and cvLoadImage (read and write to memory buffers). Thanks!
My goal is to store the Encoded (jpeg) version of the file in Memory. Same goes to cvLoadImage, I want to load a jpeg that's in memory in to the IplImage format.
This worked for me
// decode jpg (or other image from a pointer)
// imageBuf contains the jpg image
cv::Mat imgbuf = cv::Mat(480, 640, CV_8U, imageBuf);
cv::Mat imgMat = cv::imdecode(imgbuf, CV_LOAD_IMAGE_COLOR);
// imgMat is the decoded image
// encode image into jpg
cv::vector<uchar> buf;
cv::imencode(".jpg", imgMat, buf, std::vector<int>() );
// encoded image is now in buf (a vector)
imageBuf = (unsigned char *) realloc(imageBuf, buf.size());
memcpy(imageBuf, &buf[0], buf.size());
// size of imageBuf is buf.size();
I was asked about a C version instead of C++:
#include <opencv/cv.h>
#include <opencv/highgui.h>
int
main(int argc, char **argv)
{
char *cvwin = "camimg";
cvNamedWindow(cvwin, CV_WINDOW_AUTOSIZE);
// setup code, initialization, etc ...
[ ... ]
while (1) {
// getImage was my routine for getting a jpeg from a camera
char *img = getImage(fp);
CvMat mat;
// substitute 640/480 with your image width, height
cvInitMatHeader(&mat, 640, 480, CV_8UC3, img, 0);
IplImage *cvImg = cvDecodeImage(&mat, CV_LOAD_IMAGE_COLOR);
cvShowImage(cvwin, cvImg);
cvReleaseImage(&cvImg);
if (27 == cvWaitKey(1)) // exit when user hits 'ESC' key
break;
}
cvDestroyWindow(cvwin);
}
There are a couple of undocumented functions in the SVN version of the libary:
CV_IMPL CvMat* cvEncodeImage( const char* ext,
const CvArr* arr, const int* _params )
CV_IMPL IplImage* cvDecodeImage( const CvMat* _buf, int iscolor )
Latest check in message states that they are for native encoding/decoding for bmp, png, ppm and tiff (encoding only).
Alternatively you could use a standard image encoding library (e.g. libjpeg) and manipulate the data in the IplImage to match the input structure of the encoding library.
I'm assuming you're working in linux. From libjpeg.doc:
The rough outline of a JPEG
compression operation is:
Allocate
and initialize a JPEG compression
object
Specify the destination for
the compressed data (eg, a file)
Set
parameters for compression, including
image size & colorspace
jpeg_start_compress(...);
while
(scan lines remain to be written)
jpeg_write_scanlines(...);
jpeg_finish_compress(...);
Release
the JPEG compression object
The real trick for doing what you want to do is providing a custom "data destination (or source) manager" which is defined in jpeglib.h:
struct jpeg_destination_mgr {
JOCTET * next_output_byte; /* => next byte to write in buffer */
size_t free_in_buffer; /* # of byte spaces remaining in buffer */
JMETHOD(void, init_destination, (j_compress_ptr cinfo));
JMETHOD(boolean, empty_output_buffer, (j_compress_ptr cinfo));
JMETHOD(void, term_destination, (j_compress_ptr cinfo));
};
Basically set that up so your source and/or destination are the memory buffers you want, and you should be good to go.
As an aside, this post could be a lot better but the libjpeg62 documentation is, quite frankly, superb. Just apt-get libjpeg62-dev and read libjpeg.doc and look at example.c. If you run into problems and can't get something to work, just post again and I'm sure someone will be able to help.
All you need to load files from the memory buffer is a different src manager (libjpeg). I have tested the following code in Ubuntu 8.10.
/******************************** First define mem buffer function bodies **************/
<pre>
/*
* memsrc.c
*
* Copyright (C) 1994-1996, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains decompression data source routines for the case of
* reading JPEG data from a memory buffer that is preloaded with the entire
* JPEG file. This would not seem especially useful at first sight, but
* a number of people have asked for it.
* This is really just a stripped-down version of jdatasrc.c. Comparison
* of this code with jdatasrc.c may be helpful in seeing how to make
* custom source managers for other purposes.
*/
/* this is not a core library module, so it doesn't define JPEG_INTERNALS */
//include "jinclude.h"
include "jpeglib.h"
include "jerror.h"
/* Expanded data source object for memory input */
typedef struct {
struct jpeg_source_mgr pub; /* public fields */
JOCTET eoi_buffer[2]; /* a place to put a dummy EOI */
} my_source_mgr;
typedef my_source_mgr * my_src_ptr;
/*
* Initialize source --- called by jpeg_read_header
* before any data is actually read.
*/
METHODDEF(void)
init_source (j_decompress_ptr cinfo)
{
/* No work, since jpeg_memory_src set up the buffer pointer and count.
* Indeed, if we want to read multiple JPEG images from one buffer,
* this *must* not do anything to the pointer.
*/
}
/*
* Fill the input buffer --- called whenever buffer is emptied.
*
* In this application, this routine should never be called; if it is called,
* the decompressor has overrun the end of the input buffer, implying we
* supplied an incomplete or corrupt JPEG datastream. A simple error exit
* might be the most appropriate response.
*
* But what we choose to do in this code is to supply dummy EOI markers
* in order to force the decompressor to finish processing and supply
* some sort of output image, no matter how corrupted.
*/
METHODDEF(boolean)
fill_input_buffer (j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
WARNMS(cinfo, JWRN_JPEG_EOF);
/* Create a fake EOI marker */
src->eoi_buffer[0] = (JOCTET) 0xFF;
src->eoi_buffer[1] = (JOCTET) JPEG_EOI;
src->pub.next_input_byte = src->eoi_buffer;
src->pub.bytes_in_buffer = 2;
return TRUE;
}
/*
* Skip data --- used to skip over a potentially large amount of
* uninteresting data (such as an APPn marker).
*
* If we overrun the end of the buffer, we let fill_input_buffer deal with
* it. An extremely large skip could cause some time-wasting here, but
* it really isn't supposed to happen ... and the decompressor will never
* skip more than 64K anyway.
*/
METHODDEF(void)
skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
if (num_bytes > 0) {
while (num_bytes > (long) src->pub.bytes_in_buffer) {
num_bytes -= (long) src->pub.bytes_in_buffer;
(void) fill_input_buffer(cinfo);
/* note we assume that fill_input_buffer will never return FALSE,
* so suspension need not be handled.
*/
}
src->pub.next_input_byte += (size_t) num_bytes;
src->pub.bytes_in_buffer -= (size_t) num_bytes;
}
}
/*
* An additional method that can be provided by data source modules is the
* resync_to_restart method for error recovery in the presence of RST markers.
* For the moment, this source module just uses the default resync method
* provided by the JPEG library. That method assumes that no backtracking
* is possible.
*/
/*
* Terminate source --- called by jpeg_finish_decompress
* after all data has been read. Often a no-op.
*
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
* application must deal with any cleanup that should happen even
* for error exit.
*/
METHODDEF(void)
term_source (j_decompress_ptr cinfo)
{
/* no work necessary here */
}
/*
* Prepare for input from a memory buffer.
*/
GLOBAL(void)
jpeg_memory_src (j_decompress_ptr cinfo, const JOCTET * buffer, size_t bufsize)
{
my_src_ptr src;
/* The source object is made permanent so that a series of JPEG images
* can be read from a single buffer by calling jpeg_memory_src
* only before the first one.
* This makes it unsafe to use this manager and a different source
* manager serially with the same JPEG object. Caveat programmer.
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_source_mgr));
}
src = (my_src_ptr) cinfo->src;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->pub.term_source = term_source;
src->pub.next_input_byte = buffer;
src->pub.bytes_in_buffer = bufsize;
}
Then the usage is pretty simple. You may need to replace SIZEOF() with sizeof(). Find a standard decompression example. Just replace "jpeg_stdio_src" with "jpeg_memory_src". Hope that helps!
Here's an example in Delphi. It converts a 24bit bitmap for use with OpenCV
function BmpToPIplImageEx(Bmp: TBitmap): pIplImage;
Var
i: Integer;
offset: LongInt;
dataByte: PByteArray;
Begin
Assert(Bmp.PixelFormat = pf24bit, 'PixelFormat must be 24bit');
Result := cvCreateImageHeader(cvSize(Bmp.Width, Bmp.Height), IPL_DEPTH_8U, 3);
cvCreateData(Result);
for i := 0 to Bmp.height - 1 do
Begin
offset := longint(Result.imageData) + Result.WidthStep * i;
dataByte := PByteArray(offset);
CopyMemory(dataByte, Bmp.Scanline[i], Result.WidthStep);
End;
End;
This is an indirect answer...
In the past, I've directly used libpng and libjpeg directly to do this. They have a low-level enough API that you can use memory buffers instead of file buffers for reading and writing.