I'm making a BMP to PNG Converter.
The BMP Images are uncompressed.
So my question is when the BMP File is converted to a PNG File, then is the PNG File compressed i.e is the image data compressed. If so how is the image data aligned in the PNG File Format?
If the PNG Image Data is uncompressed then how is the BMP Image Data Aligned in PNG File.
#include<stdio.h>
#include<stdlib.h>
#pragma pack(1)
typedef struct
{
unsigned short int st_m40_FileType;
unsigned int st_m40_ImgFileSize;
unsigned short int st_m40_RsvdBytes1;
unsigned short int st_m40_RsvdBytes2;
unsigned int st_m40_ImgDataOffset;
unsigned int st_m40_Info40HeaderSze;
int st_m40_PxWdth;
int st_m40_PxHeight;
unsigned short int st_m40_NumOfColrPlnes;
unsigned short int st_m40_BitsPerPixel;
unsigned int st_m40_CmprsnType;
unsigned int st_m40_AftrCmprsnImgDataSze;
int st_m40_xResolutn_ppm;
int st_m40_yResolutn_ppm;
unsigned int st_m40_NumOfColrTbleColrs;
unsigned int st_m40_NumOfImprtntColrs;
}ST_BMP40HEADER_t;
typedef struct
{
ST_BMP40HEADER_t st_mBMP40MainHdrVar;
unsigned char * pst_mImgeData;
}ST_IMAGE_40_HEADER_t;
typedef enum
{
BI_RGB = 0x00,
BI_RLE8,
BI_RLE4,
BI_BITFIELDS,
BI_JPEG,
BI_PNG,
BI_ALPHABITFIELDS,
BI_CMYK,
BI_CMYKRLE8,
BI_CMYKRLE4,
}EN_BMP_COMPRESN_TYPE_t;
#pragma pack(1)
typedef struct
{
int st_mImgWdth;
int st_ImgHeight;
unsigned char st_mBitDepth;
unsigned char st_mColorType;
unsigned char st_mCmprsnMthd;
unsigned char st_mFltrMthd;
unsigned char st_mInterlaceMthd;
}ST_IHDR_DATA_FIELDS_t;
#pragma pack(1)
typedef struct
{
unsigned int st_mChunkDataLngth;
unsigned char st_mChunkType[4];
ST_IHDR_DATA_FIELDS_t st_IHDR_DataFieldsVar;
unsigned int st_mCRC32CheckSum;
}ST_IHDR_t;
#pragma pack(1)
typedef struct
{
unsigned int st_mPLTE_ChunkDataLngth;
unsigned char st_mPLTE_ChunkType[4];
unsigned char* st_mPLTE_ChunkDataPtr;
unsigned int st_mPLTE_CRC32CheckSum;
}ST_PLTE_t;
#pragma pack(1)
typedef struct
{
unsigned int st_mIDAT_ChunkDataLngth;
unsigned char st_mIDAT_ChunkType[4];
unsigned char* st_mIDAT_ChunkDataPtr;
unsigned int st_mIDAT_CRC32CheckSum;
}ST_IDAT_t;
#pragma pack(1)
typedef struct
{
unsigned int st_mIEND_ChunkDataLength;
unsigned char st_mIEND_ChunkType[4];
unsigned char * st_mIEND_ChunkDataPtr;
unsigned int st_mIEND_CRC32CheckSum;
}ST_IEND_t;
/* Little Endian to Big-Endian API. */
unsigned int BMP2PNG_LitToBigEndian(unsigned int f_BigEndianVal)
{
return (((f_BigEndianVal>>24) & 0x000000ff) | ((f_BigEndianVal>>8) & 0x0000ff00) |\
((f_BigEndianVal<<8) & 0x00ff0000) | ((f_BigEndianVal<<24) & 0xff000000));
}
/* CRC32 API.*/
unsigned int BMP2PNG_CmputeCRC32(unsigned char *p_fIpVal, unsigned int f_IpSize)
{
int l_LoopVar;
unsigned int l_ByteVal, l_CRCVal, l_MaskVal;
unsigned int l_TmpIncVar = 0;
l_CRCVal = 0xFFFFFFFF;
while (l_TmpIncVar <= f_IpSize)
{
// Get next byte.
l_ByteVal = p_fIpVal[l_TmpIncVar];
l_CRCVal = l_CRCVal ^ l_ByteVal;
for (l_LoopVar = 7; l_LoopVar >= 0; l_LoopVar--)
{
// Do eight times.
l_MaskVal = -(l_CRCVal & 1);
l_CRCVal = (l_CRCVal >> 1) ^ (0xEDB88320 & l_MaskVal);
}
l_TmpIncVar = l_TmpIncVar + 1;
}
return ~l_CRCVal;
}
/* API converts BMP-to-PNG format. */
char * Convert__40_BMP2PNG(ST_IMAGE_40_HEADER_t * pst_fBMP40ImgHdrVar, FILE * p_ImgFilePtr,\
unsigned char * p_fBMP_ColrTble)
{
FILE * l_BMP2PNGFilePtr;
ST_IHDR_t * pst_lIHDRChunkVar;
unsigned char l_PNGSignature[8]={137, 80, 78, 71, 13, 10, 26, 10};
unsigned int l_BigEndianVal;
unsigned int l_CRC32Val;
unsigned char * l_TempCRCBuff;
unsigned char * l_CRCBuffer;
unsigned int l_BuffLength = 0;
unsigned int l_TempIHDRChunkDataLngth;
pst_lIHDRChunkVar = (ST_IHDR_t *) malloc(sizeof(*pst_lIHDRChunkVar));
l_BMP2PNGFilePtr = fopen("BMP2PNG2.png","w");
/* Writing the 1st 8-bytes to the PNG File.*/
fwrite(l_PNGSignature,1,8,l_BMP2PNGFilePtr);
fseek(l_BMP2PNGFilePtr,8,SEEK_SET);
pst_lIHDRChunkVar->st_mChunkDataLngth = 13;
l_TempIHDRChunkDataLngth = BMP2PNG_LitToBigEndian(13);
/*Writing the IHDR Chunk Data-Length-Size value to the file.*/
fwrite(&l_TempIHDRChunkDataLngth,sizeof(unsigned int),1,l_BMP2PNGFilePtr);
pst_lIHDRChunkVar->st_mChunkType[0] = 'I';
pst_lIHDRChunkVar->st_mChunkType[1] = 'H';
pst_lIHDRChunkVar->st_mChunkType[2] = 'D';
pst_lIHDRChunkVar->st_mChunkType[3] = 'R';
/* Writing the IHDR-Chunk-Type value to the file.*/
fwrite( pst_lIHDRChunkVar->st_mChunkType ,sizeof(unsigned char),4,l_BMP2PNGFilePtr);
// pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth = BMP2PNG_LitToBigEndian(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth);
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth = BMP2PNG_LitToBigEndian(3);
// pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight = BMP2PNG_LitToBigEndian(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight);
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight = BMP2PNG_LitToBigEndian(3);
if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel <= 8)
{
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mBitDepth = pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel;
}
else if( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 24) || \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 32) )
{
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mBitDepth = 8;
}
else
{
/*No Action.*/
}
if( pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel <=8 )
{
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mColorType = 3;
}
else if (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 24)
{
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mColorType = 2;
}
else if (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 32)
{
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mColorType = 6;
}
else
{
/*No Action.*/
}
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mCmprsnMthd = 0;
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mFltrMthd = 0;
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mInterlaceMthd = 0;
fseek(l_BMP2PNGFilePtr,16,SEEK_SET);
fwrite(&pst_lIHDRChunkVar->st_IHDR_DataFieldsVar,sizeof(ST_IHDR_DATA_FIELDS_t),1,l_BMP2PNGFilePtr);
{
/* Framing the data for calculating the 32-bit CRC Checksum.*/
l_BuffLength = 4+(pst_lIHDRChunkVar->st_mChunkDataLngth);
l_CRCBuffer = (unsigned char*)malloc(l_BuffLength);
l_TempCRCBuff = l_CRCBuffer;
*l_TempCRCBuff++ = pst_lIHDRChunkVar->st_mChunkType[0];
*l_TempCRCBuff++ = pst_lIHDRChunkVar->st_mChunkType[1];
*l_TempCRCBuff++ = pst_lIHDRChunkVar->st_mChunkType[2];
*l_TempCRCBuff++ = pst_lIHDRChunkVar->st_mChunkType[3];
*l_TempCRCBuff++ = (unsigned char)pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth;
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth << 8);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth << 16);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth << 24);
*l_TempCRCBuff++ = (unsigned char)pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight;
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight << 8);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight << 16);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight << 24);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mBitDepth);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mColorType);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mCmprsnMthd);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mFltrMthd);
*l_TempCRCBuff = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mInterlaceMthd);
// Compute and output CRC
l_CRC32Val = BMP2PNG_CmputeCRC32(l_CRCBuffer, l_BuffLength);
l_CRC32Val = BMP2PNG_LitToBigEndian( l_CRC32Val);
fseek(l_BMP2PNGFilePtr,29,SEEK_SET);
unsigned int returnVal = fwrite(&l_CRC32Val,sizeof(unsigned int),1,l_BMP2PNGFilePtr);
}
unsigned char * p_lBMPImgData = pst_fBMP40ImgHdrVar->pst_mImgeData;
// unsigned int l_BMPImgeDataSze = ( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth) * \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight) );
unsigned int l_BMPImgeDataSze = (3*3)*3;
ST_IDAT_t * pst_lIDAT_ChunkVar;
pst_lIDAT_ChunkVar = (ST_IDAT_t *) malloc(sizeof(*pst_lIDAT_ChunkVar));
unsigned int l_ImgDataSzeIncVar = 0;
unsigned char * p_IDATBuf;
unsigned char * p_TempIDATBuf;
unsigned int l_IDATBufSze;
if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 24)
{
fseek(l_BMP2PNGFilePtr,33,SEEK_SET);
l_BMPImgeDataSze *= 3;
l_IDATBufSze = 4 + l_BMPImgeDataSze;
p_IDATBuf = (unsigned char*)malloc(l_IDATBufSze);
p_TempIDATBuf = p_IDATBuf;
pst_lIDAT_ChunkVar->st_mIDAT_ChunkDataLngth = BMP2PNG_LitToBigEndian(l_BMPImgeDataSze);
fwrite(&pst_lIDAT_ChunkVar->st_mIDAT_ChunkDataLngth,sizeof(unsigned int),1,l_BMP2PNGFilePtr);
pst_lIDAT_ChunkVar->st_mIDAT_ChunkType[0] = 'I';
pst_lIDAT_ChunkVar->st_mIDAT_ChunkType[1] = 'D';
pst_lIDAT_ChunkVar->st_mIDAT_ChunkType[2] = 'A';
pst_lIDAT_ChunkVar->st_mIDAT_ChunkType[3] = 'T';
fwrite( pst_lIDAT_ChunkVar->st_mIDAT_ChunkType ,sizeof(unsigned char),4,l_BMP2PNGFilePtr);
fseek(l_BMP2PNGFilePtr,41,SEEK_SET);
unsigned char ImgeData[27] = { 0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,};
while(l_ImgDataSzeIncVar <= l_BMPImgeDataSze )
{
fwrite(ImgeData,sizeof(unsigned char),1,l_BMP2PNGFilePtr);
/*
fwrite( (p_lBMPImgData+2),sizeof(unsigned char),1,l_BMP2PNGFilePtr);
*p_TempIDATBuf++ = *(p_lBMPImgData+2);
fwrite( (p_lBMPImgData+1),sizeof(unsigned char),1,l_BMP2PNGFilePtr);
*p_TempIDATBuf++ = *(p_lBMPImgData+1);
fwrite( (p_lBMPImgData),sizeof(unsigned char),1,l_BMP2PNGFilePtr);
*p_TempIDATBuf++ = *(p_lBMPImgData);
p_lBMPImgData += 3;
l_ImgDataSzeIncVar += 3;
*/
}
// Compute and output CRC
unsigned int crc32 = BMP2PNG_CmputeCRC32(p_IDATBuf, l_IDATBufSze);
fwrite(&crc32,sizeof(unsigned int),1,l_BMP2PNGFilePtr);
}
}
ST_IMAGE_40_HEADER_t * ReadBMP40HdrImage(ST_IMAGE_40_HEADER_t * pst_fBMP40ImgHdrVar, \
FILE * p_ImgFilePtr)
{
unsigned short int l_ColorTbleSze;
unsigned char * l_ColorTbleVal;
unsigned int l_ImageDataOffset;
unsigned int l_ImageDataSize;
unsigned int l_ImageDataSzeIncVar = 1;
unsigned char * l_ImageDataPtr;
unsigned int l_PixelCount = 1;
int l_NumOfReadBlks = fread(pst_fBMP40ImgHdrVar,sizeof(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar),1,p_ImgFilePtr);
printf("\n********************************************************************\n");
printf("\nPrinting the BMP Image Parameters:\n");
printf("\nBMP File Header Parameters.\n");
printf("File Type:\t'BM'\n");
printf("Total Size of the image:\t%u\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_ImgFileSize);
printf("Image Data Offset:\t%u\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_ImgDataOffset);
printf("\nBMP Info Header Parameters.\n");
printf("Size of the Info-Header:\t'%u-Bytes'.\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_Info40HeaderSze);
printf("Width of the BMP Image:\t'%d-Pixels'.\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth);
printf("Height of the BMP Image:\t'%d-Pixels'.\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight);
printf("Number of Color Planes:\t'%d'.\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_NumOfColrPlnes);
printf("Number of Bits-Per-Pixel:\t'%d'.\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel);
printf("Compression Type used for compressing the BMP Raw Image:\t'%d'.\n",\
pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_CmprsnType);
printf("Horizontal Resolution:\t'%d-Pixels Per Meter'.\n,",\
pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_xResolutn_ppm);
printf("Vertical Resolution:\t'%d-Pixels Per Meter'.\n,",\
pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_yResolutn_ppm);
if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_NumOfColrTbleColrs !=0 )
{
printf("Number of Colors in the color table:\t'%u'.\n",\
pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_NumOfColrTbleColrs);
}
if( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel <= 8) && \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_NumOfColrTbleColrs !=0) )
{
rewind(p_ImgFilePtr);
fseek(p_ImgFilePtr,55,SEEK_SET);
l_ColorTbleSze = (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_NumOfColrTbleColrs) * 4 ;
l_ColorTbleVal = (unsigned char*) malloc( l_ColorTbleSze );
l_NumOfReadBlks = fread(l_ColorTbleVal, l_ColorTbleSze, 1, p_ImgFilePtr);
if(l_NumOfReadBlks <1)
{
printf("Couldn't read the Color-Table values from the BMP File.\n");
return NULL;
}
else if(l_NumOfReadBlks == 1)
{
unsigned short int l_ClrTbleIncVar = 0;
unsigned char * l_TempColorTbleVal = l_ColorTbleVal;
unsigned short int l_IndexVal = 0;
printf("\n*****************************************************************************\n");
printf("Printing the color Table.\n");
while (l_ClrTbleIncVar <= (l_ColorTbleSze-4) )
{
printf("Index '%d' : ", l_IndexVal);
printf("Blue -> '%d'\t",*l_TempColorTbleVal);
l_TempColorTbleVal++;
printf("Green -> '%d'\t",*l_TempColorTbleVal);
l_TempColorTbleVal++;
printf("Red -> '%d'\t\n",*l_TempColorTbleVal);
l_TempColorTbleVal+=2;
l_ClrTbleIncVar += 4;
l_IndexVal++;
}
}
}
rewind(p_ImgFilePtr);
l_ImageDataOffset = pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_ImgDataOffset;
fseek(p_ImgFilePtr,l_ImageDataOffset,SEEK_SET);
if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 4)
{
l_ImageDataSize = ( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth) * \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight) )/2;
pst_fBMP40ImgHdrVar->pst_mImgeData = (unsigned char*)malloc(l_ImageDataSize);
l_ImageDataPtr = pst_fBMP40ImgHdrVar->pst_mImgeData;
l_NumOfReadBlks = fread(l_ImageDataPtr,1,l_ImageDataSize,p_ImgFilePtr);
if(l_NumOfReadBlks < 1)
{
printf("Couldn't read the image data from the file.\n");
return NULL;
}
}
else if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 8)
{
l_ImageDataSize = ( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth) * \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight) );
pst_fBMP40ImgHdrVar->pst_mImgeData = (unsigned char*)malloc(l_ImageDataSize);
l_ImageDataPtr = pst_fBMP40ImgHdrVar->pst_mImgeData;
l_NumOfReadBlks = fread(l_ImageDataPtr,l_ImageDataSize,1,p_ImgFilePtr);
if(l_NumOfReadBlks < 1)
{
printf("Couldn't read the image data from the file.\n");
return NULL;
}
}
else if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 24)
{
l_ImageDataSize = ( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth) * \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight) * 3 );
pst_fBMP40ImgHdrVar->pst_mImgeData = (unsigned char*)malloc(l_ImageDataSize);
l_ImageDataPtr = pst_fBMP40ImgHdrVar->pst_mImgeData;
l_NumOfReadBlks = fread(l_ImageDataPtr,l_ImageDataSize,1,p_ImgFilePtr);
if(l_NumOfReadBlks < 1)
{
printf("Couldn't read the image data from the file.\n");
return NULL;
}
}
else if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 32)
{
l_ImageDataSize = ( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth) * \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight) * 4 );
pst_fBMP40ImgHdrVar->pst_mImgeData = (unsigned char*)malloc(l_ImageDataSize);
l_ImageDataPtr = pst_fBMP40ImgHdrVar->pst_mImgeData;
l_NumOfReadBlks = fread(l_ImageDataPtr,l_ImageDataSize,1,p_ImgFilePtr);
if(l_NumOfReadBlks < 1)
{
printf("Couldn't read the image data from the file.\n");
return NULL;
}
}
rewind(p_ImgFilePtr);
Convert__40_BMP2PNG(pst_fBMP40ImgHdrVar,p_ImgFilePtr,l_ColorTbleVal);
}
int main()
{
FILE * l_ImgeFilePtr;
l_ImgeFilePtr = fopen("FLAG_B24.BMP","r");
unsigned short int l_ImgeFileType;
unsigned int l_InfoHdrSze;
int l_NumofReadBlocks;
l_NumofReadBlocks = fread(&l_ImgeFileType,2,1,l_ImgeFilePtr);
if(l_NumofReadBlocks <1)
{
printf("Couldn't read the bytes from the file.\n");
return 0;
}
if(l_ImgeFileType != 19778)
{
printf("Image Passed is not a BMP file.\n");
return 0;
}
fseek(l_ImgeFilePtr,14,SEEK_SET);
l_NumofReadBlocks = fread(&l_InfoHdrSze, 4, 1, l_ImgeFilePtr);
if(l_NumofReadBlocks <1)
{
printf("Couldn't read the bytes from the file.\n");
return 0;
}
rewind(l_ImgeFilePtr);
if( l_InfoHdrSze == 40 )
{
ST_IMAGE_40_HEADER_t * pst_Img40HdrVar;
pst_Img40HdrVar = malloc(sizeof(*pst_Img40HdrVar));
if(pst_Img40HdrVar == NULL)
{
printf("There isn't enough memory to allocate for the Image header variable.\n");
return 0;
}
ST_IMAGE_40_HEADER_t * pst_l40_ReadAPIReturnVal = ReadBMP40HdrImage(pst_Img40HdrVar, l_ImgeFilePtr);
}
}
is the PNG File compressed
Yes.
how is the image data aligned in the PNG File Format?
It's not aligned. From the spec, "The chunk data length may be any number of bytes up to the maximum; therefore, implementors cannot assume that chunks are aligned on any boundaries larger than bytes."
Multitudinous image handling libraries exist to save you from worrying about these details, though. I'd recommend against rolling your own converter unless your goal is specifically to learn about image file formats.
Related
Summarize the Problem:
I wrote a userspace SPI driver in linux for the NRF24L01+ transceiver. My goal is to send files to a server. A jetson nano is the sender, and a raspberry pi 3b+ the receiver. Both the spi and nano are running Linux.
I can consistently send packets and receive acknowledgements.
However, the issue is whenever I send a packet such as 0x ff ee dd 00 cc bb aa the receiver only receives the packet 0x ff ee dd 00 00 00 00. So what is happening is that whenever the first byte encountered is zero, the rest of the packet becomes zero. This causes the files I send to become corrupted.
I was able to reproduce this bug with a char array having a similar pattern. I noticed this trend when I printed out the file contents I was sending on the transmitter and receiver.
What I've tried:
I've tried altering my SPI read function. What I thought was happening was the chip select line was being flipped high early. This did not work, I got the same results.
I've printed the packets before calling the ioctl() function from the transmitter and the packet remains intact.
I've printed the return value of the ioctl() function to see how many bytes I was receiving and sending. I was sending 31 bytes from the transmitter, and receiving 32 bytes from the receiver. So it doesn't look like my reads and sends are failing.
If I had a logic analyzer my next step would be to check the SPI pins on the transmitter, but unfortunately I don't have one.
I've added a 10uF decoupling capacitor on the transceivers and that sped up communication.
Show Some Code:
Receiver side:
/**
* Reads the payload when data pipe
* is available.
*
* spi_dev_fd: file descriptor for spi device.
* */
int nrf_rx_read(int spi_dev_fd, char * payload, int * pipe, int * bytes)
{
int pipe_temp, rtn;
// TODO: Add timeout.
do
{
rtn = nrf_rx_pipe_available(spi_dev_fd, &pipe_temp);
}while(rtn != 0);
if(rtn == 0)
{
char status;
if(bytes != NULL)
{
char size;
spi_read_msg(spi_dev_fd, R_RX_PL_WID, &status, &size, 1);
*bytes = (int) size;
}
spi_read_msg(spi_dev_fd, R_RX_PAYLOAD , &status, payload, (int) NUM_PAYLOAD_BYTES);
*pipe = pipe_temp;
char msg;
msg = RX_DR;
spi_send_msg(spi_dev_fd, W_REGISTER | STATUS, &msg, 1);
return 0;
}
return 1;
}
bool nrf_rx_pipe_available(int spi_dev_fd, int * pipe)
{
char addr = NOP;
char status;
spi_read_msg(spi_dev_fd, addr, &status, NULL, 0);
if((status & RX_DR) > 0)
{
*pipe = (status >> RX_P_NO) & 0x07;
if(*pipe > 5)
{
return 1;
}
return 0;
}
return 1;
}
int spi_read_msg(int spi_dev_fd, char addr, char * status, char * copy_to, int len)
{
char data_buffer;
char recv_buffer[len + 1];
struct spi_ioc_transfer xfer;
memset(&xfer, 0, sizeof(xfer));
memset(&recv_buffer, 0, sizeof(recv_buffer));
data_buffer = addr;
xfer.tx_buf = (unsigned long) &data_buffer;
xfer.rx_buf = (unsigned long) recv_buffer;
xfer.len = len + 2;
xfer.bits_per_word = 8;
xfer.speed_hz = 1000000;
xfer.cs_change = 0;
xfer.rx_nbits = len * 8;
xfer.tx_nbits = 8;
int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer);
if(res > 0)
{
status[0] = recv_buffer[0];
if(copy_to != NULL)
{
string temp = string(recv_buffer);
temp = temp.substr(1);
strncpy(copy_to, temp.c_str(), len);
}
// debug code
for(int i = 0; i < len; ++i)
{
printf("copy_to: %x \n ", copy_to[i]);
}
// end debug code.
}
return res;
}
Transmitter side:
/**
* Function to load a payload and send a packet.
*
*
* spi_dev_fd: file descriptor for spi device.
* */
int nrf_tx_send_packet(int spi_dev_fd, char * payload, int len)
{
int rtn;
// Put low so we can add the payload.
gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_LOW);
// Set a new payload.
nrf_tx_new_payload(spi_dev_fd, payload, len);
// Start tx transmission.
gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_HIGH);
do
{
rtn = nrf_tx_pending_send(spi_dev_fd);
if(rtn == 2)
{
char clr = MAX_RT;
spi_send_msg(spi_dev_fd, W_REGISTER | STATUS, &clr, 1);
}
}while(rtn != 1);
// Go back to standby mode
gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_LOW); // Setting chip enable to 0.
char reg = W_REGISTER | STATUS;
char val = RX_DR | TX_DS | MAX_RT;
spi_send_msg(spi_dev_fd, reg, &val, 1);
return 0;
}
int spi_send_msg(int spi_dev_fd, char addr, char * data, int len)
{
char data_buffer[len + 1];
char recv_buffer;
struct spi_ioc_transfer xfer;
memset(&xfer, 0, sizeof(xfer));
memset(&recv_buffer, 0, sizeof(recv_buffer));
data_buffer[0] = addr;
for(int i = 1; i < len + 1; ++i)
{
data_buffer[i] = data[i-1];
printf("databuffer[i]: %x \n", data_buffer[i]);
}
xfer.tx_buf = (unsigned long) data_buffer;
xfer.rx_buf = (unsigned long) NULL;
xfer.len = len + 1;
xfer.bits_per_word = 8;
xfer.speed_hz = 1000000;
xfer.cs_change = 0;
//xfer.rx_nbits = 8;
xfer.rx_nbits = 0;
xfer.tx_nbits = (8 * len) + 8;
int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer);
printf("res: %i \n", res);
return res;
}
I tried to add all the relevant code, sorry if it is a bit much. Main thing to look at is the send and receive functions. They all work as expected until I encounter the zeroed out byte.
If I am missing any information that can help someone out please let me know and I can add it. I think the send and receive functions are the most important however. I'm able to set and read the registers of the transceiver.
I can send files now!
The fix was done in spi_read_msg() function.
The problem was I was converting the buffer received to a string, which caused the data to be trimmed when the byte 0x00 was encountered. This is also equivalent to the null terminating character.
Receiver code:
int spi_read_msg(int spi_dev_fd, char addr, char * status, char * copy_to, int len)
{
char data_buffer;
char recv_buffer[len + 1];
struct spi_ioc_transfer xfer;
memset(&xfer, 0, sizeof(xfer));
memset(&recv_buffer, 0, sizeof(recv_buffer));
data_buffer = addr;
xfer.tx_buf = (unsigned long) &data_buffer;
xfer.rx_buf = (unsigned long) recv_buffer;
xfer.len = len + 2;
xfer.bits_per_word = 8;
xfer.speed_hz = 1000000;
xfer.cs_change = 0;
xfer.rx_nbits = len * 8;
xfer.tx_nbits = 8;
int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer);
if(res > 0)
{
status[0] = recv_buffer[0];
if(copy_to != NULL)
{
for(int i = 0; i < len; ++i)
{
copy_to[i] = recv_buffer[i + 1];
}
}
}
return res;
}
I've writen this code but it doesn't work correctly.
This is menu interface:
*************ENCODE_DECODE_BASE64**************
******* 1. Encode ********
******* 2. Decode ********
******* 3. Exit ********
***********************************************
When i choose 1, "Encode". The function runs but the process exits.
I want when I choose 1, the function to run and then after that, the menu to display again.
Can you help me?
Here is Clientcode:
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#define MAX 1024
// read filename
char *inputString(int size){
int test=0;
char *s=(char*)malloc(size);
do{
if(test!=0){
printf("File not found !!!!!!");
}
fgets(s,size,stdin);
test++;
}while(strlen(s)<=1);
return strtok(s,"\n");
}
int main(int argc, char *argv[]){
int sockfd;
struct sockaddr serverAddr; //server address
char buff[1024];
struct sockaddr_in inAddr;
long int sentBytes,revedBytes;
sockfd=socket(AF_INET,SOCK_STREAM,0); // create socket
if (sockfd == -1)
{
printf("ERROR opening socket\n");
return 1;
}
printf("Socket done\n");
inAddr.sin_family=AF_INET; //default
inAddr.sin_port=htons(5500); // service port
inet_aton("127.0.0.1",&inAddr.sin_addr);
//connectting
if(connect(sockfd,(struct sockaddr *)&inAddr,sizeof(struct sockaddr))<0){
printf("Connect failed.\n");
return 1;
}
printf("Connection accepted\n");
char *FileName; // file input
char *Result; // file return
int choice;
do{
printf("\n*************ENCODE_DECODE_BASE64**************");
printf("\n******* 1. Encode ********");
printf("\n******* 2. Decode ********");
printf("\n******* 3. Exit ********");
printf("\n***********************************************\n");
printf("Choice: ");
choice = getchar();
while(getchar() !='\n');
switch(choice)
{
case '1':
//demo encode////////////////////////////////////////
send(sockfd,"encode",5,0); // send to server when choose 1
printf("File Encode : ");
FileName = inputString(20);
FILE *fpt = fopen(FileName,"r");
if(fpt==NULL){
printf("File not found");
return -1;
}
printf("File Result: ");
Result = inputString(20);
FILE *ft = fopen(Result,"w");
while(!feof(fpt)){
if (fgets(buff,MAX,fpt) != NULL ){
sentBytes=send(sockfd,buff,1024,0);
revedBytes=recv(sockfd,buff,1024,0);
fprintf(ft,"%s\n",buff);
}
}
printf("Encode done!thanks you !\n");
//close(sockfd);
fclose(fpt);fclose(ft);
return 0;
break;
//decode ///////////////////////////////////////////////
case '2':
send(sockfd,"decode",6,0);
printf("File Decode : ");
FileName = inputString(20);
FILE *fpt1 = fopen(FileName,"r");
if(fpt1==NULL){
printf("File not found");
return -1;
}
printf("File Result : ");
Result = inputString(20);
FILE *ft1 = fopen(Result,"w");
while(!feof(fpt1)){
if (fgets(buff,MAX,fpt1) != NULL ){
sentBytes=send(sockfd,buff,1024,0);
revedBytes=recv(sockfd,buff,1024,0);
fprintf(ft1,"%s",buff);
}
}
printf("Decode done ! thanks you !\n");
//close(sockfd);
fclose(fpt1);fclose(ft1);
return 0;
break;
///////////////////////////////////////////////////////
case '3':
printf("Thanks!\n");
break;
default: printf("wrong number, please try again!\n"); break;
//end choice///////////////////////////////////////
}
}while(choice!='3');
//end menu
//close(sockfd);
//return 0;
}
and here is ServerCode:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* decodeblock - decode 4 '6-bit' characters into 3 8-bit binary bytes */
void decodeblock(unsigned char in[], char *clrstr) {
unsigned char out[4];
out[0] = in[0] << 2 | in[1] >> 4;
out[1] = in[1] << 4 | in[2] >> 2;
out[2] = in[2] << 6 | in[3] >> 0;
out[3] = '\0';
strncat(clrstr, out, sizeof(out));
}
void b64_decode(char *b64src, char *clrdst) {
int c, phase, i;
unsigned char in[4];
char *p;
clrdst[0] = '\0';
phase = 0; i=0;
while(b64src[i]) {
c = (int) b64src[i];
if(c == '=') {
decodeblock(in, clrdst);
break;
}
p = strchr(b64, c);
if(p) {
in[phase] = p - b64;
phase = (phase + 1) % 4;
if(phase == 0) {
decodeblock(in, clrdst);
in[0]=in[1]=in[2]=in[3]=0;
}
}
i++;
}
}
/* encodeblock - encode 3 8-bit binary bytes as 4 '6-bit' characters */
void encodeblock( unsigned char in[], char b64str[], int len ) {
unsigned char out[5];
out[0] = b64[ in[0] >> 2 ];
out[1] = b64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
out[2] = (unsigned char) (len > 1 ? b64[ ((in[1] & 0x0f) << 2) |
((in[2] & 0xc0) >> 6) ] : '=');
out[3] = (unsigned char) (len > 2 ? b64[ in[2] & 0x3f ] : '=');
out[4] = '\0';
strncat(b64str, out, sizeof(out));
}
/* encode - base64 encode a stream, adding padding if needed */
void b64_encode(char *clrstr, char *b64dst) {
unsigned char in[3];
int i, len = 0;
int j = 0;
b64dst[0] = '\0';
while(clrstr[j]) {
len = 0;
for(i=0; i<3; i++) {
in[i] = (unsigned char) clrstr[j];
if(clrstr[j]) {
len++; j++;
}
else in[i] = 0;
}
if( len ) {
encodeblock( in, b64dst, len );
}
}
}
void sig_chld(int signo) //child
{
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG))>0)
printf("child %d terminated\n", pid);
return;
}
int main()
{
int listen_sock, conn_sock;
int server_len, client_len,choice;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
char myb64[1024] = ""; //encode
char mydst[1024] = ""; //decode
int sentBytes,revedBytes,bytes_readi;
char buff[1024]; //buffer to send data
listen_sock = socket(AF_INET, SOCK_STREAM, 0); //create socket
if (listen_sock == -1)
{
printf("ERROR opening socket\n");
return 0;
}
printf("Socket done\n");
//Thiet lap dia chi server
server_address.sin_family = AF_INET; //default
inet_aton("127.0.0.1",&server_address.sin_addr); //ip server
server_address.sin_port = htons(5500); // port server
server_len = sizeof(server_address);
if(bind(listen_sock, (struct sockaddr *)&server_address,server_len)<0)
{
printf("ERROR on binding\n");
return 0;
}
printf("Bind done\n");
int check = listen(listen_sock,10);
if (check == -1)
{
printf("Error connect");
return 0;
}
printf("Waiting connect..\n");
while(1) {
client_len = sizeof(client_address);
conn_sock = accept(listen_sock,(struct sockaddr *)&client_address, &client_len);
if(conn_sock==-1){
printf("Error connect\n");
return 1;
}else{
printf("Accept new connection\n");
}
if(fork() == 0){
close(listen_sock);
do{
revedBytes = recv(conn_sock,buff,1024,0);
buff[revedBytes]='\0';
if(strcmp(buff,"mahoa")==0) choice=1;
else if(strcmp(buff,"giaima")==0) choice=2; else choice = 3;
switch(choice)
{
case 1:
while((revedBytes = recv(conn_sock,buff,1024,0)) > 0){
buff[revedBytes]='\0';
//printf("string send by client encode : %s\n",buff);
b64_encode(buff, myb64); //ma hoa
sentBytes=send(conn_sock,myb64,1024,0); //gui lai string da ma hoa cho client
}
close(conn_sock);//Dong ket noi cua client
exit(0);
break;
case 2:
while((revedBytes = recv(conn_sock,buff,1024,0)) > 0){
buff[revedBytes]='\0';
//printf("string send by client decode: %s\n",buff);
b64_decode(buff,mydst); // giaima
sentBytes=send(conn_sock,mydst,1024,0);
}
close(conn_sock);
exit(0);
break;
case 3:break;
}
}while(choice!=3);
break;
}
signal(SIGCHLD,sig_chld);
close(conn_sock);
}
return 1;
}
I want to stream JPEG images or motion-JPEG file through live 555. But the problem is that in live 555 implementation for Jpegs is not available. Anyone can help ??
You can find a implementation that was posted to the devel mailing list http://lists.live555.com/pipermail/live-devel/2012-February/014672.html.
The code and a sample is available but this modification was rejected by live555 maintainer.
First we need to implement an MJPEGVideoSource than can feed a JPEGVideoRTPSink.
#include "JPEGVideoSource.hh"
class MJPEGVideoSource : public JPEGVideoSource
{
public:
static MJPEGVideoSource* createNew (UsageEnvironment& env, FramedSource* source)
{
return new MJPEGVideoSource(env,source);
}
virtual void doGetNextFrame()
{
if (m_inputSource)
m_inputSource->getNextFrame(fTo, fMaxSize, afterGettingFrameSub, this, FramedSource::handleClosure, this);
}
virtual void doStopGettingFrames()
{
FramedSource::doStopGettingFrames();
if (m_inputSource)
m_inputSource->stopGettingFrames();
}
static void afterGettingFrameSub(void* clientData, unsigned frameSize,unsigned numTruncatedBytes,struct timeval presentationTime,unsigned durationInMicroseconds)
{
MJPEGVideoSource* source = (MJPEGVideoSource*)clientData;
source->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime, durationInMicroseconds);
}
void afterGettingFrame(unsigned frameSize,unsigned numTruncatedBytes,struct timeval presentationTime,unsigned durationInMicroseconds)
{
int headerSize = 0;
bool headerOk = false;
fFrameSize = 0;
for (unsigned int i = 0; i < frameSize ; ++i)
{
// SOF
if ( (i+8) < frameSize && fTo[i] == 0xFF && fTo[i+1] == 0xC0 )
{
m_height = (fTo[i+5]<<5)|(fTo[i+6]>>3);
m_width = (fTo[i+7]<<5)|(fTo[i+8]>>3);
}
// DQT
if ( (i+5+64) < frameSize && fTo[i] == 0xFF && fTo[i+1] == 0xDB)
{
if (fTo[i+4] ==0)
{
memcpy(m_qTable, fTo + i + 5, 64);
m_qTable0Init = true;
}
else if (fTo[i+4] ==1)
{
memcpy(m_qTable + 64, fTo + i + 5, 64);
m_qTable1Init = true;
}
}
// End of header
if ( (i+1) < frameSize && fTo[i] == 0x3F && fTo[i+1] == 0x00 )
{
headerOk = true;
headerSize = i+2;
break;
}
}
if (headerOk)
{
fFrameSize = frameSize - headerSize;
memmove( fTo, fTo + headerSize, fFrameSize );
}
fNumTruncatedBytes = numTruncatedBytes;
fPresentationTime = presentationTime;
fDurationInMicroseconds = durationInMicroseconds;
afterGetting(this);
}
virtual u_int8_t type() { return 1; };
virtual u_int8_t qFactor() { return 128; };
virtual u_int8_t width() { return m_width; };
virtual u_int8_t height() { return m_height; };
u_int8_t const* quantizationTables( u_int8_t& precision, u_int16_t& length )
{
length = 0;
precision = 0;
if ( m_qTable0Init && m_qTable1Init )
{
precision = 8;
length = sizeof(m_qTable);
}
return m_qTable;
}
protected:
MJPEGVideoSource(UsageEnvironment& env, FramedSource* source) : JPEGVideoSource(env),
m_inputSource(source),
m_width(0),
m_height(0),
m_qTable0Init(false),
m_qTable1Init(false)
{
memset(&m_qTable,0,sizeof(m_qTable));
}
virtual ~MJPEGVideoSource()
{
Medium::close(m_inputSource);
}
protected:
FramedSource* m_inputSource;
u_int8_t m_width;
u_int8_t m_height;
u_int8_t m_qTable[128];
bool m_qTable0Init;
bool m_qTable1Init;
};
Next we can use it as a video source in order to build a simple RTSP server:
#include "liveMedia.hh"
#include "BasicUsageEnvironment.hh"
#include "GroupsockHelper.hh"
#include "MJPEGVideoSource.hh"
char const* inputFileName = "test.mjpeg";
int main(int argc, char** argv) {
// Begin by setting up our usage environment:
TaskScheduler* scheduler = BasicTaskScheduler::createNew();
UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);
// Create 'groupsocks' for RTP and RTCP:
struct in_addr destinationAddress;
destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env);
const unsigned short rtpPortNum = 18888;
const unsigned short rtcpPortNum = rtpPortNum+1;
const unsigned char ttl = 255;
const Port rtpPort(rtpPortNum);
const Port rtcpPort(rtcpPortNum);
Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl);
rtpGroupsock.multicastSendOnly(); // we're a SSM source
Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl);
rtcpGroupsock.multicastSendOnly(); // we're a SSM source
// Create a 'JPEG Video RTP' sink from the RTP 'groupsock':
RTPSink* videoSink = JPEGVideoRTPSink::createNew(*env, &rtpGroupsock);
// Create (and start) a 'RTCP instance' for this RTP sink:
const unsigned estimatedSessionBandwidth = 5000; // in kbps; for RTCP b/w share
const unsigned maxCNAMElen = 100;
unsigned char CNAME[maxCNAMElen+1];
gethostname((char*)CNAME, maxCNAMElen);
CNAME[maxCNAMElen] = '\0'; // just in case
RTCPInstance* rtcp = RTCPInstance::createNew(*env, &rtcpGroupsock,
estimatedSessionBandwidth, CNAME,
videoSink, NULL /* we're a server */,
True /* we're a SSM source */);
// Note: This starts RTCP running automatically
RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554);
if (rtspServer == NULL) {
*env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
exit(1);
}
ServerMediaSession* sms = ServerMediaSession::createNew(*env, "testStream", inputFileName,"Session streamed by \"testMJPEGVideoStreamer\"",
True /*SSM*/);
sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp));
rtspServer->addServerMediaSession(sms);
char* url = rtspServer->rtspURL(sms);
*env << "Play this stream using the URL \"" << url << "\"\n";
delete[] url;
// Start the streaming:
*env << "Beginning streaming...\n";
// Open the input file as a 'byte-stream file source':
ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(*env, inputFileName);
if (fileSource == NULL) {
*env << "Unable to open file \"" << inputFileName
<< "\" as a byte-stream file source\n";
exit(1);
}
// Create the MJPEG video source:
MJPEGVideoSource* videoSource = MJPEGVideoSource::createNew(*env, fileSource);
// Finally, start playing:
*env << "Beginning to read from file...\n";
videoSink->startPlaying(*videoSource, NULL, NULL);
env->taskScheduler().doEventLoop();
return 0;
}
Hope you have done it but if not-
see this Jpeg Streaming using live555
This is doing the same thing as you have asked to stream the images/Jpegs.
For MJpegs you'll have to do the same process.
I have one string which is base 32 bit decoded now I want to Decode that string I also want to encode any string to base 32 bit decoded string.
Is there any way,any Algorithm(even in C) or any API for that so i can solve this issue.
Thanx in advance.
I am not sure if I understand your question, but if you want to convert a base 32 number to base 10(decimal) number, take this:
#include <stdio.h>
#include <string.h>
#include <math.h>
#define BASE 32
unsigned int convert_number (const char *s) {
unsigned int len = strlen(s) - 1;
unsigned int result = 0;
char start_ch = 0, ch;
while(*s != '\0') {
ch = *s;
if (ch >= 'a') {
start_ch = 'a' - 10;
} else if (ch >= 'A') {
start_ch = 'A' - 10;
} else {
start_ch = '0';
}
if(len >= 0)
result += (ch - start_ch) * pow(BASE, len);
else
result += (ch - start_ch);
++s;
--len;
}
return result;
}
I know there is an Objective-C wrapper around YAJL, but this is a really fat thing which blows up the whole JASON parser to a ridiculous huge amount of 21 files, many of them with tiny scroll bars.
So to keep my app binary small I'd like to stick with the C-version of that parser. But I'm having a hard time finding any useful documentation for this rather than the wrapper.
Maybe someone who used the C-base can point out such a tutorial or documentation?
The documentation with C examples can be found here: http://lloyd.github.com/yajl/
The github repository with examples can be found here : https://github.com/lloyd/yajl
Here is a C example that reformats JSON from stdin:
#include <yajl/yajl_parse.h>
#include <yajl/yajl_gen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int reformat_null(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_null(g);
}
static int reformat_boolean(void * ctx, int boolean)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_bool(g, boolean);
}
static int reformat_number(void * ctx, const char * s, size_t l)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_number(g, s, l);
}
static int reformat_string(void * ctx, const unsigned char * stringVal,
size_t stringLen)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_string(g, stringVal, stringLen);
}
static int reformat_map_key(void * ctx, const unsigned char * stringVal,
size_t stringLen)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_string(g, stringVal, stringLen);
}
static int reformat_start_map(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_map_open(g);
}
static int reformat_end_map(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_map_close(g);
}
static int reformat_start_array(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_array_open(g);
}
static int reformat_end_array(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_array_close(g);
}
static yajl_callbacks callbacks = {
reformat_null,
reformat_boolean,
NULL,
NULL,
reformat_number,
reformat_string,
reformat_start_map,
reformat_map_key,
reformat_end_map,
reformat_start_array,
reformat_end_array
};
static void
usage(const char * progname)
{
fprintf(stderr, "%s: reformat json from stdin\n"
"usage: json_reformat [options]\n"
" -m minimize json rather than beautify (default)\n"
" -u allow invalid UTF8 inside strings during parsing\n",
progname);
exit(1);
}
int
main(int argc, char ** argv)
{
yajl_handle hand;
static unsigned char fileData[65536];
/* generator config */
yajl_gen g;
yajl_status stat;
size_t rd;
int retval = 0;
int a = 1;
g = yajl_gen_alloc(NULL);
yajl_gen_config(g, yajl_gen_beautify, 1);
yajl_gen_config(g, yajl_gen_validate_utf8, 1);
/* ok. open file. let's read and parse */
hand = yajl_alloc(&callbacks, NULL, (void *) g);
/* and let's allow comments by default */
yajl_config(hand, yajl_allow_comments, 1);
/* check arguments.*/
while ((a < argc) && (argv[a][0] == '-') && (strlen(argv[a]) > 1)) {
unsigned int i;
for ( i=1; i < strlen(argv[a]); i++) {
switch (argv[a][i]) {
case 'm':
yajl_gen_config(g, yajl_gen_beautify, 0);
break;
case 'u':
yajl_config(hand, yajl_dont_validate_strings, 1);
break;
default:
fprintf(stderr, "unrecognized option: '%c'\n\n",
argv[a][i]);
usage(argv[0]);
}
}
++a;
}
if (a < argc) {
usage(argv[0]);
}
for (;;) {
rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin);
if (rd == 0) {
if (!feof(stdin)) {
fprintf(stderr, "error on file read.\n");
retval = 1;
}
break;
}
fileData[rd] = 0;
stat = yajl_parse(hand, fileData, rd);
if (stat != yajl_status_ok) break;
{
const unsigned char * buf;
size_t len;
yajl_gen_get_buf(g, &buf, &len);
fwrite(buf, 1, len, stdout);
yajl_gen_clear(g);
}
}
stat = yajl_complete_parse(hand);
if (stat != yajl_status_ok) {
unsigned char * str = yajl_get_error(hand, 1, fileData, rd);
fprintf(stderr, "%s", (const char *) str);
yajl_free_error(hand, str);
retval = 1;
}
yajl_gen_free(g);
yajl_free(hand);
return retval;
}