We have following method implemented using ijl15.lib API.
We want to use libjpeg libraries instead of ijl. How should I implement WriteJPGBuffer using libjpeg libraries? We are aware of LoadJPG and SaveJPG from file. However i want to write and read the jpg image in buffer using libjpeg libraries. Any inputs will be very helpul. Thank you in advance.
unsigned char WriteJPGBuffer(unsigned int &size)
{
size = 0;
int jErr;
JPEG_CORE_PROPERTIES jpgProps;
bool colorsSwapped;
if (!jpgSupported)
return NULL;
jErr = ijlInit(&jpgProps);
if (jErr != IJL_OK)
return NULL;
jpgProps.DIBWidth = m_width;
jpgProps.DIBHeight = -m_height;
jpgProps.DIBBytes = (unsigned char *)m_pData;
jpgProps.DIBPadBytes = 0 ;
jpgProps.DIBChannels = 4;
jpgProps.DIBColor = IJL_RGB;
jpgProps.JPGFile = NULL;
jpgProps.JPGWidth = m_width;
jpgProps.JPGHeight = m_height;
jpgProps.JPGChannels = 3;
jpgProps.JPGColor = IJL_YCBCR;
jpgProps.JPGSubsampling = IJL_411;
jpgProps.jquality = jpgQuality;
unsigned int iSize = m_width*m_height*3;
unsigned char * pBuffer = new unsigned char[iSize];
jpgProps.JPGSizeBytes = iSize;
jpgProps.JPGBytes = pBuffer;
jpgProps.jprops.jpeg_comment_size = (unsigned short)m_strCommentAdobe.length;
jpgProps.jprops.jpeg_comment = (char*)m_strCommentAdobe;
colorsSwapped = SetInternalFormat(RGB);
jErr = ijlWrite(&jpgProps, IJL_JBUFF_WRITEWHOLEIMAGE);
if (colorsSwapped)
SetInternalFormat(BGR);
if (jErr != IJL_OK)
{
ijlFree(&jpgProps);
return NULL;
}
size = jpgProps.JPGSizeBytes;
ijlFree(&jpgProps);
return jpgProps.JPGBytes;
}
Thanks for your inputs. I have implemented the solution below through RND. In below implementation, we have image data stored in the class member variable in the form of RGBQUAD which i am converting into unsigned char* first using ConversionfromGLRGBQUADToUnsignedChar function and then writing it jpeg buffer.
void ConversionfromGLRGBQUADToUnsignedChar(unsigned char* dataInCharFromGLRGBQUAD)
{
int spot,spotDst;
for (int y = 0;y < m_height;y++)
{
for (int x = 0;x<m_width;x++)
{
spot = y * m_width + x;
spotDst = spot * 3;
dataInCharFromGLRGBQUAD[spotDst] = m_pData[spot].red;
dataInCharFromGLRGBQUAD[spotDst + 1] = m_pData[spot].green;
dataInCharFromGLRGBQUAD[spotDst + 2] = m_pData[spot].blue;
}
}
}
unsigned char * WriteJPGBuffer(unsigned int &size)
{
size = 0;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
JSAMPROW row_pointer[1];
unsigned char* dataInCharFromGLRGBQUAD;
bool colorsSwapped;
int row_stride;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
unsigned long sizeOfJPGBuffer = 0;
jpeg_mem_dest(&cinfo, &m_pDIBData, &sizeOfJPGBuffer);
cinfo.image_width = m_width;
cinfo.image_height = m_height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
cinfo.jpeg_color_space = JCS_YCbCr;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, jpgQuality, true);
jpeg_start_compress(&cinfo, true);
colorsSwapped = SetInternalFormat(RGB);
FlipVert();
dataInCharFromGLRGBQUAD = new unsigned char[m_width*m_height*3];
ConversionfromGLRGBQUADToUnsignedChar(dataInCharFromGLRGBQUAD);
row_stride = cinfo.image_width * cinfo.input_components;
while (cinfo.next_scanline < cinfo.image_height)
{
row_pointer[0] = &dataInCharFromGLRGBQUAD[cinfo.next_scanline * row_stride];
jpeg_write_scanlines(&cinfo, row_pointer, 1);
}
if (colorsSwapped)
SetInternalFormat(BGR);
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
size = sizeOfJPGBuffer;
delete[] dataInCharFromGLRGBQUAD;
return m_pDIBData;
}
Related
I compiled the libe57 in order to use it in my project. I did it and now I'm trying to use it. (I'm on windows 10 x64)
Basing on this tutorial, I did this
int
main(int argc, char** argv)
{
char sFile[] = "PTX/file.e57";
_bstr_t bsFile = sFile; //converts Unicode to UTF-8
e57::Reader eReader((char*)bsFile);
e57::E57Root rootHeader;
eReader.GetE57Root(rootHeader);
const char* fileGuid = rootHeader.guid.c_str();
e57::DateTime fileGPSTime = rootHeader.creationDateTime;
int data3DCount = eReader.GetData3DCount();
int scanIndex = 0;
e57::Data3D scanHeader;
eReader.ReadData3D(scanIndex, scanHeader);
_bstr_t bstrName = scanHeader.name.c_str();
_bstr_t bstrGuid = scanHeader.guid.c_str();
_bstr_t bstrDesc = scanHeader.description.c_str();
int64_t nColumn = 0;
int64_t nRow = 0;
int64_t nPointsSize = 0; //Number of points
int64_t nGroupsSize = 0; //Number of groups
int64_t nCountSize = 0; //Number of points per group
bool bColumnIndex = false; //indicates that idElementName is "columnIndex"
eReader.GetData3DSizes(scanIndex, nRow, nColumn, nPointsSize, nGroupsSize, nCountSize, bColumnIndex);
int64_t nSize = nRow;
if (nSize == 0) nSize = 1024; // choose a chunk size
int8_t * isInvalidData = NULL;
if (scanHeader.pointFields.cartesianInvalidStateField)
isInvalidData = new int8_t[nSize];
double * xData = NULL;
if (scanHeader.pointFields.cartesianXField)
xData = new double[nSize];
double * yData = NULL;
if (scanHeader.pointFields.cartesianYField)
yData = new double[nSize];
double * zData = NULL;
if (scanHeader.pointFields.cartesianZField)
zData = new double[nSize];
double * intData = NULL;
bool bIntensity = false;
double intRange = 0;
double intOffset = 0;
if (scanHeader.pointFields.intensityField)
{
bIntensity = true;
intData = new double[nSize];
intRange = scanHeader.intensityLimits.intensityMaximum - scanHeader.intensityLimits.intensityMinimum;
intOffset = scanHeader.intensityLimits.intensityMinimum;
}
uint16_t * redData = NULL;
uint16_t * greenData = NULL;
uint16_t * blueData = NULL;
bool bColor = false;
int32_t colorRedRange = 1;
int32_t colorRedOffset = 0;
int32_t colorGreenRange = 1;
int32_t colorGreenOffset = 0;
int32_t colorBlueRange = 1;
int32_t colorBlueOffset = 0;
if (scanHeader.pointFields.colorRedField)
{
bColor = true;
redData = new uint16_t[nSize];
greenData = new uint16_t[nSize];
blueData = new uint16_t[nSize];
colorRedRange = scanHeader.colorLimits.colorRedMaximum - scanHeader.colorLimits.colorRedMinimum;
colorRedOffset = scanHeader.colorLimits.colorRedMinimum;
colorGreenRange = scanHeader.colorLimits.colorGreenMaximum - scanHeader.colorLimits.colorGreenMinimum;
colorGreenOffset = scanHeader.colorLimits.colorGreenMinimum;
colorBlueRange = scanHeader.colorLimits.colorBlueMaximum - scanHeader.colorLimits.colorBlueMinimum;
colorBlueOffset = scanHeader.colorLimits.colorBlueMinimum;
}
int64_t * idElementValue = NULL;
int64_t * startPointIndex = NULL;
int64_t * pointCount = NULL;
if (nGroupsSize > 0)
{
idElementValue = new int64_t[nGroupsSize];
startPointIndex = new int64_t[nGroupsSize];
pointCount = new int64_t[nGroupsSize];
if (!eReader.ReadData3DGroupsData(scanIndex, nGroupsSize, idElementValue,
startPointIndex, pointCount))
nGroupsSize = 0;
}
int32_t * rowIndex = NULL;
int32_t * columnIndex = NULL;
if (scanHeader.pointFields.rowIndexField)
rowIndex = new int32_t[nSize];
if (scanHeader.pointFields.columnIndexField)
columnIndex = new int32_t[nRow];
e57::CompressedVectorReader dataReader = eReader.SetUpData3DPointsData(
scanIndex, //!< data block index given by the NewData3D
nRow, //!< size of each of the buffers given
xData, //!< pointer to a buffer with the x data
yData, //!< pointer to a buffer with the y data
zData, //!< pointer to a buffer with the z data
isInvalidData, //!< pointer to a buffer with the valid indication
intData, //!< pointer to a buffer with the lidar return intesity
NULL,
redData, //!< pointer to a buffer with the color red data
greenData, //!< pointer to a buffer with the color green data
blueData, //!< pointer to a buffer with the color blue data
NULL,
NULL,
NULL,
NULL,
NULL,
rowIndex, //!< pointer to a buffer with the rowIndex
columnIndex //!< pointer to a buffer with the columnIndex
);
int64_t count = 0;
unsigned size = 0;
int col = 0;
int row = 0;
int cpt = 0;
while (size = dataReader.read())
{
cpt++;
}
std::cout << cpt << std::endl;
dataReader.close();
if (isInvalidData) delete isInvalidData;
if (xData) delete xData;
if (yData) delete yData;
if (zData) delete zData;
if (intData) delete intData;
if (redData) delete redData;
if (greenData) delete greenData;
if (blueData) delete blueData;
}
The problem is that everytime, the reader says that there are 65536 rows and 1 cols, meaning that my pointcloud contain always 65536 points. I tried with several files that have more than 200k points each, but the result are always the same, it writes in my XYZ file 65536 points, and no more.
EDIT 2: shorter example : the problem is still the same
#include "E57Foundation.h"
#include "E57Simple.h"
#include "comutil.h"
#include <iostream>
#include <vector>
int
main(int argc, char** argv)
{
e57::Reader eReader("PTX/file.e57");
int scanIndex = 0; //picking the first scan
e57::Data3D scanHeader; //read scan's header information
eReader.ReadData3D(scanIndex, scanHeader);
_bstr_t scanGuid = scanHeader.guid.c_str(); //get guid
int64_t nColumn = 0; //Number of Columns in a structure scan (from "indexBounds" if structure data)
int64_t nRow = 0; //Number of Rows in a structure scan
int64_t nPointsSize = 0; //Number of points
int64_t nGroupsSize = 0; //Number of groups (from "groupingByLine" if present)
int64_t nCountsSize = 0; //Number of points per group
bool bColumnIndex = false;
eReader.GetData3DSizes(scanIndex, nRow, nColumn, nPointsSize, nGroupsSize, nCountsSize, bColumnIndex);
int64_t nSize = (nRow > 0) ? nRow : 1024; //Pick a size for buffers
double *xData = new double[nSize];
double *yData = new double[nSize];
double *zData = new double[nSize];
e57::CompressedVectorReader dataReader = eReader.SetUpData3DPointsData(
scanIndex, //!< scan data index
nSize, //!< size of each of the buffers given
xData, //!< pointer to a buffer with the x data
yData, //!< pointer to a buffer with the y data
zData); //!< pointer to a buffer with the z data
//still a size of 65536
dataReader.close();
delete xData;
delete yData;
delete zData;
}
I've been looking for some time for a quick and reliable way of creating grayscale videos with avconv library from frames that are captured/created with OpenCV, in a C++ application.
I know that OpenCV have it's internal way of creating videos, however, it has some encoding performance and options limitations.
So, in this way, I would like to know which are the options for accomplishing this task?
For accomplishing this task, one of the options that I've found, which complies with my needs is the following class:
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/mathematics.h>
}
class AVConvVideoMaker
{
AVCodec* codec;
AVCodecContext* context;
AVFrame* picture;
int imgWidth, imgHeight, imgBufferSize;
FILE* outputFile;
int outputBufferSize;
uint8_t* outputBuffer;
int pictureBufferSize;
uint8_t* pictureBuffer;
int outputSize;
public:
AVConvVideoMaker(std::string outputFilePath, int imgWidth, int imgHeight)
: codec(NULL)
, context(NULL)
, picture(NULL)
, imgWidth(imgWidth)
, imgHeight(imgHeight)
, imgBufferSize(imgWidth*imgHeight)
, outputFile(fopen(outputFilePath.c_str(), "wb"))
, outputBufferSize(100000)
, outputBuffer(new uint8_t[outputBufferSize])
, pictureBufferSize((imgBufferSize*3)/2)
, pictureBuffer(new uint8_t[pictureBufferSize])
, outputSize(0)
{
avcodec_register_all();
this->codec = avcodec_find_encoder(CODEC_ID_MPEG1VIDEO);
if (!this->codec)
{
throw std::runtime_error("Codec not found");
}
this->context = avcodec_alloc_context3(codec);
this->picture = avcodec_alloc_frame();
this->context->bit_rate = 400000;
this->context->width = this->imgWidth;
this->context->height = this->imgHeight;
this->context->time_base = (AVRational){1, 25};
this->context->gop_size = 10;
this->context->max_b_frames = 1;
this->context->pix_fmt = PIX_FMT_YUV420P;
if(avcodec_open2(this->context, this->codec, NULL) < 0)
{
throw std::runtime_error("Could not open codec");
}
if(!this->outputFile)
{
throw std::runtime_error("Could not open video output file");
}
this->picture->data[0] = this->pictureBuffer;
this->picture->data[1] = this->picture->data[0] + imgBufferSize;
this->picture->data[2] = this->picture->data[1] + imgBufferSize / 4;
this->picture->linesize[0] = this->imgWidth;
this->picture->linesize[1] = this->imgWidth / 2;
this->picture->linesize[2] = this->imgWidth / 2;
}
void insertFrame(cv::Mat1b& img)
{
fflush(stdout);
/* Y */
for(int y=0; y < this->context->height; y++)
{
for(int x=0; x < this->context->width; x++)
{
this->picture->data[0][y * picture->linesize[0] + x] = img.at<uchar>(y,x);
}
}
/* Cb and Cr */
for(int y=0; y < this->context->height/2; y++)
{
for(int x=0; x < this->context->width/2; x++)
{
this->picture->data[1][y * this->picture->linesize[1] + x] = 128;
this->picture->data[2][y * this->picture->linesize[2] + x] = 128;
}
}
this->outputSize = avcodec_encode_video(this->context, this->outputBuffer, this->outputBufferSize, this->picture);
fwrite(this->outputBuffer, 1, outputSize, this->outputFile);
}
~AVConvVideoMaker()
{
this->outputBuffer[0] = 0x00;
this->outputBuffer[1] = 0x00;
this->outputBuffer[2] = 0x01;
this->outputBuffer[3] = 0xb7;
fwrite(this->outputBuffer, 1, 4, this->outputFile);
fclose(this->outputFile);
avcodec_close(this->context);
av_free(this->context);
av_free(this->picture);
delete outputBuffer;
delete pictureBuffer;
}
};
For compiling this in Ubuntu 16.04, you have to link with:
g++ --std=c++11 main.cpp -lopencv_core -lopencv_highgui -lavutil -lavcodec
Hy ,so my project to migrate to Visual Studio 2015. However I got stuck when I saw that receive 13 errors.
Error C2872 'data': ambiguous symbol Error C2872 'size': ambiguous symbol
Before you migrate to vss2015 everything work perfectly, I can not understand why we have moved the program after receiving this error.
Here is my Jpeg.cpp
#include "StdAfx.h"
#include "JpegFile.h"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <libjpeg-6b/jpeglib.h>
#include <libjpeg-6b/jpegLibLink.h>
#define OUTBUFFER_SIZE 0x8000
static FILE*fi;
static JOCTET * buffer;
static unsigned char*dest;
static int len;
static int destlen;
static unsigned char*data;
static int pos;
static int size;
static void file_init_destination(j_compress_ptr cinfo)
{
struct jpeg_destination_mgr*dmgr =
(struct jpeg_destination_mgr*)(cinfo->dest);
buffer = (JOCTET*)malloc(OUTBUFFER_SIZE);
if(!buffer) {
perror("malloc");
printf("Out of memory!\n");
exit(1);
}
dmgr->next_output_byte = buffer;
dmgr->free_in_buffer = OUTBUFFER_SIZE;
}
static boolean file_empty_output_buffer(j_compress_ptr cinfo)
{
struct jpeg_destination_mgr*dmgr =
(struct jpeg_destination_mgr*)(cinfo->dest);
if(fi)
fwrite(buffer, OUTBUFFER_SIZE, 1, fi);
dmgr->next_output_byte = buffer;
dmgr->free_in_buffer = OUTBUFFER_SIZE;
return 1;
}
static void file_term_destination(j_compress_ptr cinfo)
{ struct jpeg_destination_mgr*dmgr =
(struct jpeg_destination_mgr*)(cinfo->dest);
if(fi)
fwrite(buffer, OUTBUFFER_SIZE-dmgr->free_in_buffer, 1, fi);
free(buffer);
buffer = 0;
dmgr->free_in_buffer = 0;
}
static void mem_init_destination(j_compress_ptr cinfo)
{
struct jpeg_destination_mgr*dmgr =
(struct jpeg_destination_mgr*)(cinfo->dest);
dmgr->next_output_byte = dest;
dmgr->free_in_buffer = destlen;
}
static boolean mem_empty_output_buffer(j_compress_ptr cinfo)
{
printf("jpeg mem overflow!\n");
exit(1);
}
static void mem_term_destination(j_compress_ptr cinfo)
{
struct jpeg_destination_mgr*dmgr =
(struct jpeg_destination_mgr*)(cinfo->dest);
len = destlen - dmgr->free_in_buffer;
dmgr->free_in_buffer = 0;
}
int jpeg_save(unsigned char*data, int width, int height, int quality, const char*filename)
{
struct jpeg_destination_mgr mgr;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
int t;
if(filename) {
fi = fopen(filename, "wb");
if(fi == NULL)
return 0;
} else
fi = NULL;
memset(&cinfo, 0, sizeof(cinfo));
memset(&jerr, 0, sizeof(jerr));
memset(&mgr, 0, sizeof(mgr));
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
mgr.init_destination = file_init_destination;
mgr.empty_output_buffer = file_empty_output_buffer;
mgr.term_destination = file_term_destination;
cinfo.dest = &mgr;
// init compression
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo,quality,TRUE);
//jpeg_write_tables(&cinfo);
//jpeg_suppress_tables(&cinfo, TRUE);
jpeg_start_compress(&cinfo, FALSE);
for(t=0;t<height;t++) {
unsigned char*data2 = &data[width*3*t];
jpeg_write_scanlines(&cinfo, &data2, 1);
}
jpeg_finish_compress(&cinfo);
if(fi)
fclose(fi);
jpeg_destroy_compress(&cinfo);
return 1;
}
int jpeg_save_to_file(unsigned char*data, int width, int height, int quality, FILE*_fi)
{
struct jpeg_destination_mgr mgr;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
int t;
fi = _fi;
memset(&cinfo, 0, sizeof(cinfo));
memset(&jerr, 0, sizeof(jerr));
memset(&mgr, 0, sizeof(mgr));
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
mgr.init_destination = file_init_destination;
mgr.empty_output_buffer = file_empty_output_buffer;
mgr.term_destination = file_term_destination;
cinfo.dest = &mgr;
// init compression
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
cinfo.dct_method = JDCT_IFAST;
jpeg_set_quality(&cinfo,quality,TRUE);
//jpeg_write_tables(&cinfo);
//jpeg_suppress_tables(&cinfo, TRUE);
jpeg_start_compress(&cinfo, FALSE);
for(t=0;t<height;t++) {
unsigned char*data2 = &data[width*3*t];
jpeg_write_scanlines(&cinfo, &data2, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
return 1;
}
int jpeg_save_to_mem(unsigned char*data, int width, int height, int quality, unsigned char*_dest, int _destlen)
{
struct jpeg_destination_mgr mgr;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
int t;
memset(&cinfo, 0, sizeof(cinfo));
memset(&jerr, 0, sizeof(jerr));
memset(&mgr, 0, sizeof(mgr));
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
dest = _dest;
len = 0;
destlen = _destlen;
mgr.init_destination = mem_init_destination;
mgr.empty_output_buffer = mem_empty_output_buffer;
mgr.term_destination = mem_term_destination;
cinfo.dest = &mgr;
// init compression
cinfo.image_width = width;
cinfo.image_height = height;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
cinfo.dct_method = JDCT_IFAST;
jpeg_set_quality(&cinfo,quality,TRUE);
jpeg_start_compress(&cinfo, FALSE);
for(t=0;t<height;t++) {
unsigned char*data2 = &data[width*3*t];
jpeg_write_scanlines(&cinfo, &data2, 1);
}
jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
return len;
}
void mem_init_source (j_decompress_ptr cinfo)
{
struct jpeg_source_mgr* mgr = cinfo->src;
mgr->next_input_byte = data;
mgr->bytes_in_buffer = size;
//printf("init %d\n", size - mgr->bytes_in_buffer);
}
boolean mem_fill_input_buffer (j_decompress_ptr cinfo)
{
struct jpeg_source_mgr* mgr = cinfo->src;
printf("fill %d\n", size - mgr->bytes_in_buffer);
return 0;
}
void mem_skip_input_data (j_decompress_ptr cinfo, long num_bytes)
{
struct jpeg_source_mgr* mgr = cinfo->src;
printf("skip %d +%d\n", size - mgr->bytes_in_buffer, num_bytes);
if(num_bytes<=0)
return;
mgr->next_input_byte += num_bytes;
mgr->bytes_in_buffer -= num_bytes;
}
boolean mem_resync_to_restart (j_decompress_ptr cinfo, int desired)
{
struct jpeg_source_mgr* mgr = cinfo->src;
printf("resync %d\n", size - mgr->bytes_in_buffer);
mgr->next_input_byte = data;
mgr->bytes_in_buffer = size;
return 1;
}
void mem_term_source (j_decompress_ptr cinfo)
{
struct jpeg_source_mgr* mgr = cinfo->src;
//printf("term %d\n", size - mgr->bytes_in_buffer);
}
int jpeg_load_from_mem(unsigned char*_data, int _size, unsigned char*dest, int width, int height)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
struct jpeg_source_mgr mgr;
int y;
//int x;
data = _data;
size = _size;
jpeg_create_decompress(&cinfo);
mgr.next_input_byte = data;
mgr.bytes_in_buffer = size;
mgr.init_source =mem_init_source ;
mgr.fill_input_buffer =mem_fill_input_buffer ;
mgr.skip_input_data =mem_skip_input_data ;
mgr.resync_to_restart =mem_resync_to_restart ;
mgr.term_source =mem_term_source ;
cinfo.err = jpeg_std_error(&jerr);
cinfo.src = &mgr;
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
for(y=0;y<height;y++) {
unsigned char*j = &dest[width*y*3];
jpeg_read_scanlines(&cinfo,&j,1);
}
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
return 1;
}
typedef struct _RGBA {
unsigned char a,r,g,b;
} RGBA;
typedef unsigned char U8;
int jpeg_load(const char*filename, unsigned char**dest, int*_width, int*_height)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
//struct jpeg_source_mgr mgr;
FILE*fi = fopen(filename, "rb");
if(!fi) {
fprintf(stderr, "Couldn't open file %s\n", filename);
return 0;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
jpeg_stdio_src(&cinfo, fi);
jpeg_read_header(&cinfo, TRUE);
jpeg_start_decompress(&cinfo);
U8*scanline = (U8 *)malloc(4 * cinfo.output_width);
int width = *_width = cinfo.output_width;
int height = *_height = cinfo.output_height;
*dest = (unsigned char*)malloc(width*height*4);
int y;
for (y=0;y<height;y++) {
int x;
U8 *js = scanline;
RGBA*line = &((RGBA*)(*dest))[y*width];
jpeg_read_scanlines(&cinfo, &js, 1);
if (cinfo.out_color_space == JCS_GRAYSCALE) {
for (x = 0; x < width; x++) {
line[x].a = 255;
line[x].r = line[x].g = line[x].b = js[x];
}
} else if (cinfo.out_color_space == JCS_RGB) {
for (x = width - 1; x >= 0; x--) {
line[x].a = 255;
line[x].r = js[x*3+0];
line[x].g = js[x*3+1];
line[x].b = js[x*3+2];
}
} else if (cinfo.out_color_space == JCS_YCCK) {
fprintf(stderr, "Error: Can't convert YCCK to RGB.\n");
return 0;
} else if (cinfo.out_color_space == JCS_YCbCr) {
for (x = 0; x < width; x++) {
int y = js[x * 3 + 0];
int u = js[x * 3 + 1];
int v = js[x * 3 + 1];
line[x].a = 255;
line[x].r = y + ((360 * (v - 128)) >> 8);
line[x].g = y - ((88 * (u - 128) + 183 * (v - 128)) >> 8);
line[x].b = y + ((455 * (u - 128)) >> 8);
}
} else if (cinfo.out_color_space == JCS_CMYK) {
for (x = 0; x < width; x++) {
int white = 255 - js[x * 4 + 3];
line[x].a = 255;
line[x].r = white - ((js[x * 4] * white) >> 8);
line[x].g = white - ((js[x * 4 + 1] * white) >> 8);
line[x].b = white - ((js[x * 4 + 2] * white) >> 8);
}
}
}
free(scanline);
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
fclose(fi);
return 1;
}
And here is Jpeg.h
#include <stdio.h>
int jpeg_save(unsigned char*data, int width, int height, int quality, const char*filename);
int jpeg_save_to_file(unsigned char*data, int width, int height, int quality, FILE*fi);
int jpeg_save_to_mem(unsigned char*data, int width, int height, int quality, unsigned char*dest, int destsize);
int jpeg_load(const char*filename, unsigned char**dest, int*width, int*height);
int jpeg_load_from_mem(unsigned char*_data, int size, unsigned char*dest, int width, int height);
I get the error for "data" and also for "size" symbol.
Best regards.
Why in visual studio 2013 i dont have that this error? And how to solve..
I get ambiguous symbol 10 times, in 10 sintax in jpeg.cpp
Im having a weird issue while initializing FMOD, FMOD enters in some kind of 'infinite loop' and the program stops. What i'm doing wrong?
This is the function:
FMOD::System *fmodsyst = 0;
FMOD::Sound *sound = 0;
FMOD::Channel *channel = 0;
FMOD_RESULT result = FMOD_OK;
unsigned int version = 0;
unsigned int soundlength = 0;
bool dspenabled = false;
void *extradriverdata = 0;
unsigned int recordpos = 0;
unsigned int recorddelta = 0;
unsigned int minrecorddelta = (unsigned int)-1;
unsigned int lastrecordpos = 0;
unsigned int samplesrecorded = 0;
unsigned int playpos = 0;
float smootheddelta = 0;
int recordrate = 0;
int recordchannels = 0;
unsigned int adjustedlatency = 0;
unsigned int driftthreshold = 0;
FMOD_CREATESOUNDEXINFO exinfo;
bool Basics::InitializeFMOD()
{
FMOD_RESULT result;
unsigned int version;
result = FMOD::System_Create(&fmodsyst);
FMOD_ERRCHECK(result);
result = fmodsyst->getVersion(&version);
FMOD_ERRCHECK(result);
if (version < FMOD_VERSION)
{
return false;
}
result = fmodsyst->init(100, FMOD_INIT_NORMAL, extradriverdata); //this is the line which crashes the .dll
FMOD_ERRCHECK(result);
result = fmodsyst->getRecordDriverInfo(0, NULL, NULL, 0, 0, &recordrate, 0, &recordchannels);
FMOD_ERRCHECK(result);
adjustedlatency = (recordrate * LATENCY_MS) / 1000;
driftthreshold = adjustedlatency / 2;
memset(&exinfo, 0, sizeof(FMOD_CREATESOUNDEXINFO));
exinfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
exinfo.numchannels = recordchannels;
exinfo.format = FMOD_SOUND_FORMAT_PCM16;
exinfo.defaultfrequency = recordrate;
exinfo.length = exinfo.defaultfrequency * sizeof(short)* exinfo.numchannels * 5; /* 5 second buffer, doesnt really matter how big this is, but not too small of course. */
result = fmodsyst->createSound(0, FMOD_LOOP_NORMAL | FMOD_OPENUSER, &exinfo, &sound);
FMOD_ERRCHECK(result);
result = fmodsyst->recordStart(0, sound, true);
FMOD_ERRCHECK(result);
result = sound->getLength(&soundlength, FMOD_TIMEUNIT_PCM);
FMOD_ERRCHECK(result);
return true;
}
Also the function FMOD_ERRCHECK doesnt say anything.
It might be that you want FMOD_STUDIO_INIT_NORMAL instead of FMOD_INIT_NORMAL because you are, in fact, initializing the Studio component and not the low level audio system (at least not via that pointer).
We may have different versions, as mine requires an extra parameter:
_pAudioSystem->initialize(32, FMOD_STUDIO_INIT_NORMAL, FMOD_INIT_NORMAL, nullptr);
I'm developing a project where I need to convert PCM 16-bits 2 channels sound into a IEEE Float 32-bits 2 channels.
To do this I'm using the following code:
void CAudioConverter::ConvI16ToF32(BYTE* pcmFrom, BYTE* floatTo, int length)
{
short* src = reinterpret_cast<short*>(pcmFrom);
float* dst = reinterpret_cast<float*>(floatTo);
for (int n = 0; n < length; n++)
{
dst[n] = static_cast<float>(src[n]) / 32768.0f;
}
}
I have initialized the variable __pcm32_bytesPerFrame with:
WAVEFORMATEX* closestFormat;
ws->default_pb_dev->GetMixFormat(&closestFormat);
__pcm32_bytesPerFrame = closestFormat->nAvgBytesPerSec * (prm->samples_per_frame * 1000 / (prm->clock_rate * closestFormat->nChannels)) / 1000;
strm->pb_max_frame_count is:
hr = ws->default_pb_dev->GetBufferSize(&ws->pb_max_frame_count);
I have a while loop in a dedicated thread the does something like:
hr = strm->default_pb_dev->GetCurrentPadding(&padding);
incoming_frame = __pcm32_bytesPerFrame / 4;
frame_to_render = strm->pb_max_frame_count - padding;
if (frame_to_render >= incoming_frame)
{
frame_to_render = incoming_frame;
} else {
/* Don't get new frame because there's no space */
frame_to_render = 0;
}
if (frame_to_render > 0)
{
pjmedia_frame frame;
hr = strm->pb_client->GetBuffer(frame_to_render, &cur_pb_buf);
if (FAILED(hr)) {
continue;
}
void* destBuffer = (void*)malloc(strm->bytes_per_frame*frame_to_render*sizeof(pj_uint16_t));
if (strm->fmt_id == PJMEDIA_FORMAT_L16) {
/* PCM mode */
frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
frame.size = strm->bytes_per_frame;
frame.timestamp.u64 = strm->pb_timestamp.u64;
frame.bit_info = 0;
frame.buf = destBuffer;
}
status = (*strm->pb_cb)(strm->user_data, &frame);
CAudioConverter* conv = new CAudioConverter();
conv->ConvI16ToF32((BYTE*)destBuffer, cur_pb_buf, frame_to_render);
hr = strm->pb_client->ReleaseBuffer(frame_to_render, 0);
(...)
But, to send the sound to the WASAPI capture buffer I need a BYTE*.
How can I fill my 'floatTo' argument?
Any ideas?
Thanks
What about this:
void CAudioConverter::ConvI16ToF32(BYTE* pcmFrom, BYTE* floatTo, int length)
{
short* src = reinterpret_cast<short*>(pcmFrom);
float* dst = reinterpret_cast<float*>(floatTo);
for (int n = 0; n < length; n++)
{
dst[n] = static_cast<float>(src[n]) / 32768.0f;
}
}
Additionally make sure length indicates the number of elments in pcmFrom and floatTo, and not the number of bytes allocated. In you case pcmFrom should have allocated length*2 bytes and floatTo needs room for length*4 bytes.