/* Hi there, the archived file you got should contain the C source of my JPEG encoder.
Legal stuff
-----------
You get this source for free so absolutely no warranty is provided with it.
Use it at your own risk.
Description
-----------
The principles of designing my JPEG encoder were mainly clarity and portability.
So it's made in plain ANSI C. That's why it worked, compiled on a lot of C
compilers. Here is the list: WATCOM C 10.0, DJGPP 2.0, VISUAL C 6.0,
GCC under Linux,Solaris,VMS, FreeBSD.
And its simplicity makes it fast enough I think.
The FDCT routine is taken with minor modifications from Independent JPEG Group's
JPEG software . So don't ask me details about that.
The rest it's done by me.
The program should give the same results on any C compiler which provides at least
256 kb of free memory. I needed that for the precalculated bitcode (3*64k) and
category (64k) arrays , not to mention the memory needed for the truecolor BMP.
Since it's made to encode a truecolor BMP into a JPG file, I think that it
should be no problem for you to figure out how to modify the C source in order
to use it with any RGB image you want to compress (small enough to fit into
your memory) .
A note: The JPG format I used is a personal choice:
The sampling factors are 1:1 for simplicity reasons, the Huffman tables
are those given in the standard (so it's not optimized for that particular
image you want to encode), etc.
I coded only what I needed from a JPEG encoder. Probably it could have
more advanced features.
There are a lot of other JPG formats (markers in another order, another markers),
so don't ask me why a JPG file not encoded with this encoder has a different
format (different locations , another markers...).
Though not necessary, an email saying at least 'THANKS ' would be nice if
you find it useful.
You are free to use/modify it in a your production(s) but it would be nice to say
in your documentation that you used ideas/routines from the JPEG encoder made by
Cristi Cuturicu.
For more info you can check the doc "jpgalgo.txt" or the JPEG standard.
Both can be found at www.wotsit.org
If you have questions regarding this encoder, want to improve it, maybe report bugs,
here is my email address:
cccrx@kermit.cs.pub.ro
or cristic22@yahoo.com */
//////////////////////////////////////////////////
//THE SOURCE !
/////////////////////////////////////////////////
//////////////////////////////////////////////
//END OF HEADERS
//////////////////////////////////////////////
// A BMP truecolor to JPEG encoder
// Copyright 1999 Cristi Cuturicu
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include "jtypes.h"
//#include "jglobals.h"
//#include "jtables.h"
//#include "headers.h"
#include "jpg.h"
void write_APP0info()
//Nothing to overwrite for APP0info
{
writeword(APP0info.marker);
writeword(APP0info.length);
writebyte('J');writebyte('F');writebyte('I');writebyte('F');writebyte(0);
writebyte(APP0info.versionhi);writebyte(APP0info.versionlo);
writebyte(APP0info.xyunits);
writeword(APP0info.xdensity);writeword(APP0info.ydensity);
writebyte(APP0info.thumbnwidth);writebyte(APP0info.thumbnheight);
}
void write_SOF0info()
// We should overwrite width and height
{
writeword(SOF0info.marker);
writeword(SOF0info.length);
writebyte(SOF0info.precision);
writeword(SOF0info.height);writeword(SOF0info.width);
writebyte(SOF0info.nrofcomponents);
writebyte(SOF0info.IdY);writebyte(SOF0info.HVY);writebyte(SOF0info.QTY);
writebyte(SOF0info.IdCb);writebyte(SOF0info.HVCb);writebyte(SOF0info.QTCb);
writebyte(SOF0info.IdCr);writebyte(SOF0info.HVCr);writebyte(SOF0info.QTCr);
}
void write_DQTinfo()
{
BYTE i;
writeword(DQTinfo.marker);
writeword(DQTinfo.length);
writebyte(DQTinfo.QTYinfo);for (i=0;i<64;i++) writebyte(DQTinfo.Ytable[i]);
writebyte(DQTinfo.QTCbinfo);for (i=0;i<64;i++) writebyte(DQTinfo.Cbtable[i]);
}
void set_quant_table(BYTE *basic_table,BYTE scale_factor,BYTE *newtable)
// Set quantization table and zigzag reorder it
{
BYTE i;
long temp;
for (i = 0; i < 64; i++) {
temp = ((long) basic_table[i] * scale_factor + 50L) / 100L;
/* limit the values to the valid range */
if (temp <= 0L) temp = 1L;
if (temp > 255L) temp = 255L; /* limit to baseline range if requested */
newtable[zigzag[i]] = (WORD) temp;
}
}
void set_DQTinfo()
{
BYTE scalefactor=50;// scalefactor controls the visual quality of the image
// the smaller is, the better image we'll get, and the smaller
// compression we'll achieve
DQTinfo.marker=0xFFDB;
DQTinfo.length=132;
DQTinfo.QTYinfo=0;
DQTinfo.QTCbinfo=1;
set_quant_table(std_luminance_qt,scalefactor,DQTinfo.Ytable);
set_quant_table(std_chrominance_qt,scalefactor,DQTinfo.Cbtable);
}
void write_DHTinfo()
{
BYTE i;
writeword(DHTinfo.marker);
writeword(DHTinfo.length);
writebyte(DHTinfo.HTYDCinfo);
for (i=0;i<16;i++) writebyte(DHTinfo.YDC_nrcodes[i]);
for (i=0;i<=11;i++) writebyte(DHTinfo.YDC_values[i]);
writebyte(DHTinfo.HTYACinfo);
for (i=0;i<16;i++) writebyte(DHTinfo.YAC_nrcodes[i]);
for (i=0;i<=161;i++) writebyte(DHTinfo.YAC_values[i]);
writebyte(DHTinfo.HTCbDCinfo);
for (i=0;i<16;i++) writebyte(DHTinfo.CbDC_nrcodes[i]);
for (i=0;i<=11;i++) writebyte(DHTinfo.CbDC_values[i]);
writebyte(DHTinfo.HTCbACinfo);
for (i=0;i<16;i++) writebyte(DHTinfo.CbAC_nrcodes[i]);
for (i=0;i<=161;i++) writebyte(DHTinfo.CbAC_values[i]);
}
void set_DHTinfo()
{
BYTE i;
DHTinfo.marker=0xFFC4;
DHTinfo.length=0x01A2;
DHTinfo.HTYDCinfo=0;
for (i=0;i<16;i++) DHTinfo.YDC_nrcodes[i]=std_dc_luminance_nrcodes[i+1];
for (i=0;i<=11;i++) DHTinfo.YDC_values[i]=std_dc_luminance_values[i];
DHTinfo.HTYACinfo=0x10;
for (i=0;i<16;i++) DHTinfo.YAC_nrcodes[i]=std_ac_luminance_nrcodes[i+1];
for (i=0;i<=161;i++) DHTinfo.YAC_values[i]=std_ac_luminance_values[i];
DHTinfo.HTCbDCinfo=1;
for (i=0;i<16;i++) DHTinfo.CbDC_nrcodes[i]=std_dc_chrominance_nrcodes[i+1];
for (i=0;i<=11;i++) DHTinfo.CbDC_values[i]=std_dc_chrominance_values[i];
DHTinfo.HTCbACinfo=0x11;
for (i=0;i<16;i++) DHTinfo.CbAC_nrcodes[i]=std_ac_chrominance_nrcodes[i+1];
for (i=0;i<=161;i++) DHTinfo.CbAC_values[i]=std_ac_chrominance_values[i];
}
void write_SOSinfo()
//Nothing to overwrite for SOSinfo
{
writeword(SOSinfo.marker);
writeword(SOSinfo.length);
writebyte(SOSinfo.nrofcomponents);
writebyte(SOSinfo.IdY);writebyte(SOSinfo.HTY);
writebyte(SOSinfo.IdCb);writebyte(SOSinfo.HTCb);
writebyte(SOSinfo.IdCr);writebyte(SOSinfo.HTCr);
writebyte(SOSinfo.Ss);writebyte(SOSinfo.Se);writebyte(SOSinfo.Bf);
}
void write_comment(BYTE *comment)
{
WORD i,length;
writeword(0xFFFE); //The COM marker
length=strlen((const char *)comment);
writeword(length+2);
for (i=0;i<length;i++) writebyte(comment[i]);
}
void writebits(bitstring bs)
// A portable version; it should be done in assembler
{
WORD value;
SBYTE posval;//bit position in the bitstring we read, should be<=15 and >=0
value=bs.value;
posval=bs.length-1;
while (posval>=0)
{
if (value & mask[posval]) bytenew|=mask[bytepos];
posval--;bytepos--;
if (bytepos<0) { if (bytenew==0xFF) {writebyte(0xFF);writebyte(0);}
else {writebyte(bytenew);}
bytepos=7;bytenew=0;
}
}
}
void compute_Huffman_table(BYTE *nrcodes,BYTE *std_table,bitstring *HT)
{
BYTE k,j;
BYTE pos_in_table;
WORD codevalue;
codevalue=0; pos_in_table=0;
for (k=1;k<=16;k++)
{
for (j=1;j<=nrcodes[k];j++) {HT[std_table[pos_in_table]].value=codevalue;
HT[std_table[pos_in_table]].length=k;
pos_in_table++;
codevalue++;
}
codevalue*=2;
}
}
void init_Huffman_tables()
{
comput
- 1
- 2
前往页