⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jpeg.htm

📁 C++builder学习资料C++builder
💻 HTM
📖 第 1 页 / 共 2 页
字号:
  > make -f makefile.bc55

</PRE> 

<P> 

Don't forget the <TT>-f</TT> switch. It tells make the name of your makefile. Some people forget the <TT>-f</TT> switch, and do this: 

</P> 

<PRE>

  // Error!!!!!

  &gt; make makefile.bc55

</PRE> 

<P> 

When you build the project, you should get a LIB file called <TT>libjpeg.lib</TT>, and some EXEs. The JPEG makefile is designed to 

create both the library and the example programs. The two main example programs are <TT>cjpeg.exe</TT>, for compression, and 

<TT>djpeg.exe</TT> for decompression. The makefile also has a <TT>clean</TT> target that will erase OBJs and other intermediate files. 

This target is not called by default, you must explicitly invoke it. There is also a target for running the example programs. 

<PRE>

  &gt; make -f makefile.bc55 clean

  &gt; make -f makefile.bc55 test

</PRE> 

<P> 

Beware of what the <TT>clean</TT> target actually does! It deletes the LIB files, and the sample programs, as well as the executables. You might 

want to edit the makefile if you do not like this behavior. 

</P> 

<P> 

The default makefiles from the IJG assume that you want to build the jpeg library in release mode. This makes sense. However, you may 

want to build a debug library if you will need to debug into the JPEG source code. The makefile that I produced allows you to build a 

debug library as well as a release library. To build the debug library, define <TT>DEBUG</TT> using the <TT>-D</TT> switch when you 

invoke <TT>make</TT>. 

</P> 

<PRE>

  &gt; make -B -f makefile.bc55 -DDEBUG

</PRE> 

<P> 

The extra <TT>-B</TT> switch ensures that all C files are rebuilt. If there are release OBJs lying around, <TT>make</TT> won't rebuild 

them just because you define <TT>DEBUG</TT>. You don't want any release OBJs making it into your debug JPEG library. 

</P> 

<P> 

When you define <TT>DEBUG</TT>, make will produce a LIB file with a different name, <TT>jpegd.lib</TT>. I decided that the debug library 

should have a different name then the release library. If you don't like this practice, or if you don't like the filename that I chose, 

then you can alter the makefile. The library filename is stored in the <TT>JPEGLIB</TT> macro. 

</P> 

<P> 

Of course, you don't need to bother with a debug library just to step into the JPEG source when debugging. Another easy way to debug 

the JPEG source is to simply add the JPEG source files to your project and compile them straight in. Your projects won't compile as 

quickly as they would if you used the LIB file, but the JPEG files compile pretty fast anyway, so its not much of an issue. 

</P> 

<BR> 

<H3> 

<A NAME="example">Using the compiled JPEG library in a project</A> 

</H3> 

<P> 

Once you have built the JPEG library, you should not need to compile the JPEG source after that. When you need to use the JPEG 

library, just link with the LIB file (<TT>libjpeg.lib</TT> or <TT>jpegd.lib</TT>). When you compile, tell the compiler where the JPEG 

header files are by using the <TT>-I</TT> switch. 

</P> 

<P> 

To demonstrate how to do this, I have put together a simple example project. This project creates a JPEG from a 24 bit RGB test pattern. 

You can download the example <a HREF="download/bc55jpegdemo.zip">here</a>.

</p>

<P>

I won't show the source code for this project, as its pretty boring. But I will show the makefile.

</P>

<PRE>

BORLAND=$(MAKEDIR)\..

CC= bcc32

LINK=ilink32

JPEGPATH=c:\jpeg\borland

INCLUDEPATH=$(BORLAND)\include;$(JPEGPATH)

LIBPATH=$(BORLAND)\lib;$(JPEGPATH)



!if $d(DEBUG)

CFLAGS= -tWC -tWM- -Od -H- -v -vi- -c -y -w-par -w-stu \

        -w-ccc -w-rch -I$(INCLUDEPATH)

LFLAGS= -Tpe -ap -x -Gn -L$(LIBPATH)

# name the jpeg library something different for debug builds.

JPEGLIB=jpegd.lib

!else

CFLAGS= -tWC -tWM- -O2 -H- -c  -w-par -w-stu -w-ccc -w-rch -I$(INCLUDEPATH)

LFLAGS= -Tpe -ap -x -Gn -L$(LIBPATH)

JPEGLIB=libjpeg.lib

!endif



OBJS = c0x32.obj

LIBS = cw32.lib import32.lib $(JPEGLIB)



all: bccjpeg.exe



main.obj: main.cpp

    $(CC) $(CFLAGS) main.cpp



bccjpeg.exe: main.obj

    $(LINK) $(LFLAGS) $(OBJS) main.obj, bccjpeg.exe,, $(LIBS) $(JPEGLIB), ,



clean:

	- del *.obj

    - del *.tds

    - del *.\#0?

    - del *.csm

    - del *.~??

</PRE>

<P>

There are two points of interest in this makefile. First, notice that I have added the path <TT>c:\jpeg\borland</TT> to the include path

that gets passed to both the linker and the compiler. This allows the compiler to locate the JPEG header files, and it allows the linker

to locate the JPEG LIB file. You will need to edit the <TT>JPEGPATH</TT> macro if you installed the JPEG header files to a location other

than <TT>c:\jpeg\borland</TT>. Second, we have to pass the JPEG lib file to the linker. This is done through the <TT>JPEGLIB</TT> macro.

Other than these two items, this is a pretty standard makefile.

</P>

<BR>

<H3>

<A NAME="notes">Notes</A>

</H3>

<P>

<B>Note 1:</B> It is important that you compile your program with the same compiler options that you used to compile the JPEG library.

Specifically, the compiler options for structure alignment (the -a family of options), and enum size (-b) must match. There may be other

options that have to match too. If these compiler options do not match, then your client program and the JPEG library will not agree on how

big the JPEG structures should be. The structures increase or decrease in size depending on the -a and -b switches.

</P>

<P>

This structure alignment issue can be a major pain. Ideally, you should not be forced to use the same alignment options that the JPEG

library uses. To rectify the problem, you have a couple of choices. First, you could forget about the LIB file altogether, and just compile

the JPEG source files right into your projects. When you do this, you guarantee that the JPEG source is compiled with the same options that

the rest of your project is compiled with.

</P>

<P>

Another way to solve this problem is to place a <TT>#pragma option push</TT> statment in <TT>jpeglib.h</TT>. This is called a compiler

option guard. It ensures that the JPEG source is compiled with a given set of compiler options, and it ensures that clients of the LIB

file know about those compiler options. Here is how you would edit <TT>jpeglib.h</TT>

</P>

<pre>

<font color="green">#ifndef JPEGLIB_H</font>

<font color="green">#define JPEGLIB_H</font>



<font color="green">#ifdef __cplusplus</font>

<b>extern</b> <font color="blue">&quot;C&quot;</font> <b>{</b>

<font color="green">#endif</font>



<font color="navy">/* HJH modification: protect compiler options for structure alignment and enum

 * size if the compiler is Borland C++ */</font>

<font color="green">#pragma option push -b</font>

<font color="green">#pragma option push -a1</font>



<font color="navy">// ...</font>

<font color="navy">// body of file</font>

<font color="navy">// ...</font>



<font color="green">#pragma option pop <font color="navy">/* pop -a switch */</font></font>

<font color="green">#pragma option pop <font color="navy">/* pop -b */</font></font>



<font color="green">#ifdef __cplusplus</font>

<b>}</b>

<font color="green">#endif</font>



<font color="green">#endif <font color="navy">/* JPEGLIB_H */</font></font>

</pre>

<P>

Keep in mind that you don't have to use -b and -a1. You could use -b- and -a4. It doesn't really matter. The key is to protect the

structures and the enums in the library so they always compile to the same size, regardless of the compiler options in the makefile. The

-a4 might actually result in slightly better performance.

</P>

<P>

<B>Note 2:</B> If you do place compiler option guards in the JPEG header file, you might want to use a <TT>#ifdef __BORLANDC__</TT>

statement. This way, the #pragmas only play a role if the compiler is BC55 or Borland C++Builder. You might not want to have these

#pragma's in your code if you need to compile the source with another compiler.

</P>

<P>

The ANSI C++ standard promises that compilers are supposed to ignore <TT>#pragma</TT> statements that they don't understand. However,

many compilers will interpret <TT>#pragma option push</TT> the same way Borland does. But there is a catch. On another compiler, -a and

-b might mean totally different things. For this reason, it makes sense to only compile in the <TT>#pragma</TT>'s if you detect that

the code is being compiled with the Borland compiler. Here is how you would change the header file.

</P>

<pre>

<font color="green">#ifndef JPEGLIB_H</font>

<font color="green">#define JPEGLIB_H</font>



<font color="green">#ifdef __cplusplus</font>

<b>extern</b> <font color="blue">&quot;C&quot;</font> <b>{</b>

<font color="green">#endif</font>



<font color="navy">/* HJH modification: protect compiler options for structure alignment and enum

 * size if the compiler is Borland C++ */</font>

<font color="green">#ifdef __BORLANDC__</font>

<font color="green">#pragma option push -b</font>

<font color="green">#pragma option push -a1</font>

<font color="green">#endif</font>



<font color="navy">// ...</font>

<font color="navy">// body of file</font>

<font color="navy">// ...</font>



<font color="green">#ifdef __BORLANDC__</font>

<font color="green">#pragma option pop <font color="navy">/* pop -a switch */</font></font>

<font color="green">#pragma option pop <font color="navy">/* pop -b */</font></font>

<font color="green">#endif</font>



<font color="green">#ifdef __cplusplus</font>

<b>}</b>

<font color="green">#endif</font>



<font color="green">#endif <font color="navy">/* JPEGLIB_H */</font></font>

</pre>

<P>

<B>Note 3:</B> The <a HREF="download/bc55jpeg.zip"><TT>jpeglib.h</TT> file for BC55</a> has been updated to 

include the <TT>#pragma option</TT> guards. 

</P> 

 

<P> 

<B>Note 4:</B> When you compress an image, you pass rows of image data to the JPEG compressor by calling 

<TT>jpeg_write_scanlines</TT>. Probably the most common way to pass in data is to send the compressor 24-bit RGB data. 

There is one important item to watch out for when you are working on the Windows platform. On Windows, the first byte of 

a 24-bit RGB pixel is the blue intensity. However, the JPEG library expects the first byte to be the red intensity. Both 

Windows and the JPEG library agree that the second byte should be green. But they disagree on the third byte. In a 

Windows bitmap the third byte is red, whereas the JPEG library expects the third byte to be blue. In other words, the 

JPEG library and Windows have swapped the meaning of the first and third bytes in a 24-bit RGB pixel. 

</P> 

<P> 

Before we continue, let's clarify some terminology. When I say the first byte should be blue, what I really mean is that 

the lowest memory address of the pixel should contain the blue intensity. Let's say that you have a row of image data in 

an <TT>unsigned char</TT> array, like this: 

</P> 

<pre>

<b>unsigned</b> <b>char</b> buff<b>[</b><font color="blue">640</font><b>*</b><font color="blue">3</font><b>]</b><b>;</b>  <font color="navy">// a buffer of 24-bit RGB data</font>

</pre> 

<P> 

Each pixel in the buffer consumes 3 bytes. The first pixel spans across <TT>buff[0]</TT>, <TT>buff[1]</TT>, and 

<TT>buff[2]</TT>. The first byte of the first pixel is <TT>buff[0]</TT>, the byte at the lowest address. In a Windows bitmap, 

<TT>buff[0]</TT> would contain the blue intensity of the first pixel, and <TT>buff[2]</TT> would contain the red. When 

you pass <TT>buff</TT> to <TT>jpeg_write_scanlines</TT>, the JPEG library expects these two bytes to be reversed. <TT>buff[0]</TT> 

should contain the red intensity, and <TT>buff[2]</TT> should contain the blue. 

</P> 

<P> 

This fact is incredibly easy to miss. If you forget to take this into account, your images will compress just fine, but 

the resulting JPEG will not look right. On some real world images, it can be difficult to notice the difference, 

especially if the image contains a lot of green. On other images, the problem stands out more clearly (ie a blue car 

would suddenly become red when compressed into a JPEG). 

</P> 

<P> 

There are a couple ways to deal with this problem. First, you can loop through your 24-bit RGB bitmap data and swap the 

red and the blue bytes before passing the data to the JPEG compressor. Make sure that you do this in an offscreen 

buffer, and that you don't paint the bitmap on the screen (it won't look right because you just messed up every pixel in 

the bitmap). You must also perform this reversal if you decompress a JPEG in your program. The red and blue pixels 

coming out of the decompressor should be swapped before you display the RGB data on the screen. 

</P> 

<P> 

Another option is to modify three defines in <TT>jmorecfg.h</TT>. The IJG designed the JPEG library to allow you to 

specify the ordering of bytes in an RGB pixel. The defines are <TT>RGB_RED</TT>, <TT>RGB_GREEN</TT>, and <TT>RGB_BLUE</TT>. 

The default implementation of <TT>jmorecfg.h</TT> looks like this: 

</P> 

<pre>

<font color="green">#define RGB_RED		0	<font color="navy">/* Offset of Red in an RGB scanline element */</font></font>

<font color="green">#define RGB_GREEN	1	<font color="navy">/* Offset of Green */</font></font>

<font color="green">#define RGB_BLUE	2	<font color="navy">/* Offset of Blue */</font></font>

</pre> 

<P> 

To force the JPEG library to treat RGB pixels the same way Windows does, change the defines to: 

</P> 

<pre>

<font color="green">#define RGB_RED		2	<font color="navy">/* Offset of Red in an RGB scanline element */</font></font>

<font color="green">#define RGB_GREEN	1	<font color="navy">/* Offset of Green */</font></font>

<font color="green">#define RGB_BLUE	0	<font color="navy">/* Offset of Blue */</font></font>

</pre> 

<P> 

Keep in mind that these indexing problems play a role when you are compressing a 24-bit RGB image into a color JPEG 

(YCbCr) or a grayscale JPEG. However, if you are compressing a grayscale image, then you don't have to worry about it. 

</P> 

<P> 

See <TT>jmorecfg.h</TT> for more information. 

</P>                                

 

 

<BR> 

<H3> 

<A NAME="downloads">Downloads</A> 

</H3> 

 

 

<BR> 

<TABLE  BORDER=1 CELLPADDING=10 CELLSPACING=0 WIDTH="100%"> 

<TR> <TD colspan = 2><B>Downloads for this article</B> </TD> </TR> 

<TR> <TD><TT><A HREF="http://www.borland.com/bcppbuilder/freecompiler/" >bc55 </A></TT></TD><TD>Free C++ compiler from Borland.</TD> </TR> 

<TR> <TD><TT><a HREF="download/jpegsr6.zip">jpegsr6.zip</a></TT></TD><TD>JPEG source from IJG (version 6b).</TD> </TR>

<TR> <TD><TT><a HREF="download/bc55jpeg.zip">bc55jpeg.zip</a></TT></TD><TD>Makefile and modified JPEG source for BC55</TD> </TR>

<TR> <TD><TT><a HREF="download/bc55jpegdemo.zip">bc55jpegdemo.zip</a></TT></TD><TD>BC55 demo project that uses the JPEG library</TD> </TR>

</TABLE>





</TD> </TR>



</TABLE>

</CENTER>

</BODY>

</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -