mirror of https://github.com/aseprite/aseprite.git
				
				
				
			Added libjpeg in the repository.
Fixed some bugs in the GUI system. Added tabs, and removed the list-menu.
This commit is contained in:
		
							parent
							
								
									4c980d3e46
								
							
						
					
					
						commit
						df0104734f
					
				|  | @ -63,6 +63,9 @@ THANKFULNESS | |||
|   Jordan Russell and Martijn Laan: For Inno Setup. | ||||
|   <http://www.innosetup.com/> | ||||
| 
 | ||||
|   Jose Luis Torres Pantoja for his gift: the book "Digital Image | ||||
|   Processing, Gonzalez and Woods, Addison-Wesley, 2002" | ||||
| 
 | ||||
|   Juraj Michalek: For the support to ASE in his portal. | ||||
|   <http://games.linux.sk/> | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										13
									
								
								ChangeLog
								
								
								
								
							
							
						
						
									
										13
									
								
								ChangeLog
								
								
								
								
							|  | @ -1,3 +1,16 @@ | |||
| 2007-11-28  David A. Capello  <dacap@users.sourceforge.net> | ||||
| 
 | ||||
| 	* src/widgets/tabs.c: Done (finished the buttons to move the | ||||
| 	scroll). | ||||
| 
 | ||||
| 	* jinete/src/jwidget.c (jwidget_pick): Fixed a bug: the disabled | ||||
| 	widgets didn't get the mouse never (so the button-pressed message | ||||
| 	was never sent to disable widgets). | ||||
| 
 | ||||
| 2007-11-25  David A. Capello  <dacap@users.sourceforge.net> | ||||
| 
 | ||||
| 	* src/widgets/tabs.c: Added tab. | ||||
| 
 | ||||
| 2007-11-24  David A. Capello  <dacap@users.sourceforge.net> | ||||
| 
 | ||||
| 	* src/commands/cmd_new_frame.c (copy_cel_in_next_frame): Fixed | ||||
|  |  | |||
							
								
								
									
										1
									
								
								NEWS.txt
								
								
								
								
							
							
						
						
									
										1
									
								
								NEWS.txt
								
								
								
								
							|  | @ -5,6 +5,7 @@ NEWS | |||
| 0.6 | ||||
| --- | ||||
| 
 | ||||
| + Replaced the "List" menu with the tabs selector. | ||||
| + Better file selector. | ||||
| + Restructured all the menus (more user friendly options). | ||||
|   - Temporaly removed a lot of complex functionality:  | ||||
|  |  | |||
							
								
								
									
										2
									
								
								config.h
								
								
								
								
							
							
						
						
									
										2
									
								
								config.h
								
								
								
								
							|  | @ -25,7 +25,7 @@ | |||
| /* general information */ | ||||
| #define PACKAGE			"ase" | ||||
| #define VERSION			"0.6" | ||||
| #define WEBSITE			"http://www.aseprite.com/"
 | ||||
| #define WEBSITE			"http://www.aseprite.org/"
 | ||||
| #define BUGREPORT		"ase-help@lists.sourceforge.net" | ||||
| #define COPYRIGHT		"Copyright (C) 2001-2005, 2007 David A. Capello" | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										
											BIN
										
									
								
								data/aseicon.ico
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								data/aseicon.ico
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 3.6 KiB | 
|  | @ -1,5 +1,6 @@ | |||
| <!-- Copyright (C) 2007 by David A. Capello --> | ||||
| <gui> | ||||
|     <!-- keyboard shortcuts --> | ||||
|     <keyboard> | ||||
| 	<!-- file --> | ||||
| 	<key command="new_file" shortcut="Ctrl+N" /> | ||||
|  | @ -71,6 +72,8 @@ | |||
| 	<key command="tips" shortcut="F1" /> | ||||
| 	<key command="options" shortcut="Shift+Ctrl+O" /> | ||||
|     </keyboard> | ||||
| 
 | ||||
|     <!-- main bar menu --> | ||||
|     <menu id="main_menu"> | ||||
| 	<menu name="&File"> | ||||
| 	    <item command="new_file" name="&New" /> | ||||
|  | @ -127,9 +130,9 @@ | |||
| 	<menu name="&Sprite"> | ||||
| 	    <item command="sprite_properties" name="&Properties" /> | ||||
| 	    <separator /> | ||||
| 	    <item command="duplicate_sprite" name="&Duplicate" /> | ||||
| 	    <item command="change_image_type" name="Image &Type" /> | ||||
| 	    <item command="change_image_type" name="&Color Mode" /> | ||||
| 	    <separator /> | ||||
| 	    <item command="duplicate_sprite" name="&Duplicate" /> | ||||
| 	    <item command="crop_sprite" name="Cr&op" /> | ||||
| 	    <item command="autocrop_sprite" name="&Auto Crop" /> | ||||
| 	</menu> | ||||
|  | @ -137,7 +140,7 @@ | |||
| 	    <item command="layer_properties" name="&Properties" /> | ||||
| 	    <separator /> | ||||
| 	    <item command="new_layer" name="&New" /> | ||||
| 	    <item command="new_layer_set" name="New &Set" /> | ||||
| <!-- 	    <item command="new_layer_set" name="New &Set" /> --> | ||||
| 	    <item command="remove_layer" name="&Remove" /> | ||||
| 	    <separator /> | ||||
| 	    <item command="duplicate_layer" name="&Duplicate" /> | ||||
|  | @ -211,6 +214,6 @@ | |||
| 	    <item command="tips" name="T&ips" /> | ||||
| 	    <item command="options" name="&Options" /> | ||||
| 	</menu> | ||||
| 	<item id="sprite_list" name="L&ist" /> | ||||
|     </menu> | ||||
| 
 | ||||
| </gui> | ||||
|  |  | |||
|  | @ -3,14 +3,14 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Cel Properties") name="cel_properties"> | ||||
| <window text="Cel Properties" name="cel_properties"> | ||||
|   <box vertical> | ||||
|     <box horizontal expansive> | ||||
|       <box vertical homogeneous> | ||||
|         <label text=_("Frame:") /> | ||||
|         <label text=_("X position:") /> | ||||
|         <label text=_("Y position:") /> | ||||
|         <label text=_("Opacity:") /> | ||||
|         <label text="Frame:" /> | ||||
|         <label text="X position:" /> | ||||
|         <label text="Y position:" /> | ||||
|         <label text="Opacity:" /> | ||||
|       </box> | ||||
|       <box vertical homogeneous expansive> | ||||
| 	<entry maxsize=32 name="frame" /> | ||||
|  | @ -20,8 +20,8 @@ | |||
|       </box> | ||||
|     </box> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,15 +3,15 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Color Curve") name="color_curve"> | ||||
| <window text="Color Curve" name="color_curve"> | ||||
|   <box vertical> | ||||
|     <box horizontal expansive> | ||||
|       <view expansive name="curve" /><!-- custom widget --> | ||||
|       <box vertical> | ||||
|         <button text=_("&OK") name="button_ok" magnetic /> | ||||
|         <button text=_("&Cancel") /> | ||||
|         <button text="&OK" name="button_ok" magnetic /> | ||||
|         <button text="&Cancel" /> | ||||
|         <box name="target" /> | ||||
|         <check text=_("&Preview") name="preview" /> | ||||
|         <check text="&Preview" name="preview" /> | ||||
|       </box> | ||||
|     </box> | ||||
|   </box> | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Color Selection") name="color_selection"> | ||||
| <window text="Color Selection" name="color_selection"> | ||||
| <!--   <box horizontal> --> | ||||
|     <box vertical expansive> | ||||
|       <box horizontal> | ||||
|  | @ -35,8 +35,8 @@ | |||
|       <view name="palette_editor" expansive /> <!-- custom-widget --> | ||||
|       <box name="color_viewer" expansive /> <!-- custom-widget --> | ||||
|       <box horizontal homogeneous> | ||||
| 	<button text=_("&OK") name="button_ok" magnetic /> | ||||
| 	<button text=_("&Cancel") /> | ||||
| 	<button text="&OK" name="button_ok" magnetic /> | ||||
| 	<button text="&Cancel" /> | ||||
|       </box> | ||||
|     </box> | ||||
| <!--     <box vertical> --> | ||||
|  |  | |||
|  | @ -0,0 +1,27 @@ | |||
| <!-- ASE - Allegro Sprite Editor --> | ||||
| <!-- Copyright (C) 2001-2005, 2007 by David A. Capello --> | ||||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text="Configure Screen" name="configure_screen" width="200"> | ||||
|   <box vertical> | ||||
|     <box horizontal expansive> | ||||
|       <box vertical homogeneous> | ||||
|         <label text="Resolution:" /> | ||||
|         <label text="Color depth:" /> | ||||
|         <label text="Pixel scale:" /> | ||||
|         <check text="Fullscreen" name="fullscreen" /> | ||||
|       </box> | ||||
|       <box vertical homogeneous expansive> | ||||
| 	<combobox name="resolution" /> | ||||
|         <combobox name="color_depth" /> | ||||
|         <combobox name="pixel_scale" /> | ||||
|         <label text="" /> | ||||
|       </box> | ||||
|     </box> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text="&OK" name="ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  | @ -3,64 +3,64 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Convolution Matrix") name="convolution_matrix"> | ||||
| <window text="Convolution Matrix" name="convolution_matrix"> | ||||
|   <box vertical> | ||||
|     <box horizontal expansive> | ||||
|       <view expansive name="view" /><!-- custom widget --> | ||||
|       <box vertical> | ||||
|         <button text=_("&OK") name="button_ok" magnetic /> | ||||
|         <button text=_("&Cancel") /> | ||||
|         <button text="&OK" name="button_ok" magnetic /> | ||||
|         <button text="&Cancel" /> | ||||
|         <box name="target" /> | ||||
|         <check text=_("&Preview") name="preview" /> | ||||
|         <check text=_("&Tiled") name="tiled" /> | ||||
|         <check text="&Preview" name="preview" /> | ||||
|         <check text="&Tiled" name="tiled" /> | ||||
|       </box> | ||||
|     </box> | ||||
|     <box horizontal> | ||||
|       <button text=_("&Reload Stock") name="reload" /> | ||||
|       <button text=_("&Generate") name="generate" /> | ||||
|       <button text="&Reload Stock" name="reload" /> | ||||
|       <button text="&Generate" name="generate" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
| 
 | ||||
| <window text=_("Generate New Matrix") name="generate_convolution_matrix"> | ||||
| <window text="Generate New Matrix" name="generate_convolution_matrix"> | ||||
|   <box vertical> | ||||
|     <box horizontal expansive homogeneous> | ||||
|       <box vertical expansive> | ||||
|         <label text=_("X axis") /> | ||||
|         <label text="X axis" /> | ||||
|         <view expansive name="view_x" /><!-- custom widget --> | ||||
|       </box> | ||||
|       <box vertical expansive> | ||||
|         <label text=_("Y axis") /> | ||||
|         <label text="Y axis" /> | ||||
|         <view expansive name="view_y" /><!-- custom widget --> | ||||
|       </box> | ||||
|     </box> | ||||
|     <box horizontal homogeneous> | ||||
|       <box horizontal> | ||||
|         <box vertical homogeneous> | ||||
|           <label text=_("Width:") /> | ||||
|           <label text=_("Height:") /> | ||||
|           <label text="Width:" /> | ||||
|           <label text="Height:" /> | ||||
| 	</box> | ||||
|         <box vertical homogeneous expansive> | ||||
|           <slider min="1" max="31" name="width" /> | ||||
|           <slider min="1" max="31" name="height" /> | ||||
| 	</box> | ||||
|         <box vertical homogeneous> | ||||
|           <label text=_("Div:") /> | ||||
|           <label text=_("Bias:") /> | ||||
|           <label text="Div:" /> | ||||
|           <label text="Bias:" /> | ||||
| 	</box> | ||||
|         <box vertical homogeneous expansive> | ||||
|           <entry maxsize=32 name="div" /> | ||||
|           <entry maxsize=32 name="bias" /> | ||||
| 	</box> | ||||
|         <box vertical homogeneous> | ||||
|           <check text=_("Auto") name="div_auto" /> | ||||
|           <check text=_("Auto") name="bias_auto" /> | ||||
|           <check text="Auto" name="div_auto" /> | ||||
|           <check text="Auto" name="bias_auto" /> | ||||
| 	</box> | ||||
|       </box> | ||||
|     </box> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="button_ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="button_ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,35 +3,35 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Draw Text") name="drawtext_window"> | ||||
| <window text="Draw Text" name="drawtext_window"> | ||||
|   <box vertical> | ||||
|     <box horizontal> | ||||
|       <box vertical homogeneous> | ||||
| 	<label text=_("Font:") /> | ||||
| 	<label text=_("Size:") /> | ||||
| 	<label text="Font:" /> | ||||
| 	<label text="Size:" /> | ||||
|       </box> | ||||
|       <box vertical homogeneous expansive> | ||||
| 	<button text="" name="font" /> | ||||
| 	<entry maxsize=8 name="size"/> | ||||
|       </box> | ||||
|     </box> | ||||
| <!--     <label text=_("Fixed Size:") /> --> | ||||
| <!--     <label text="Fixed Size:" /> --> | ||||
| <!--     <view expansive> --> | ||||
| <!--       <listbox /> --> | ||||
| <!--     </view> --> | ||||
|     <separator horizontal /> | ||||
|     <box horizontal> | ||||
|       <box vertical homogeneous> | ||||
| 	<label text=_("Text:") /> | ||||
| 	<label text=_("Color:") /> | ||||
| 	<label text="Text:" /> | ||||
| 	<label text="Color:" /> | ||||
|       </box> | ||||
|       <box vertical homogeneous expansive name="color_box"> | ||||
| 	<entry maxsize=256 name="text" expansive /> | ||||
|       </box> | ||||
|     </box> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,22 +3,22 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Duplicate Sprite") name="duplicate_sprite"> | ||||
| <window text="Duplicate Sprite" name="duplicate_sprite"> | ||||
|   <box vertical> | ||||
|     <box horizontal expansive> | ||||
|       <box vertical homogeneous> | ||||
|         <label text=_("Duplicate:") /> | ||||
|         <label text=_("As:") /> | ||||
|         <label text="Duplicate:" /> | ||||
|         <label text="As:" /> | ||||
|       </box> | ||||
|       <box vertical homogeneous expansive> | ||||
|         <label text="" name="src_name" /> | ||||
|         <entry maxsize="256" name="dst_name" /> | ||||
|       </box> | ||||
|     </box> | ||||
|     <check text=_("Duplicate merged layers only") name="flatten" /> | ||||
|     <check text="Duplicate merged layers only" name="flatten" /> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,12 +3,12 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Frame Duration") name="frame_duration"> | ||||
| <window text="Frame Duration" name="frame_duration"> | ||||
|   <box vertical> | ||||
|     <box horizontal expansive> | ||||
|       <box vertical homogeneous> | ||||
|         <label text=_("Frame number:") /> | ||||
|         <label text=_("Duration (milliseconds):") /> | ||||
|         <label text="Frame number:" /> | ||||
|         <label text="Duration (milliseconds):" /> | ||||
|       </box> | ||||
|       <box vertical homogeneous expansive> | ||||
|         <label text="" name="frame" /> | ||||
|  | @ -16,8 +16,8 @@ | |||
|       </box> | ||||
|     </box> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,24 +3,24 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Convert Image Type") name="image_type"> | ||||
| <window text="Convert Color" name="image_type"> | ||||
|   <box vertical> | ||||
|     <box vertical expansive> | ||||
|       <box horizontal> | ||||
|         <label text=_("From:") /> | ||||
|         <label text="From:" /> | ||||
|         <label text="" name="from" /> | ||||
|       </box> | ||||
|       <label text=_("To:") /> | ||||
|       <radio name="imgtype1" text=_("&RGB") group=1 /> | ||||
|       <radio name="imgtype2" text=_("&Grayscale") group=1 /> | ||||
|       <radio name="imgtype3" text=_("&Indexed") group=1 /> | ||||
|       <label text="To:" /> | ||||
|       <radio name="imgtype1" text="&RGB Color" group=1 /> | ||||
|       <radio name="imgtype2" text="&Grayscale" group=1 /> | ||||
|       <radio name="imgtype3" text="&Indexed" group=1 /> | ||||
|       <separator horizontal /> | ||||
|       <radio name="dither1" text=_("&No Dithering") group=2 /> | ||||
|       <radio name="dither2" text=_("&Ordered Dither") group=2 /> | ||||
|       <radio name="dither1" text="&No Dithering" group=2 /> | ||||
|       <radio name="dither2" text="&Ordered Dither" group=2 /> | ||||
|     </box> | ||||
|     <box horizontal expansive homogeneous> | ||||
|       <button text=_("&OK") name="ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,13 +3,13 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Invert Color") name="invert_color"> | ||||
| <window text="Invert Color" name="invert_color"> | ||||
|   <box vertical> | ||||
|     <box vertical expansive name="target" /> | ||||
|     <check text=_("&Preview") name="preview" /> | ||||
|     <check text="&Preview" name="preview" /> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="button_ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="button_ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| <window noborders desktop text="Main Window" name="main_window"> | ||||
|   <box noborders vertical> | ||||
|     <box noborders horizontal name="menu_bar" /> | ||||
|     <box noborders horizontal name="tabs_bar" /> | ||||
|     <box noborders horizontal expansive> | ||||
|       <box noborders vertical name="color_bar" /> | ||||
|       <box noborders horizontal name="editor" expansive /> | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Map Generator") name="mapgen"> | ||||
| <window text="Map Generator" name="mapgen"> | ||||
|   <panel horizontal> | ||||
|     <view name="mapview" expansive /><!-- custom-widget --> | ||||
|     <box vertical> | ||||
|  | @ -11,8 +11,8 @@ | |||
|       <box horizontal> | ||||
| 	<box horizontal expansive> | ||||
|           <box vertical homogeneous> | ||||
|             <label text=_("Width:") /> | ||||
|             <label text=_("Height:") /> | ||||
|             <label text="Width:" /> | ||||
|             <label text="Height:" /> | ||||
|           </box> | ||||
|           <box vertical homogeneous expansive> | ||||
|             <entry expansive name="width" maxsize=8 /> | ||||
|  | @ -21,22 +21,22 @@ | |||
| 	</box> | ||||
|       </box> | ||||
| 
 | ||||
|       <label text=_("Seed:") /> | ||||
|       <label text="Seed:" /> | ||||
|       <box horizontal> | ||||
|         <entry expansive name="seed" maxsize=32 /> | ||||
|         <button text="&Random" name="random_seed" /> | ||||
|       </box> | ||||
| 
 | ||||
|       <label text=_("Fractal Factor:") /> | ||||
|       <label text="Fractal Factor:" /> | ||||
|       <box horizontal> | ||||
| 	<entry expansive name="fractal_factor" maxsize=32 /> | ||||
|         <button text="sqrt2" name="sqrt2_factor" /> | ||||
|       </box> | ||||
| 
 | ||||
|       <check text=_("&Preview") name="preview" /> | ||||
|       <check text=_("&Tiled") name="tiled" /> | ||||
|       <button text=_("&OK") name="button_ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <check text="&Preview" name="preview" /> | ||||
|       <check text="&Tiled" name="tiled" /> | ||||
|       <button text="&OK" name="button_ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,13 +3,13 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Median Blur") name="median"> | ||||
| <window text="Median Blur" name="median"> | ||||
|   <box vertical> | ||||
|     <box horizontal> | ||||
|       <box horizontal expansive> | ||||
|         <box vertical homogeneous> | ||||
|           <label text=_("Width:") /> | ||||
|           <label text=_("Height:") /> | ||||
|           <label text="Width:" /> | ||||
|           <label text="Height:" /> | ||||
|         </box> | ||||
|         <box vertical homogeneous expansive> | ||||
|           <entry expansive name="width" maxsize=4 /> | ||||
|  | @ -18,13 +18,13 @@ | |||
|       </box> | ||||
|       <box vertical> | ||||
|         <box name="target" /> | ||||
|         <check text=_("&Preview") name="preview" /> | ||||
|         <check text=_("&Tiled") name="tiled" /> | ||||
|         <check text="&Preview" name="preview" /> | ||||
|         <check text="&Tiled" name="tiled" /> | ||||
|       </box> | ||||
|     </box> | ||||
|     <box horizontal homogeneous expansive> | ||||
|       <button text=_("&OK") name="button_ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="button_ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,36 +3,36 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("New Image Layer") name="new_layer"> | ||||
| <window text="New Image Layer" name="new_layer"> | ||||
|   <box vertical> | ||||
|     <box horizontal> | ||||
|       <box vertical homogeneous> | ||||
|         <label text=_("Name:") /> | ||||
|         <label text=_("Width:") /> | ||||
|         <label text=_("Height:") /> | ||||
|         <label text="Name:" /> | ||||
|         <label text="Width:" /> | ||||
|         <label text="Height:" /> | ||||
|       </box> | ||||
|       <box vertical homogeneous> | ||||
|         <entry maxsize=256 text=_("New Layer") name="name" /> | ||||
|         <entry maxsize=256 text="New Layer" name="name" /> | ||||
|         <entry maxsize=4 name="width" /> | ||||
|         <entry maxsize=4 name="height" /> | ||||
|       </box> | ||||
|     </box> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
| 
 | ||||
| <window text=_("New Layer Set") name="new_layer_set"> | ||||
| <window text="New Layer Set" name="new_layer_set"> | ||||
|   <box vertical> | ||||
|     <box horizontal> | ||||
|       <label text=_("Name:") /> | ||||
|       <entry maxsize=256 text=_("New Set") name="name" /> | ||||
|       <label text="Name:" /> | ||||
|       <entry maxsize=256 text="New Set" name="name" /> | ||||
|     </box> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,16 +3,16 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("New Sprite") name="new_sprite"> | ||||
| <window text="New Sprite" name="new_sprite"> | ||||
|   <box vertical> | ||||
|     <box horizontal> | ||||
|       <box vertical expansive> | ||||
|         <separator text=_("Size:") left horizontal /> | ||||
|         <separator text="Size:" left horizontal /> | ||||
|         <box vertical expansive> | ||||
|           <box horizontal> | ||||
|             <box vertical homogeneous> | ||||
|               <label text=_("Width:") /> | ||||
|               <label text=_("Height:") /> | ||||
|               <label text="Width:" /> | ||||
|               <label text="Height:" /> | ||||
|             </box> | ||||
|             <box vertical homogeneous expansive> | ||||
|               <entry expansive name="width" maxsize=8 /> | ||||
|  | @ -22,27 +22,27 @@ | |||
|         </box> | ||||
|       </box> | ||||
|       <box vertical> | ||||
|         <separator text=_("Type:") left horizontal /> | ||||
|         <separator text="Color Mode:" left horizontal /> | ||||
|         <box vertical homogeneous> | ||||
|           <radio name="radio1" text=_("&RGB") group=1 /> | ||||
| 	  <radio name="radio2" text=_("&Grayscale") group=1 /> | ||||
| 	  <radio name="radio3" text=_("&Indexed") group=1 /> | ||||
|           <radio name="radio1" text="&RGB Color" group=1 /> | ||||
| 	  <radio name="radio2" text="&Grayscale" group=1 /> | ||||
| 	  <radio name="radio3" text="&Indexed" group=1 /> | ||||
| 	</box> | ||||
|       </box> | ||||
|     </box> | ||||
|     <separator text=_("Background:") left horizontal /> | ||||
|     <separator text="Background:" left horizontal /> | ||||
|     <view maxsize expansive> | ||||
|       <listbox name="bg_box"> | ||||
|         <listitem text=_("Transparent (mask color)") /> | ||||
|         <listitem text=_("Black") /> | ||||
|         <listitem text=_("White") /> | ||||
|         <listitem text=_("Magenta") /> | ||||
|         <listitem text=_("Custom") /> | ||||
|         <listitem text="Transparent (mask color)" /> | ||||
|         <listitem text="Black" /> | ||||
|         <listitem text="White" /> | ||||
|         <listitem text="Magenta" /> | ||||
|         <listitem text="Custom" /> | ||||
|       </listbox> | ||||
|     </view> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="ok_button" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="ok_button" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,49 +3,49 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Options") name="options"> | ||||
| <window text="Options" name="options"> | ||||
|   <box vertical> | ||||
|     <box horizontal> | ||||
|       <box vertical> | ||||
| 
 | ||||
| 	<label text=_("Mouse Speed:") /> | ||||
| 	<label text="Mouse Speed:" /> | ||||
| 	<box horizontal> | ||||
| 	  <box vertical homogeneous> | ||||
|             <label text=_("X:") /> | ||||
|             <label text=_("Y:") /> | ||||
|             <label text="X:" /> | ||||
|             <label text="Y:" /> | ||||
| 	  </box> | ||||
| 	  <box vertical homogeneous expansive> | ||||
|             <slider min="-8" max="8" name="mouse_x" /> | ||||
|             <slider min="-8" max="8" name="mouse_y" /> | ||||
| 	  </box> | ||||
| 	</box> | ||||
| 	<check text=_("Lock X/Y") name="lock_axis" /> | ||||
| 	<check text="Lock X/Y" name="lock_axis" /> | ||||
| 
 | ||||
| 	<separator horizontal /> | ||||
| 
 | ||||
| 	<label text=_("Movement Delay (milliseconds):") /> | ||||
| 	<label text="Movement Delay (milliseconds):" /> | ||||
| 	<slider min="0" max="1000" name="move_delay" /> | ||||
| 	<check text=_("Smooth auto-scroll") name="smooth" /> | ||||
| 	<check text=_("Real-time ordered dithering") name="dither" /> | ||||
| 	<check text="Smooth auto-scroll" name="smooth" /> | ||||
| 	<check text="Real-time ordered dithering" name="dither" /> | ||||
| 
 | ||||
|       </box> | ||||
|       <separator vertical /> | ||||
|       <box vertical> | ||||
| 
 | ||||
| 	<label text="" name="label_font" /> | ||||
| 	<button text=_("Change GUI Font") name="button_font" /> | ||||
| 	<button text=_("Change Language") name="button_lang" /> | ||||
| 	<button text="Change GUI Font" name="button_font" /> | ||||
| 	<button text="Change Language" name="button_lang" /> | ||||
| 	<separator horizontal /> | ||||
| 	<check text=_("2 Click Movement") name="move_click2" /> | ||||
| 	<check text=_("2 Click Drawing") name="draw_click2" /> | ||||
| 	<check text="2 Click Movement" name="move_click2" /> | ||||
| 	<check text="2 Click Drawing" name="draw_click2" /> | ||||
| 
 | ||||
|       </box> | ||||
|     </box> | ||||
| 
 | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="button_ok" magnetic /> | ||||
|       <button text=_("&Save") name="button_save" /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="button_ok" magnetic /> | ||||
|       <button text="&Save" name="button_save" /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Palette Editor") name="palette_editor"> | ||||
| <window text="Palette Editor" name="palette_editor"> | ||||
|   <box vertical> | ||||
|     <box horizontal expansive> | ||||
|       <box vertical> | ||||
|  | @ -34,27 +34,27 @@ | |||
|           </box> | ||||
| 	</box> | ||||
| 	<box name="color_viewer" expansive /> <!-- custom-widget --> | ||||
| 	<button text=_("Select &All") name="select_all" /> | ||||
| 	<button text="Select &All" name="select_all" /> | ||||
| 	<box vertical> | ||||
| 	  <box horizontal homogeneous> | ||||
| 	    <button text=_("&Undo") name="undo" /> | ||||
| 	    <button text=_("&Redo") name="redo" /> | ||||
| 	    <button text="&Undo" name="undo" /> | ||||
| 	    <button text="&Redo" name="redo" /> | ||||
| 	  </box> | ||||
| 	  <box horizontal homogeneous> | ||||
| 	    <button text=_("&Load") name="load" /> | ||||
| 	    <button text=_("&Save") name="save" /> | ||||
| 	    <button text="&Load" name="load" /> | ||||
| 	    <button text="&Save" name="save" /> | ||||
| 	  </box> | ||||
| 	  <box horizontal homogeneous> | ||||
| 	    <button text=_("&Ramp") name="ramp" /> | ||||
| 	    <button text=_("&Quantize") name="quantize" /> | ||||
| 	    <button text="&Ramp" name="ramp" /> | ||||
| 	    <button text="&Quantize" name="quantize" /> | ||||
| 	  </box> | ||||
| 	</box> | ||||
|       </box> | ||||
|     </box> | ||||
|     <slider min="0" max="1" name="frame" /> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="button_ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="button_ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,14 +3,14 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Play FLI/FLC") name="play_fli"> | ||||
| <window text="Play FLI/FLC" name="play_fli"> | ||||
|   <box vertical> | ||||
|     <check text=_("Loop") name="loop" /> | ||||
|     <check text=_("Fullscreen") name="fullscreen" /> | ||||
|     <button text=_("&Open") name="button_open" /> | ||||
|     <check text="Loop" name="loop" /> | ||||
|     <check text="Fullscreen" name="fullscreen" /> | ||||
|     <button text="&Open" name="button_open" /> | ||||
|     <box horizontal homogeneous expansive> | ||||
|       <button text=_("&Play") name="button_play" magnetic /> | ||||
|       <button text=_("&Close") /> | ||||
|       <button text="&Play" name="button_play" magnetic /> | ||||
|       <button text="&Close" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,12 +3,12 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Point Properties") name="point_properties"> | ||||
| <window text="Point Properties" name="point_properties"> | ||||
|   <box vertical> | ||||
|     <box horizontal expansive> | ||||
|       <box vertical homogeneous> | ||||
|         <label text=_("X:") /> | ||||
|         <label text=_("Y:") /> | ||||
|         <label text="X:" /> | ||||
|         <label text="Y:" /> | ||||
|       </box> | ||||
|       <box vertical homogeneous expansive> | ||||
|         <entry maxsize="32" name="x" /> | ||||
|  | @ -16,8 +16,8 @@ | |||
|       </box> | ||||
|     </box> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="button_ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="button_ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,13 +3,13 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Replace Color") name="replace_color"> | ||||
| <window text="Replace Color" name="replace_color"> | ||||
|   <box horizontal> | ||||
|     <box vertical expansive> | ||||
|       <box horizontal expansive> | ||||
|         <box vertical homogeneous> | ||||
|           <label text=_("Get:") /> | ||||
|           <label text=_("Put:") /> | ||||
|           <label text="Get:" /> | ||||
|           <label text="Put:" /> | ||||
|         </box> | ||||
|         <box vertical homogeneous expansive> | ||||
|           <box horizontal expansive> | ||||
|  | @ -25,14 +25,14 @@ | |||
|           </box> | ||||
|         </box> | ||||
|       </box> | ||||
|       <label text=_("Fuzziness:") /> | ||||
|       <label text="Fuzziness:" /> | ||||
|       <slider min=0 max=255 name="fuzziness" /> | ||||
|     </box> | ||||
|     <box vertical> | ||||
|       <button text=_("&OK") name="button_ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="button_ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|       <box name="target" /> | ||||
|       <check text=_("&Preview") name="preview" /> | ||||
|       <check text="&Preview" name="preview" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,14 +3,14 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Sprite Properties") name="sprite_properties"> | ||||
| <window text="Sprite Properties" name="sprite_properties"> | ||||
|   <box vertical> | ||||
|     <box horizontal expansive> | ||||
|       <box vertical homogeneous> | ||||
|         <label text=_("File name:") /> | ||||
|         <label text=_("Type:") /> | ||||
|         <label text=_("Size:") /> | ||||
|         <label text=_("Frames:") /> | ||||
|         <label text="File name:" /> | ||||
|         <label text="Type:" /> | ||||
|         <label text="Size:" /> | ||||
|         <label text="Frames:" /> | ||||
|       </box> | ||||
|       <box vertical homogeneous expansive> | ||||
|         <entry maxsize=256 name="name" /> | ||||
|  | @ -19,10 +19,10 @@ | |||
|         <entry maxsize=4 name="frames" /> | ||||
|       </box> | ||||
|     </box> | ||||
|     <button text=_("Constant Frame-Rate Speed") name="speed" /> | ||||
|     <button text="Constant Frame-Rate Speed" name="speed" /> | ||||
|     <box horizontal homogeneous> | ||||
|       <button text=_("&OK") name="ok" magnetic /> | ||||
|       <button text=_("&Cancel") /> | ||||
|       <button text="&OK" name="ok" magnetic /> | ||||
|       <button text="&Cancel" /> | ||||
|     </box> | ||||
|   </box> | ||||
| </window> | ||||
|  |  | |||
|  | @ -3,27 +3,27 @@ | |||
| 
 | ||||
| <!-- Read "LEGAL.txt" for more information. --> | ||||
| 
 | ||||
| <window text=_("Tools Setup") name="configure_tool"> | ||||
| <window text="Tools Setup" name="configure_tool"> | ||||
|   <box vertical> | ||||
|     <box horizontal expansive> | ||||
|       <box vertical> | ||||
|         <separator text=_("General:") horizontal left /> | ||||
|         <check text=_("Filled") name="filled" /> | ||||
|         <check text=_("Tiled") name="tiled" /> | ||||
| 	<check text=_("Onionskin") name="onionskin" /> | ||||
|         <separator text=_("Grid:") horizontal left /> | ||||
|         <check text=_("Snap to Grid") name="use_grid" /> | ||||
|         <check text=_("View Grid") name="view_grid" /> | ||||
|         <button text=_("Set &Grid") name="set_grid" /> | ||||
|         <separator text=_("Cursor:") horizontal left /> | ||||
|         <separator text="General:" horizontal left /> | ||||
|         <check text="Filled" name="filled" /> | ||||
|         <check text="Tiled" name="tiled" /> | ||||
| 	<check text="Onionskin" name="onionskin" /> | ||||
|         <separator text="Grid:" horizontal left /> | ||||
|         <check text="Snap to Grid" name="use_grid" /> | ||||
|         <check text="View Grid" name="view_grid" /> | ||||
|         <button text="Set &Grid" name="set_grid" /> | ||||
|         <separator text="Cursor:" horizontal left /> | ||||
| 	<box name="cursor_color_box" /><!-- custom widget --> | ||||
|       </box> | ||||
|       <box vertical expansive> | ||||
|         <separator text=_("Brush:") horizontal left /> | ||||
|         <separator text="Brush:" horizontal left /> | ||||
|         <box horizontal> | ||||
|           <box vertical homogeneous> | ||||
|             <label text=_("Size:") /> | ||||
|             <label text=_("Angle:") /> | ||||
|             <label text="Size:" /> | ||||
|             <label text="Angle:" /> | ||||
|           </box> | ||||
|           <box vertical homogeneous expansive> | ||||
|             <slider min=1 max=32 name="brush_size" /> | ||||
|  | @ -35,13 +35,13 @@ | |||
|           </box> | ||||
| 	  <box name="brush_preview_box" /><!-- custom widget --> | ||||
|         </box> | ||||
| 	<separator text=_("Glass Dirty:") horizontal left /> | ||||
| 	<separator text="Glass Dirty:" horizontal left /> | ||||
|         <slider min=0 max=255 name="glass_dirty" /> | ||||
|         <separator text=_("Spray:") horizontal left /> | ||||
|         <separator text="Spray:" horizontal left /> | ||||
| 	<box horizontal> | ||||
| 	  <box vertical homogeneous> | ||||
| 	    <label text=_("Spray Width:") /> | ||||
| 	    <label text=_("Air Speed:") /> | ||||
| 	    <label text="Spray Width:" /> | ||||
| 	    <label text="Air Speed:" /> | ||||
| 	  </box> | ||||
| 	  <box vertical homogeneous expansive> | ||||
| 	    <slider min=1 max=32 name="spray_width" /> | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ | |||
| Welcome to ASE 0.6 | ||||
| 
 | ||||
| You can find help in ASE Wiki: | ||||
| http://www.allegrospriteeditor.com.ar/wiki/ | ||||
| http://www.aseprite.org/wiki/ | ||||
| 
 | ||||
| Report bugs to: | ||||
| ase-help@lists.sourceforge.net | ||||
|  | @ -125,6 +125,6 @@ directory for some examples. | |||
| \image sprite.pcx | ||||
| And remember look for updates in: | ||||
| 
 | ||||
| http://www.allegrospriteeditor.com.ar/ | ||||
| http://www.aseprite.org/ | ||||
| 
 | ||||
| Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 by David A. Capello | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ | |||
| Bienvenido a ASE 0.6 | ||||
| 
 | ||||
| Puede encontrar ayuda en la Wiki de ASE: | ||||
| http://www.allegrospriteeditor.com.ar/wiki/ | ||||
| http://www.aseprite.org/wiki/ | ||||
| 
 | ||||
| Reporte bugs y errores a: | ||||
| ase-help@lists.sourceforge.net | ||||
|  | @ -115,6 +115,6 @@ tareas repetitivas?  Puede buscar la documentaci | |||
| \image sprite.pcx | ||||
| Y recuerde buscar actualizaciones en: | ||||
| 
 | ||||
| http://www.allegrospriteeditor.com.ar/ | ||||
| http://www.aseprite.org/ | ||||
| 
 | ||||
| Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 por David A. Capello | ||||
|  |  | |||
							
								
								
									
										27
									
								
								fix.sh
								
								
								
								
							
							
						
						
									
										27
									
								
								fix.sh
								
								
								
								
							|  | @ -41,18 +41,6 @@ fi | |||
| readln "Do you want use precompiled header (needs GCC >= 3.4) (y/n)?" "n" | ||||
| precompiled_header=$ans | ||||
| 
 | ||||
| ###################################################################### | ||||
| # libraries | ||||
| 
 | ||||
| readln "Do you have LibJPEG (6.2 recommended) library (y/n)?" "n" | ||||
| libjpeg=$ans | ||||
| 
 | ||||
| if [ "$libjpeg" != "y" ] ; then | ||||
|   readln "Do you have JPGalleg (2.3 needed) library (y/n)?" "n" | ||||
|   jpgalleg=$ans | ||||
|   libjpeg="" | ||||
| fi | ||||
| 
 | ||||
| ###################################################################### | ||||
| # show information | ||||
| 
 | ||||
|  | @ -80,15 +68,6 @@ fi | |||
| echo -n "  Precompiled header:	" | ||||
| if [ "$precompiled_header" == "y" ] ; then echo "yes" ; else echo "no" ; fi | ||||
| 
 | ||||
| echo -n "  JPEG suppport:	" | ||||
| if [ "$libjpeg" == "y" ] ; then | ||||
|   echo "yes (LibJPEG)" | ||||
| elif [ "$jpgalleg" == "y" ] ; then | ||||
|   echo "yes (JPGalleg)" | ||||
| else | ||||
|   echo "no" | ||||
| fi | ||||
| 
 | ||||
| echo "" | ||||
| readln "Is it right (y/n)?" "y" | ||||
| if [ $ans != "y" ] ; then exit ; fi | ||||
|  | @ -135,12 +114,6 @@ gen_makefile() | |||
|   if [ "$precompiled_header" != "y" ] ; then echo -n "#" >> $makefile ; fi | ||||
|   echo "USE_PRECOMPILED_HEADER = 1" >> $makefile | ||||
| 
 | ||||
|   if [ "$libjpeg" != "y" ] ; then echo -n "#" >> $makefile ; fi | ||||
|   echo "HAVE_LIBJPEG = 1" >> $makefile | ||||
| 
 | ||||
|   if [ "$jpgalleg" != "y" ] ; then echo -n "#" >> $makefile ; fi | ||||
|   echo "HAVE_JPGALLEG = 1" >> $makefile | ||||
| 
 | ||||
|   echo "#USE_X86_INT_MULT = 1" >> $makefile | ||||
|   echo "" >> $makefile | ||||
|   echo "include $makefile_name" >> $makefile | ||||
|  |  | |||
|  | @ -119,7 +119,7 @@ void jmessage_broadcast_to_parents(JMessage msg, JWidget widget); | |||
| 
 | ||||
| void jmessage_set_sub_msg(JMessage msg, JMessage sub_msg); | ||||
| 
 | ||||
| /* XXX */ | ||||
| /* TODO */ | ||||
| /* void jmessage_set_marshal(JMessage msg, JMarshal marshal); */ | ||||
| 
 | ||||
| JI_END_DECLS | ||||
|  |  | |||
|  | @ -55,6 +55,12 @@ struct jtheme | |||
|   void (*init_widget)(JWidget widget); | ||||
|   JRegion (*get_window_mask)(JWidget widget); | ||||
|   void (*map_decorative_widget)(JWidget widget); | ||||
|   int (*color_foreground)(void); | ||||
|   int (*color_disabled)(void); | ||||
|   int (*color_face)(void); | ||||
|   int (*color_hotface)(void); | ||||
|   int (*color_selected)(void); | ||||
|   int (*color_background)(void); | ||||
|   int nmethods; | ||||
|   JDrawFunc *methods; | ||||
| }; | ||||
|  | @ -74,6 +80,15 @@ void ji_set_standard_theme(void); | |||
| JTheme ji_get_theme(void); | ||||
| void ji_regen_theme(void); | ||||
| 
 | ||||
| int ji_color_foreground(void); | ||||
| int ji_color_disabled(void); | ||||
| int ji_color_face(void); | ||||
| int ji_color_facelight(void); | ||||
| int ji_color_faceshadow(void); | ||||
| int ji_color_hotface(void); | ||||
| int ji_color_selected(void); | ||||
| int ji_color_background(void); | ||||
| 
 | ||||
| JI_END_DECLS | ||||
| 
 | ||||
| #endif /* JINETE_THEME_H */ | ||||
|  |  | |||
|  | @ -222,7 +222,7 @@ void jradio_set_group(JWidget widget, int radio_group) | |||
| 
 | ||||
|   radio->group = radio_group; | ||||
| 
 | ||||
|   /* XXX: update old and new groups */ | ||||
|   /* TODO: update old and new groups */ | ||||
| } | ||||
| 
 | ||||
| int jradio_get_group(JWidget widget) | ||||
|  | @ -387,30 +387,31 @@ static bool button_msg_proc(JWidget widget, JMessage msg) | |||
| 	  if (jwidget_is_enabled(widget)) { | ||||
| 	    jwidget_select(widget); | ||||
| 	    jwidget_capture_mouse(widget); | ||||
| 	    return TRUE; | ||||
| 	  } | ||||
| 	  break; | ||||
| 	  return TRUE; | ||||
| 
 | ||||
| 	case JI_CHECK: | ||||
| 	  if (jwidget_is_enabled(widget)) { | ||||
| 	    if (jwidget_is_selected(widget)) | ||||
| 	      jwidget_deselect(widget); | ||||
| 	    else | ||||
| 	      jwidget_select(widget); | ||||
| 
 | ||||
| 	    jwidget_capture_mouse(widget); | ||||
| 	  } | ||||
| 	  return TRUE; | ||||
| 	  break; | ||||
| 
 | ||||
| 	case JI_RADIO: | ||||
| 	  if (jwidget_is_enabled(widget)) { | ||||
| 	    if (jwidget_is_deselected(widget)) { | ||||
| 	      jwidget_signal_off(widget); | ||||
| 	      jwidget_select(widget); | ||||
| 	      jwidget_signal_on(widget); | ||||
| 
 | ||||
| 	      jwidget_capture_mouse(widget); | ||||
| 	    return TRUE; | ||||
| 	    } | ||||
| 	  break; | ||||
| 	  } | ||||
| 	  return TRUE; | ||||
|       } | ||||
|       break; | ||||
| 
 | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ | |||
| #include "jinete/system.h" | ||||
| #include "jinete/widget.h" | ||||
| 
 | ||||
| /* XXXX optional anti-aliased textout */ | ||||
| /* TODO optional anti-aliased textout */ | ||||
| #define SETUP_ANTIALISING(f, bg, fill_bg)				\ | ||||
|   ji_font_set_aa_mode (f, fill_bg ||					\ | ||||
| 			  bitmap_color_depth (ji_screen) == 8 ? bg: -1) | ||||
|  |  | |||
|  | @ -217,7 +217,8 @@ char *ji_file_select_ex(const char *message, | |||
|   jwidget_set_static_size(panel, JI_SCREEN_W*9/10, JI_SCREEN_H*3/5); | ||||
|   jwindow_remap(window); | ||||
|   jwindow_center(window); | ||||
|   jwidget_set_static_size(panel, 0, 0); | ||||
| /*   jwidget_set_static_size(panel, JI_SCREEN_W*9/10, JI_SCREEN_H*3/5); */ | ||||
| /*   jwidget_set_static_size(panel, 0, 0); */ | ||||
| 
 | ||||
|   /* fill the listbox with the files in the current directory */ | ||||
|   fill_listbox_with_files(buf, size); | ||||
|  |  | |||
|  | @ -171,7 +171,7 @@ void jmanager_free(JWidget widget) | |||
|     /* no more cursor */ | ||||
|     jmouse_set_cursor(JI_CURSOR_NULL); | ||||
| 
 | ||||
|     /* XXX destroy the AUTODESTROY windows in these lists */ | ||||
|     /* TODO destroy the AUTODESTROY windows in these lists */ | ||||
|     jlist_free(new_windows); | ||||
|     jlist_free(old_windows); | ||||
| 
 | ||||
|  | @ -219,7 +219,7 @@ bool jmanager_poll(JWidget manager, bool all_windows) | |||
|   /* poll keyboard */ | ||||
|   poll_keyboard(); | ||||
| 
 | ||||
|   /* XXX check for STAGE */ | ||||
|   /* TODO check for STAGE */ | ||||
| 
 | ||||
|   if (first_time_poll) { | ||||
|     first_time_poll = FALSE; | ||||
|  | @ -286,7 +286,7 @@ bool jmanager_poll(JWidget manager, bool all_windows) | |||
|   /* mouse movement */ | ||||
|   if (mousemove) { | ||||
|     msg = new_mouse_msg(JM_MOTION); | ||||
|     /* XXX rigid marshal */ | ||||
|     /* TODO rigid marshal */ | ||||
| 
 | ||||
|     /* reset double click status */ | ||||
|     jmouse_set_click_level(JI_CLICK_NOT); | ||||
|  | @ -304,7 +304,7 @@ bool jmanager_poll(JWidget manager, bool all_windows) | |||
|   /* mouse wheel */ | ||||
|   if (jmouse_z(0) != jmouse_z(1)) { | ||||
|     msg = new_mouse_msg(JM_WHEEL); | ||||
|     /* XXX rigid marshal */ | ||||
|     /* TODO rigid marshal */ | ||||
| 
 | ||||
|     /* send the mouse wheel message */ | ||||
|     if (capture_widget) | ||||
|  | @ -322,7 +322,7 @@ bool jmanager_poll(JWidget manager, bool all_windows) | |||
|     /* press and release button messages */ | ||||
|     msg = new_mouse_msg((!jmouse_b(1))? JM_BUTTONPRESSED: | ||||
| 					JM_BUTTONRELEASED); | ||||
|     /* XXX rigid marshal */ | ||||
|     /* TODO rigid marshal */ | ||||
| 
 | ||||
|     if (msg->type == JM_BUTTONPRESSED) | ||||
|       if (jmouse_get_click_level() == JI_CLICK_NOT) | ||||
|  | @ -386,7 +386,7 @@ bool jmanager_poll(JWidget manager, bool all_windows) | |||
|   /* double clicks */ | ||||
|   if (jmouse_get_click_level() == JI_CLICK_AGAIN) { | ||||
|     msg = new_mouse_msg(JM_DOUBLECLICK); | ||||
|     /* XXX rigid marshal */ | ||||
|     /* TODO rigid marshal */ | ||||
| 
 | ||||
|     jmouse_set_click_level(JI_CLICK_NOT); | ||||
| 
 | ||||
|  | @ -593,7 +593,6 @@ void jmanager_set_focus(JWidget widget) | |||
| 
 | ||||
| void jmanager_set_mouse(JWidget widget) | ||||
| { | ||||
| #if 1 | ||||
|   if ((mouse_widget != widget) | ||||
|       && (!capture_widget || !(capture_widget->flags & JI_HARDCAPTURE))) { | ||||
|     JList widget_parents = NULL; | ||||
|  | @ -658,34 +657,6 @@ void jmanager_set_mouse(JWidget widget) | |||
| 
 | ||||
|     jlist_free(widget_parents); | ||||
|   } | ||||
| #else | ||||
|   if ((mouse_widget != widget) | ||||
|       && (!capture_widget || !(capture_widget->flags & JI_HARDCAPTURE))) { | ||||
|     JMessage msg; | ||||
| 
 | ||||
|     /* fetch the mouse */ | ||||
| 
 | ||||
|     if (mouse_widget) { | ||||
|       msg = jmessage_new(JM_MOUSELEAVE); | ||||
|       mouse_widget->flags &= ~JI_HASMOUSE; | ||||
|       jmessage_add_dest(msg, mouse_widget); | ||||
|       jmanager_send_message(msg); | ||||
|       jmessage_free(msg); | ||||
|     } | ||||
| 
 | ||||
|     /* put the mouse */ | ||||
| 
 | ||||
|     mouse_widget = widget; | ||||
| 
 | ||||
|     if (widget) { | ||||
|       msg = jmessage_new(JM_MOUSEENTER); | ||||
|       mouse_widget->flags |= JI_HASMOUSE; | ||||
|       jmessage_add_dest(msg, mouse_widget); | ||||
|       jmanager_send_message(msg); | ||||
|       jmessage_free(msg); | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void jmanager_set_capture(JWidget widget) | ||||
|  | @ -807,7 +778,7 @@ void _jmanager_close_window(JWidget manager, JWidget window, | |||
|   else | ||||
|     reg1 = NULL; | ||||
| 
 | ||||
| /*   jmanager_dispatch_messages (); /\* XXX WARNING!!! *\/ */ | ||||
| /*   jmanager_dispatch_messages (); /\* TODO WARNING!!! *\/ */ | ||||
| 
 | ||||
|   /* printf ("			%d CLOSED BY MANAGER\n", window_id); */ | ||||
| 
 | ||||
|  | @ -838,7 +809,7 @@ void _jmanager_close_window(JWidget manager, JWidget window, | |||
|   /* hide window */ | ||||
|   jwidget_hide(window); | ||||
| 
 | ||||
| /*   jmanager_dispatch_messages(); /\* XXX WARNING!!! *\/ */ | ||||
| /*   jmanager_dispatch_messages(); /\* TODO WARNING!!! *\/ */ | ||||
| 
 | ||||
|   /* close message */ | ||||
|   msg = jmessage_new(JM_CLOSE); | ||||
|  | @ -846,7 +817,7 @@ void _jmanager_close_window(JWidget manager, JWidget window, | |||
|   jmanager_send_message(msg); | ||||
|   jmessage_free(msg); | ||||
| 
 | ||||
|   jmanager_dispatch_messages(); /* XXX WARNING!!! */ | ||||
|   jmanager_dispatch_messages(); /* TODO WARNING!!! */ | ||||
| 
 | ||||
|   /* update manager list stuff */ | ||||
|   jlist_remove(manager->children, window); | ||||
|  | @ -895,7 +866,7 @@ static bool manager_msg_proc(JWidget widget, JMessage msg) | |||
|       return TRUE; | ||||
| 
 | ||||
|     case JM_CHAR: | ||||
| #if 0				/* XXX do this */
 | ||||
| #if 0				/* TODO do this */
 | ||||
|       /* close desktop? */ | ||||
|       if (msg->key.scancode == KEY_ESC) { | ||||
| 	JWidget window; | ||||
|  | @ -973,7 +944,7 @@ static void manager_redraw_region(JWidget widget, JRegion region) | |||
|   JRegion reg3; | ||||
|   JLink link; | ||||
| 
 | ||||
|   /* XXXX intersect with jwidget_get_drawable_region ()??? */ | ||||
|   /* TODO intersect with jwidget_get_drawable_region ()??? */ | ||||
|   jregion_intersect(reg1, region, reg2); | ||||
| 
 | ||||
|   /* redraw windows from top to background */ | ||||
|  | @ -1114,12 +1085,12 @@ static void dispatch_msgs(void) | |||
| 	  jmouse_show(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (done)		/* XXX use marshal? */ | ||||
| 	if (done)		/* TODO use marshal? */ | ||||
| 	  break; | ||||
|       } | ||||
| 
 | ||||
|       /* done? */ | ||||
|       if (done)			/* XXX use marshal? */ | ||||
|       if (done)			/* TODO use marshal? */ | ||||
| 	/* don't go to sub-msg */ | ||||
| 	msg = NULL; | ||||
|       else | ||||
|  |  | |||
|  | @ -105,32 +105,35 @@ void jtheme_slider_info (JWidget widget, int *min, int *max, int *value) | |||
|   if (value) *value = slider->value; | ||||
| } | ||||
| 
 | ||||
| static bool slider_msg_proc (JWidget widget, JMessage msg) | ||||
| static bool slider_msg_proc(JWidget widget, JMessage msg) | ||||
| { | ||||
|   static int slider_press_x; | ||||
|   static int slider_press_value; | ||||
|   static int slider_press_left; | ||||
|   Slider *slider = jwidget_get_data (widget, JI_SLIDER); | ||||
|   Slider *slider = jwidget_get_data(widget, JI_SLIDER); | ||||
| 
 | ||||
|   switch (msg->type) { | ||||
| 
 | ||||
|     case JM_DESTROY: | ||||
|       jfree (slider); | ||||
|       jfree(slider); | ||||
|       break; | ||||
| 
 | ||||
|     case JM_REQSIZE: | ||||
|       slider_request_size (widget, &msg->reqsize.w, &msg->reqsize.h); | ||||
|       slider_request_size(widget, &msg->reqsize.w, &msg->reqsize.h); | ||||
|       return TRUE; | ||||
| 
 | ||||
|     case JM_FOCUSENTER: | ||||
|     case JM_FOCUSLEAVE: | ||||
|       if (jwidget_is_enabled (widget)) | ||||
| 	jwidget_dirty (widget); | ||||
|       if (jwidget_is_enabled(widget)) | ||||
| 	jwidget_dirty(widget); | ||||
|       break; | ||||
| 
 | ||||
|     case JM_BUTTONPRESSED: | ||||
|       jwidget_select (widget); | ||||
|       jwidget_capture_mouse (widget); | ||||
|       if (jwidget_is_disabled(widget)) | ||||
| 	return TRUE; | ||||
| 
 | ||||
|       jwidget_select(widget); | ||||
|       jwidget_capture_mouse(widget); | ||||
| 
 | ||||
|       slider_press_x = msg->mouse.x; | ||||
|       slider_press_value = slider->value; | ||||
|  | @ -141,9 +144,11 @@ static bool slider_msg_proc (JWidget widget, JMessage msg) | |||
|       else | ||||
| 	jmouse_set_cursor(JI_CURSOR_MOVE); | ||||
| 
 | ||||
|       /* continue to JM_MOTION */ | ||||
| 
 | ||||
|     case JM_MOTION: | ||||
|       if (jwidget_has_capture (widget)) { | ||||
| 	JRect rect = jrect_new (0, 0, JI_SCREEN_W, JI_SCREEN_H); | ||||
|       if (jwidget_has_capture(widget)) { | ||||
| 	JRect rect = jrect_new(0, 0, JI_SCREEN_W, JI_SCREEN_H); | ||||
| 	int value, accuracy, range; | ||||
| 
 | ||||
| 	range = slider->max - slider->min + 1; | ||||
|  | @ -155,7 +160,7 @@ static bool slider_msg_proc (JWidget widget, JMessage msg) | |||
| 	} | ||||
| 	/* with right click */ | ||||
| 	else { | ||||
| 	  accuracy = MID (1, | ||||
| 	  accuracy = MID(1, | ||||
| 			 jrect_w(widget->rc) / range, | ||||
| 			 jrect_w(widget->rc)); | ||||
| 
 | ||||
|  | @ -163,11 +168,11 @@ static bool slider_msg_proc (JWidget widget, JMessage msg) | |||
| 	    (msg->mouse.x - slider_press_x) / accuracy; | ||||
| 	} | ||||
| 
 | ||||
| 	value = MID (slider->min, value, slider->max); | ||||
| 	value = MID(slider->min, value, slider->max); | ||||
| 
 | ||||
| 	if (slider->value != value) { | ||||
| 	  jslider_set_value (widget, value); | ||||
| 	  jwidget_emit_signal (widget, JI_SIGNAL_SLIDER_CHANGE); | ||||
| 	  jslider_set_value(widget, value); | ||||
| 	  jwidget_emit_signal(widget, JI_SIGNAL_SLIDER_CHANGE); | ||||
| 	} | ||||
| 
 | ||||
| 	/* for right click */ | ||||
|  | @ -177,15 +182,15 @@ static bool slider_msg_proc (JWidget widget, JMessage msg) | |||
| 	  slider_press_value = slider->value; | ||||
| 	} | ||||
| 
 | ||||
| 	jrect_free (rect); | ||||
| 	jrect_free(rect); | ||||
| 	return TRUE; | ||||
|       } | ||||
|       break; | ||||
| 
 | ||||
|     case JM_BUTTONRELEASED: | ||||
|       if (jwidget_has_capture (widget)) { | ||||
| 	jwidget_deselect (widget); | ||||
| 	jwidget_release_mouse (widget); | ||||
|       if (jwidget_has_capture(widget)) { | ||||
| 	jwidget_deselect(widget); | ||||
| 	jwidget_release_mouse(widget); | ||||
| 
 | ||||
| 	jmouse_set_cursor(JI_CURSOR_NORMAL); | ||||
|       } | ||||
|  | @ -193,20 +198,20 @@ static bool slider_msg_proc (JWidget widget, JMessage msg) | |||
| 
 | ||||
|     case JM_MOUSEENTER: | ||||
|     case JM_MOUSELEAVE: | ||||
| /*       if (jwidget_is_enabled (widget) && */ | ||||
| /* 	  jwidget_has_capture (widget)) { */ | ||||
| /*       if (jwidget_is_enabled(widget) && */ | ||||
| /* 	  jwidget_has_capture(widget)) { */ | ||||
| /* 	/\* swap the select status *\/ */ | ||||
| /* 	if (jwidget_is_selected (widget)) */ | ||||
| /* 	  jwidget_deselect (widget); */ | ||||
| /* 	if (jwidget_is_selected(widget)) */ | ||||
| /* 	  jwidget_deselect(widget); */ | ||||
| /* 	else */ | ||||
| /* 	  jwidget_select (widget); */ | ||||
| /* 	  jwidget_select(widget); */ | ||||
| 
 | ||||
| /* 	/\* XXX switch slider signal *\/ */ | ||||
| /*       } */ | ||||
| 
 | ||||
|       /* XXX theme stuff */ | ||||
|       if (jwidget_is_enabled (widget)) | ||||
| 	jwidget_dirty (widget); | ||||
|       /* TODO theme stuff */ | ||||
|       if (jwidget_is_enabled(widget)) | ||||
| 	jwidget_dirty(widget); | ||||
|       break; | ||||
| 
 | ||||
|     case JM_CHAR: | ||||
|  | @ -216,10 +221,10 @@ static bool slider_msg_proc (JWidget widget, JMessage msg) | |||
| 	int value = slider->value; | ||||
| 
 | ||||
| 	switch (msg->key.scancode) { | ||||
| 	  case KEY_LEFT:  value = MAX (value-1, min); break; | ||||
| 	  case KEY_RIGHT: value = MIN (value+1, max); break; | ||||
| 	  case KEY_PGDN:  value = MAX (value-(max-min+1)/4, min); break; | ||||
| 	  case KEY_PGUP:  value = MIN (value+(max-min+1)/4, max); break; | ||||
| 	  case KEY_LEFT:  value = MAX(value-1, min); break; | ||||
| 	  case KEY_RIGHT: value = MIN(value+1, max); break; | ||||
| 	  case KEY_PGDN:  value = MAX(value-(max-min+1)/4, min); break; | ||||
| 	  case KEY_PGUP:  value = MIN(value+(max-min+1)/4, max); break; | ||||
| 	  case KEY_HOME:  value = min; break; | ||||
| 	  case KEY_END:   value = max; break; | ||||
| 	  default: | ||||
|  | @ -227,8 +232,8 @@ static bool slider_msg_proc (JWidget widget, JMessage msg) | |||
| 	} | ||||
| 
 | ||||
| 	if (slider->value != value) { | ||||
| 	  jslider_set_value (widget, value); | ||||
| 	  jwidget_emit_signal (widget, JI_SIGNAL_SLIDER_CHANGE); | ||||
| 	  jslider_set_value(widget, value); | ||||
| 	  jwidget_emit_signal(widget, JI_SIGNAL_SLIDER_CHANGE); | ||||
| 	} | ||||
| 
 | ||||
| 	return TRUE; | ||||
|  | @ -253,20 +258,20 @@ static bool slider_msg_proc (JWidget widget, JMessage msg) | |||
|   return FALSE; | ||||
| } | ||||
| 
 | ||||
| static void slider_request_size (JWidget widget, int *w, int *h) | ||||
| static void slider_request_size(JWidget widget, int *w, int *h) | ||||
| { | ||||
|   Slider *slider = jwidget_get_data (widget, JI_SLIDER); | ||||
|   Slider *slider = jwidget_get_data(widget, JI_SLIDER); | ||||
|   int min_w, max_w; | ||||
|   char buf[256]; | ||||
| 
 | ||||
|   usprintf (buf, "%d", slider->min); | ||||
|   min_w = ji_font_text_len (widget->text_font, buf); | ||||
|   usprintf(buf, "%d", slider->min); | ||||
|   min_w = ji_font_text_len(widget->text_font, buf); | ||||
| 
 | ||||
|   usprintf (buf, "%d", slider->max); | ||||
|   max_w = ji_font_text_len (widget->text_font, buf); | ||||
|   usprintf(buf, "%d", slider->max); | ||||
|   max_w = ji_font_text_len(widget->text_font, buf); | ||||
| 
 | ||||
|   *w = MAX (min_w, max_w); | ||||
|   *h = text_height (widget->text_font); | ||||
|   *w = MAX(min_w, max_w); | ||||
|   *h = text_height(widget->text_font); | ||||
| 
 | ||||
|   *w += widget->border_width.l + widget->border_width.r; | ||||
|   *h += widget->border_width.t + widget->border_width.b; | ||||
|  |  | |||
|  | @ -177,6 +177,70 @@ void ji_regen_theme(void) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| int ji_color_foreground(void) | ||||
| { | ||||
|   if (ji_current_theme && ji_current_theme->color_foreground) | ||||
|     return (*ji_current_theme->color_foreground)(); | ||||
|   else | ||||
|     return makecol(0, 0, 0); | ||||
| } | ||||
| 
 | ||||
| int ji_color_disabled(void) | ||||
| { | ||||
|   if (ji_current_theme && ji_current_theme->color_disabled) | ||||
|     return (*ji_current_theme->color_disabled)(); | ||||
|   else | ||||
|     return makecol(128, 128, 128); | ||||
| } | ||||
| 
 | ||||
| int ji_color_face(void) | ||||
| { | ||||
|   if (ji_current_theme && ji_current_theme->color_face) | ||||
|     return (*ji_current_theme->color_face)(); | ||||
|   else | ||||
|     return makecol(255, 255, 255); | ||||
| } | ||||
| 
 | ||||
| int ji_color_facelight(void) | ||||
| { | ||||
|   register int c = ji_color_face(); | ||||
|   return makecol(MIN(getr(c)+64, 255), | ||||
| 		 MIN(getg(c)+64, 255), | ||||
| 		 MIN(getb(c)+64, 255)); | ||||
| } | ||||
| 
 | ||||
| int ji_color_faceshadow(void) | ||||
| { | ||||
|   register int c = ji_color_face(); | ||||
|   return makecol(MAX(getr(c)-64, 0), | ||||
| 		 MAX(getg(c)-64, 0), | ||||
| 		 MAX(getb(c)-64, 0)); | ||||
| } | ||||
| 
 | ||||
| int ji_color_hotface(void) | ||||
| { | ||||
|   if (ji_current_theme && ji_current_theme->color_hotface) | ||||
|     return (*ji_current_theme->color_hotface)(); | ||||
|   else | ||||
|     return makecol(255, 255, 255); | ||||
| } | ||||
| 
 | ||||
| int ji_color_selected(void) | ||||
| { | ||||
|   if (ji_current_theme && ji_current_theme->color_selected) | ||||
|     return (*ji_current_theme->color_selected)(); | ||||
|   else | ||||
|     return makecol(0, 0, 255); | ||||
| } | ||||
| 
 | ||||
| int ji_color_background(void) | ||||
| { | ||||
|   if (ji_current_theme && ji_current_theme->color_background) | ||||
|     return (*ji_current_theme->color_background)(); | ||||
|   else | ||||
|     return makecol(255, 255, 255); | ||||
| } | ||||
| 
 | ||||
| void _ji_theme_draw_sprite_color(BITMAP *bmp, BITMAP *sprite, | ||||
| 				 int x, int y, int color) | ||||
| { | ||||
|  | @ -394,9 +458,9 @@ void _ji_theme_textbox_draw(BITMAP *bmp, JWidget widget, int *w, int *h) | |||
| static void draw_text(BITMAP *bmp, FONT *f, const char *text, int x, int y, | ||||
| 		      int fg_color, int bg_color, bool fill_bg) | ||||
| { | ||||
|   /* XXXX optional anti-aliased textout */ | ||||
|   /* TODO optional anti-aliased textout */ | ||||
|   ji_font_set_aa_mode(f, bg_color); | ||||
|   text_mode(fill_bg ? bg_color: -1); | ||||
|   textout(bmp, f, text, x, y, fg_color); | ||||
|   /* XXXX */ | ||||
|   /* TODO */ | ||||
| } | ||||
|  |  | |||
|  | @ -639,9 +639,8 @@ JWidget jwidget_pick(JWidget widget, int x, int y) | |||
|   JWidget inside, picked = NULL; | ||||
|   JLink link; | ||||
| 
 | ||||
|   if (!(widget->flags & JI_DISABLED) && /* is enabled */ | ||||
|       !(widget->flags & JI_HIDDEN) &&   /* is visible */ | ||||
|       jrect_point_in (widget->rc, x, y)) { | ||||
|   if (!(widget->flags & JI_HIDDEN) &&   /* is visible */ | ||||
|       jrect_point_in(widget->rc, x, y)) { /* the point is inside the bounds */ | ||||
|     picked = widget; | ||||
| 
 | ||||
|     JI_LIST_FOR_EACH(widget->children, link) { | ||||
|  | @ -1120,7 +1119,7 @@ void jwidget_scroll(JWidget widget, int dx, int dy, const JRect rect, | |||
| 		    widget->update_region, update_region); | ||||
|   } | ||||
| 
 | ||||
|   /* XXXXX */ | ||||
|   /* TODO */ | ||||
|   /* refresh the update_region */ | ||||
| /*   jwidget_flush_redraw(widget); */ | ||||
| /*   jmanager_dispatch_messages(); */ | ||||
|  |  | |||
|  | @ -61,14 +61,14 @@ static JRect click_pos = NULL; | |||
| static int press_x, press_y; | ||||
| static int window_action = WINDOW_NONE; | ||||
| 
 | ||||
| static JWidget window_new (int desktop, const char *text); | ||||
| static bool window_msg_proc (JWidget widget, JMessage msg); | ||||
| static void window_request_size (JWidget widget, int *w, int *h); | ||||
| static void window_set_position (JWidget widget, JRect rect); | ||||
| static JWidget window_new(int desktop, const char *text); | ||||
| static bool window_msg_proc(JWidget widget, JMessage msg); | ||||
| static void window_request_size(JWidget widget, int *w, int *h); | ||||
| static void window_set_position(JWidget widget, JRect rect); | ||||
| 
 | ||||
| static int setup_cursor (JWidget widget, int x, int y); | ||||
| static void limit_size (JWidget widget, int *w, int *h); | ||||
| static void move_window (JWidget widget, JRect rect, bool use_blit); | ||||
| static int setup_cursor(JWidget widget, int x, int y); | ||||
| static void limit_size(JWidget widget, int *w, int *h); | ||||
| static void move_window(JWidget widget, JRect rect, bool use_blit); | ||||
| static void displace_widgets(JWidget widget, int x, int y); | ||||
| 
 | ||||
| bool _jwindow_is_moving(void) | ||||
|  | @ -78,17 +78,17 @@ bool _jwindow_is_moving(void) | |||
| 
 | ||||
| JWidget jwindow_new(const char *text) | ||||
| { | ||||
|   return window_new (FALSE, text); | ||||
|   return window_new(FALSE, text); | ||||
| } | ||||
| 
 | ||||
| JWidget jwindow_new_desktop(void) | ||||
| { | ||||
|   return window_new (TRUE, NULL); | ||||
|   return window_new(TRUE, NULL); | ||||
| } | ||||
| 
 | ||||
| JWidget jwindow_get_killer(JWidget widget) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW); | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW); | ||||
| 
 | ||||
|   return window->killer; | ||||
| } | ||||
|  | @ -102,51 +102,51 @@ JWidget jwindow_get_manager(JWidget widget) | |||
|     widget = widget->parent; | ||||
|   } | ||||
| 
 | ||||
|   return ji_get_default_manager (); | ||||
|   return ji_get_default_manager(); | ||||
| } | ||||
| 
 | ||||
| void jwindow_moveable(JWidget widget, bool state) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW);  | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW);  | ||||
| 
 | ||||
|   window->is_moveable = state; | ||||
| } | ||||
| 
 | ||||
| void jwindow_sizeable(JWidget widget, bool state) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW);  | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW);  | ||||
| 
 | ||||
|   window->is_sizeable = state; | ||||
| } | ||||
| 
 | ||||
| void jwindow_ontop(JWidget widget, bool state) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW);  | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW);  | ||||
| 
 | ||||
|   window->is_ontop = state; | ||||
| } | ||||
| 
 | ||||
| void jwindow_remap(JWidget widget) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW);  | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW);  | ||||
|   int req_w, req_h; | ||||
|   JRect rect; | ||||
| 
 | ||||
|   if (window->is_autoremap) { | ||||
|     window->is_autoremap = FALSE; | ||||
|     jwidget_show (widget); | ||||
|     jwidget_show(widget); | ||||
|   } | ||||
| 
 | ||||
|   jwidget_request_size (widget, &req_w, &req_h); | ||||
|   jwidget_request_size(widget, &req_w, &req_h); | ||||
| 
 | ||||
|   rect = jrect_new (widget->rc->x1, widget->rc->y1, | ||||
|   rect = jrect_new(widget->rc->x1, widget->rc->y1, | ||||
| 		   widget->rc->x1+req_w, | ||||
| 		   widget->rc->y1+req_h); | ||||
|   jwidget_set_rect (widget, rect); | ||||
|   jrect_free (rect); | ||||
|   jwidget_set_rect(widget, rect); | ||||
|   jrect_free(rect); | ||||
| 
 | ||||
|   jwidget_emit_signal (widget, JI_SIGNAL_WINDOW_RESIZE); | ||||
|   jwidget_dirty (widget); | ||||
|   jwidget_emit_signal(widget, JI_SIGNAL_WINDOW_RESIZE); | ||||
|   jwidget_dirty(widget); | ||||
| } | ||||
| 
 | ||||
| void jwindow_center(JWidget widget) | ||||
|  | @ -155,16 +155,16 @@ void jwindow_center(JWidget widget) | |||
|   JWidget manager = jwindow_get_manager (widget); | ||||
| 
 | ||||
|   if (window->is_autoremap) | ||||
|     jwindow_remap (widget); | ||||
|     jwindow_remap(widget); | ||||
| 
 | ||||
|   jwindow_position (widget, | ||||
|   jwindow_position(widget, | ||||
| 		   jrect_w(manager->rc)/2 - jrect_w(widget->rc)/2, | ||||
| 		   jrect_h(manager->rc)/2 - jrect_h(widget->rc)/2); | ||||
| } | ||||
| 
 | ||||
| void jwindow_position(JWidget widget, int x, int y) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW);  | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW);  | ||||
|   int old_action = window_action; | ||||
|   JRect rect; | ||||
| 
 | ||||
|  | @ -173,13 +173,13 @@ void jwindow_position(JWidget widget, int x, int y) | |||
|   if (window->is_autoremap) | ||||
|     jwindow_remap (widget); | ||||
| 
 | ||||
|   rect = jrect_new (x, y, x+jrect_w(widget->rc), y+jrect_h(widget->rc)); | ||||
|   jwidget_set_rect (widget, rect); | ||||
|   jrect_free (rect); | ||||
|   rect = jrect_new(x, y, x+jrect_w(widget->rc), y+jrect_h(widget->rc)); | ||||
|   jwidget_set_rect(widget, rect); | ||||
|   jrect_free(rect); | ||||
| 
 | ||||
|   window_action = old_action; | ||||
| 
 | ||||
|   jwidget_dirty (widget); | ||||
|   jwidget_dirty(widget); | ||||
| } | ||||
| 
 | ||||
| void jwindow_move(JWidget widget, JRect rect) | ||||
|  | @ -201,24 +201,24 @@ void jwindow_open(JWidget widget) | |||
| 
 | ||||
| void jwindow_open_fg(JWidget widget) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW);  | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW);  | ||||
|   JWidget manager; | ||||
| 
 | ||||
|   jwindow_open (widget); | ||||
|   manager = jwindow_get_manager (widget); | ||||
|   jwindow_open(widget); | ||||
|   manager = jwindow_get_manager(widget); | ||||
| 
 | ||||
|   window->is_foreground = TRUE; | ||||
| 
 | ||||
|   do { | ||||
|   } while (jmanager_poll (manager, FALSE)); | ||||
|   } while (jmanager_poll(manager, FALSE)); | ||||
| 
 | ||||
|   window->is_foreground = FALSE; | ||||
| } | ||||
| 
 | ||||
| void jwindow_open_bg(JWidget widget) | ||||
| { | ||||
|   widget->flags |= JI_AUTODESTROY;	/* XXX */ | ||||
|   jwindow_open (widget); | ||||
|   widget->flags |= JI_AUTODESTROY;	/* TODO */ | ||||
|   jwindow_open(widget); | ||||
| } | ||||
| 
 | ||||
| void jwindow_close(JWidget widget, JWidget killer) | ||||
|  | @ -247,24 +247,24 @@ bool jwindow_is_foreground(JWidget widget) | |||
|   return window->is_foreground; | ||||
| } | ||||
| 
 | ||||
| bool jwindow_is_desktop (JWidget widget) | ||||
| bool jwindow_is_desktop(JWidget widget) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW); | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW); | ||||
| 
 | ||||
|   return window->is_desktop; | ||||
| } | ||||
| 
 | ||||
| bool jwindow_is_ontop (JWidget widget) | ||||
| bool jwindow_is_ontop(JWidget widget) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW);  | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW);  | ||||
| 
 | ||||
|   return window->is_ontop; | ||||
| } | ||||
| 
 | ||||
| static JWidget window_new (int desktop, const char *text) | ||||
| static JWidget window_new(int desktop, const char *text) | ||||
| { | ||||
|   JWidget widget = jwidget_new (JI_WINDOW); | ||||
|   Window *window = jnew (Window, 1); | ||||
|   JWidget widget = jwidget_new(JI_WINDOW); | ||||
|   Window *window = jnew(Window, 1); | ||||
| 
 | ||||
|   window->killer = NULL; | ||||
|   window->is_desktop = desktop; | ||||
|  | @ -274,34 +274,34 @@ static JWidget window_new (int desktop, const char *text) | |||
|   window->is_foreground = FALSE; | ||||
|   window->is_autoremap = TRUE; | ||||
| 
 | ||||
|   jwidget_hide (widget); | ||||
|   jwidget_add_hook (widget, JI_WINDOW, window_msg_proc, window); | ||||
|   jwidget_set_text (widget, text); | ||||
|   jwidget_set_align (widget, JI_LEFT | JI_MIDDLE); | ||||
|   jwidget_hide(widget); | ||||
|   jwidget_add_hook(widget, JI_WINDOW, window_msg_proc, window); | ||||
|   jwidget_set_text(widget, text); | ||||
|   jwidget_set_align(widget, JI_LEFT | JI_MIDDLE); | ||||
| 
 | ||||
|   jwidget_init_theme (widget); | ||||
|   jwidget_init_theme(widget); | ||||
| 
 | ||||
|   return widget; | ||||
| } | ||||
| 
 | ||||
| static bool window_msg_proc (JWidget widget, JMessage msg) | ||||
| static bool window_msg_proc(JWidget widget, JMessage msg) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW); | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW); | ||||
| 
 | ||||
|   switch (msg->type) { | ||||
| 
 | ||||
|     case JM_DESTROY: | ||||
|       _jmanager_close_window(jwindow_get_manager (widget), widget, | ||||
|       _jmanager_close_window(jwindow_get_manager(widget), widget, | ||||
| 			     FALSE, FALSE); | ||||
|       jfree(window); | ||||
|       break; | ||||
| 
 | ||||
|     case JM_REQSIZE: | ||||
|       window_request_size (widget, &msg->reqsize.w, &msg->reqsize.h); | ||||
|       window_request_size(widget, &msg->reqsize.w, &msg->reqsize.h); | ||||
|       return TRUE; | ||||
| 
 | ||||
|     case JM_SETPOS: | ||||
|       window_set_position (widget, &msg->setpos.rect); | ||||
|       window_set_position(widget, &msg->setpos.rect); | ||||
|       return TRUE; | ||||
| 
 | ||||
|     case JM_OPEN: | ||||
|  | @ -309,12 +309,12 @@ static bool window_msg_proc (JWidget widget, JMessage msg) | |||
|       break; | ||||
| 
 | ||||
|     case JM_CLOSE: | ||||
|       jwidget_emit_signal (widget, JI_SIGNAL_WINDOW_CLOSE); | ||||
|       jwidget_emit_signal(widget, JI_SIGNAL_WINDOW_CLOSE); | ||||
|       break; | ||||
| 
 | ||||
|     case JM_SIGNAL: | ||||
|       if (msg->signal.num == JI_SIGNAL_SET_TEXT) | ||||
| 	jwidget_init_theme (widget); | ||||
| 	jwidget_init_theme(widget); | ||||
|       break; | ||||
| 
 | ||||
|     case JM_BUTTONPRESSED: { | ||||
|  | @ -322,16 +322,16 @@ static bool window_msg_proc (JWidget widget, JMessage msg) | |||
| 	break; | ||||
| 
 | ||||
|       if (!click_pos) | ||||
| 	click_pos = jrect_new_copy (widget->rc); | ||||
| 	click_pos = jrect_new_copy(widget->rc); | ||||
|       else | ||||
| 	jrect_copy (click_pos, widget->rc); | ||||
| 	jrect_copy(click_pos, widget->rc); | ||||
| 
 | ||||
|       press_x = msg->mouse.x; | ||||
|       press_y = msg->mouse.y; | ||||
|       window_action = setup_cursor (widget, press_x, press_y); | ||||
|       window_action = setup_cursor(widget, press_x, press_y); | ||||
| 
 | ||||
|       if (window_action != WINDOW_NONE) { | ||||
| 	jwidget_hard_capture_mouse (widget); | ||||
| 	jwidget_hard_capture_mouse(widget); | ||||
| 	return TRUE; | ||||
|       } | ||||
|       else | ||||
|  | @ -339,8 +339,8 @@ static bool window_msg_proc (JWidget widget, JMessage msg) | |||
|     } | ||||
| 
 | ||||
|     case JM_BUTTONRELEASED: | ||||
|       if (jwidget_has_capture (widget)) { | ||||
| 	jwidget_release_mouse (widget); | ||||
|       if (jwidget_has_capture(widget)) { | ||||
| 	jwidget_release_mouse(widget); | ||||
| 	jmouse_set_cursor(JI_CURSOR_NORMAL); | ||||
| 
 | ||||
| 	window_action = WINDOW_NONE; | ||||
|  | @ -349,7 +349,7 @@ static bool window_msg_proc (JWidget widget, JMessage msg) | |||
|       break; | ||||
| 
 | ||||
|     case JM_MOUSELEAVE: | ||||
|       setup_cursor (widget, msg->mouse.x, msg->mouse.y); | ||||
|       setup_cursor(widget, msg->mouse.x, msg->mouse.y); | ||||
|       break; | ||||
| 
 | ||||
|     case JM_MOTION: | ||||
|  | @ -358,9 +358,8 @@ static bool window_msg_proc (JWidget widget, JMessage msg) | |||
| 
 | ||||
|       /* without capture */ | ||||
|       if (!jwidget_has_capture (widget)) { | ||||
| 	if (!jmanager_get_capture ()) | ||||
| 	  return setup_cursor (widget, | ||||
| 			       msg->mouse.x, msg->mouse.y) != WINDOW_NONE; | ||||
| 	if (!jmanager_get_capture()) | ||||
| 	  return setup_cursor(widget, msg->mouse.x, msg->mouse.y) != WINDOW_NONE; | ||||
| 	else | ||||
| 	  break; | ||||
|       } | ||||
|  | @ -370,11 +369,11 @@ static bool window_msg_proc (JWidget widget, JMessage msg) | |||
| 	if (window_action == WINDOW_MOVE) { | ||||
| 	  int x = click_pos->x1 + (msg->mouse.x - press_x); | ||||
| 	  int y = click_pos->y1 + (msg->mouse.y - press_y); | ||||
| 	  JRect rect = jrect_new (x, y, | ||||
| 	  JRect rect = jrect_new(x, y, | ||||
| 				 x+jrect_w(widget->rc), | ||||
| 				 y+jrect_h(widget->rc)); | ||||
| 	  move_window (widget, rect, TRUE); | ||||
| 	  jrect_free (rect); | ||||
| 	  move_window(widget, rect, TRUE); | ||||
| 	  jrect_free(rect); | ||||
| 	} | ||||
| 	else { | ||||
| 	  int x, y, w, h; | ||||
|  | @ -407,23 +406,23 @@ static bool window_msg_proc (JWidget widget, JMessage msg) | |||
| 	      y = widget->rc->y1; | ||||
| 
 | ||||
| 	    { | ||||
| 	      JRect rect = jrect_new (x, y, x+w, y+h);  | ||||
| 	      move_window (widget, rect, FALSE); | ||||
| 	      jrect_free (rect); | ||||
| 	      JRect rect = jrect_new(x, y, x+w, y+h);  | ||||
| 	      move_window(widget, rect, FALSE); | ||||
| 	      jrect_free(rect); | ||||
| 
 | ||||
| 	      jwidget_emit_signal (widget, JI_SIGNAL_WINDOW_RESIZE); | ||||
| 	      jwidget_dirty (widget); | ||||
| 	      jwidget_emit_signal(widget, JI_SIGNAL_WINDOW_RESIZE); | ||||
| 	      jwidget_dirty(widget); | ||||
| 	    } | ||||
| 	  } | ||||
| 	} | ||||
|       } | ||||
| 
 | ||||
|       /* XXXX */ | ||||
|       /* TODO */ | ||||
| /*       { */ | ||||
| /* 	JWidget manager = jwindow_get_manager (widget); */ | ||||
| /* 	JWidget view = jwidget_get_view (manager); */ | ||||
| /* 	JWidget manager = jwindow_get_manager(widget); */ | ||||
| /* 	JWidget view = jwidget_get_view(manager); */ | ||||
| /* 	if (view) { */ | ||||
| /* 	  jview_update (view); */ | ||||
| /* 	  jview_update(view); */ | ||||
| /* 	} */ | ||||
| /*       } */ | ||||
|       break; | ||||
|  | @ -432,10 +431,10 @@ static bool window_msg_proc (JWidget widget, JMessage msg) | |||
|   return FALSE; | ||||
| } | ||||
| 
 | ||||
| static void window_request_size (JWidget widget, int *w, int *h) | ||||
| static void window_request_size(JWidget widget, int *w, int *h) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW); | ||||
|   JWidget manager = jwindow_get_manager (widget); | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW); | ||||
|   JWidget manager = jwindow_get_manager(widget); | ||||
| 
 | ||||
|   if (window->is_desktop) { | ||||
|     JRect cpos = jwidget_get_child_rect(manager); | ||||
|  | @ -469,7 +468,7 @@ static void window_request_size (JWidget widget, int *w, int *h) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| static void window_set_position (JWidget widget, JRect rect) | ||||
| static void window_set_position(JWidget widget, JRect rect) | ||||
| { | ||||
|   JWidget child; | ||||
|   JRect cpos; | ||||
|  | @ -492,9 +491,9 @@ static void window_set_position (JWidget widget, JRect rect) | |||
|   jrect_free(cpos); | ||||
| } | ||||
| 
 | ||||
| static int setup_cursor (JWidget widget, int x, int y) | ||||
| static int setup_cursor(JWidget widget, int x, int y) | ||||
| { | ||||
|   Window *window = jwidget_get_data (widget, JI_WINDOW); | ||||
|   Window *window = jwidget_get_data(widget, JI_WINDOW); | ||||
|   int action = WINDOW_NONE; | ||||
|   int cursor; | ||||
|   JRect pos; | ||||
|  | @ -504,8 +503,8 @@ static int setup_cursor (JWidget widget, int x, int y) | |||
|     return action; | ||||
| 
 | ||||
|   cursor = JI_CURSOR_NORMAL; | ||||
|   pos = jwidget_get_rect (widget); | ||||
|   cpos = jwidget_get_child_rect (widget); | ||||
|   pos = jwidget_get_rect(widget); | ||||
|   cpos = jwidget_get_child_rect(widget); | ||||
| 
 | ||||
|   /* move */ | ||||
|   if ((widget->text) | ||||
|  | @ -603,23 +602,23 @@ static int setup_cursor (JWidget widget, int x, int y) | |||
|   if (jmouse_get_cursor() != cursor) | ||||
|     jmouse_set_cursor(cursor); | ||||
| 
 | ||||
|   jrect_free (pos); | ||||
|   jrect_free (cpos); | ||||
|   jrect_free(pos); | ||||
|   jrect_free(cpos); | ||||
| 
 | ||||
|   return action; | ||||
| } | ||||
| 
 | ||||
| static void limit_size (JWidget widget, int *w, int *h) | ||||
| static void limit_size(JWidget widget, int *w, int *h) | ||||
| { | ||||
|   int req_w, req_h; | ||||
| 
 | ||||
|   jwidget_request_size (widget, &req_w, &req_h); | ||||
|   jwidget_request_size(widget, &req_w, &req_h); | ||||
| 
 | ||||
|   *w = MAX (*w, widget->border_width.l+widget->border_width.r); | ||||
|   *h = MAX (*h, widget->border_width.t+widget->border_width.b); | ||||
|   *w = MAX(*w, widget->border_width.l+widget->border_width.r); | ||||
|   *h = MAX(*h, widget->border_width.t+widget->border_width.b); | ||||
| } | ||||
| 
 | ||||
| /* XXX add support to blit available regions */ | ||||
| /* TODO add support to blit available regions */ | ||||
| static void move_window(JWidget widget, JRect rect, bool use_blit) | ||||
| { | ||||
| #define FLAGS JI_GDR_CUTTOPWINDOWS | JI_GDR_USECHILDAREA | ||||
|  | @ -651,16 +650,16 @@ static void move_window(JWidget widget, JRect rect, bool use_blit) | |||
| 		     rect->y1 - old_pos->y1); | ||||
|   } | ||||
| 
 | ||||
|   new_drawable_region = jwidget_get_drawable_region (widget, FLAGS); | ||||
|   new_drawable_region = jwidget_get_drawable_region(widget, FLAGS); | ||||
| 
 | ||||
|   manager_refresh_region = jregion_new (NULL, 0); | ||||
|   window_refresh_region = jregion_new (NULL, 0); | ||||
|   manager_refresh_region = jregion_new(NULL, 0); | ||||
|   window_refresh_region = jregion_new(NULL, 0); | ||||
|   jregion_copy(manager_refresh_region, old_drawable_region); | ||||
| 
 | ||||
|   /* redraw new position */ | ||||
| /*   if (!use_blit || !jwindow_is_toplevel (widget)) */ | ||||
|   if (!use_blit) { | ||||
|     jregion_copy (window_refresh_region, new_drawable_region); | ||||
|     jregion_copy(window_refresh_region, new_drawable_region); | ||||
|   } | ||||
|   /* try to blit new position from old position (to redraw the less
 | ||||
|      possible) */ | ||||
|  | @ -720,9 +719,9 @@ static void move_window(JWidget widget, JRect rect, bool use_blit) | |||
|     jregion_free(moveable_region); | ||||
|   } | ||||
| 
 | ||||
| /*   jwidget_invalidate_region (jwindow_get_manager (widget), */ | ||||
| /*   jwidget_invalidate_region(jwindow_get_manager (widget), */ | ||||
| /* 			       manager_refresh_region); */ | ||||
| /*   jwidget_invalidate_region (widget, window_refresh_region); */ | ||||
| /*   jwidget_invalidate_region(widget, window_refresh_region); */ | ||||
|   jwidget_redraw_region(jwindow_get_manager(widget), | ||||
| 			  manager_refresh_region); | ||||
|   jwidget_redraw_region(widget, window_refresh_region); | ||||
|  |  | |||
|  | @ -43,6 +43,13 @@ | |||
| 
 | ||||
| #define BGCOLOR			(get_bg_color(widget)) | ||||
| 
 | ||||
| #define COLOR_FOREGROUND	makecol(0, 0, 0) | ||||
| #define COLOR_DISABLED		makecol(128, 128, 128) | ||||
| #define COLOR_FACE		makecol(210, 200, 190) | ||||
| #define COLOR_HOTFACE		makecol(250, 240, 230) | ||||
| #define COLOR_SELECTED		makecol(44, 76, 145) | ||||
| #define COLOR_BACKGROUND	makecol(255, 255, 255) | ||||
| 
 | ||||
| /* "icons_data" indexes */ | ||||
| enum { | ||||
|   FIRST_CURSOR = 0, | ||||
|  | @ -91,6 +98,12 @@ static BITMAP *theme_set_cursor(int type, int *focus_x, int *focus_y); | |||
| static void theme_init_widget(JWidget widget); | ||||
| static JRegion theme_get_window_mask(JWidget widget); | ||||
| static void theme_map_decorative_widget(JWidget widget); | ||||
| static int theme_color_foreground(void); | ||||
| static int theme_color_disabled(void); | ||||
| static int theme_color_face(void); | ||||
| static int theme_color_hotface(void); | ||||
| static int theme_color_selected(void); | ||||
| static int theme_color_background(void); | ||||
| static void theme_draw_box(JWidget widget); | ||||
| static void theme_draw_button(JWidget widget); | ||||
| static void theme_draw_check(JWidget widget); | ||||
|  | @ -140,25 +153,31 @@ JTheme jtheme_new_standard (void) | |||
|   theme->init_widget = theme_init_widget; | ||||
|   theme->get_window_mask = theme_get_window_mask; | ||||
|   theme->map_decorative_widget = theme_map_decorative_widget; | ||||
|   theme->color_foreground = theme_color_foreground; | ||||
|   theme->color_disabled = theme_color_disabled; | ||||
|   theme->color_face = theme_color_face; | ||||
|   theme->color_hotface = theme_color_hotface; | ||||
|   theme->color_selected = theme_color_selected; | ||||
|   theme->color_background = theme_color_background; | ||||
| 
 | ||||
|   jtheme_set_method (theme, JI_BOX, theme_draw_box); | ||||
|   jtheme_set_method (theme, JI_BUTTON, theme_draw_button); | ||||
|   jtheme_set_method (theme, JI_CHECK, theme_draw_check); | ||||
|   jtheme_set_method (theme, JI_ENTRY, theme_draw_entry); | ||||
|   jtheme_set_method (theme, JI_LABEL, theme_draw_label); | ||||
|   jtheme_set_method (theme, JI_LISTBOX, theme_draw_listbox); | ||||
|   jtheme_set_method (theme, JI_LISTITEM, theme_draw_listitem); | ||||
|   jtheme_set_method (theme, JI_MENU, theme_draw_menu); | ||||
|   jtheme_set_method (theme, JI_MENUITEM, theme_draw_menuitem); | ||||
|   jtheme_set_method (theme, JI_PANEL, theme_draw_panel); | ||||
|   jtheme_set_method (theme, JI_RADIO, theme_draw_radio); | ||||
|   jtheme_set_method (theme, JI_SEPARATOR, theme_draw_separator); | ||||
|   jtheme_set_method (theme, JI_SLIDER, theme_draw_slider); | ||||
|   jtheme_set_method (theme, JI_TEXTBOX, theme_draw_textbox); | ||||
|   jtheme_set_method (theme, JI_VIEW, theme_draw_view); | ||||
|   jtheme_set_method (theme, JI_VIEW_SCROLLBAR, theme_draw_view_scrollbar); | ||||
|   jtheme_set_method (theme, JI_VIEW_VIEWPORT, theme_draw_view_viewport); | ||||
|   jtheme_set_method (theme, JI_WINDOW, theme_draw_window); | ||||
|   jtheme_set_method(theme, JI_BOX, theme_draw_box); | ||||
|   jtheme_set_method(theme, JI_BUTTON, theme_draw_button); | ||||
|   jtheme_set_method(theme, JI_CHECK, theme_draw_check); | ||||
|   jtheme_set_method(theme, JI_ENTRY, theme_draw_entry); | ||||
|   jtheme_set_method(theme, JI_LABEL, theme_draw_label); | ||||
|   jtheme_set_method(theme, JI_LISTBOX, theme_draw_listbox); | ||||
|   jtheme_set_method(theme, JI_LISTITEM, theme_draw_listitem); | ||||
|   jtheme_set_method(theme, JI_MENU, theme_draw_menu); | ||||
|   jtheme_set_method(theme, JI_MENUITEM, theme_draw_menuitem); | ||||
|   jtheme_set_method(theme, JI_PANEL, theme_draw_panel); | ||||
|   jtheme_set_method(theme, JI_RADIO, theme_draw_radio); | ||||
|   jtheme_set_method(theme, JI_SEPARATOR, theme_draw_separator); | ||||
|   jtheme_set_method(theme, JI_SLIDER, theme_draw_slider); | ||||
|   jtheme_set_method(theme, JI_TEXTBOX, theme_draw_textbox); | ||||
|   jtheme_set_method(theme, JI_VIEW, theme_draw_view); | ||||
|   jtheme_set_method(theme, JI_VIEW_SCROLLBAR, theme_draw_view_scrollbar); | ||||
|   jtheme_set_method(theme, JI_VIEW_VIEWPORT, theme_draw_view_viewport); | ||||
|   jtheme_set_method(theme, JI_WINDOW, theme_draw_window); | ||||
| 
 | ||||
|   return theme; | ||||
| } | ||||
|  | @ -180,18 +199,18 @@ static void theme_regen (void) | |||
|   JTheme theme = ji_get_theme (); | ||||
|   int c, cmap[8], mask_cmap[2]; | ||||
| 
 | ||||
|   theme->desktop_color = makecol (128, 128, 128); | ||||
|   theme->textbox_fg_color = makecol (0, 0, 0); | ||||
|   theme->textbox_bg_color = makecol (255, 255, 255); | ||||
|   theme->desktop_color = COLOR_DISABLED; | ||||
|   theme->textbox_fg_color = COLOR_FOREGROUND; | ||||
|   theme->textbox_bg_color = COLOR_BACKGROUND; | ||||
| 
 | ||||
|   /* fixup cursors */ | ||||
| 
 | ||||
|   cmap[0] = bitmap_mask_color (ji_screen); | ||||
|   cmap[1] = makecol (0, 0, 0); | ||||
|   cmap[2] = makecol (128, 128, 128); | ||||
|   cmap[3] = makecol (255, 255, 255); | ||||
|   cmap[4] = makecol (192, 192, 192); | ||||
|   cmap[5] = makecol (224, 224, 224); | ||||
|   cmap[0] = bitmap_mask_color(ji_screen); | ||||
|   cmap[1] = COLOR_FOREGROUND; | ||||
|   cmap[2] = COLOR_DISABLED; | ||||
|   cmap[3] = COLOR_BACKGROUND; | ||||
|   cmap[4] = COLOR_FACE; | ||||
|   cmap[5] = COLOR_HOTFACE; | ||||
| 
 | ||||
|   mask_cmap[0] = 0; | ||||
|   mask_cmap[1] = 1; | ||||
|  | @ -201,9 +220,9 @@ static void theme_regen (void) | |||
|       destroy_bitmap (icons_bitmap[c]); | ||||
| 
 | ||||
|     if (icons_data[c].mask) | ||||
|       icons_bitmap[c] = data2bmp (8, icons_data[c].data, mask_cmap); | ||||
|       icons_bitmap[c] = data2bmp(8, icons_data[c].data, mask_cmap); | ||||
|     else | ||||
|       icons_bitmap[c] = data2bmp (bitmap_color_depth (ji_screen), | ||||
|       icons_bitmap[c] = data2bmp(bitmap_color_depth (ji_screen), | ||||
| 				 icons_data[c].data, cmap); | ||||
|   } | ||||
| } | ||||
|  | @ -431,6 +450,36 @@ static void theme_map_decorative_widget (JWidget widget) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| static int theme_color_foreground(void) | ||||
| { | ||||
|   return COLOR_FOREGROUND; | ||||
| } | ||||
| 
 | ||||
| static int theme_color_disabled(void) | ||||
| { | ||||
|   return COLOR_DISABLED; | ||||
| } | ||||
| 
 | ||||
| static int theme_color_face(void) | ||||
| { | ||||
|   return COLOR_FACE; | ||||
| } | ||||
| 
 | ||||
| static int theme_color_hotface(void) | ||||
| { | ||||
|   return COLOR_HOTFACE; | ||||
| } | ||||
| 
 | ||||
| static int theme_color_selected(void) | ||||
| { | ||||
|   return COLOR_SELECTED; | ||||
| } | ||||
| 
 | ||||
| static int theme_color_background(void) | ||||
| { | ||||
|   return COLOR_BACKGROUND; | ||||
| } | ||||
| 
 | ||||
| static void theme_draw_box(JWidget widget) | ||||
| { | ||||
|   jdraw_rectfill (widget->rc, BGCOLOR); | ||||
|  | @ -442,7 +491,7 @@ static void theme_draw_button(JWidget widget) | |||
|   int icon_align = ji_generic_button_get_icon_align(widget); | ||||
|   struct jrect box, text, icon; | ||||
|   int x1, y1, x2, y2; | ||||
|   int bg, c1, c2; | ||||
|   int fg, bg, c1, c2; | ||||
|   int bevel[4]; | ||||
|   JRect crect; | ||||
| 
 | ||||
|  | @ -452,21 +501,26 @@ static void theme_draw_button(JWidget widget) | |||
| 			      icon_bmp ? icon_bmp->h : 0); | ||||
| 
 | ||||
|   /* with mouse */ | ||||
|   if (jwidget_has_mouse(widget)) | ||||
|     bg = makecol (224, 224, 224); | ||||
|   if (jwidget_is_enabled(widget) && jwidget_has_mouse(widget)) | ||||
|     bg = COLOR_HOTFACE; | ||||
|   /* without mouse */ | ||||
|   else | ||||
|     bg = makecol(192, 192, 192); /* BGCOLOR */ | ||||
|     bg = COLOR_FACE; | ||||
| 
 | ||||
|   /* selected */ | ||||
|   if (jwidget_is_selected(widget)) { | ||||
|     c1 = makecol(128, 128, 128); | ||||
|     c2 = makecol(255, 255, 255); | ||||
|     fg = COLOR_BACKGROUND; | ||||
|     bg = COLOR_SELECTED; | ||||
| 
 | ||||
|     c1 = ji_color_faceshadow(); | ||||
|     c2 = ji_color_facelight(); | ||||
|   } | ||||
|   /* non-selected */ | ||||
|   else { | ||||
|     c1 = makecol(255, 255, 255); | ||||
|     c2 = makecol(128, 128, 128); | ||||
|     fg = COLOR_FOREGROUND; | ||||
| 
 | ||||
|     c1 = ji_color_facelight(); | ||||
|     c2 = ji_color_faceshadow(); | ||||
|   } | ||||
| 
 | ||||
|   /* widget position */ | ||||
|  | @ -476,15 +530,15 @@ static void theme_draw_button(JWidget widget) | |||
|   y2 = widget->rc->y2-1; | ||||
| 
 | ||||
|   /* extern background */ | ||||
|   rectfill (ji_screen, x1, y1, x2, y2, BGCOLOR); | ||||
|   rectfill(ji_screen, x1, y1, x2, y2, BGCOLOR); | ||||
| 
 | ||||
|   /* get bevel info */ | ||||
|   jbutton_get_bevel (widget, bevel); | ||||
|   jbutton_get_bevel(widget, bevel); | ||||
| 
 | ||||
|   /* 1st border */ | ||||
|   if (jwidget_has_focus (widget)) | ||||
|     draw_bevel_box (x1, y1, x2, y2, | ||||
| 		    makecol (0, 0, 0), makecol (0, 0, 0), bevel); | ||||
|   if (jwidget_has_focus(widget)) | ||||
|     draw_bevel_box(x1, y1, x2, y2, | ||||
| 		   COLOR_FOREGROUND, COLOR_FOREGROUND, bevel); | ||||
|   else { | ||||
|     less_bevel(bevel); | ||||
|     draw_bevel_box (x1, y1, x2, y2, c1, c2, bevel); | ||||
|  | @ -515,7 +569,7 @@ static void theme_draw_button(JWidget widget) | |||
| 
 | ||||
|   /* text */ | ||||
|   crect = jwidget_get_child_rect(widget); | ||||
|   draw_textstring(NULL, -1, bg, FALSE, widget, crect, 1); | ||||
|   draw_textstring(NULL, fg, bg, FALSE, widget, crect, 1); | ||||
|   jrect_free(crect); | ||||
| 
 | ||||
|   /* icon */ | ||||
|  | @ -523,13 +577,35 @@ static void theme_draw_button(JWidget widget) | |||
|     if (jwidget_is_selected(widget)) | ||||
|       jrect_displace(&icon, 1, 1); | ||||
| 
 | ||||
|     if (jwidget_is_enabled (widget)) | ||||
|     /* enabled */ | ||||
|     if (jwidget_is_enabled(widget)) { | ||||
|       /* selected */ | ||||
|       if (jwidget_is_selected(widget)) { | ||||
| 	register int c, mask = bitmap_mask_color(icon_bmp); | ||||
| 	int x, y; | ||||
| 
 | ||||
| 	for (y=0; y<icon_bmp->h; ++y) { | ||||
| 	  for (x=0; x<icon_bmp->w; ++x) { | ||||
| 	    c = getpixel(icon_bmp, x, y); | ||||
| 	    if (c != mask) | ||||
| 	      putpixel(ji_screen, icon.x1+x, icon.y1+y, | ||||
| 		       makecol(255-getr(c), | ||||
| 			       255-getg(c), | ||||
| 			       255-getb(c))); | ||||
| 	  } | ||||
| 	} | ||||
|       } | ||||
|       /* non-selected */ | ||||
|       else { | ||||
| 	draw_sprite(ji_screen, icon_bmp, icon.x1, icon.y1); | ||||
|       } | ||||
|     } | ||||
|     /* disabled */ | ||||
|     else { | ||||
|       _ji_theme_draw_sprite_color(ji_screen, icon_bmp, icon.x1+1, icon.y1+1, | ||||
| 				  makecol(255, 255, 255)); | ||||
| 				  COLOR_BACKGROUND); | ||||
|       _ji_theme_draw_sprite_color(ji_screen, icon_bmp, icon.x1, icon.y1, | ||||
| 				  makecol(128, 128, 128)); | ||||
| 				  COLOR_DISABLED); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -548,13 +624,13 @@ static void theme_draw_check(JWidget widget) | |||
|   jdraw_rectfill (widget->rc, bg = BGCOLOR); | ||||
| 
 | ||||
|   /* mouse */ | ||||
|   if (jwidget_has_mouse (widget)) | ||||
|     jdraw_rectfill (&box, bg = makecol (224, 224, 224)); | ||||
|   if (jwidget_is_enabled(widget) && jwidget_has_mouse(widget)) | ||||
|     jdraw_rectfill (&box, bg = COLOR_HOTFACE); | ||||
| 
 | ||||
|   /* focus */ | ||||
|   if (jwidget_has_focus (widget)) { | ||||
|     jrect_stretch (&box, 1); | ||||
|     jdraw_rect (&box, makecol (0, 0, 0)); | ||||
|   if (jwidget_has_focus(widget)) { | ||||
|     jrect_stretch(&box, 1); | ||||
|     jdraw_rect(&box, COLOR_FOREGROUND); | ||||
|   } | ||||
| 
 | ||||
|   /* text */ | ||||
|  | @ -581,16 +657,16 @@ static void theme_draw_entry(JWidget widget) | |||
|   x2 = widget->rc->x2 - 1; | ||||
|   y2 = widget->rc->y2 - 1; | ||||
| 
 | ||||
|   bg = makecol (255, 255, 255); | ||||
|   bg = COLOR_BACKGROUND; | ||||
| 
 | ||||
|   /* 1st border */ | ||||
|   _ji_theme_rectedge (ji_screen, x1, y1, x2, y2, | ||||
| 		      makecol (128, 128, 128), makecol (255, 255, 255)); | ||||
|   _ji_theme_rectedge(ji_screen, x1, y1, x2, y2, | ||||
| 		     COLOR_DISABLED, COLOR_BACKGROUND); | ||||
| 
 | ||||
|   /* 2nd border */ | ||||
|   x1++, y1++, x2--, y2--; | ||||
|   if (jwidget_has_focus (widget)) | ||||
|     rect (ji_screen, x1, y1, x2, y2, makecol (0, 0, 0)); | ||||
|     rect (ji_screen, x1, y1, x2, y2, COLOR_FOREGROUND); | ||||
|   else | ||||
|     rect (ji_screen, x1, y1, x2, y2, BGCOLOR); | ||||
| 
 | ||||
|  | @ -607,21 +683,21 @@ static void theme_draw_entry(JWidget widget) | |||
| 
 | ||||
|     /* normal text */ | ||||
|     bg = -1; | ||||
|     fg = makecol (0, 0, 0); | ||||
|     fg = COLOR_FOREGROUND; | ||||
| 
 | ||||
|     /* selected */ | ||||
|     if ((c >= selbeg) && (c <= selend)) { | ||||
|       if (jwidget_has_focus (widget)) | ||||
| 	bg = makecol (44, 76, 145); | ||||
|       if (jwidget_has_focus(widget)) | ||||
| 	bg = COLOR_SELECTED; | ||||
|       else | ||||
| 	bg = makecol (128, 128, 128); | ||||
|       fg = makecol (255, 255, 255); | ||||
| 	bg = COLOR_DISABLED; | ||||
|       fg = COLOR_BACKGROUND; | ||||
|     } | ||||
| 
 | ||||
|     /* disabled */ | ||||
|     if (jwidget_is_disabled (widget)) { | ||||
|       bg = -1; | ||||
|       fg = makecol (128, 128, 128); | ||||
|       fg = COLOR_DISABLED; | ||||
|     } | ||||
| 
 | ||||
|     w = CHARACTER_LENGTH (widget->text_font, ch); | ||||
|  | @ -630,7 +706,7 @@ static void theme_draw_entry(JWidget widget) | |||
| 
 | ||||
|     cursor_x = x; | ||||
|     ji_font_set_aa_mode (widget->text_font, | ||||
| 			 bg >= 0 ? bg: makecol (255, 255, 255)); | ||||
| 			 bg >= 0 ? bg: COLOR_BACKGROUND); | ||||
|     widget->text_font->vtable->render_char (widget->text_font, | ||||
| 					    ch, fg, bg, ji_screen, x, y); | ||||
|     x += w; | ||||
|  | @ -660,12 +736,12 @@ static void theme_draw_listbox(JWidget widget) | |||
| { | ||||
|   int bg; | ||||
| 
 | ||||
|   if (jwidget_is_disabled (widget)) | ||||
|     bg = makecol (192, 192, 192); | ||||
|   if (jwidget_is_disabled(widget)) | ||||
|     bg = COLOR_FACE; | ||||
|   else | ||||
|     bg = makecol (255, 255, 255); | ||||
|     bg = COLOR_BACKGROUND; | ||||
| 
 | ||||
|   jdraw_rectfill (widget->rc, makecol (255, 255, 255)); | ||||
|   jdraw_rectfill(widget->rc, COLOR_BACKGROUND); | ||||
| } | ||||
| 
 | ||||
| static void theme_draw_listitem(JWidget widget) | ||||
|  | @ -673,17 +749,17 @@ static void theme_draw_listitem(JWidget widget) | |||
|   int fg, bg; | ||||
|   int x, y; | ||||
| 
 | ||||
|   if (jwidget_is_disabled (widget)) { | ||||
|     bg = makecol (192, 192, 192); | ||||
|     fg = makecol (128, 128, 128); | ||||
|   if (jwidget_is_disabled(widget)) { | ||||
|     bg = COLOR_FACE; | ||||
|     fg = COLOR_DISABLED; | ||||
|   } | ||||
|   else if (jwidget_is_selected (widget)) { | ||||
|     bg = makecol (44, 76, 145); | ||||
|     fg = makecol (255, 255, 255); | ||||
|     bg = COLOR_SELECTED; | ||||
|     fg = COLOR_BACKGROUND; | ||||
|   } | ||||
|   else { | ||||
|     bg = makecol (255, 255, 255); | ||||
|     fg = makecol (0, 0, 0); | ||||
|     bg = COLOR_BACKGROUND; | ||||
|     fg = COLOR_FOREGROUND; | ||||
|   } | ||||
| 
 | ||||
|   x = widget->rc->x1+widget->border_width.l; | ||||
|  | @ -708,40 +784,40 @@ static void theme_draw_listitem(JWidget widget) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| static void theme_draw_menu (JWidget widget) | ||||
| static void theme_draw_menu(JWidget widget) | ||||
| { | ||||
|   jdraw_rectfill (widget->rc, BGCOLOR); | ||||
| } | ||||
| 
 | ||||
| static void theme_draw_menuitem (JWidget widget) | ||||
| static void theme_draw_menuitem(JWidget widget) | ||||
| { | ||||
|   int c, bg, fg, bar; | ||||
|   int x1, y1, x2, y2; | ||||
|   JRect pos; | ||||
| 
 | ||||
|   /* XXXX assert? */ | ||||
|   /* TODO assert? */ | ||||
|   if (!widget->parent->parent) | ||||
|     return; | ||||
| 
 | ||||
|   bar = (widget->parent->parent->type == JI_MENUBAR); | ||||
| 
 | ||||
|   /* colors */ | ||||
|   if (jwidget_is_disabled (widget)) { | ||||
|   if (jwidget_is_disabled(widget)) { | ||||
|     bg = BGCOLOR; | ||||
|     fg = -1; | ||||
|   } | ||||
|   else { | ||||
|     if (jmenuitem_is_highlight (widget)) { | ||||
|       bg = makecol (44, 76, 145); | ||||
|       fg = makecol (255, 255, 255); | ||||
|     if (jmenuitem_is_highlight(widget)) { | ||||
|       bg = COLOR_SELECTED; | ||||
|       fg = COLOR_BACKGROUND; | ||||
|     } | ||||
|     else if (jwidget_has_mouse (widget)) { | ||||
|       bg = makecol (224, 224, 224); | ||||
|       fg = makecol (0, 0, 0); | ||||
|     else if (jwidget_has_mouse(widget)) { | ||||
|       bg = COLOR_HOTFACE; | ||||
|       fg = COLOR_FOREGROUND; | ||||
|     } | ||||
|     else { | ||||
|       bg = BGCOLOR; | ||||
|       fg = makecol (0, 0, 0); | ||||
|       fg = COLOR_FOREGROUND; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | @ -763,8 +839,8 @@ static void theme_draw_menuitem (JWidget widget) | |||
|     if (jwidget_is_enabled(widget)) | ||||
|       draw_character(ji_screen, icon, x, y, fg); | ||||
|     else { | ||||
|       draw_character(ji_screen, icon, x+1, y+1, makecol (255, 255, 255)); | ||||
|       draw_character(ji_screen, icon, x, y, makecol (128, 128, 128)); | ||||
|       draw_character(ji_screen, icon, x+1, y+1, COLOR_BACKGROUND); | ||||
|       draw_character(ji_screen, icon, x, y, COLOR_DISABLED); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | @ -798,12 +874,12 @@ static void theme_draw_menuitem (JWidget widget) | |||
| 	  vline (ji_screen, | ||||
| 		 widget->rc->x2-3-c+1, | ||||
| 		 (widget->rc->y1+widget->rc->y2)/2-c+1, | ||||
| 		 (widget->rc->y1+widget->rc->y2)/2+c+1, makecol (255, 255, 255)); | ||||
| 		 (widget->rc->y1+widget->rc->y2)/2+c+1, COLOR_BACKGROUND); | ||||
| 	for (c=0; c<3; c++) | ||||
| 	  vline (ji_screen, | ||||
| 		 widget->rc->x2-3-c, | ||||
| 		 (widget->rc->y1+widget->rc->y2)/2-c, | ||||
| 		 (widget->rc->y1+widget->rc->y2)/2+c, makecol (128, 128, 128)); | ||||
| 		 (widget->rc->y1+widget->rc->y2)/2+c, COLOR_DISABLED); | ||||
|       } | ||||
|     } | ||||
|     /* draw the keyboard shortcut */ | ||||
|  | @ -835,8 +911,8 @@ static void theme_draw_panel (JWidget widget) | |||
| /* 		   (jwidget_pick(widget, */ | ||||
| /* 				   ji_mouse_x(0), */ | ||||
| /* 				   ji_mouse_y(0)) == widget) ? */ | ||||
| /* 		   makecol (224, 224, 224): makecol (192, 192, 192)); */ | ||||
|   jdraw_rectfill(widget->rc, makecol (192, 192, 192)); | ||||
| /* 		   COLOR_HOTFACE: COLOR_FACE); */ | ||||
|   jdraw_rectfill(widget->rc, COLOR_FACE); | ||||
| 
 | ||||
|   JI_LIST_FOR_EACH(widget->children, link) { | ||||
|     if (link->next != widget->children->end) { | ||||
|  | @ -847,35 +923,35 @@ static void theme_draw_panel (JWidget widget) | |||
| /* 	vline (ji_screen, */ | ||||
| /* 	       (c1->pos->x+c1->pos->w+c2->pos->x-1)/2, */ | ||||
| /* 	       widget->rect->y, */ | ||||
| /* 	       widget->rect->y+widget->rect->h/2-4, makecol (0, 0, 0)); */ | ||||
| /* 	       widget->rect->y+widget->rect->h/2-4, COLOR_FOREGROUND); */ | ||||
| 
 | ||||
| /* 	vline (ji_screen, */ | ||||
| /* 	       (c1->pos->x+c1->pos->w+c2->pos->x-1)/2, */ | ||||
| /* 	       widget->rect->y+widget->rect->h/2+4, */ | ||||
| /* 	       widget->rect->y+widget->rect->h-1, makecol (0, 0, 0)); */ | ||||
| /* 	       widget->rect->y+widget->rect->h-1, COLOR_FOREGROUND); */ | ||||
| 
 | ||||
| 	for (c=-4; c<=4; c+=2) | ||||
| 	  hline(ji_screen, | ||||
| 		c1->rc->x2+2, | ||||
| 		(widget->rc->y1+widget->rc->y2)/2+c, | ||||
| 		c2->rc->x1-3, makecol(0, 0, 0)); | ||||
| 		c2->rc->x1-3, COLOR_FOREGROUND); | ||||
|       } | ||||
|       else { | ||||
| /* 	hline (ji_screen, */ | ||||
| /* 	       widget->rect->x, */ | ||||
| /* 	       (c1->pos->y+c1->pos->h+c2->pos->y-1)/2, */ | ||||
| /* 	       widget->rect->x+widget->rect->w/2-4, makecol (0, 0, 0)); */ | ||||
| /* 	       widget->rect->x+widget->rect->w/2-4, COLOR_FOREGROUND); */ | ||||
| 
 | ||||
| /* 	hline (ji_screen, */ | ||||
| /* 	       widget->rect->x+widget->rect->w/2+4, */ | ||||
| /* 	       (c1->pos->y+c1->pos->h+c2->pos->y-1)/2, */ | ||||
| /* 	       widget->rect->x+widget->rect->w-1, makecol (0, 0, 0)); */ | ||||
| /* 	       widget->rect->x+widget->rect->w-1, COLOR_FOREGROUND); */ | ||||
| 
 | ||||
| 	for (c=-4; c<=4; c+=2) | ||||
| 	  vline(ji_screen, | ||||
| 		(widget->rc->x1+widget->rc->x2)/2+c, | ||||
| 		c1->rc->y2+2, | ||||
| 		c2->rc->y1-3, makecol(0, 0, 0)); | ||||
| 		c2->rc->y1-3, COLOR_FOREGROUND); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | @ -895,22 +971,22 @@ static void theme_draw_radio (JWidget widget) | |||
|   jdraw_rectfill (widget->rc, bg); | ||||
| 
 | ||||
|   /* mouse */ | ||||
|   if (jwidget_has_mouse (widget)) | ||||
|     jdraw_rectfill (&box, bg = makecol (224, 224, 224)); | ||||
|   if (jwidget_is_enabled(widget) && jwidget_has_mouse(widget)) | ||||
|     jdraw_rectfill(&box, bg = COLOR_HOTFACE); | ||||
| 
 | ||||
|   /* focus */ | ||||
|   if (jwidget_has_focus (widget)) | ||||
|     rect (ji_screen, box.x1-1, box.y1-1, box.x2, box.y2, | ||||
| 	  makecol (0, 0, 0)); | ||||
|   if (jwidget_has_focus(widget)) | ||||
|     rect(ji_screen, box.x1-1, box.y1-1, box.x2, box.y2, | ||||
| 	 COLOR_FOREGROUND); | ||||
| 
 | ||||
|   /* text */ | ||||
|   draw_textstring (NULL, -1, bg, FALSE, widget, &text, 0); | ||||
|   draw_textstring(NULL, -1, bg, FALSE, widget, &text, 0); | ||||
| 
 | ||||
|   /* icon */ | ||||
|   draw_icons (icon.x1, icon.y1, widget, ICON_RADIO_EDGE); | ||||
|   draw_icons(icon.x1, icon.y1, widget, ICON_RADIO_EDGE); | ||||
| } | ||||
| 
 | ||||
| static void theme_draw_separator (JWidget widget) | ||||
| static void theme_draw_separator(JWidget widget) | ||||
| { | ||||
|   int x1, y1, x2, y2; | ||||
| 
 | ||||
|  | @ -925,32 +1001,32 @@ static void theme_draw_separator (JWidget widget) | |||
| 
 | ||||
|   /* TOP line */ | ||||
|   if (widget->align & JI_HORIZONTAL) { | ||||
|     hline (ji_screen, x1, y1-1, x2, makecol (128, 128, 128)); | ||||
|     hline (ji_screen, x1, y1, x2, makecol (255, 255, 255)); | ||||
|     hline (ji_screen, x1, y1-1, x2, COLOR_DISABLED); | ||||
|     hline (ji_screen, x1, y1, x2, COLOR_BACKGROUND); | ||||
|   } | ||||
| 
 | ||||
|   /* LEFT line */ | ||||
|   if (widget->align & JI_VERTICAL) { | ||||
|     vline (ji_screen, x1-1, y1, y2, makecol (128, 128, 128)); | ||||
|     vline (ji_screen, x1, y1, y2, makecol (255, 255, 255)); | ||||
|     vline (ji_screen, x1-1, y1, y2, COLOR_DISABLED); | ||||
|     vline (ji_screen, x1, y1, y2, COLOR_BACKGROUND); | ||||
|   } | ||||
| 
 | ||||
|   /* frame */ | ||||
|   if ((widget->align & JI_HORIZONTAL) && | ||||
|       (widget->align & JI_VERTICAL)) { | ||||
|     /* union between the LEFT and TOP lines */ | ||||
|     putpixel (ji_screen, x1-1, y1-1, makecol (128, 128, 128)); | ||||
|     putpixel (ji_screen, x1-1, y1-1, COLOR_DISABLED); | ||||
| 
 | ||||
|     /* BOTTOM line */ | ||||
|     hline (ji_screen, x1, y2, x2, makecol (128, 128, 128)); | ||||
|     hline (ji_screen, x1-1, y2+1, x2, makecol (255, 255, 255)); | ||||
|     hline (ji_screen, x1, y2, x2, COLOR_DISABLED); | ||||
|     hline (ji_screen, x1-1, y2+1, x2, COLOR_BACKGROUND); | ||||
| 
 | ||||
|     /* RIGHT line */ | ||||
|     vline (ji_screen, x2, y1, y2, makecol (128, 128, 128)); | ||||
|     vline (ji_screen, x2+1, y1-1, y2, makecol (255, 255, 255)); | ||||
|     vline (ji_screen, x2, y1, y2, COLOR_DISABLED); | ||||
|     vline (ji_screen, x2+1, y1-1, y2, COLOR_BACKGROUND); | ||||
| 
 | ||||
|     /* union between the RIGHT and BOTTOM lines */ | ||||
|     putpixel (ji_screen, x2+1, y2+1, makecol (255, 255, 255)); | ||||
|     putpixel (ji_screen, x2+1, y2+1, COLOR_BACKGROUND); | ||||
|   } | ||||
| 
 | ||||
|   /* text */ | ||||
|  | @ -962,7 +1038,7 @@ static void theme_draw_separator (JWidget widget) | |||
| } | ||||
| 
 | ||||
| #if 1 | ||||
| /* XXXX when Allegro 4.1 will be officially released, replace this
 | ||||
| /* TODO when Allegro 4.1 will be officially released, replace this
 | ||||
|    with the get_clip_rect, add_clip_rect, set_clip_rect functions */ | ||||
| static int my_add_clip_rect (BITMAP *bitmap, int x1, int y1, int x2, int y2) | ||||
| { | ||||
|  | @ -980,9 +1056,8 @@ static int my_add_clip_rect (BITMAP *bitmap, int x1, int y1, int x2, int y2) | |||
| } | ||||
| #endif | ||||
| 
 | ||||
| static void theme_draw_slider (JWidget widget) | ||||
| static void theme_draw_slider(JWidget widget) | ||||
| { | ||||
| #if 1 | ||||
|   int x, x1, y1, x2, y2, bg, c1, c2; | ||||
|   int min, max, value; | ||||
|   char buf[256]; | ||||
|  | @ -996,31 +1071,31 @@ static void theme_draw_slider (JWidget widget) | |||
|   y2 = widget->rc->y2 - 1; | ||||
| 
 | ||||
|   /* with mouse */ | ||||
|   if (jwidget_has_mouse (widget)) | ||||
|     bg = makecol (224, 224, 224); | ||||
|   if (jwidget_is_enabled(widget) && jwidget_has_mouse(widget)) | ||||
|     bg = COLOR_HOTFACE; | ||||
|   /* without mouse */ | ||||
|   else | ||||
|     bg = makecol (192, 192, 192); | ||||
|     bg = COLOR_FACE; | ||||
| 
 | ||||
|   /* 1st border */ | ||||
|   _ji_theme_rectedge (ji_screen, x1, y1, x2, y2, | ||||
| 		      makecol (128, 128, 128), makecol (255, 255, 255)); | ||||
|   _ji_theme_rectedge(ji_screen, x1, y1, x2, y2, | ||||
| 		     COLOR_DISABLED, COLOR_BACKGROUND); | ||||
| 
 | ||||
|   /* 2nd border */ | ||||
|   x1++, y1++, x2--, y2--; | ||||
|   if (jwidget_has_focus (widget)) | ||||
|     rect (ji_screen, x1, y1, x2, y2, makecol (0, 0, 0)); | ||||
|     rect (ji_screen, x1, y1, x2, y2, COLOR_FOREGROUND); | ||||
|   else | ||||
|     rect (ji_screen, x1, y1, x2, y2, bg); | ||||
| 
 | ||||
|   /* 3rd border */ | ||||
|   if (!jwidget_is_selected (widget)) { | ||||
|     c1 = makecol (255, 255, 255); | ||||
|     c2 = makecol (128, 128, 128); | ||||
|     c1 = COLOR_BACKGROUND; | ||||
|     c2 = COLOR_DISABLED; | ||||
|   } | ||||
|   else { | ||||
|     c1 = makecol (128, 128, 128); | ||||
|     c2 = makecol (255, 255, 255); | ||||
|     c1 = COLOR_DISABLED; | ||||
|     c2 = COLOR_BACKGROUND; | ||||
|   } | ||||
| 
 | ||||
|   x1++, y1++, x2--, y2--; | ||||
|  | @ -1040,7 +1115,7 @@ static void theme_draw_slider (JWidget widget) | |||
|   else { | ||||
|     rectfill (ji_screen, x1, y1, x, y2, | ||||
| 	      (jwidget_is_disabled (widget)) ? | ||||
| 	      bg: makecol (44, 76, 145)); | ||||
| 	      bg: COLOR_SELECTED); | ||||
| 
 | ||||
|     if (x < x2) | ||||
|       rectfill (ji_screen, x+1, y1, x2, y2, bg); | ||||
|  | @ -1059,8 +1134,9 @@ static void theme_draw_slider (JWidget widget) | |||
| 
 | ||||
|     r = jrect_new(x1, y1, x2+1, y2+1); | ||||
| 
 | ||||
|     /* XXXX when Allegro 4.1 will be officially released, replace this
 | ||||
|        with the get_clip_rect, add_clip_rect, set_clip_rect functions */ | ||||
|     /* TODO when Allegro 4.1 will be officially released, replace this
 | ||||
|        with the get_clip_rect, add_clip_rect, set_clip_rect | ||||
|        functions */ | ||||
| 
 | ||||
|     cx1 = ji_screen->cl; | ||||
|     cy1 = ji_screen->ct; | ||||
|  | @ -1068,120 +1144,20 @@ static void theme_draw_slider (JWidget widget) | |||
|     cy2 = ji_screen->cb-1; | ||||
| 
 | ||||
|     if (my_add_clip_rect(ji_screen, x1, y1, x, y2)) | ||||
|       draw_textstring(NULL, makecol(255, 255, 255), | ||||
|       draw_textstring(NULL, COLOR_BACKGROUND, | ||||
| 		      jwidget_is_disabled(widget) ? | ||||
| 		      bg: makecol(44, 76, 145), FALSE, widget, r, 0); | ||||
| 		      bg: COLOR_SELECTED, FALSE, widget, r, 0); | ||||
| 
 | ||||
|     set_clip(ji_screen, cx1, cy1, cx2, cy2); | ||||
| 
 | ||||
|     if (my_add_clip_rect(ji_screen, x+1, y1, x2, y2)) | ||||
|       draw_textstring(NULL, makecol (0, 0, 0), bg, FALSE, widget, r, 0); | ||||
|       draw_textstring(NULL, COLOR_FOREGROUND, bg, FALSE, widget, r, 0); | ||||
| 
 | ||||
|     set_clip(ji_screen, cx1, cy1, cx2, cy2); | ||||
| 
 | ||||
|     widget->text = old_text; | ||||
|     jrect_free(r); | ||||
|   } | ||||
| #else | ||||
|   int min, max, value, bg, c1, c2; | ||||
|   char buf[256]; | ||||
|   JRect pos = jwidget_get_rect(widget); | ||||
| 
 | ||||
|   jtheme_slider_info(widget, &min, &max, &value); | ||||
| 
 | ||||
|   /* with mouse */ | ||||
|   if (jwidget_has_mouse(widget)) | ||||
|     bg = makecol(224, 224, 224); | ||||
|   /* without mouse */ | ||||
|   else | ||||
|     bg = makecol(192, 192, 192); | ||||
| 
 | ||||
|   /* 1st border */ | ||||
|   jdraw_rectedge(pos, makecol(128, 128, 128), makecol(255, 255, 255)); | ||||
| 
 | ||||
|   /* 2nd border */ | ||||
|   jrect_shrink(pos, 1); | ||||
|   if (jwidget_has_focus(widget)) | ||||
|     jdraw_rect(pos, makecol(0, 0, 0)); | ||||
|   else | ||||
|     jdraw_rect(pos, bg); | ||||
| 
 | ||||
|   /* 3rd border */ | ||||
|   if (!jwidget_is_selected (widget)) { | ||||
|     c1 = makecol(255, 255, 255); | ||||
|     c2 = makecol(128, 128, 128); | ||||
|   } | ||||
|   else { | ||||
|     c1 = makecol(128, 128, 128); | ||||
|     c2 = makecol(255, 255, 255); | ||||
|   } | ||||
| 
 | ||||
|   jrect_shrink(pos, 1); | ||||
|   jdraw_rectedge(pos, c1, c2); | ||||
| 
 | ||||
|   /* background and text */ | ||||
|   jrect_shrink(pos, 1); | ||||
| 
 | ||||
|   if (min != max) { | ||||
|     char *old_text = widget->text; | ||||
|     int x1, x2; | ||||
|     JRect rc; | ||||
| 
 | ||||
|     usprintf(buf, "%d", value); | ||||
|     widget->align = JI_CENTER | JI_MIDDLE; | ||||
|     widget->text = buf; | ||||
| 
 | ||||
| #if 0 | ||||
|     x = pos->x1 + (pos->x2-pos->x1) * (value-min) / (max-min+1); | ||||
|     w = jwidget_get_text_length(widget)+2; | ||||
|     if (x-w/2 < pos->x1) { | ||||
|       x1 = pos->x1; | ||||
|       x2 = MIN(pos->x1+w, pos->x2); | ||||
|     } | ||||
|     else if (x+w/2 > pos->x2) { | ||||
|       x1 = pos->x2-w; | ||||
|       x2 = pos->x2; | ||||
|     } | ||||
|     else { | ||||
|       x1 = x-w/2; | ||||
|       x2 = x+w/2; | ||||
|     } | ||||
| #else | ||||
|     if (max == min) { | ||||
|       x1 = pos->x1; | ||||
|       x2 = pos->x2; | ||||
|     } | ||||
|     else { | ||||
|       int x, w; | ||||
| 
 | ||||
|       w = ji_font_text_len(widget->text_font, "888"); | ||||
|       w = MAX(w, (pos->x2-pos->x1) / (max-min+1)); | ||||
|       x = pos->x1 + ((value-min) * w); | ||||
| 
 | ||||
|       x1 = x; | ||||
|       if (x1 < pos->x1) | ||||
| 	x1 = pos->x1; | ||||
|       x2 = x+w; | ||||
|       if (x2 > pos->x2) | ||||
| 	x1 = pos->x2-w; | ||||
|     } | ||||
| #endif | ||||
|     rc = jrect_new(x1, pos->y1, x2, pos->y2); | ||||
| 
 | ||||
|     jdraw_rectfill(pos, bg); | ||||
|     jdraw_rectfill(rc, (jwidget_is_disabled(widget)) ? | ||||
| 		     bg: makecol(44, 76, 145)); | ||||
| 
 | ||||
|     draw_textstring(NULL, makecol(255, 255, 255), | ||||
| 		    jwidget_is_disabled(widget) ? | ||||
| 		    bg: makecol(44, 76, 145), FALSE, widget, rc, 0); | ||||
| 
 | ||||
|     jrect_free(rc); | ||||
|     widget->text = old_text; | ||||
|   } | ||||
| 
 | ||||
|   jrect_free(pos); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| static void theme_draw_textbox(JWidget widget) | ||||
|  | @ -1195,15 +1171,15 @@ static void theme_draw_view(JWidget widget) | |||
| 
 | ||||
|   if (jwidget_has_focus(widget)) { | ||||
|     /* 1st border */ | ||||
|     jdraw_rectedge(pos, makecol (128, 128, 128), makecol (255, 255, 255)); | ||||
|     jdraw_rectedge(pos, COLOR_DISABLED, COLOR_BACKGROUND); | ||||
| 
 | ||||
|     /* 2nd border */ | ||||
|     jrect_shrink(pos, 1); | ||||
|     jdraw_rect(pos, makecol (0, 0, 0)); | ||||
|     jdraw_rect(pos, COLOR_FOREGROUND); | ||||
|   } | ||||
|   else { | ||||
|     /* 1st border */ | ||||
|     jdraw_rectedge(pos, makecol (128, 128, 128), makecol (255, 255, 255)); | ||||
|     jdraw_rectedge(pos, COLOR_DISABLED, COLOR_BACKGROUND); | ||||
| 
 | ||||
|     /* 2nd border */ | ||||
|     jrect_shrink(pos, 1); | ||||
|  | @ -1217,7 +1193,7 @@ static void theme_draw_view(JWidget widget) | |||
|   jrect_free (pos); | ||||
| } | ||||
| 
 | ||||
| static void theme_draw_view_scrollbar (JWidget widget) | ||||
| static void theme_draw_view_scrollbar(JWidget widget) | ||||
| { | ||||
|   int x1, y1, x2, y2; | ||||
|   int u1, v1, u2, v2; | ||||
|  | @ -1259,75 +1235,17 @@ static void theme_draw_view_scrollbar (JWidget widget) | |||
|   /* 1st border */ | ||||
|   if (jwidget_is_selected (widget)) | ||||
|     _ji_theme_rectedge (ji_screen, u1, v1, u2, v2, | ||||
| 			makecol (128, 128, 128), makecol (255, 255, 255)); | ||||
| 			COLOR_DISABLED, COLOR_BACKGROUND); | ||||
|   else | ||||
|     _ji_theme_rectedge (ji_screen, u1, v1, u2, v2, | ||||
| 			makecol (255, 255, 255), makecol (128, 128, 128)); | ||||
| 			COLOR_BACKGROUND, COLOR_DISABLED); | ||||
| 
 | ||||
|   /* bar-block background */ | ||||
|   u1++, v1++, u2--, v2--; | ||||
|   if (jwidget_has_mouse (widget)) | ||||
|     rectfill (ji_screen, u1, v1, u2, v2, makecol (224, 224, 224)); | ||||
|   if (jwidget_is_enabled(widget) && jwidget_has_mouse(widget)) | ||||
|     rectfill(ji_screen, u1, v1, u2, v2, COLOR_HOTFACE); | ||||
|   else | ||||
|     rectfill (ji_screen, u1, v1, u2, v2, BGCOLOR); | ||||
| #if 0 | ||||
|   int x1, y1, x2, y2; | ||||
|   int u1, v1, u2, v2; | ||||
|   int pos, len; | ||||
| 
 | ||||
|   jtheme_scrollbar_info (widget, &pos, &len); | ||||
| 
 | ||||
|   x1 = widget->rc->x1; | ||||
|   y1 = widget->rc->y1; | ||||
|   x2 = widget->rc->x2-1; | ||||
|   y2 = widget->rc->y2-1; | ||||
| 
 | ||||
|   /* 1st border */ | ||||
|   _ji_theme_rectedge (ji_screen, x1, y1, x2, y2, | ||||
| 		      makecol (255, 255, 255), makecol (128, 128, 128)); | ||||
| 
 | ||||
|   /* 2nd border */ | ||||
|   x1++, y1++, x2--, y2--; | ||||
|   rect (ji_screen, x1, y1, x2, y2, BGCOLOR); | ||||
| 
 | ||||
|   /* draw the content */ | ||||
|   x1++, y1++, x2--, y2--; | ||||
| 
 | ||||
|   /* horizontal bar */ | ||||
|   if (widget->align & JI_HORIZONTAL) { | ||||
|     u1 = x1+pos; | ||||
|     v1 = y1; | ||||
|     u2 = x1+pos+len-1; | ||||
|     v2 = y2; | ||||
|   } | ||||
|   /* vertical bar */ | ||||
|   else { | ||||
|     u1 = x1; | ||||
|     v1 = y1+pos; | ||||
|     u2 = x2; | ||||
|     v2 = y1+pos+len-1; | ||||
|   } | ||||
| 
 | ||||
|   /* background */ | ||||
|   _ji_theme_rectfill_exclude (ji_screen, | ||||
| 			      x1, y1, x2, y2, | ||||
| 			      u1, v1, u2, v2, BGCOLOR); | ||||
| 
 | ||||
|   /* 1st border */ | ||||
|   if (jwidget_is_selected (widget)) | ||||
|     _ji_theme_rectedge (ji_screen, u1, v1, u2, v2, | ||||
| 			makecol (128, 128, 128), makecol (255, 255, 255)); | ||||
|   else | ||||
|     _ji_theme_rectedge (ji_screen, u1, v1, u2, v2, | ||||
| 			makecol (255, 255, 255), makecol (128, 128, 128)); | ||||
| 
 | ||||
|   /* bar-block background */ | ||||
|   u1++, v1++, u2--, v2--; | ||||
|   if (jwidget_has_mouse (widget)) | ||||
|     rectfill (ji_screen, u1, v1, u2, v2, makecol (224, 224, 224)); | ||||
|   else | ||||
|     rectfill (ji_screen, u1, v1, u2, v2, BGCOLOR); | ||||
| #endif | ||||
|     rectfill(ji_screen, u1, v1, u2, v2, BGCOLOR); | ||||
| } | ||||
| 
 | ||||
| static void theme_draw_view_viewport (JWidget widget) | ||||
|  | @ -1342,15 +1260,15 @@ static void theme_draw_window(JWidget widget) | |||
| 
 | ||||
|   /* extra lines */ | ||||
|   if (!jwindow_is_desktop(widget)) { | ||||
|     jdraw_rect(pos, makecol(0, 0, 0)); | ||||
|     jdraw_rect(pos, COLOR_FOREGROUND); | ||||
|     jrect_shrink(pos, 1); | ||||
|     jdraw_rectedge(pos, makecol(255, 255, 255), makecol(128, 128, 128)); | ||||
|     jdraw_rectedge(pos, COLOR_BACKGROUND, COLOR_DISABLED); | ||||
|     jrect_shrink(pos, 1); | ||||
|     jdraw_rectfill(pos, BGCOLOR); | ||||
| 
 | ||||
|     /* draw title bar */ | ||||
|     if (widget->text) { | ||||
|       int bg = makecol(44, 76, 145); | ||||
|       int bg = COLOR_SELECTED; | ||||
| 
 | ||||
|       jrect_shrink(pos, 1); | ||||
| /*       pos->y2 = cpos->y1-1; */ | ||||
|  | @ -1358,12 +1276,12 @@ static void theme_draw_window(JWidget widget) | |||
|       jdraw_rectfill(pos, bg); | ||||
| 
 | ||||
|       jrect_stretch(pos, 1); | ||||
|       jdraw_rectedge(cpos, makecol(128, 128, 128), makecol(255, 255, 255)); | ||||
|       jdraw_rectedge(cpos, COLOR_DISABLED, COLOR_BACKGROUND); | ||||
| 
 | ||||
|       jdraw_text(widget->text_font, widget->text, | ||||
| 		   cpos->x1, | ||||
| 		   pos->y1+jrect_h(pos)/2-text_height(widget->text_font)/2, | ||||
| 		   makecol(255, 255, 255), bg, FALSE); | ||||
| 		   COLOR_BACKGROUND, bg, FALSE); | ||||
|     } | ||||
|   } | ||||
|   /* desktop */ | ||||
|  | @ -1380,8 +1298,8 @@ static int get_bg_color (JWidget widget) | |||
|   int c = jwidget_get_bg_color (widget); | ||||
|   int decorative = jwidget_is_decorative (widget); | ||||
| 
 | ||||
|   return c >= 0 ? c: (decorative ? makecol (44, 76, 145): | ||||
| 				   makecol (192, 192, 192)); | ||||
|   return c >= 0 ? c: (decorative ? COLOR_SELECTED: | ||||
| 				   COLOR_FACE); | ||||
| } | ||||
| 
 | ||||
| static void draw_textstring (const char *t, int fg_color, int bg_color, | ||||
|  | @ -1434,13 +1352,13 @@ static void draw_textstring (const char *t, int fg_color, int bg_color, | |||
| 
 | ||||
|     /* text */ | ||||
|     if (jwidget_is_disabled (widget)) { | ||||
|       /* XXXX avoid this */ | ||||
|       /* TODO avoid this */ | ||||
|       if (fill_bg)		/* only to draw the background */ | ||||
| 	jdraw_text(widget->text_font, t, x, y, 0, bg_color, fill_bg); | ||||
| 
 | ||||
|       /* draw white part */ | ||||
|       jdraw_text(widget->text_font, t, x+1, y+1, | ||||
| 		 makecol(255, 255, 255), bg_color, fill_bg); | ||||
| 		 COLOR_BACKGROUND, bg_color, fill_bg); | ||||
| 
 | ||||
|       if (fill_bg) | ||||
| 	fill_bg = FALSE; | ||||
|  | @ -1448,8 +1366,8 @@ static void draw_textstring (const char *t, int fg_color, int bg_color, | |||
| 
 | ||||
|     jdraw_text(widget->text_font, t, x, y, | ||||
| 	       jwidget_is_disabled(widget) ? | ||||
| 	       makecol(128, 128, 128): (fg_color >= 0 ? fg_color : | ||||
| 							makecol(0, 0, 0)), | ||||
| 	       COLOR_DISABLED: (fg_color >= 0 ? fg_color : | ||||
| 						COLOR_FOREGROUND), | ||||
| 	       bg_color, fill_bg); | ||||
|   } | ||||
| } | ||||
|  | @ -1458,8 +1376,8 @@ static void draw_entry_cursor(JWidget widget, int x, int y) | |||
| { | ||||
|   int h = jwidget_get_text_height(widget); | ||||
| 
 | ||||
|   vline(ji_screen, x,   y-1, y+h, makecol (0, 0, 0)); | ||||
|   vline(ji_screen, x+1, y-1, y+h, makecol (0, 0, 0)); | ||||
|   vline(ji_screen, x,   y-1, y+h, COLOR_FOREGROUND); | ||||
|   vline(ji_screen, x+1, y-1, y+h, COLOR_FOREGROUND); | ||||
| } | ||||
| 
 | ||||
| static void draw_icons(int x, int y, JWidget widget, int edge_icon) | ||||
|  |  | |||
|  | @ -24,14 +24,6 @@ | |||
| 
 | ||||
| #USE_PRECOMPILED_HEADER = 1 | ||||
| 
 | ||||
| ###################################################################### | ||||
| # Uncomment if you have some of these libraries (the version is just | ||||
| # suggested and is the version that was used to compile ASE) | ||||
| 
 | ||||
| #HAVE_LIBJPEG = 1        # LibJPEG 6.2: used to load/save JPEG files | ||||
| 
 | ||||
| #HAVE_JPGALLEG = 1       # JPGalleg 2.3: alternative JPEG support | ||||
| 
 | ||||
| ###################################################################### | ||||
| # Uncomment if you want to use the "_int_mult" routine written in | ||||
| # assembler for i386 processors in replacement of the INT_MULT() macro | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| # Copyright (C) 2001-2005 by David A. Capello		-*-Makefile-*- | ||||
| # Copyright (C) 2001-2005, 2007 by David A. Capello		-*-Makefile-*- | ||||
| 
 | ||||
| ifndef CONFIGURED | ||||
| include makefile.cfg | ||||
|  | @ -41,7 +41,7 @@ default: all | |||
| all: $(ASE) | ||||
| 
 | ||||
| clean: | ||||
| 	-rm -f $(ALL_OBJS) $(ALL_LIBS) | ||||
| 	-rm -f $(ALL_OBJS) $(THIRD_PARTY_LIBS) | ||||
| 
 | ||||
| distclean: clean | ||||
| 	-rm -f $(ASE) | ||||
|  |  | |||
							
								
								
									
										64
									
								
								makefile.gcc
								
								
								
								
							
							
						
						
									
										64
									
								
								makefile.gcc
								
								
								
								
							|  | @ -9,14 +9,16 @@ _default: default | |||
| CFLAGS += -Wall -I. -Isrc -Ijinete/include -Ithird_party \ | ||||
| 	  -I$(JINETE_DIR)/freetype/include \ | ||||
|           -I$(LIBLUA_DIR)/include \ | ||||
| 	  -I$(LIBJPEG_DIR) \ | ||||
| 	  -I$(LIBGFLI_DIR) \ | ||||
| 	  -I$(LIBPNG_DIR) \ | ||||
| 	  -I$(ZLIB_DIR) \ | ||||
| 	  -Wno-deprecated-declarations \ | ||||
| 	  -DPNG_NO_MMX_CODE | ||||
| 
 | ||||
| LFLAGS += $(JINETE_LIB) $(LIBLUA_LIB) $(LIBGFLI_LIB) $(LIBART_LIB) \ | ||||
| 	  $(LIBPNG_LIB) $(ZLIB_LIB) | ||||
| #	  -I$(LIBGD_DIR)  | ||||
| 
 | ||||
| LFLAGS += $(JINETE_LIB) $(THIRD_PARTY_LIBS) | ||||
| 
 | ||||
| ifdef PROFILE | ||||
|   CFLAGS += -pg | ||||
|  | @ -39,16 +41,6 @@ ifdef USE_PRECOMPILED_HEADER | |||
|   CFLAGS += -DUSE_PRECOMPILED_HEADER | ||||
| endif | ||||
| 
 | ||||
| ifdef HAVE_LIBJPEG | ||||
|   CFLAGS += -DHAVE_LIBJPEG | ||||
|   LFLAGS += -ljpeg | ||||
| endif | ||||
| 
 | ||||
| ifdef HAVE_JPGALLEG | ||||
|   CFLAGS += -DHAVE_JPGALLEG | ||||
|   LFLAGS += -ljpgal | ||||
| endif | ||||
| 
 | ||||
| ###################################################################### | ||||
| # Rules to make Jinete | ||||
| 
 | ||||
|  | @ -59,7 +51,11 @@ include $(JINETE_DIR)/makefile.gcc | |||
| ###################################################################### | ||||
| # Rules to make third party libraries | ||||
| 
 | ||||
| $(LIBLUA_LIB): $(LIBLUA_OBJS) | ||||
| $(LIBART_LIB): $(LIBART_OBJS) | ||||
| 	-rm -f $@ | ||||
| 	ar rs $@ $^ | ||||
| 
 | ||||
| $(LIBGD_LIB): $(LIBGD_OBJS) | ||||
| 	-rm -f $@ | ||||
| 	ar rs $@ $^ | ||||
| 
 | ||||
|  | @ -67,7 +63,11 @@ $(LIBGFLI_LIB): $(LIBGFLI_OBJS) | |||
| 	-rm -f $@ | ||||
| 	ar rs $@ $^ | ||||
| 
 | ||||
| $(LIBART_LIB): $(LIBART_OBJS) | ||||
| $(LIBJPEG_LIB): $(LIBJPEG_OBJS) | ||||
| 	-rm -f $@ | ||||
| 	ar rs $@ $^ | ||||
| 
 | ||||
| $(LIBLUA_LIB): $(LIBLUA_OBJS) | ||||
| 	-rm -f $@ | ||||
| 	ar rs $@ $^ | ||||
| 
 | ||||
|  | @ -98,10 +98,12 @@ VPATH = src					\ | |||
| 	src/util				\ | ||||
| 	src/widgets				\ | ||||
| 	src/widgets/editor			\ | ||||
| 	$(LIBART_DIR)				\ | ||||
| 	$(LIBGD_DIR)				\ | ||||
| 	$(LIBGFLI_DIR)				\ | ||||
| 	$(LIBJPEG_DIR)				\ | ||||
| 	$(LIBLUA_DIR)/src			\ | ||||
| 	$(LIBLUA_DIR)/src/lib			\ | ||||
| 	$(LIBGFLI_DIR)				\ | ||||
| 	$(LIBART_DIR)				\ | ||||
| 	$(LIBPNG_DIR)				\ | ||||
| 	$(ZLIB_DIR)				\ | ||||
| 	$(JINETE_DIR)/src			\ | ||||
|  | @ -128,17 +130,41 @@ ASE_DEPS = config.h.gch | |||
| else | ||||
| ASE_DEPS =  | ||||
| endif | ||||
| ASE_DEPS += $(ASE_OBJS) $(JINETE_LIB) $(LIBART_LIB) $(LIBGFLI_LIB) \ | ||||
| 	    $(LIBLUA_LIB) $(LIBPNG_LIB) $(ZLIB_LIB) | ||||
| ASE_DEPS += $(ASE_OBJS) $(JINETE_LIB) $(THIRD_PARTY_LIBS) | ||||
| 
 | ||||
| ifdef USE_PRECOMPILED_HEADER | ||||
| config.h.gch: config.h | ||||
| 	$(CC) $(CFLAGS) -o $@ -c $< | ||||
| endif | ||||
| 
 | ||||
| $(OBJ_DIR)/%.o: %.c | ||||
| # rules to build the object files | ||||
| 
 | ||||
| $(OBJ_DIR)/%$(OBJ): %.c | ||||
| 	$(CC) $(CFLAGS) -o $@ -c $< | ||||
| 
 | ||||
| $(OBJ_DIR)/art.%$(OBJ): %.c | ||||
| 	$(CC) $(CFLAGS) -o $@ -c $< | ||||
| 
 | ||||
| $(OBJ_DIR)/gd.%$(OBJ): %.c | ||||
| 	$(CC) $(CFLAGS) -DNONDLL -DHAVE_CONFIG_H -o $@ -c $< | ||||
| 
 | ||||
| $(OBJ_DIR)/gfli.%$(OBJ): %.c | ||||
| 	$(CC) $(CFLAGS) -o $@ -c $< | ||||
| 
 | ||||
| $(OBJ_DIR)/jpeg.%$(OBJ): %.c | ||||
| 	$(CC) $(CFLAGS) -o $@ -c $< | ||||
| 
 | ||||
| $(OBJ_DIR)/lua.%$(OBJ): %.c | ||||
| 	$(CC) $(CFLAGS) -o $@ -c $< | ||||
| 
 | ||||
| $(OBJ_DIR)/png.%$(OBJ): %.c | ||||
| 	$(CC) $(CFLAGS) -I$(LIBPNG_DIR) -o $@ -c $< | ||||
| 
 | ||||
| $(OBJ_DIR)/zlib.%$(OBJ): %.c | ||||
| 	$(CC) $(CFLAGS) -o $@ -c $< | ||||
| 
 | ||||
| # application | ||||
| 
 | ||||
| ifndef WITHICON | ||||
| $(ASE): $(ASE_DEPS) | ||||
| 	$(CC) -o $@ $(ASE_OBJS) $(LFLAGS) $(LFLAGS_LAST) | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ default: all | |||
| all: $(ASE) | ||||
| 
 | ||||
| clean: | ||||
| 	-rm -f $(ALL_OBJS) $(ALL_LIBS) | ||||
| 	-rm -f $(ALL_OBJS) $(THIRD_PARTY_LIBS) | ||||
| 
 | ||||
| distclean: clean | ||||
| 	-rm -f $(ASE) | ||||
|  |  | |||
							
								
								
									
										206
									
								
								makefile.lst
								
								
								
								
							
							
						
						
									
										206
									
								
								makefile.lst
								
								
								
								
							|  | @ -173,6 +173,7 @@ ASE_SOURCES =						\ | |||
| 	src/widgets/paledit.c				\ | ||||
| 	src/widgets/preview.c				\ | ||||
| 	src/widgets/statebar.c				\ | ||||
| 	src/widgets/tabs.c				\ | ||||
| 	src/widgets/target.c				\ | ||||
| 	src/widgets/toolbar.c | ||||
| 
 | ||||
|  | @ -180,51 +181,6 @@ ASE_OBJS = $(addprefix $(OBJ_DIR)/,					  \ | |||
| 	     $(addsuffix $(OBJ),			\ | ||||
| 	       $(notdir $(basename $(ASE_SOURCES))))) | ||||
| 
 | ||||
| ###################################################################### | ||||
| # Lua | ||||
| 
 | ||||
| LIBLUA_LIB = $(OBJ_DIR)/liblua$(LIB) | ||||
| LIBLUA_DIR = third_party/lua | ||||
| LIBLUA_SOURCES =				\ | ||||
|         $(LIBLUA_DIR)/src/lapi.c		\ | ||||
|         $(LIBLUA_DIR)/src/lcode.c		\ | ||||
|         $(LIBLUA_DIR)/src/ldebug.c		\ | ||||
|         $(LIBLUA_DIR)/src/ldo.c			\ | ||||
|         $(LIBLUA_DIR)/src/ldump.c		\ | ||||
|         $(LIBLUA_DIR)/src/lfunc.c		\ | ||||
|         $(LIBLUA_DIR)/src/lgc.c			\ | ||||
|         $(LIBLUA_DIR)/src/llex.c		\ | ||||
|         $(LIBLUA_DIR)/src/lmem.c		\ | ||||
|         $(LIBLUA_DIR)/src/lobject.c		\ | ||||
|         $(LIBLUA_DIR)/src/lopcodes.c		\ | ||||
|         $(LIBLUA_DIR)/src/lparser.c		\ | ||||
|         $(LIBLUA_DIR)/src/lstate.c		\ | ||||
|         $(LIBLUA_DIR)/src/lstring.c		\ | ||||
|         $(LIBLUA_DIR)/src/ltable.c		\ | ||||
|         $(LIBLUA_DIR)/src/ltests.c		\ | ||||
|         $(LIBLUA_DIR)/src/ltm.c			\ | ||||
|         $(LIBLUA_DIR)/src/lundump.c		\ | ||||
|         $(LIBLUA_DIR)/src/lvm.c			\ | ||||
|         $(LIBLUA_DIR)/src/lzio.c		\ | ||||
|         $(LIBLUA_DIR)/src/lib/lauxlib.c		\ | ||||
|         $(LIBLUA_DIR)/src/lib/lbaselib.c | ||||
| 
 | ||||
| LIBLUA_OBJS = $(addprefix $(OBJ_DIR)/,					     \ | ||||
| 		       $(addsuffix $(OBJ),				     \ | ||||
|                                    $(notdir $(basename $(LIBLUA_SOURCES))))) | ||||
| 
 | ||||
| ###################################################################### | ||||
| # GFli | ||||
| 
 | ||||
| LIBGFLI_LIB = $(OBJ_DIR)/libgfli$(LIB) | ||||
| LIBGFLI_DIR = third_party/gfli | ||||
| LIBGFLI_SOURCES =				\ | ||||
| 	$(LIBGFLI_DIR)/gfli.c | ||||
| 
 | ||||
| LIBGFLI_OBJS = $(addprefix $(OBJ_DIR)/,						  \ | ||||
| 			   $(addsuffix $(OBJ),					  \ | ||||
| 				       $(notdir $(basename $(LIBGFLI_SOURCES))))) | ||||
| 
 | ||||
| ###################################################################### | ||||
| # Libart | ||||
| 
 | ||||
|  | @ -269,10 +225,151 @@ LIBART_SOURCES =				\ | |||
| 	$(LIBART_DIR)/art_vpath_svp.c		\ | ||||
| 	$(LIBART_DIR)/libart-features.c | ||||
| 
 | ||||
| LIBART_OBJS = $(addprefix $(OBJ_DIR)/,						\ | ||||
| LIBART_OBJS = $(addprefix $(OBJ_DIR)/art.,					\ | ||||
| 			  $(addsuffix $(OBJ),					\ | ||||
| 				      $(notdir $(basename $(LIBART_SOURCES))))) | ||||
| 
 | ||||
| ###################################################################### | ||||
| # GD Library | ||||
| 
 | ||||
| LIBGD_LIB = $(OBJ_DIR)/libgd$(LIB) | ||||
| LIBGD_DIR = third_party/gd | ||||
| LIBGD_SOURCES =					\ | ||||
| 	$(LIBGD_DIR)/gd				\ | ||||
| 	$(LIBGD_DIR)/gdfx			\ | ||||
| 	$(LIBGD_DIR)/gd_security		\ | ||||
| 	$(LIBGD_DIR)/gd_gd			\ | ||||
| 	$(LIBGD_DIR)/gd_gd2			\ | ||||
| 	$(LIBGD_DIR)/gd_io			\ | ||||
| 	$(LIBGD_DIR)/gd_io_dp			\ | ||||
| 	$(LIBGD_DIR)/gd_gif_in			\ | ||||
| 	$(LIBGD_DIR)/gd_gif_out			\ | ||||
| 	$(LIBGD_DIR)/gd_io_file			\ | ||||
| 	$(LIBGD_DIR)/gd_io_ss			\ | ||||
| 	$(LIBGD_DIR)/gd_jpeg			\ | ||||
| 	$(LIBGD_DIR)/gd_png			\ | ||||
| 	$(LIBGD_DIR)/gd_ss			\ | ||||
| 	$(LIBGD_DIR)/gd_topal			\ | ||||
| 	$(LIBGD_DIR)/gd_wbmp			\ | ||||
| 	$(LIBGD_DIR)/gdcache			\ | ||||
| 	$(LIBGD_DIR)/gdfontg			\ | ||||
| 	$(LIBGD_DIR)/gdfontl			\ | ||||
| 	$(LIBGD_DIR)/gdfontmb			\ | ||||
| 	$(LIBGD_DIR)/gdfonts			\ | ||||
| 	$(LIBGD_DIR)/gdfontt			\ | ||||
| 	$(LIBGD_DIR)/gdft			\ | ||||
| 	$(LIBGD_DIR)/gdhelpers			\ | ||||
| 	$(LIBGD_DIR)/gdkanji			\ | ||||
| 	$(LIBGD_DIR)/gdtables			\ | ||||
| 	$(LIBGD_DIR)/gdxpm			\ | ||||
| 	$(LIBGD_DIR)/wbmp | ||||
| 
 | ||||
| LIBGD_OBJS = $(addprefix $(OBJ_DIR)/gd.,			\ | ||||
| 	       $(addsuffix $(OBJ),				\ | ||||
| 		 $(notdir $(basename $(LIBGD_SOURCES))))) | ||||
| 
 | ||||
| ###################################################################### | ||||
| # GFli | ||||
| 
 | ||||
| LIBGFLI_LIB = $(OBJ_DIR)/libgfli$(LIB) | ||||
| LIBGFLI_DIR = third_party/gfli | ||||
| LIBGFLI_SOURCES =				\ | ||||
| 	$(LIBGFLI_DIR)/gfli.c | ||||
| 
 | ||||
| LIBGFLI_OBJS = $(addprefix $(OBJ_DIR)/gfli.,						\ | ||||
| 			   $(addsuffix $(OBJ),						\ | ||||
| 				       $(notdir $(basename $(LIBGFLI_SOURCES))))) | ||||
| 
 | ||||
| ###################################################################### | ||||
| # Lua | ||||
| 
 | ||||
| LIBLUA_LIB = $(OBJ_DIR)/liblua$(LIB) | ||||
| LIBLUA_DIR = third_party/lua | ||||
| LIBLUA_SOURCES =				\ | ||||
|         $(LIBLUA_DIR)/src/lapi.c		\ | ||||
|         $(LIBLUA_DIR)/src/lcode.c		\ | ||||
|         $(LIBLUA_DIR)/src/ldebug.c		\ | ||||
|         $(LIBLUA_DIR)/src/ldo.c			\ | ||||
|         $(LIBLUA_DIR)/src/ldump.c		\ | ||||
|         $(LIBLUA_DIR)/src/lfunc.c		\ | ||||
|         $(LIBLUA_DIR)/src/lgc.c			\ | ||||
|         $(LIBLUA_DIR)/src/llex.c		\ | ||||
|         $(LIBLUA_DIR)/src/lmem.c		\ | ||||
|         $(LIBLUA_DIR)/src/lobject.c		\ | ||||
|         $(LIBLUA_DIR)/src/lopcodes.c		\ | ||||
|         $(LIBLUA_DIR)/src/lparser.c		\ | ||||
|         $(LIBLUA_DIR)/src/lstate.c		\ | ||||
|         $(LIBLUA_DIR)/src/lstring.c		\ | ||||
|         $(LIBLUA_DIR)/src/ltable.c		\ | ||||
|         $(LIBLUA_DIR)/src/ltests.c		\ | ||||
|         $(LIBLUA_DIR)/src/ltm.c			\ | ||||
|         $(LIBLUA_DIR)/src/lundump.c		\ | ||||
|         $(LIBLUA_DIR)/src/lvm.c			\ | ||||
|         $(LIBLUA_DIR)/src/lzio.c		\ | ||||
|         $(LIBLUA_DIR)/src/lib/lauxlib.c		\ | ||||
|         $(LIBLUA_DIR)/src/lib/lbaselib.c | ||||
| 
 | ||||
| LIBLUA_OBJS = $(addprefix $(OBJ_DIR)/lua.,				     \ | ||||
| 		       $(addsuffix $(OBJ),				     \ | ||||
|                                    $(notdir $(basename $(LIBLUA_SOURCES))))) | ||||
| 
 | ||||
| ###################################################################### | ||||
| # JPEG | ||||
| 
 | ||||
| LIBJPEG_LIB = $(OBJ_DIR)/libjpeg$(LIB) | ||||
| LIBJPEG_DIR = third_party/jpeg | ||||
| LIBJPEG_SOURCES =				\ | ||||
| 	$(LIBJPEG_DIR)/jcapimin.c		\ | ||||
| 	$(LIBJPEG_DIR)/jcapistd.c		\ | ||||
| 	$(LIBJPEG_DIR)/jccoefct.c		\ | ||||
| 	$(LIBJPEG_DIR)/jccolor.c		\ | ||||
| 	$(LIBJPEG_DIR)/jcdctmgr.c		\ | ||||
| 	$(LIBJPEG_DIR)/jchuff.c			\ | ||||
| 	$(LIBJPEG_DIR)/jcinit.c			\ | ||||
| 	$(LIBJPEG_DIR)/jcmainct.c		\ | ||||
| 	$(LIBJPEG_DIR)/jcmarker.c		\ | ||||
| 	$(LIBJPEG_DIR)/jcmaster.c		\ | ||||
| 	$(LIBJPEG_DIR)/jcomapi.c		\ | ||||
| 	$(LIBJPEG_DIR)/jcparam.c		\ | ||||
| 	$(LIBJPEG_DIR)/jcphuff.c		\ | ||||
| 	$(LIBJPEG_DIR)/jcprepct.c		\ | ||||
| 	$(LIBJPEG_DIR)/jcsample.c		\ | ||||
| 	$(LIBJPEG_DIR)/jctrans.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdapimin.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdapistd.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdatadst.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdatasrc.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdcoefct.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdcolor.c		\ | ||||
| 	$(LIBJPEG_DIR)/jddctmgr.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdhuff.c			\ | ||||
| 	$(LIBJPEG_DIR)/jdinput.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdmainct.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdmarker.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdmaster.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdmerge.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdphuff.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdpostct.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdsample.c		\ | ||||
| 	$(LIBJPEG_DIR)/jdtrans.c		\ | ||||
| 	$(LIBJPEG_DIR)/jerror.c			\ | ||||
| 	$(LIBJPEG_DIR)/jfdctflt.c		\ | ||||
| 	$(LIBJPEG_DIR)/jfdctfst.c		\ | ||||
| 	$(LIBJPEG_DIR)/jfdctint.c		\ | ||||
| 	$(LIBJPEG_DIR)/jidctflt.c		\ | ||||
| 	$(LIBJPEG_DIR)/jidctfst.c		\ | ||||
| 	$(LIBJPEG_DIR)/jidctint.c		\ | ||||
| 	$(LIBJPEG_DIR)/jidctred.c		\ | ||||
| 	$(LIBJPEG_DIR)/jmemansi.c		\ | ||||
| 	$(LIBJPEG_DIR)/jmemmgr.c		\ | ||||
| 	$(LIBJPEG_DIR)/jquant1.c		\ | ||||
| 	$(LIBJPEG_DIR)/jquant2.c		\ | ||||
| 	$(LIBJPEG_DIR)/jutils.c | ||||
| 
 | ||||
| LIBJPEG_OBJS = $(addprefix $(OBJ_DIR)/jpeg.,			\ | ||||
| 		$(addsuffix $(OBJ),				\ | ||||
| 		  $(notdir $(basename $(LIBJPEG_SOURCES))))) | ||||
| 
 | ||||
| ###################################################################### | ||||
| # LibPNG | ||||
| 
 | ||||
|  | @ -295,7 +392,7 @@ LIBPNG_SOURCES =				\ | |||
| 	$(LIBPNG_DIR)/pngwtran.c		\ | ||||
| 	$(LIBPNG_DIR)/pngwutil.c | ||||
| 
 | ||||
| LIBPNG_OBJS = $(addprefix $(OBJ_DIR)/,						\ | ||||
| LIBPNG_OBJS = $(addprefix $(OBJ_DIR)/png.,			\ | ||||
| 		$(addsuffix $(OBJ),				\ | ||||
| 		  $(notdir $(basename $(LIBPNG_SOURCES))))) | ||||
| 
 | ||||
|  | @ -318,7 +415,7 @@ ZLIB_SOURCES =					\ | |||
| 	$(ZLIB_DIR)/uncompr.c			\ | ||||
| 	$(ZLIB_DIR)/zutil.c | ||||
| 
 | ||||
| ZLIB_OBJS = $(addprefix $(OBJ_DIR)/,						\ | ||||
| ZLIB_OBJS = $(addprefix $(OBJ_DIR)/zlib.,		\ | ||||
| 	      $(addsuffix $(OBJ),			\ | ||||
| 		$(notdir $(basename $(ZLIB_SOURCES))))) | ||||
| 
 | ||||
|  | @ -330,10 +427,13 @@ ALL_OBJS =					\ | |||
| 	$(LIBLUA_OBJS)				\ | ||||
| 	$(LIBGFLI_OBJS)				\ | ||||
| 	$(LIBART_OBJS)				\ | ||||
| 	$(LIBPNG_OBJS) | ||||
| 	$(LIBPNG_OBJS)				\ | ||||
| 	$(ZLIB_OBJS) | ||||
| 
 | ||||
| ALL_LIBS =					\ | ||||
| 	$(LIBLUA_LIB)				\ | ||||
| 	$(LIBGFLI_LIB)				\ | ||||
| THIRD_PARTY_LIBS =				\ | ||||
| 	$(LIBART_LIB)				\ | ||||
| 	$(LIBPNG_LIB) | ||||
| 	$(LIBGFLI_LIB)				\ | ||||
| 	$(LIBJPEG_LIB)				\ | ||||
| 	$(LIBLUA_LIB)				\ | ||||
| 	$(LIBPNG_LIB)				\ | ||||
| 	$(ZLIB_LIB) | ||||
|  |  | |||
|  | @ -55,7 +55,7 @@ default: all | |||
| all: $(ASE) | ||||
| 
 | ||||
| clean: | ||||
| 	-rm -f $(ALL_OBJS) $(ALL_LIBS) | ||||
| 	-rm -f $(ALL_OBJS) $(THIRD_PARTY_LIBS) | ||||
| 
 | ||||
| distclean: clean | ||||
| 	-rm -f $(ASE) | ||||
|  |  | |||
|  | @ -214,7 +214,7 @@ $1/docs/*.pdf" | |||
| 
 | ||||
| # cd $dir/.. | ||||
| # rm ase | ||||
| # make -f makefile.lnx CONFIGURED=1 HAVE_LIBJPEG=1 | ||||
| # make -f makefile.lnx CONFIGURED=1 | ||||
| # strip ase | ||||
| # def_common_files . | ||||
| # mkdir $dir/$distdir-unix | ||||
|  | @ -233,7 +233,7 @@ $1/docs/*.pdf" | |||
| 
 | ||||
| # cd $dir/.. | ||||
| # rm ase.exe | ||||
| # djgpp make -f makefile.dj CONFIGURED=1 HAVE_LIBJPEG=1 | ||||
| # djgpp make -f makefile.dj CONFIGURED=1 | ||||
| # djgpp strip ase.exe | ||||
| # def_common_files . | ||||
| # mkdir $dir/$distdir-dos | ||||
|  | @ -256,7 +256,7 @@ if [ ! -f $distdir-win32.zip ] ; then | |||
| 
 | ||||
| cd "$dir/.." | ||||
| rm ase | ||||
| mingw32 make -f makefile.mgw CONFIGURED=1 HAVE_LIBJPEG=1 | ||||
| mingw32 make -f makefile.mgw CONFIGURED=1 | ||||
| mingw32 strip ase.exe | ||||
| def_common_files . | ||||
| mkdir "$dir/$distdir-win32" | ||||
|  |  | |||
|  | @ -67,6 +67,7 @@ void command_execute_about(const char *argument) | |||
|    | ||||
|   jwidget_magnetic(button1, TRUE); | ||||
| 
 | ||||
|   jwidget_set_border(box1, 4, 4, 4, 4); | ||||
|   jwidget_add_childs(box1, label1, label2, separator1, NULL); | ||||
|   if (textbox) { | ||||
|     jview_attach(view, textbox); | ||||
|  |  | |||
|  | @ -39,12 +39,14 @@ void command_execute_advanced_mode(const char *argument) | |||
|     jwidget_hide(app_get_menu_bar()); | ||||
|     jwidget_hide(app_get_status_bar()); | ||||
|     jwidget_hide(app_get_color_bar()); | ||||
|     jwidget_hide(app_get_tabs_bar()); | ||||
|   } | ||||
|   else { | ||||
|     jwidget_show(app_get_tool_bar()); | ||||
|     jwidget_show(app_get_menu_bar()); | ||||
|     jwidget_show(app_get_status_bar()); | ||||
|     jwidget_show(app_get_color_bar()); | ||||
|     jwidget_show(app_get_tabs_bar()); | ||||
|   } | ||||
| 
 | ||||
|   jwindow_remap(app_get_top_window()); | ||||
|  |  | |||
|  | @ -73,11 +73,11 @@ void command_execute_new_file(const char *argument) | |||
|   bg_box = jwidget_find_name(window, "bg_box"); | ||||
| 
 | ||||
|   /* default values: Indexed, 320x200, Transparent */ | ||||
|   imgtype = get_config_int("NewSprite", "Type", IMAGE_INDEXED); | ||||
|   imgtype = get_config_int("NewSprite", "Type", IMAGE_RGB); | ||||
|   imgtype = MID(IMAGE_RGB, imgtype, IMAGE_INDEXED); | ||||
|   w = get_config_int("NewSprite", "Width", 320); | ||||
|   h = get_config_int("NewSprite", "Height", 200); | ||||
|   bg = get_config_int("NewSprite", "Background", 0); | ||||
|   bg = get_config_int("NewSprite", "Background", 1); | ||||
| 
 | ||||
|   usprintf(buf, "%d", w); jwidget_set_text(width, buf); | ||||
|   usprintf(buf, "%d", h); jwidget_set_text(height, buf); | ||||
|  |  | |||
|  | @ -56,6 +56,7 @@ | |||
| #include "widgets/editor.h" | ||||
| #include "widgets/menuitem.h" | ||||
| #include "widgets/statebar.h" | ||||
| #include "widgets/tabs.h" | ||||
| #include "widgets/toolbar.h" | ||||
| 
 | ||||
| #endif | ||||
|  | @ -80,10 +81,12 @@ static JWidget box_menu_bar = NULL;   /* box where the menu bar is */ | |||
| static JWidget box_color_bar = NULL;  /* box where the color bar is */ | ||||
| static JWidget box_tool_bar = NULL;   /* box where the tools bar is */ | ||||
| static JWidget box_status_bar = NULL; /* box where the status bar is */ | ||||
| static JWidget box_tabs_bar = NULL;   /* box where the tabs bar is */ | ||||
| static JWidget menu_bar = NULL;	      /* the menu bar widget */ | ||||
| static JWidget status_bar = NULL;     /* the status bar widget */ | ||||
| static JWidget color_bar = NULL;      /* the color bar widget */ | ||||
| static JWidget tool_bar = NULL;	      /* the tool bar widget */ | ||||
| static JWidget tabs_bar = NULL;	      /* the tabs bar widget */ | ||||
| 
 | ||||
| static JList options; /* list of "Option" structures (options to execute) */ | ||||
| static char *palette_filename = NULL; | ||||
|  | @ -182,19 +185,25 @@ void app_loop(void) | |||
|     box_color_bar = jwidget_find_name(top_window, "color_bar"); | ||||
|     box_tool_bar = jwidget_find_name(top_window, "tool_bar"); | ||||
|     box_status_bar = jwidget_find_name(top_window, "status_bar"); | ||||
|     box_tabs_bar = jwidget_find_name(top_window, "tabs_bar"); | ||||
| 
 | ||||
|     menu_bar = jmenubar_new(); | ||||
|     status_bar = status_bar_new(); | ||||
|     color_bar = color_bar_new(box_color_bar->align); | ||||
|     tool_bar = tool_bar_new(box_tool_bar->align); | ||||
|     tabs_bar = tabs_new(sprite_show); | ||||
|     view = editor_view_new(); | ||||
|     editor = create_new_editor(); | ||||
| 
 | ||||
|     /* append the NULL sprite to the tabs */ | ||||
|     tabs_append_tab(tabs_bar, "Nothing", NULL); | ||||
| 
 | ||||
|     /* configure all widgets to expansives */ | ||||
|     jwidget_expansive(menu_bar, TRUE); | ||||
|     jwidget_expansive(status_bar, TRUE); | ||||
|     jwidget_expansive(color_bar, TRUE); | ||||
|     jwidget_expansive(tool_bar, TRUE); | ||||
|     jwidget_expansive(tabs_bar, TRUE); | ||||
|     jwidget_expansive(view, TRUE); | ||||
| 
 | ||||
|     /* prepare the first editor */ | ||||
|  | @ -207,11 +216,12 @@ void app_loop(void) | |||
|     app_default_status_bar_message(); | ||||
| 
 | ||||
|     /* add the widgets in the boxes */ | ||||
|     jwidget_add_child(box_menu_bar, menu_bar); | ||||
|     jwidget_add_child(box_editors, view); | ||||
|     jwidget_add_child(box_color_bar, color_bar); | ||||
|     jwidget_add_child(box_tool_bar, tool_bar); | ||||
|     jwidget_add_child(box_status_bar, status_bar); | ||||
|     if (box_menu_bar) jwidget_add_child(box_menu_bar, menu_bar); | ||||
|     if (box_editors) jwidget_add_child(box_editors, view); | ||||
|     if (box_color_bar) jwidget_add_child(box_color_bar, color_bar); | ||||
|     if (box_tool_bar) jwidget_add_child(box_tool_bar, tool_bar); | ||||
|     if (box_status_bar) jwidget_add_child(box_status_bar, status_bar); | ||||
|     if (box_tabs_bar) jwidget_add_child(box_tabs_bar, tabs_bar); | ||||
| 
 | ||||
|     /* prepare the window */ | ||||
|     jwindow_remap(top_window); | ||||
|  | @ -361,10 +371,21 @@ void app_refresh_screen(void) | |||
|    you should use rebuild_sprite_list () instead (src/gui/gui.c) */ | ||||
| void app_realloc_sprite_list(void) | ||||
| { | ||||
|   JWidget list_menuitem = get_sprite_list_menuitem(); | ||||
|   JWidget menuitem; | ||||
|   Sprite *sprite; | ||||
|   JLink link; | ||||
| #if 1 | ||||
|   PRINTF("Reallocating sprite list...\n"); | ||||
| 
 | ||||
|   /* insert all other sprites */ | ||||
|   JI_LIST_FOR_EACH(get_sprite_list(), link) { | ||||
|     sprite = link->data; | ||||
|     tabs_set_text_for_tab(tabs_bar, | ||||
| 			  get_filename(sprite->filename), | ||||
| 			  sprite); | ||||
|   } | ||||
| #else   | ||||
|   JWidget list_menuitem = get_sprite_list_menuitem(); | ||||
|   JWidget menuitem; | ||||
| 
 | ||||
|   PRINTF("Reallocating sprite list...\n"); | ||||
| 
 | ||||
|  | @ -453,6 +474,7 @@ void app_realloc_sprite_list(void) | |||
|       } | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /* updates the recent list menu. WARNING!: This routine can't be used
 | ||||
|  | @ -472,8 +494,8 @@ void app_realloc_recent_list(void) | |||
| 
 | ||||
|     submenu = jmenuitem_get_submenu (list_menuitem); | ||||
|     if (submenu) { | ||||
|       jmenuitem_set_submenu (list_menuitem, NULL); | ||||
|       jwidget_free (submenu); | ||||
|       jmenuitem_set_submenu(list_menuitem, NULL); | ||||
|       jwidget_free(submenu); | ||||
|     } | ||||
| 
 | ||||
|     submenu = jmenu_new(); | ||||
|  | @ -513,6 +535,7 @@ JWidget app_get_menu_bar(void) { return menu_bar; } | |||
| JWidget app_get_status_bar(void) { return status_bar; } | ||||
| JWidget app_get_color_bar(void) { return color_bar; } | ||||
| JWidget app_get_tool_bar(void) { return tool_bar; } | ||||
| JWidget app_get_tabs_bar(void) { return tabs_bar; } | ||||
| 
 | ||||
| void app_default_status_bar_message(void) | ||||
| { | ||||
|  |  | |||
|  | @ -37,6 +37,7 @@ JWidget app_get_menu_bar(void); | |||
| JWidget app_get_status_bar(void); | ||||
| JWidget app_get_color_bar(void); | ||||
| JWidget app_get_tool_bar(void); | ||||
| JWidget app_get_tabs_bar(void); | ||||
| 
 | ||||
| void app_default_status_bar_message(void); | ||||
| 
 | ||||
|  |  | |||
|  | @ -198,13 +198,13 @@ DIRS *cfg_filename_dirs(void) | |||
| 
 | ||||
| #if defined UNIX_LIKE | ||||
| 
 | ||||
|   /* $HOME/.aserc */ | ||||
|   dirs_cat_dirs(dirs, filename_in_homedir(".aserc")); | ||||
|   /* $HOME/.aserc-VERSION */ | ||||
|   dirs_cat_dirs(dirs, filename_in_homedir(".aserc-" VERSION)); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|   /* $BINDIR/ase.cfg */ | ||||
|   dirs_cat_dirs(dirs, filename_in_bindir("ase.cfg")); | ||||
|   /* $BINDIR/ase-VERSION.cfg */ | ||||
|   dirs_cat_dirs(dirs, filename_in_bindir("ase-" VERSION ".cfg")); | ||||
| 
 | ||||
|   return dirs; | ||||
| } | ||||
|  |  | |||
|  | @ -416,7 +416,7 @@ int sprite_save(Sprite *sprite) | |||
| 
 | ||||
|     case IMAGE_RGB: | ||||
|       if (!(file->flags & FILE_SUPPORT_RGB)) { | ||||
| 	usprintf(buf+ustrlen (buf), "<<- %s", _("RGB format")); | ||||
| 	usprintf(buf+ustrlen(buf), "<<- %s", _("RGB format")); | ||||
| 	fatal = TRUE; | ||||
|       } | ||||
|       if (!(file->flags & FILE_SUPPORT_RGBA)) { | ||||
|  | @ -446,13 +446,13 @@ int sprite_save(Sprite *sprite) | |||
|   if (!(file->flags & (FILE_SUPPORT_FRAMES | | ||||
| 		       FILE_SUPPORT_SEQUENCES))) { | ||||
|     if (sprite->frames > 1) | ||||
|       usprintf(buf+ustrlen (buf), "<<- %s", _("Frames")); | ||||
|       usprintf(buf+ustrlen(buf), "<<- %s", _("Frames")); | ||||
|   } | ||||
| 
 | ||||
|   /* layers support */ | ||||
|   if (jlist_length(sprite->set->layers) > 1) { | ||||
|     if (!(file->flags & FILE_SUPPORT_LAYERS)) { | ||||
|       usprintf(buf+ustrlen (buf), "<<- %s", _("Layers")); | ||||
|       usprintf(buf+ustrlen(buf), "<<- %s", _("Layers")); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | @ -460,7 +460,7 @@ int sprite_save(Sprite *sprite) | |||
|   if (jlist_length(sprite->palettes) > 1) { | ||||
|     if (!(file->flags & (FILE_SUPPORT_PALETTES | | ||||
| 			 FILE_SUPPORT_SEQUENCES))) { | ||||
|       usprintf(buf+ustrlen (buf), "<<- %s", _("Palette changes")); | ||||
|       usprintf(buf+ustrlen(buf), "<<- %s", _("Palette changes")); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  | @ -481,13 +481,13 @@ int sprite_save(Sprite *sprite) | |||
|     } | ||||
| 
 | ||||
|     if ((count > 0) && !(file->flags & FILE_SUPPORT_MASKS_REPOSITORY)) { | ||||
|       usprintf (buf+ustrlen (buf), "<<- %s", _("Mask Repository")); | ||||
|       usprintf(buf+ustrlen(buf), "<<- %s", _("Mask Repository")); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (!jlist_empty(sprite->repository.paths)) { | ||||
|     if (!(file->flags & FILE_SUPPORT_PATHS_REPOSITORY)) { | ||||
|       usprintf (buf+ustrlen (buf), "<<- %s", _("Path Repository")); | ||||
|       usprintf(buf+ustrlen(buf), "<<- %s", _("Path Repository")); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										187
									
								
								src/file/jpeg.c
								
								
								
								
							
							
						
						
									
										187
									
								
								src/file/jpeg.c
								
								
								
								
							|  | @ -36,17 +36,7 @@ | |||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /**********************************************************************/ | ||||
| 
 | ||||
| #if defined HAVE_LIBJPEG | ||||
| #include <jpeglib.h> | ||||
| #elif defined HAVE_JPGALLEG | ||||
| #include <jpgalleg.h> | ||||
| #endif | ||||
| 
 | ||||
| /**********************************************************************/ | ||||
| 
 | ||||
| #if defined HAVE_LIBJPEG || HAVE_JPGALLEG | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| static Sprite *load_jpeg(const char *filename); | ||||
| static int save_jpeg(Sprite *sprite); | ||||
|  | @ -64,12 +54,6 @@ FileType filetype_jpeg = | |||
|   FILE_SUPPORT_SEQUENCES | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /**********************************************************************/ | ||||
| 
 | ||||
| #if defined HAVE_LIBJPEG | ||||
| 
 | ||||
| static void progress_monitor(j_common_ptr cinfo) | ||||
| { | ||||
|   if (cinfo->progress->pass_limit > 1) | ||||
|  | @ -388,173 +372,6 @@ static int save_jpeg(Sprite *sprite) | |||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| /**********************************************************************/ | ||||
| 
 | ||||
| #elif defined HAVE_JPGALLEG | ||||
| 
 | ||||
| static bool initialised = FALSE; | ||||
| 
 | ||||
| static Sprite *load_jpeg(const char *filename) | ||||
| { | ||||
|   BITMAP *bmp; | ||||
|   Image *image; | ||||
| 
 | ||||
|   if (!initialised) { | ||||
|     initialised = TRUE; | ||||
|     if (jpgalleg_init() < 0) | ||||
|       return NULL; | ||||
|   } | ||||
| 
 | ||||
|   /* load the bitmap */ | ||||
| 
 | ||||
|   set_color_conversion(COLORCONV_NONE); | ||||
|   bmp = load_jpg_ex(filename, NULL, do_progress); | ||||
|   set_color_conversion(COLORCONV_TOTAL); | ||||
| 
 | ||||
|   if (!bmp) { | ||||
|     if (!file_sequence_sprite()) | ||||
|       console_printf(_("Error opening file.\n")); | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   /* create the image */ | ||||
|   image = file_sequence_image | ||||
|     (bitmap_color_depth(bmp) == 24 ? IMAGE_RGB: | ||||
| 				     IMAGE_GRAYSCALE, bmp->w, bmp->h); | ||||
|   if (!image) { | ||||
|     destroy_bitmap(bmp); | ||||
|     return NULL; | ||||
|   } | ||||
| 
 | ||||
|   if (bitmap_color_depth(bmp) == 24) { | ||||
|     /* RGB */ | ||||
|     unsigned char *src_address; | ||||
|     unsigned long *dst_address; | ||||
|     int r, g, b, x, y; | ||||
| 
 | ||||
|     for (y=0; y<image->h; y++) { | ||||
|       src_address = ((unsigned char **)bmp->line)[y]; | ||||
|       dst_address = ((unsigned long **)image->lines)[y]; | ||||
|        | ||||
|       for (x=0; x<image->w; x++) { | ||||
|         r = *src_address++; | ||||
|         g = *src_address++; | ||||
|         b = *src_address++; | ||||
|         *(dst_address++) = _rgba(r, g, b, 255); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     /* Greyscale */ | ||||
|     unsigned char *src_address; | ||||
|     unsigned short *dst_address; | ||||
|     int x, y, i; | ||||
| 
 | ||||
|     for (y=0; y<image->h; y++) { | ||||
|       src_address = ((unsigned char **)bmp->line)[y]; | ||||
|       dst_address = ((unsigned short **)image->lines)[y]; | ||||
| 
 | ||||
|       for (x=0; x<image->w; x++) | ||||
|         *(dst_address++) = _graya(*(src_address++), 255); | ||||
|     } | ||||
| 
 | ||||
|     /* palette */ | ||||
|     for (i=0; i<256; i++) | ||||
|       file_sequence_set_color(i, i>>2, i>>2, i>>2); | ||||
|   } | ||||
| 
 | ||||
|   destroy_bitmap(bmp); | ||||
| 
 | ||||
|   return file_sequence_sprite(); | ||||
| } | ||||
| 
 | ||||
| static int save_jpeg(Sprite *sprite) | ||||
| { | ||||
|   Image *image; | ||||
|   BITMAP *bmp; | ||||
|   int flags; | ||||
|   /* options */ | ||||
|   int smooth; | ||||
|   int quality; | ||||
|   int method; | ||||
| 
 | ||||
|   if (!initialised) { | ||||
|     initialised = TRUE; | ||||
|     if (jpgalleg_init() < 0) | ||||
|       return -1; | ||||
|   } | ||||
| 
 | ||||
|   /* configure */ | ||||
|   if (configure_jpeg() < 0) | ||||
|     return 0; | ||||
| 
 | ||||
|   /* options */ | ||||
|   smooth = get_config_int("JPEG", "Smooth", 0); | ||||
|   quality = get_config_int("JPEG", "Quality", 100); | ||||
|   method = get_config_int("JPEG", "Method", 0); | ||||
| 
 | ||||
|   /* get image to save */ | ||||
|   image = file_sequence_image_to_save(); | ||||
|   bmp = create_bitmap_ex(32, image->w, image->h); | ||||
|   if (!bmp) { | ||||
|     console_printf(_("Not enough memory\n")); | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   /* RGB */ | ||||
|   if (image->imgtype == IMAGE_RGB) { | ||||
|     unsigned long *src_address = image->bytes; | ||||
|     unsigned long *dst_address = bmp->dat; | ||||
|     int c, r, g, b, size = image->w * image->h; | ||||
| 
 | ||||
|     flags = JPG_SAMPLING_444; | ||||
| 
 | ||||
|     for (c=0; c<size; c++) { | ||||
|       r = _rgba_getr(*(src_address)); | ||||
|       g = _rgba_getg(*(src_address)); | ||||
|       b = _rgba_getb(*(src_address++)); | ||||
|       *(dst_address++) = makeacol32 (r, g, b, 255); | ||||
|     } | ||||
|   } | ||||
|   /* Grayscale */ | ||||
|   else if (image->imgtype == IMAGE_GRAYSCALE) { | ||||
|     unsigned short *src_address = image->bytes; | ||||
|     unsigned long *dst_address = bmp->dat; | ||||
|     int c, k, size = image->w * image->h; | ||||
| 
 | ||||
|     flags = JPG_GREYSCALE; | ||||
| 
 | ||||
|     for (c=0; c<size; c++) { | ||||
|       k = _graya_getk(*src_address++); | ||||
|       *(dst_address++) = makeacol32(k, k, k, 255); | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     destroy_bitmap(bmp); | ||||
|     return -1; | ||||
|   } | ||||
| 
 | ||||
|   /* XXX ToDo: what about JPG optimization settings? */ | ||||
|    | ||||
|   if (save_jpg_ex(sprite->filename, bmp, NULL, quality, flags, do_progress) < 0) | ||||
|     return -1; | ||||
| 
 | ||||
|   destroy_bitmap(bmp); | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| /**********************************************************************/ | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| FileType filetype_jpeg = { "jpeg", "jpeg,jpg", NULL, NULL, 0 }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /**********************************************************************/ | ||||
| 
 | ||||
| #if defined HAVE_LIBJPEG || HAVE_JPGALLEG | ||||
| 
 | ||||
| /**
 | ||||
|  * Shows the JPEG configuration dialog. | ||||
|  */ | ||||
|  | @ -636,5 +453,3 @@ static int configure_jpeg(void) | |||
|   jwidget_free(window); | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -26,7 +26,9 @@ | |||
| #include "jinete/intern.h" | ||||
| #include "jinete/system.h" | ||||
| 
 | ||||
| #include "console/console.h" | ||||
| #include "core/cfg.h" | ||||
| #include "core/dirs.h" | ||||
| #include "modules/gfx.h" | ||||
| #include "modules/palette.h" | ||||
| #include "modules/tools.h" | ||||
|  | @ -34,6 +36,7 @@ | |||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| /* static BITMAP *icons_pcx; */ | ||||
| static BITMAP *gfx_bmps[GFX_BITMAP_COUNT]; | ||||
| 
 | ||||
| #include "modules/gfxdata.c" | ||||
|  | @ -75,8 +78,26 @@ static void gen_gfx(void) | |||
| 
 | ||||
| int init_module_graphics(void) | ||||
| { | ||||
| /*   DIRS *dirs, *dir; */ | ||||
| /*   PALETTE pal; */ | ||||
|   int c; | ||||
| 
 | ||||
| /*   dirs = filename_in_datadir("icons.pcx"); */ | ||||
| /*   for (dir=dirs; dir; dir=dir->next) { */ | ||||
| /*     set_color_conversion(COLORCONV_NONE); */ | ||||
| /*     icons_pcx = load_bitmap(dir->path, pal); */ | ||||
| /*     set_color_conversion(COLORCONV_TOTAL); */ | ||||
| 
 | ||||
| /*     if (icons_pcx) */ | ||||
| /*       break; */ | ||||
| /*   } */ | ||||
| /*   dirs_free(dirs); */ | ||||
| 
 | ||||
| /*   if (!icons_pcx) { */ | ||||
| /*     user_printf("Error loading icons.pcx"); */ | ||||
| /*     return -1; */ | ||||
| /*   } */ | ||||
|    | ||||
|   for(c=0; c<GFX_BITMAP_COUNT; c++) | ||||
|     gfx_bmps[c] = NULL; | ||||
| 
 | ||||
|  | @ -95,12 +116,58 @@ void exit_module_graphics(void) | |||
|       destroy_bitmap(gfx_bmps[c]); | ||||
|       gfx_bmps[c] = NULL; | ||||
|     } | ||||
| 
 | ||||
| /*   if (icons_pcx) */ | ||||
| /*     destroy_bitmap(icons_pcx); */ | ||||
| } | ||||
| 
 | ||||
| BITMAP *get_gfx (int id) | ||||
| BITMAP *get_gfx(int id) | ||||
| { | ||||
|   if (!gfx_bmps[id]) | ||||
|     convert_data_to_bitmap (&gfx_data[id], &gfx_bmps[id]); | ||||
|   if (!gfx_bmps[id]) { | ||||
| /*     if (id == GFX_TOOL_MARKER) { */ | ||||
| /*       gfx_bmps[id] = create_bitmap(9, 9); */ | ||||
| /*       blit(icons_pcx, gfx_bmps[id], 9*1, 9*0, 0, 0, 9, 9); */ | ||||
| /*     } */ | ||||
| /*     else if (id == GFX_TOOL_DOTS) { */ | ||||
| /*       gfx_bmps[id] = create_bitmap(9, 9); */ | ||||
| /*       blit(icons_pcx, gfx_bmps[id], 9*1, 9*1, 0, 0, 9, 9); */ | ||||
| /*     } */ | ||||
| /*     else if (id == GFX_TOOL_PENCIL) { */ | ||||
| /*       gfx_bmps[id] = create_bitmap(9, 9); */ | ||||
| /*       blit(icons_pcx, gfx_bmps[id], 9*1, 9*2, 0, 0, 9, 9); */ | ||||
| /*     } */ | ||||
| /*     else if (id == GFX_TOOL_BRUSH) { */ | ||||
| /*       gfx_bmps[id] = create_bitmap(9, 9); */ | ||||
| /*       blit(icons_pcx, gfx_bmps[id], 9*1, 9*3, 0, 0, 9, 9); */ | ||||
| /*     } */ | ||||
| /*     else if (id == GFX_TOOL_FLOODFILL) { */ | ||||
| /*       gfx_bmps[id] = create_bitmap(9, 9); */ | ||||
| /*       blit(icons_pcx, gfx_bmps[id], 9*1, 9*4, 0, 0, 9, 9); */ | ||||
| /*     } */ | ||||
| /*     else if (id == GFX_TOOL_SPRAY) { */ | ||||
| /*       gfx_bmps[id] = create_bitmap(9, 9); */ | ||||
| /*       blit(icons_pcx, gfx_bmps[id], 9*1, 9*5, 0, 0, 9, 9); */ | ||||
| /*     } */ | ||||
| /*     else if (id == GFX_TOOL_LINE) { */ | ||||
| /*       gfx_bmps[id] = create_bitmap(9, 9); */ | ||||
| /*       blit(icons_pcx, gfx_bmps[id], 9*1, 9*6, 0, 0, 9, 9); */ | ||||
| /*     } */ | ||||
| /*     else if (id == GFX_TOOL_RECTANGLE) { */ | ||||
| /*       gfx_bmps[id] = create_bitmap(9, 9); */ | ||||
| /*       blit(icons_pcx, gfx_bmps[id], 9*1, 9*7, 0, 0, 9, 9); */ | ||||
| /*     } */ | ||||
| /*     else if (id == GFX_TOOL_ELLIPSE) { */ | ||||
| /*       gfx_bmps[id] = create_bitmap(9, 9); */ | ||||
| /*       blit(icons_pcx, gfx_bmps[id], 9*1, 9*8, 0, 0, 9, 9); */ | ||||
| /*     } */ | ||||
| /*     else if (id == GFX_TOOL_CONFIGURATION) { */ | ||||
| /*       gfx_bmps[id] = create_bitmap(9, 9); */ | ||||
| /*       blit(icons_pcx, gfx_bmps[id], 9*1, 9*9, 0, 0, 9, 9); */ | ||||
| /*     } */ | ||||
| /*     else { */ | ||||
|       convert_data_to_bitmap(&gfx_data[id], &gfx_bmps[id]); | ||||
| /*     } */ | ||||
|   } | ||||
| 
 | ||||
|   return gfx_bmps[id]; | ||||
| } | ||||
|  | @ -222,22 +289,22 @@ void dotted_mode(int offset) | |||
|   drawing_mode (DRAW_MODE_COPY_PATTERN, pattern, 0, 0); | ||||
| } | ||||
| 
 | ||||
| void simple_dotted_mode (BITMAP *bmp, int fg, int bg) | ||||
| void simple_dotted_mode(BITMAP *bmp, int fg, int bg) | ||||
| { | ||||
|   static BITMAP *pattern = NULL; | ||||
| 
 | ||||
|   if (pattern && bitmap_color_depth (pattern) != bitmap_color_depth (bmp)) | ||||
|     destroy_bitmap (pattern); | ||||
|   if (pattern && bitmap_color_depth(pattern) != bitmap_color_depth(bmp)) | ||||
|     destroy_bitmap(pattern); | ||||
| 
 | ||||
|   pattern = create_bitmap_ex (bitmap_color_depth (bmp), 2, 2); | ||||
|   clear_bitmap (pattern); | ||||
|   pattern = create_bitmap_ex(bitmap_color_depth (bmp), 2, 2); | ||||
|   clear_bitmap(pattern); | ||||
| 
 | ||||
|   putpixel (pattern, 0, 0, fg); | ||||
|   putpixel (pattern, 0, 1, bg); | ||||
|   putpixel (pattern, 1, 0, bg); | ||||
|   putpixel (pattern, 1, 1, fg); | ||||
|   putpixel(pattern, 0, 0, fg); | ||||
|   putpixel(pattern, 0, 1, bg); | ||||
|   putpixel(pattern, 1, 0, bg); | ||||
|   putpixel(pattern, 1, 1, fg); | ||||
| 
 | ||||
|   drawing_mode (DRAW_MODE_COPY_PATTERN, pattern, 0, 0); | ||||
|   drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0); | ||||
| } | ||||
| 
 | ||||
|  | ||||
|  | @ -250,7 +317,7 @@ typedef struct CLIP_DATA | |||
|   int cl, ct, cr, cb; | ||||
| } CLIP_DATA; | ||||
| 
 | ||||
| void *subclip (BITMAP *bmp, int x1, int y1, int x2, int y2) | ||||
| void *subclip(BITMAP *bmp, int x1, int y1, int x2, int y2) | ||||
| { | ||||
|   int cl, ct, cr, cb; | ||||
|   CLIP_DATA *data; | ||||
|  | @ -280,11 +347,11 @@ void *subclip (BITMAP *bmp, int x1, int y1, int x2, int y2) | |||
|   return data; | ||||
| } | ||||
| 
 | ||||
| void backclip (void *_data) | ||||
| void backclip(void *_data) | ||||
| { | ||||
|   CLIP_DATA *data = _data; | ||||
|   set_clip (data->bmp, data->cl, data->ct, data->cr, data->cb); | ||||
|   jfree (data); | ||||
|   set_clip(data->bmp, data->cl, data->ct, data->cr, data->cb); | ||||
|   jfree(data); | ||||
| } | ||||
| 
 | ||||
|  | ||||
|  |  | |||
|  | @ -35,7 +35,6 @@ struct BITMAP; | |||
| /* graphics ids */ | ||||
| enum { | ||||
|   GFX_LINKFRAME, | ||||
|   GFX_KEYFRAME, | ||||
| 
 | ||||
|   GFX_ANI_FIRST, | ||||
|   GFX_ANI_PREV, | ||||
|  | @ -80,6 +79,9 @@ enum { | |||
|   GFX_ROTATE_2, | ||||
|   GFX_ROTATE_3, | ||||
| 
 | ||||
|   GFX_ARROW_LEFT, | ||||
|   GFX_ARROW_RIGHT, | ||||
| 
 | ||||
|   GFX_BITMAP_COUNT, | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -34,13 +34,6 @@ static DATA gfx_data[GFX_BITMAP_COUNT] = | |||
|     "#....#.#" | ||||
|     "#......#" | ||||
|     "########" }, | ||||
|   /* GFX_KEYFRAME */ | ||||
|   { 4, 5, | ||||
|     " ## " | ||||
|     "#  #" | ||||
|     "#  #" | ||||
|     "#  #" | ||||
|     " ## " }, | ||||
|   /* GFX_ANI_FIRST */ | ||||
|   { 8, 8, | ||||
|     " ##   # " | ||||
|  | @ -437,4 +430,24 @@ static DATA gfx_data[GFX_BITMAP_COUNT] = | |||
|     "  ##..#   " | ||||
|     "    ##.#  " | ||||
|     "      ##  " }, | ||||
|   /* GFX_ARROW_LEFT */ | ||||
|   { 8, 8, | ||||
|     "     #  " | ||||
|     "    ##  " | ||||
|     "   ###  " | ||||
|     "  ####  " | ||||
|     "   ###  " | ||||
|     "    ##  " | ||||
|     "     #  " | ||||
|     "        " }, | ||||
|   /* GFX_ARROW_RIGHT */ | ||||
|   { 8, 8, | ||||
|     "  #     " | ||||
|     "  ##    " | ||||
|     "  ###   " | ||||
|     "  ####  " | ||||
|     "  ###   " | ||||
|     "  ##    " | ||||
|     "  #     " | ||||
|     "        " }, | ||||
| }; | ||||
|  |  | |||
|  | @ -53,8 +53,8 @@ | |||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #define GUI_DEFAULT_WIDTH	640 | ||||
| #define GUI_DEFAULT_HEIGHT	480 | ||||
| #define GUI_DEFAULT_WIDTH	800 | ||||
| #define GUI_DEFAULT_HEIGHT	600 | ||||
| #define GUI_DEFAULT_DEPTH	8 | ||||
| #define GUI_DEFAULT_FULLSCREEN	FALSE | ||||
| #define GUI_DEFAULT_SCALE	2 | ||||
|  | @ -139,25 +139,43 @@ int init_module_gui(void) | |||
|       bpp = GUI_DEFAULT_DEPTH; | ||||
|   } | ||||
| 
 | ||||
|   while (screen_scaling > 0) { | ||||
|     /* try original mode */ | ||||
|   for (;;) { | ||||
|     /* original */ | ||||
|     set_color_depth(bpp); | ||||
|     if (set_gfx_mode(autodetect, w, h, 0, 0) < 0) { | ||||
|       /* try the same resolution but with 8 bpp */ | ||||
|       set_color_depth(bpp = 8); | ||||
|       if (set_gfx_mode(autodetect, w, h, 0, 0) < 0) { | ||||
| 	/* try 320x200 in 8 bpp */ | ||||
| 	if (set_gfx_mode(autodetect, w = 320, h = 200, 0, 0) < 0) { | ||||
| 	  if (screen_scaling == 1) { | ||||
|     if (set_gfx_mode(autodetect, w, h, 0, 0) == 0) | ||||
|       break; | ||||
| 
 | ||||
|     /* 800x600 screen scaling=2 */ | ||||
|     if (set_gfx_mode(autodetect, 800, 600, 0, 0) == 0) { | ||||
|       screen_scaling = 2; | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|     /* 640x480 screen scaling=2 */ | ||||
|     if (set_gfx_mode(autodetect, 640, 480, 0, 0) == 0) { | ||||
|       screen_scaling = 2; | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|     /* 320x240 screen scaling=1 */ | ||||
|     if (set_gfx_mode(autodetect, 320, 240, 0, 0) == 0) { | ||||
|       screen_scaling = 1; | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|     /* 320x200 screen scaling=1 */ | ||||
|     if (set_gfx_mode(autodetect, 320, 200, 0, 0) == 0) { | ||||
|       screen_scaling = 1; | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|     if (bpp == 8) { | ||||
|       user_printf(_("Error setting graphics mode\n%s\n" | ||||
| 		    "Try \"ase -res WIDTHxHEIGHTxBPP\"\n"), allegro_error); | ||||
|       return -1; | ||||
|     } | ||||
|     else | ||||
| 	    --screen_scaling; | ||||
| 	} else break; | ||||
|       } else break; | ||||
|     } else break; | ||||
|       bpp = 8; | ||||
|   } | ||||
| 
 | ||||
|   /* create the default-manager */ | ||||
|  | @ -377,11 +395,11 @@ void reload_default_font(void) | |||
|     dirs_add_path (dirs, default_font); | ||||
| 
 | ||||
|   /* big font */ | ||||
|   if (JI_SCREEN_W > 320) | ||||
|     dirs_cat_dirs (dirs, filename_in_datadir ("fonts/default2.pcx")); | ||||
|   /* tiny font */ | ||||
|   else | ||||
|     dirs_cat_dirs (dirs, filename_in_datadir ("fonts/default.pcx")); | ||||
| /*   if (JI_SCREEN_W > 320) */ | ||||
| /*     dirs_cat_dirs(dirs, filename_in_datadir("fonts/default2.pcx")); */ | ||||
| /*   /\* tiny font *\/ */ | ||||
| /*   else */ | ||||
|     dirs_cat_dirs(dirs, filename_in_datadir("fonts/default.pcx")); | ||||
| 
 | ||||
|   /* try to load the font */ | ||||
|   for (dir=dirs; dir; dir=dir->next) { | ||||
|  |  | |||
|  | @ -49,8 +49,14 @@ static JList hooks; | |||
| /* system color (in order of importance) */ | ||||
| static RGB system_color[] = | ||||
| { | ||||
|   { 63, 63, 63, 0 }, {  0,  0,  0, 0 }, { 32, 32, 32, 0 }, { 48, 48, 48, 0 }, | ||||
|   { 11, 19, 36, 0 }, { 56, 56, 56, 0 }, { 63, 63,  0, 0 }, {  0,  0, 63, 0 } | ||||
|   { 255/4, 255/4, 255/4, 0 },	/* background */ | ||||
|   {   0/4,   0/4,   0/4, 0 },	/* foreground */ | ||||
|   { 128/4, 128/4, 128/4, 0 },	/* disabled */ | ||||
|   { 210/4, 200/4, 190/4, 0 },	/* face */ | ||||
|   {  44/4,  76/4, 145/4, 0 },	/* selected */ | ||||
|   { 250/4, 240/4, 230/4, 0 },	/* hotface */ | ||||
|   { 255/4, 255/4,   0/4, 0 },	/* yellow */ | ||||
|   {   0/4,   0/4, 255/4, 0 }	/* blue */ | ||||
| }; | ||||
| 
 | ||||
| #define SYSTEM_COLORS   (sizeof(system_color) / sizeof(RGB)) | ||||
|  |  | |||
|  | @ -39,7 +39,6 @@ | |||
| 
 | ||||
| static JWidget root_menu; | ||||
| 
 | ||||
| static JWidget sprite_list_menuitem; | ||||
| static JWidget recent_list_menuitem; | ||||
| static JWidget layer_popup_menuitem; | ||||
| static JWidget frame_popup_menuitem; | ||||
|  | @ -59,7 +58,6 @@ int init_module_rootmenu(void) | |||
| 
 | ||||
| void exit_module_rootmenu(void) | ||||
| { | ||||
|   sprite_list_menuitem = NULL; | ||||
|   recent_list_menuitem = NULL; | ||||
|   layer_popup_menuitem = NULL; | ||||
|   frame_popup_menuitem = NULL; | ||||
|  | @ -88,7 +86,6 @@ int load_root_menu(void) | |||
| 
 | ||||
|   /* create a new empty-menu */ | ||||
|   root_menu = NULL; | ||||
|   sprite_list_menuitem = NULL; | ||||
|   recent_list_menuitem = NULL; | ||||
|   layer_popup_menuitem = NULL; | ||||
|   frame_popup_menuitem = NULL; | ||||
|  | @ -208,7 +205,6 @@ int load_root_menu(void) | |||
| 
 | ||||
| JWidget get_root_menu(void) { return root_menu; } | ||||
| 
 | ||||
| JWidget get_sprite_list_menuitem(void) { return sprite_list_menuitem; } | ||||
| JWidget get_recent_list_menuitem(void) { return recent_list_menuitem; } | ||||
| JWidget get_layer_popup_menuitem(void) { return layer_popup_menuitem; } | ||||
| JWidget get_frame_popup_menuitem(void) { return frame_popup_menuitem; } | ||||
|  | @ -271,11 +267,8 @@ static JWidget convert_xmlelem_to_menuitem(JXmlElem elem) | |||
|   /* has it a ID? */ | ||||
|   id = jxmlelem_get_attr(elem, "id"); | ||||
|   if (id) { | ||||
|     if (strcmp(id, "sprite_list") == 0) { | ||||
|       sprite_list_menuitem = menuitem; | ||||
|     } | ||||
|     /* recent list menu */ | ||||
|     else if (strcmp(id, "recent_list") == 0) { | ||||
|     if (strcmp(id, "recent_list") == 0) { | ||||
|       recent_list_menuitem = menuitem; | ||||
|     } | ||||
|     /* layer popup menu */ | ||||
|  |  | |||
|  | @ -36,7 +36,6 @@ int load_root_menu(void); | |||
| 
 | ||||
| JWidget get_root_menu(void); | ||||
| 
 | ||||
| JWidget get_sprite_list_menuitem(void); | ||||
| JWidget get_recent_list_menuitem(void); | ||||
| JWidget get_layer_popup_menuitem(void); | ||||
| JWidget get_frame_popup_menuitem(void); | ||||
|  |  | |||
|  | @ -20,8 +20,11 @@ | |||
| 
 | ||||
| #ifndef USE_PRECOMPILED_HEADER | ||||
| 
 | ||||
| #include <allegro/file.h> | ||||
| 
 | ||||
| #include "jinete/list.h" | ||||
| 
 | ||||
| #include "core/app.h" | ||||
| #include "core/core.h" | ||||
| #include "file/file.h" | ||||
| #include "modules/editors.h" | ||||
|  | @ -35,6 +38,7 @@ | |||
| #include "script/bindings.h" | ||||
| #include "util/misc.h" | ||||
| #include "widgets/editor.h" | ||||
| #include "widgets/tabs.h" | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|  | @ -46,8 +50,8 @@ Sprite *current_sprite = NULL; | |||
| static JList sprites_list; | ||||
| static Sprite *clipboard_sprite; | ||||
| 
 | ||||
| static Stock *layer_get_images (Sprite *sprite, Layer *layer, int target, int write); | ||||
| static void layer_get_pos (Sprite *sprite, Layer *layer, int target, int write, int **x, int **y, int *count); | ||||
| static Stock *layer_get_images(Sprite *sprite, Layer *layer, int target, int write); | ||||
| static void layer_get_pos(Sprite *sprite, Layer *layer, int target, int write, int **x, int **y, int *count); | ||||
| 
 | ||||
| int init_module_sprites(void) | ||||
| { | ||||
|  | @ -110,8 +114,8 @@ void set_clipboard_sprite(Sprite *sprite) | |||
| 
 | ||||
|   clipboard_sprite = sprite; | ||||
| 
 | ||||
|   if (is_interactive ()) | ||||
|     rebuild_sprite_list (); | ||||
|   if (is_interactive()) | ||||
|     rebuild_sprite_list(); | ||||
| } | ||||
| 
 | ||||
| /* adds the "sprite" in the list of sprites */ | ||||
|  | @ -120,9 +124,14 @@ void sprite_mount(Sprite *sprite) | |||
|   /* append the sprite to the list */ | ||||
|   jlist_prepend(sprites_list, sprite); | ||||
| 
 | ||||
|   if (is_interactive()) { | ||||
|     /* add the tab for this sprite */ | ||||
|     tabs_append_tab(app_get_tabs_bar(), | ||||
| 		    get_filename(sprite->filename), sprite); | ||||
| 
 | ||||
|     /* rebuild the menu list of sprites */ | ||||
|   if (is_interactive()) | ||||
|     rebuild_sprite_list(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* removes the "sprite" from the list of sprites */ | ||||
|  | @ -136,6 +145,9 @@ void sprite_unmount(Sprite *sprite) | |||
|     clipboard_sprite = NULL; | ||||
| 
 | ||||
|   if (is_interactive()) { | ||||
|     /* remove this sprite from tabs */ | ||||
|     tabs_remove_tab(app_get_tabs_bar(), sprite); | ||||
| 
 | ||||
|     /* rebuild the menu list of sprites */ | ||||
|     rebuild_sprite_list(); | ||||
| 
 | ||||
|  | @ -161,6 +173,9 @@ void set_current_sprite(Sprite *sprite) | |||
| { | ||||
|   current_sprite = sprite; | ||||
|   update_global_script_variables(); | ||||
| 
 | ||||
|   /* select the sprite in the tabs */ | ||||
|   tabs_select_tab(app_get_tabs_bar(), sprite); | ||||
| } | ||||
| 
 | ||||
| void send_sprite_to_top(Sprite *sprite) | ||||
|  | @ -178,7 +193,7 @@ void sprite_show(Sprite *sprite) | |||
|     set_sprite_in_more_reliable_editor(sprite); | ||||
| } | ||||
| 
 | ||||
| Stock *sprite_get_images (Sprite *sprite, int target, int write, int **x, int **y) | ||||
| Stock *sprite_get_images(Sprite *sprite, int target, int write, int **x, int **y) | ||||
| { | ||||
|   Layer *layer = (target & TARGET_LAYERS) ? sprite->set: sprite->layer; | ||||
|   Stock *stock; | ||||
|  | @ -260,7 +275,7 @@ static Stock *layer_get_images(Sprite *sprite, Layer *layer, int target, int wri | |||
|   return stock; | ||||
| } | ||||
| 
 | ||||
| static void layer_get_pos (Sprite *sprite, Layer *layer, int target, int write, int **x, int **y, int *count) | ||||
| static void layer_get_pos(Sprite *sprite, Layer *layer, int target, int write, int **x, int **y, int *count) | ||||
| { | ||||
|   int frame = sprite->frame; | ||||
| 
 | ||||
|  |  | |||
|  | @ -235,10 +235,10 @@ static bool status_bar_msg_proc(JWidget widget, JMessage msg) | |||
|     case JM_DRAW: { | ||||
|       JRect rect = jwidget_get_rect(widget); | ||||
| 
 | ||||
|       jdraw_rectedge(rect, makecol(255,255,255), makecol(128,128,128)); | ||||
|       jdraw_rectedge(rect, ji_color_facelight(), ji_color_faceshadow()); | ||||
|       jrect_shrink(rect, 1); | ||||
| 
 | ||||
|       jdraw_rect(rect, makecol(192,192,192)); | ||||
|       jdraw_rect(rect, ji_color_face()); | ||||
|       jrect_shrink(rect, 1); | ||||
| 
 | ||||
|       /* progress bar */ | ||||
|  | @ -246,9 +246,10 @@ static bool status_bar_msg_proc(JWidget widget, JMessage msg) | |||
| 	int i, pos, x1, y1, x2, y2; | ||||
| 	double x, width; | ||||
| 
 | ||||
| 	jdraw_rectedge (rect, | ||||
| 			  makecol (128, 128, 128), makecol (255, 255, 255)); | ||||
| 	jrect_shrink (rect, 1); | ||||
| 	jdraw_rectedge(rect, | ||||
| 		       ji_color_faceshadow(), | ||||
| 		       ji_color_facelight()); | ||||
| 	jrect_shrink(rect, 1); | ||||
| 
 | ||||
| 	x1 = rect->x1; | ||||
| 	y1 = rect->y1; | ||||
|  | @ -273,19 +274,19 @@ static bool status_bar_msg_proc(JWidget widget, JMessage msg) | |||
| 	} | ||||
| 
 | ||||
| 	x = MID(x1, x, x2); | ||||
| 	rectfill(ji_screen, x1, y1, x, y2, makecol(44,76,145)); | ||||
| 	rectfill(ji_screen, x1, y1, x, y2, ji_color_selected()); | ||||
| 	if (x < x2) | ||||
| 	  rectfill(ji_screen, x+1, y1, x2, y2, makecol(255, 255, 255)); | ||||
| 	  rectfill(ji_screen, x+1, y1, x2, y2, ji_color_background()); | ||||
|       } | ||||
|       /* status bar text */ | ||||
|       else if (widget->text) { | ||||
| 	jdraw_rectfill(rect, makecol(192,192,192)); | ||||
| 	jdraw_rectfill(rect, ji_color_face()); | ||||
| 
 | ||||
| 	text_mode(-1); | ||||
| 	textout(ji_screen, widget->text_font, widget->text, | ||||
| 		rect->x1+2, | ||||
| 		(widget->rc->y1+widget->rc->y2)/2-text_height (widget->text_font)/2, | ||||
| 		makecol (0, 0, 0)); | ||||
| 		ji_color_foreground()); | ||||
|       } | ||||
| 
 | ||||
|       jrect_free(rect); | ||||
|  | @ -293,33 +294,33 @@ static bool status_bar_msg_proc(JWidget widget, JMessage msg) | |||
|     } | ||||
| 
 | ||||
|     case JM_MOUSEENTER: | ||||
|       if (!jwidget_has_child (widget, status_bar->commands_box)) { | ||||
|       if (!jwidget_has_child(widget, status_bar->commands_box)) { | ||||
| 	Sprite *sprite = current_sprite; | ||||
| 
 | ||||
| 	if (!sprite) { | ||||
| 	  jwidget_disable (status_bar->b_first); | ||||
| 	  jwidget_disable (status_bar->b_prev); | ||||
| 	  jwidget_disable (status_bar->b_play); | ||||
| 	  jwidget_disable (status_bar->b_next); | ||||
| 	  jwidget_disable (status_bar->b_last); | ||||
| 	  jwidget_disable(status_bar->b_first); | ||||
| 	  jwidget_disable(status_bar->b_prev); | ||||
| 	  jwidget_disable(status_bar->b_play); | ||||
| 	  jwidget_disable(status_bar->b_next); | ||||
| 	  jwidget_disable(status_bar->b_last); | ||||
| 	} | ||||
| 	else { | ||||
| 	  jwidget_enable (status_bar->b_first); | ||||
| 	  jwidget_enable (status_bar->b_prev); | ||||
| 	  jwidget_enable (status_bar->b_play); | ||||
| 	  jwidget_enable (status_bar->b_next); | ||||
| 	  jwidget_enable (status_bar->b_last); | ||||
| 	  jwidget_enable(status_bar->b_first); | ||||
| 	  jwidget_enable(status_bar->b_prev); | ||||
| 	  jwidget_enable(status_bar->b_play); | ||||
| 	  jwidget_enable(status_bar->b_next); | ||||
| 	  jwidget_enable(status_bar->b_last); | ||||
| 	} | ||||
| 
 | ||||
| 	update_from_layer (status_bar); | ||||
| 	update_from_layer(status_bar); | ||||
| 
 | ||||
| 	jwidget_add_child (widget, status_bar->commands_box); | ||||
| 	jwidget_dirty (widget); | ||||
| 	jwidget_add_child(widget, status_bar->commands_box); | ||||
| 	jwidget_dirty(widget); | ||||
|       } | ||||
|       break; | ||||
| 
 | ||||
|     case JM_MOUSELEAVE: | ||||
|       if (jwidget_has_child (widget, status_bar->commands_box)) | ||||
|       if (jwidget_has_child(widget, status_bar->commands_box)) | ||||
| 	status_bar->restore = TRUE; | ||||
|       break; | ||||
| 
 | ||||
|  | @ -327,13 +328,13 @@ static bool status_bar_msg_proc(JWidget widget, JMessage msg) | |||
|       /* if we want restore the state-bar and the slider doesn't have
 | ||||
| 	 the capture... */ | ||||
|       if (status_bar->restore && | ||||
| 	  jmanager_get_capture () != status_bar->slider) { | ||||
| 	  jmanager_get_capture() != status_bar->slider) { | ||||
| 	/* exit from command mode */ | ||||
| 	status_bar->restore = FALSE; | ||||
| 	jmanager_free_focus (); | ||||
| 	jmanager_free_focus(); | ||||
| 
 | ||||
| 	jwidget_remove_child (widget, status_bar->commands_box); | ||||
| 	jwidget_dirty (widget); | ||||
| 	jwidget_remove_child(widget, status_bar->commands_box); | ||||
| 	jwidget_dirty(widget); | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
|  |  | |||
|  | @ -0,0 +1,518 @@ | |||
| /* ASE - Allegro Sprite Editor
 | ||||
|  * Copyright (C) 2001-2005, 2007  David A. Capello | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #ifndef USE_PRECOMPILED_HEADER | ||||
| 
 | ||||
| #include <allegro.h> | ||||
| 
 | ||||
| #include "jinete.h" | ||||
| #include "jinete/intern.h" | ||||
| 
 | ||||
| #include "modules/gfx.h" | ||||
| #include "modules/gui.h" | ||||
| #include "widgets/tabs.h" | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #define CALC_TAB_WIDTH(widget, tab)			\ | ||||
|   (4 + text_length(widget->text_font, tab->text) + 4) | ||||
| 
 | ||||
| #define ARROW_W		12 | ||||
| 
 | ||||
| #define HAS_ARROWS ((jwidget_get_parent(tabs->button_left) == widget)) | ||||
| 
 | ||||
| typedef struct Tab | ||||
| { | ||||
|   char *text; | ||||
|   void *data; | ||||
|   int width; | ||||
| } Tab; | ||||
| 
 | ||||
| typedef struct Tabs | ||||
| { | ||||
|   JList list_of_tabs; | ||||
|   Tab *hot; | ||||
|   Tab *selected; | ||||
|   void (*select_callback)(void *data); | ||||
|   int scroll_x; | ||||
| /*   int hot_arrow; */ | ||||
|   JWidget button_left; | ||||
|   JWidget button_right; | ||||
| } Tabs; | ||||
| 
 | ||||
| static int tabs_type(void); | ||||
| static bool tabs_msg_proc(JWidget widget, JMessage msg); | ||||
| static bool tabs_button_msg_proc(JWidget widget, JMessage msg); | ||||
| 
 | ||||
| static Tab *get_tab_by_data(JWidget widget, void *data); | ||||
| static int get_max_scroll_x(JWidget widget); | ||||
| static void make_tab_visible(JWidget widget, Tab *tab); | ||||
| static void set_scroll_x(JWidget widget, int scroll_x); | ||||
| static void calculate_hot(JWidget widget); | ||||
| static void draw_bevel_box(JRect box, int c1, int c2, int bottom); | ||||
| 
 | ||||
| static Tab *tab_new(const char *text, void *data); | ||||
| static void tab_free(Tab *tab); | ||||
| 
 | ||||
| /**************************************************************/ | ||||
| /* Tabs                                                       */ | ||||
| /**************************************************************/ | ||||
| 
 | ||||
| JWidget tabs_new(void (*select_callback)(void *data)) | ||||
| { | ||||
|   JWidget widget = jwidget_new(tabs_type()); | ||||
|   Tabs *tabs = jnew0(Tabs, 1); | ||||
| 
 | ||||
|   tabs->list_of_tabs = jlist_new(); | ||||
|   tabs->hot = NULL; | ||||
|   tabs->selected = NULL; | ||||
|   tabs->select_callback = select_callback; | ||||
|   tabs->scroll_x = 0; | ||||
| /*   tabs->hot_arrow = 0; */ | ||||
| 
 | ||||
|   tabs->button_left = jbutton_new(NULL); | ||||
|   tabs->button_right = jbutton_new(NULL); | ||||
| 
 | ||||
|   jbutton_set_bevel(tabs->button_left, 0, 0, 0, 0); | ||||
|   jbutton_set_bevel(tabs->button_right, 0, 0, 0, 0); | ||||
| 
 | ||||
|   jwidget_focusrest(tabs->button_left, FALSE); | ||||
|   jwidget_focusrest(tabs->button_right, FALSE); | ||||
|    | ||||
|   add_gfxicon_to_button(tabs->button_left, GFX_ARROW_LEFT, JI_CENTER | JI_MIDDLE); | ||||
|   add_gfxicon_to_button(tabs->button_right, GFX_ARROW_RIGHT, JI_CENTER | JI_MIDDLE); | ||||
| 
 | ||||
|   jwidget_add_hook(widget, tabs_type(), tabs_msg_proc, tabs); | ||||
|   jwidget_add_hook(tabs->button_left, tabs_type(), tabs_button_msg_proc, (void *)-1); | ||||
|   jwidget_add_hook(tabs->button_right, tabs_type(), tabs_button_msg_proc, (void *)+1); | ||||
| 
 | ||||
|   return widget; | ||||
| } | ||||
| 
 | ||||
| void tabs_append_tab(JWidget widget, const char *text, void *data) | ||||
| { | ||||
|   Tabs *tabs = jwidget_get_data(widget, tabs_type()); | ||||
|   Tab *tab = tab_new(text, data); | ||||
|   tab->width = CALC_TAB_WIDTH(widget, tab); | ||||
| 
 | ||||
|   jlist_append(tabs->list_of_tabs, tab); | ||||
| 
 | ||||
|   /* update scroll (in the same position if we can */ | ||||
|   set_scroll_x(widget, tabs->scroll_x); | ||||
|    | ||||
|   jwidget_dirty(widget); | ||||
| } | ||||
| 
 | ||||
| void tabs_remove_tab(JWidget widget, void *data) | ||||
| { | ||||
|   Tabs *tabs = jwidget_get_data(widget, tabs_type()); | ||||
|   Tab *tab = get_tab_by_data(widget, data); | ||||
| 
 | ||||
|   if (tab) { | ||||
|     jlist_remove(tabs->list_of_tabs, tab); | ||||
|     tab_free(tab); | ||||
| 
 | ||||
|     /* update scroll (in the same position if we can */ | ||||
|     set_scroll_x(widget, tabs->scroll_x); | ||||
| 
 | ||||
|     jwidget_dirty(widget); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void tabs_set_text_for_tab(JWidget widget, const char *text, void *data) | ||||
| { | ||||
|   Tabs *tabs = jwidget_get_data(widget, tabs_type()); | ||||
|   Tab *tab = get_tab_by_data(widget, data); | ||||
| 
 | ||||
|   if (tab) { | ||||
|     /* free old text */ | ||||
|     if (tab->text) | ||||
|       jfree(tab->text); | ||||
| 
 | ||||
|     /* change text of the tab */ | ||||
|     tab->text = jstrdup(text); | ||||
|     tab->width = CALC_TAB_WIDTH(widget, tab); | ||||
| 
 | ||||
|     /* make it visible (if it's the selected) */ | ||||
|     if (tabs->selected == tab) | ||||
|       make_tab_visible(widget, tab); | ||||
|      | ||||
|     jwidget_dirty(widget); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void tabs_select_tab(JWidget widget, void *data) | ||||
| { | ||||
|   Tabs *tabs = jwidget_get_data(widget, tabs_type()); | ||||
|   Tab *tab = get_tab_by_data(widget, data); | ||||
| 
 | ||||
|   if (tab) { | ||||
|     tabs->selected = tab; | ||||
|     make_tab_visible(widget, tab); | ||||
|     jwidget_dirty(widget); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static int tabs_type(void) | ||||
| { | ||||
|   static int type = 0; | ||||
|   if (!type) | ||||
|     type = ji_register_widget_type(); | ||||
|   return type; | ||||
| } | ||||
| 
 | ||||
| static bool tabs_msg_proc(JWidget widget, JMessage msg) | ||||
| { | ||||
|   Tabs *tabs = jwidget_get_data(widget, tabs_type()); | ||||
| 
 | ||||
|   switch (msg->type) { | ||||
| 
 | ||||
|     case JM_DESTROY: { | ||||
|       JLink link; | ||||
| 
 | ||||
|       JI_LIST_FOR_EACH(tabs->list_of_tabs, link) | ||||
| 	tab_free(link->data); | ||||
| 
 | ||||
|       jwidget_free(tabs->button_left); | ||||
|       jwidget_free(tabs->button_right); | ||||
|        | ||||
|       jlist_free(tabs->list_of_tabs); | ||||
|       jfree(tabs); | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|     case JM_REQSIZE: | ||||
|       msg->reqsize.w = | ||||
| 	msg->reqsize.h = 4 + jwidget_get_text_height(widget) + 5; | ||||
|       return TRUE; | ||||
| 
 | ||||
| /*     case JM_SIGNAL: */ | ||||
| /*       if (msg->signal.num == JI_SIGNAL_SHOW) */ | ||||
| /* 	set_scroll_x(widget, tabs->scroll_x); */ | ||||
| /*       break; */ | ||||
| 
 | ||||
|     case JM_SETPOS: | ||||
|       jrect_copy(widget->rc, &msg->setpos.rect); | ||||
|       set_scroll_x(widget, tabs->scroll_x); | ||||
|       return TRUE; | ||||
| 
 | ||||
|     case JM_DRAW: { | ||||
|       JRect rect = jwidget_get_rect(widget); | ||||
|       JRect box = jrect_new(rect->x1-tabs->scroll_x, rect->y1, 0, rect->y2-1); | ||||
|       JLink link; | ||||
| 
 | ||||
|       /* for each tab */ | ||||
|       JI_LIST_FOR_EACH(tabs->list_of_tabs, link) { | ||||
| 	Tab *tab = link->data; | ||||
| 	int fg, face, bottom; | ||||
| 
 | ||||
| 	box->x2 = box->x1 + tab->width; | ||||
| 
 | ||||
| 	/* is the tab inside the bounds of the widget? */ | ||||
| 	if (box->x1 < rect->x2 && box->x2 > rect->x1) { | ||||
| 	  /* selected */ | ||||
| 	  if (tabs->selected == tab) { | ||||
| 	    fg = ji_color_background(); | ||||
| 	    face = ji_color_selected(); | ||||
| 	    bottom = face; | ||||
| 	  } | ||||
| 	  /* non-selected */ | ||||
| 	  else { | ||||
| 	    fg = ji_color_foreground(); | ||||
| 	    face = tabs->hot == tab ? ji_color_hotface(): | ||||
| 				      ji_color_face(); | ||||
| 	    bottom = ji_color_facelight(); | ||||
| 	  } | ||||
| 
 | ||||
| 	  hline(ji_screen, box->x1, box->y1, box->x2-1, ji_color_face()); | ||||
| 	  rectfill(ji_screen, box->x1+1, box->y1+1, box->x2-2, box->y2-1, face); | ||||
| 	  hline(ji_screen, box->x1, rect->y2-1, box->x2-1, ji_color_selected()); | ||||
| 
 | ||||
| 	  draw_bevel_box(box, | ||||
| 			 ji_color_facelight(), | ||||
| 			 ji_color_faceshadow(), | ||||
| 			 bottom); | ||||
| 
 | ||||
| 	  jdraw_text(widget->text_font, tab->text, | ||||
| 		     box->x1+4, | ||||
| 		     (box->y1+box->y2)/2-text_height(widget->text_font)/2, | ||||
| 		     fg, face, FALSE); | ||||
| 	} | ||||
| 
 | ||||
| 	box->x1 = box->x2; | ||||
|       } | ||||
| 
 | ||||
|       /* fill the gap to the right-side */ | ||||
|       if (box->x1 < rect->x2) { | ||||
| 	rectfill(ji_screen, box->x1, rect->y1, rect->x2-1, rect->y2-3, | ||||
| 		 ji_color_face()); | ||||
| 	hline(ji_screen, box->x1, rect->y2-2, rect->x2-1, ji_color_facelight()); | ||||
| 	hline(ji_screen, box->x1, rect->y2-1, rect->x2-1, ji_color_selected()); | ||||
|       } | ||||
| 
 | ||||
|       /* draw bottom lines below the arrow-buttons */ | ||||
|       if (HAS_ARROWS) { | ||||
| 	hline(ji_screen, box->x1, rect->y2-2, rect->x2-1, ji_color_facelight()); | ||||
| 	hline(ji_screen, box->x1, rect->y2-1, rect->x2-1, ji_color_selected()); | ||||
|       } | ||||
| 
 | ||||
|       jrect_free(rect); | ||||
|       jrect_free(box); | ||||
|       return TRUE; | ||||
|     } | ||||
| 
 | ||||
|     case JM_MOUSEENTER: | ||||
|     case JM_MOTION: | ||||
|       calculate_hot(widget); | ||||
|       return TRUE; | ||||
| 
 | ||||
|     case JM_MOUSELEAVE: | ||||
|       if (tabs->hot != NULL) { | ||||
| 	tabs->hot = NULL; | ||||
| 	jwidget_dirty(widget); | ||||
|       } | ||||
|       return TRUE; | ||||
| 
 | ||||
|     case JM_BUTTONPRESSED: | ||||
|       if (tabs->selected != tabs->hot) { | ||||
| 	tabs->selected = tabs->hot; | ||||
| 	jwidget_dirty(widget); | ||||
| 
 | ||||
| 	if (tabs->selected && tabs->select_callback) | ||||
| 	  (*tabs->select_callback)(tabs->selected->data); | ||||
|       } | ||||
|       return TRUE; | ||||
| 
 | ||||
|     case JM_WHEEL: { | ||||
|       int dx = (jmouse_z(1) - jmouse_z(0)) * jrect_w(widget->rc)/6; | ||||
|       set_scroll_x(widget, tabs->scroll_x+dx); | ||||
|       return TRUE; | ||||
|     } | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   return FALSE; | ||||
| } | ||||
| 
 | ||||
| static bool tabs_button_msg_proc(JWidget widget, JMessage msg) | ||||
| { | ||||
|   switch (msg->type) { | ||||
| 
 | ||||
|     case JM_SIGNAL: | ||||
|       if (msg->signal.num == JI_SIGNAL_BUTTON_SELECT) | ||||
| 	return TRUE; | ||||
|       else if (msg->signal.num == JI_SIGNAL_DISABLE) { | ||||
| 	if (jwidget_is_selected(widget)) | ||||
| 	  jwidget_deselect(widget); | ||||
| 	return TRUE; | ||||
|       } | ||||
|       break; | ||||
| 
 | ||||
|     case JM_IDLE: | ||||
|       if (jwidget_has_capture(widget)) { | ||||
| 	JWidget parent = jwidget_get_parent(widget); | ||||
| 	Tabs *tabs = jwidget_get_data(parent, tabs_type()); | ||||
| 	int dir = (int) jwidget_get_data(widget, tabs_type()); | ||||
| 	set_scroll_x(parent, tabs->scroll_x + dir*8); | ||||
|       } | ||||
|       break; | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|   return FALSE; | ||||
| } | ||||
| 
 | ||||
| static Tab *get_tab_by_data(JWidget widget, void *data) | ||||
| { | ||||
|   Tabs *tabs = jwidget_get_data(widget, tabs_type()); | ||||
|   JLink link; | ||||
| 
 | ||||
|   JI_LIST_FOR_EACH(tabs->list_of_tabs, link) { | ||||
|     Tab *tab = link->data; | ||||
|     if (tab->data == data) | ||||
|       return tab; | ||||
|   } | ||||
| 
 | ||||
|   return NULL; | ||||
| } | ||||
| 
 | ||||
| static int get_max_scroll_x(JWidget widget) | ||||
| { | ||||
|   Tabs *tabs = jwidget_get_data(widget, tabs_type()); | ||||
|   JLink link; | ||||
|   int x = 0; | ||||
| 
 | ||||
|   JI_LIST_FOR_EACH(tabs->list_of_tabs, link) { | ||||
|     Tab *tab = link->data; | ||||
|     x += tab->width; | ||||
|   } | ||||
| 
 | ||||
|   x -= jrect_w(widget->rc); | ||||
| 
 | ||||
|   if (x < 0) | ||||
|     return 0; | ||||
|   else | ||||
|     return x + ARROW_W*2; | ||||
| } | ||||
| 
 | ||||
| static void make_tab_visible(JWidget widget, Tab *make_visible_this_tab) | ||||
| { | ||||
|   Tabs *tabs = jwidget_get_data(widget, tabs_type()); | ||||
|   JLink link; | ||||
|   int x = 0; | ||||
|   int extra_x = get_max_scroll_x(widget) > 0 ? ARROW_W*2: 0; | ||||
| 
 | ||||
|   JI_LIST_FOR_EACH(tabs->list_of_tabs, link) { | ||||
|     Tab *tab = link->data; | ||||
| 
 | ||||
|     if (tab == make_visible_this_tab) { | ||||
|       if (x - tabs->scroll_x < 0) { | ||||
| 	set_scroll_x(widget, x); | ||||
|       } | ||||
|       else if (x + tab->width - tabs->scroll_x > jrect_w(widget->rc) - extra_x) { | ||||
| 	set_scroll_x(widget, x + tab->width - jrect_w(widget->rc) + extra_x); | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|     x += tab->width; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void set_scroll_x(JWidget widget, int scroll_x) | ||||
| { | ||||
|   Tabs *tabs = jwidget_get_data(widget, tabs_type()); | ||||
|   int max_x = get_max_scroll_x(widget); | ||||
| 
 | ||||
|   scroll_x = MID(0, scroll_x, max_x); | ||||
|   if (tabs->scroll_x != scroll_x) { | ||||
|     tabs->scroll_x = scroll_x; | ||||
|     calculate_hot(widget); | ||||
|     jwidget_dirty(widget); | ||||
|   } | ||||
| 
 | ||||
|   PRINTF("max_x = %d\n", max_x); | ||||
|   PRINTF("widget->rc->x1 = %d\n", widget->rc->x1); | ||||
|   PRINTF("widget->rc->y1 = %d\n", widget->rc->y1); | ||||
|   PRINTF("widget->rc->x2 = %d\n", widget->rc->x2); | ||||
|   PRINTF("widget->rc->y2 = %d\n", widget->rc->y2); | ||||
| 
 | ||||
|   /* we need scroll buttons? */ | ||||
| /*   if (max_x > 0 && widget->rc->x2 > 0) { */ | ||||
|   if (max_x > 0) { | ||||
|     /* add childs */ | ||||
|     if (!HAS_ARROWS) { | ||||
|       jwidget_add_child(widget, tabs->button_left); | ||||
|       jwidget_add_child(widget, tabs->button_right); | ||||
|       jwidget_dirty(widget); | ||||
|     } | ||||
| 
 | ||||
|     /* disable/enable buttons */ | ||||
|     if (tabs->scroll_x > 0) | ||||
|       jwidget_enable(tabs->button_left); | ||||
|     else | ||||
|       jwidget_disable(tabs->button_left); | ||||
| 
 | ||||
|     if (tabs->scroll_x < max_x) | ||||
|       jwidget_enable(tabs->button_right); | ||||
|     else | ||||
|       jwidget_disable(tabs->button_right); | ||||
| 
 | ||||
|     /* setup the position of each button */ | ||||
|     { | ||||
|       JRect rect = jwidget_get_rect(widget); | ||||
|       JRect box = jrect_new(rect->x2-ARROW_W*2, rect->y1, | ||||
| 			    rect->x2-ARROW_W, rect->y2-2); | ||||
|       jwidget_set_rect(tabs->button_left, box); | ||||
| 
 | ||||
|       jrect_moveto(box, box->x1+ARROW_W, box->y1); | ||||
|       jwidget_set_rect(tabs->button_right, box); | ||||
| 
 | ||||
|       jrect_free(box); | ||||
|       jrect_free(rect); | ||||
|     } | ||||
|   } | ||||
|   /* remove buttons */ | ||||
|   else if (HAS_ARROWS) { | ||||
|     jwidget_remove_child(widget, tabs->button_left); | ||||
|     jwidget_remove_child(widget, tabs->button_right); | ||||
|     jwidget_dirty(widget); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void calculate_hot(JWidget widget) | ||||
| { | ||||
|   Tabs *tabs = jwidget_get_data(widget, tabs_type()); | ||||
|   JRect rect = jwidget_get_rect(widget); | ||||
|   JRect box = jrect_new(rect->x1-tabs->scroll_x, rect->y1, 0, rect->y2-1); | ||||
|   JLink link; | ||||
|   Tab *hot = NULL; | ||||
| 
 | ||||
|   /* for each tab */ | ||||
|   JI_LIST_FOR_EACH(tabs->list_of_tabs, link) { | ||||
|     Tab *tab = link->data; | ||||
| 
 | ||||
|     box->x2 = box->x1 + tab->width; | ||||
| 
 | ||||
|     if (jrect_point_in(box, jmouse_x(0), jmouse_y(0))) { | ||||
|       hot = tab; | ||||
|       break; | ||||
|     } | ||||
| 
 | ||||
|     box->x1 = box->x2; | ||||
|   } | ||||
| 
 | ||||
|   if (tabs->hot != hot) { | ||||
|     tabs->hot = hot; | ||||
|     jwidget_dirty(widget); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| static void draw_bevel_box(JRect box, int c1, int c2, int bottom) | ||||
| { | ||||
|   hline(ji_screen, box->x1+1, box->y1, box->x2-2, c1);	   /* top */ | ||||
|   hline(ji_screen, box->x1, box->y2-1, box->x2-1, bottom); /* bottom */ | ||||
|   vline(ji_screen, box->x1, box->y1+1, box->y2-2, c1);	   /* left */ | ||||
|   vline(ji_screen, box->x2-1, box->y1+1, box->y2-2, c2);   /* right */ | ||||
| } | ||||
| 
 | ||||
| /**************************************************************/ | ||||
| /* Tab                                                        */ | ||||
| /**************************************************************/ | ||||
| 
 | ||||
| static Tab *tab_new(const char *text, void *data) | ||||
| { | ||||
|   Tab *tab = jnew0(Tab, 1); | ||||
|   if (!tab) | ||||
|     return NULL; | ||||
| 
 | ||||
|   tab->text = jstrdup(text); | ||||
|   tab->data = data; | ||||
|   tab->width = 0; | ||||
| 
 | ||||
|   return tab; | ||||
| } | ||||
| 
 | ||||
| static void tab_free(Tab *tab) | ||||
| { | ||||
|   if (tab->text) | ||||
|     jfree(tab->text); | ||||
|   jfree(tab); | ||||
| } | ||||
|  | @ -0,0 +1,33 @@ | |||
| /* ASE - Allegro Sprite Editor
 | ||||
|  * Copyright (C) 2001-2005, 2007  David A. Capello | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program; if not, write to the Free Software | ||||
|  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
|  */ | ||||
| 
 | ||||
| #ifndef WIDGETS_TABS_H | ||||
| #define WIDGETS_TABS_H | ||||
| 
 | ||||
| #include "jinete/base.h" | ||||
| 
 | ||||
| JWidget tabs_new(void (*select_callback)(void *data)); | ||||
| 
 | ||||
| void tabs_append_tab(JWidget widget, const char *text, void *data); | ||||
| void tabs_remove_tab(JWidget widget, void *data); | ||||
| 
 | ||||
| void tabs_set_text_for_tab(JWidget widget, const char *text, void *data); | ||||
| 
 | ||||
| void tabs_select_tab(JWidget widget, void *data); | ||||
| 
 | ||||
| #endif /* WIDGETS_TABS_H */ | ||||
|  | @ -3,38 +3,53 @@ componentes for ASE only, I removed some unnecessary files. | |||
| 
 | ||||
| gfli/ | ||||
| 
 | ||||
|   Routines to load/save FLI/FLC files. | ||||
|   This is a shorten version of gfli 1.3, you can get the entire | ||||
|   package from: | ||||
|   Routines to load/save FLI/FLC files.  This is a shortened and | ||||
|   modified version of gfli 1.3 (I fix some bugs with color chunks), | ||||
|   you can get the entire package from: | ||||
| 
 | ||||
|     http://www.gimp.org/	(search in the plug-ins) | ||||
|   Also, I fixed some bugs with color chunks. | ||||
| 
 | ||||
| jpeg/ | ||||
| 
 | ||||
|   Routines to load/save JPEG files.  This is a shortened version of | ||||
|   jpeg 6b, you can get the entire package from: | ||||
| 
 | ||||
|     http://www.ijg.org/ | ||||
| 
 | ||||
| libart_lgpl/ | ||||
| 
 | ||||
|   Routines to handle paths. | ||||
|   This is a shorten version of libart 2.3.3, you can get the entire | ||||
|   package from: | ||||
|   Routines to handle paths.  This is a shortened version of libart | ||||
|   2.3.3, you can get the entire package from: | ||||
| 
 | ||||
|     http://www.levien.com/libart/ | ||||
| 
 | ||||
| libgd/ | ||||
| 
 | ||||
|   Routines to manage images.  This is a shortened version of libgd | ||||
|   2.0.35, you can get the entire package from: | ||||
| 
 | ||||
|     http://www.libgd.org/ | ||||
| 
 | ||||
| libpng/ | ||||
| 
 | ||||
|   Routines to load/save PNG files. | ||||
|   This is a shorten version of libpng 1.2.20, you can get the entire | ||||
|   package from: | ||||
|   Routines to load/save PNG files.  This is a shortened version of | ||||
|   libpng 1.2.20, you can get the entire package from: | ||||
| 
 | ||||
|     http://www.libpng.org/ | ||||
| 
 | ||||
| lua/ | ||||
| 
 | ||||
|   Routines to do scripting. | ||||
|   This is a shorten version of lua 5.0, you can get the entire package | ||||
|   from: | ||||
|   Routines to do scripting. This is a shortened and modified version | ||||
|   of lua 5.0, you can get the entire package from: | ||||
| 
 | ||||
|     http://www.lua.org/ | ||||
| 
 | ||||
|   Also, this version has a patch to make the operator != works like ~= | ||||
| 
 | ||||
| zlib/ | ||||
| 
 | ||||
|   Used by libpng | ||||
|   This is a shorten version of zlib 1.2.3. | ||||
|   Used by libpng. This is a shortened version of zlib 1.2.3. | ||||
| 
 | ||||
|     http://www.zlib.net/ | ||||
| 
 | ||||
| ---------------------------------------------------------------------- | ||||
|  |  | |||
|  | @ -0,0 +1,385 @@ | |||
| The Independent JPEG Group's JPEG software | ||||
| ========================================== | ||||
| 
 | ||||
| README for release 6b of 27-Mar-1998 | ||||
| ==================================== | ||||
| 
 | ||||
| This distribution contains the sixth public release of the Independent JPEG | ||||
| Group's free JPEG software.  You are welcome to redistribute this software and | ||||
| to use it for any purpose, subject to the conditions under LEGAL ISSUES, below. | ||||
| 
 | ||||
| Serious users of this software (particularly those incorporating it into | ||||
| larger programs) should contact IJG at jpeg-info@uunet.uu.net to be added to | ||||
| our electronic mailing list.  Mailing list members are notified of updates | ||||
| and have a chance to participate in technical discussions, etc. | ||||
| 
 | ||||
| This software is the work of Tom Lane, Philip Gladstone, Jim Boucher, | ||||
| Lee Crocker, Julian Minguillon, Luis Ortiz, George Phillips, Davide Rossi, | ||||
| Guido Vollbeding, Ge' Weijers, and other members of the Independent JPEG | ||||
| Group. | ||||
| 
 | ||||
| IJG is not affiliated with the official ISO JPEG standards committee. | ||||
| 
 | ||||
| 
 | ||||
| DOCUMENTATION ROADMAP | ||||
| ===================== | ||||
| 
 | ||||
| This file contains the following sections: | ||||
| 
 | ||||
| OVERVIEW            General description of JPEG and the IJG software. | ||||
| LEGAL ISSUES        Copyright, lack of warranty, terms of distribution. | ||||
| REFERENCES          Where to learn more about JPEG. | ||||
| ARCHIVE LOCATIONS   Where to find newer versions of this software. | ||||
| RELATED SOFTWARE    Other stuff you should get. | ||||
| FILE FORMAT WARS    Software *not* to get. | ||||
| TO DO               Plans for future IJG releases. | ||||
| 
 | ||||
| Other documentation files in the distribution are: | ||||
| 
 | ||||
| User documentation: | ||||
|   install.doc       How to configure and install the IJG software. | ||||
|   usage.doc         Usage instructions for cjpeg, djpeg, jpegtran, | ||||
|                     rdjpgcom, and wrjpgcom. | ||||
|   *.1               Unix-style man pages for programs (same info as usage.doc). | ||||
|   wizard.doc        Advanced usage instructions for JPEG wizards only. | ||||
|   change.log        Version-to-version change highlights. | ||||
| Programmer and internal documentation: | ||||
|   libjpeg.doc       How to use the JPEG library in your own programs. | ||||
|   example.c         Sample code for calling the JPEG library. | ||||
|   structure.doc     Overview of the JPEG library's internal structure. | ||||
|   filelist.doc      Road map of IJG files. | ||||
|   coderules.doc     Coding style rules --- please read if you contribute code. | ||||
| 
 | ||||
| Please read at least the files install.doc and usage.doc.  Useful information | ||||
| can also be found in the JPEG FAQ (Frequently Asked Questions) article.  See | ||||
| ARCHIVE LOCATIONS below to find out where to obtain the FAQ article. | ||||
| 
 | ||||
| If you want to understand how the JPEG code works, we suggest reading one or | ||||
| more of the REFERENCES, then looking at the documentation files (in roughly | ||||
| the order listed) before diving into the code. | ||||
| 
 | ||||
| 
 | ||||
| OVERVIEW | ||||
| ======== | ||||
| 
 | ||||
| This package contains C software to implement JPEG image compression and | ||||
| decompression.  JPEG (pronounced "jay-peg") is a standardized compression | ||||
| method for full-color and gray-scale images.  JPEG is intended for compressing | ||||
| "real-world" scenes; line drawings, cartoons and other non-realistic images | ||||
| are not its strong suit.  JPEG is lossy, meaning that the output image is not | ||||
| exactly identical to the input image.  Hence you must not use JPEG if you | ||||
| have to have identical output bits.  However, on typical photographic images, | ||||
| very good compression levels can be obtained with no visible change, and | ||||
| remarkably high compression levels are possible if you can tolerate a | ||||
| low-quality image.  For more details, see the references, or just experiment | ||||
| with various compression settings. | ||||
| 
 | ||||
| This software implements JPEG baseline, extended-sequential, and progressive | ||||
| compression processes.  Provision is made for supporting all variants of these | ||||
| processes, although some uncommon parameter settings aren't implemented yet. | ||||
| For legal reasons, we are not distributing code for the arithmetic-coding | ||||
| variants of JPEG; see LEGAL ISSUES.  We have made no provision for supporting | ||||
| the hierarchical or lossless processes defined in the standard. | ||||
| 
 | ||||
| We provide a set of library routines for reading and writing JPEG image files, | ||||
| plus two sample applications "cjpeg" and "djpeg", which use the library to | ||||
| perform conversion between JPEG and some other popular image file formats. | ||||
| The library is intended to be reused in other applications. | ||||
| 
 | ||||
| In order to support file conversion and viewing software, we have included | ||||
| considerable functionality beyond the bare JPEG coding/decoding capability; | ||||
| for example, the color quantization modules are not strictly part of JPEG | ||||
| decoding, but they are essential for output to colormapped file formats or | ||||
| colormapped displays.  These extra functions can be compiled out of the | ||||
| library if not required for a particular application.  We have also included | ||||
| "jpegtran", a utility for lossless transcoding between different JPEG | ||||
| processes, and "rdjpgcom" and "wrjpgcom", two simple applications for | ||||
| inserting and extracting textual comments in JFIF files. | ||||
| 
 | ||||
| The emphasis in designing this software has been on achieving portability and | ||||
| flexibility, while also making it fast enough to be useful.  In particular, | ||||
| the software is not intended to be read as a tutorial on JPEG.  (See the | ||||
| REFERENCES section for introductory material.)  Rather, it is intended to | ||||
| be reliable, portable, industrial-strength code.  We do not claim to have | ||||
| achieved that goal in every aspect of the software, but we strive for it. | ||||
| 
 | ||||
| We welcome the use of this software as a component of commercial products. | ||||
| No royalty is required, but we do ask for an acknowledgement in product | ||||
| documentation, as described under LEGAL ISSUES. | ||||
| 
 | ||||
| 
 | ||||
| LEGAL ISSUES | ||||
| ============ | ||||
| 
 | ||||
| In plain English: | ||||
| 
 | ||||
| 1. We don't promise that this software works.  (But if you find any bugs, | ||||
|    please let us know!) | ||||
| 2. You can use this software for whatever you want.  You don't have to pay us. | ||||
| 3. You may not pretend that you wrote this software.  If you use it in a | ||||
|    program, you must acknowledge somewhere in your documentation that | ||||
|    you've used the IJG code. | ||||
| 
 | ||||
| In legalese: | ||||
| 
 | ||||
| The authors make NO WARRANTY or representation, either express or implied, | ||||
| with respect to this software, its quality, accuracy, merchantability, or | ||||
| fitness for a particular purpose.  This software is provided "AS IS", and you, | ||||
| its user, assume the entire risk as to its quality and accuracy. | ||||
| 
 | ||||
| This software is copyright (C) 1991-1998, Thomas G. Lane. | ||||
| All Rights Reserved except as specified below. | ||||
| 
 | ||||
| Permission is hereby granted to use, copy, modify, and distribute this | ||||
| software (or portions thereof) for any purpose, without fee, subject to these | ||||
| conditions: | ||||
| (1) If any part of the source code for this software is distributed, then this | ||||
| README file must be included, with this copyright and no-warranty notice | ||||
| unaltered; and any additions, deletions, or changes to the original files | ||||
| must be clearly indicated in accompanying documentation. | ||||
| (2) If only executable code is distributed, then the accompanying | ||||
| documentation must state that "this software is based in part on the work of | ||||
| the Independent JPEG Group". | ||||
| (3) Permission for use of this software is granted only if the user accepts | ||||
| full responsibility for any undesirable consequences; the authors accept | ||||
| NO LIABILITY for damages of any kind. | ||||
| 
 | ||||
| These conditions apply to any software derived from or based on the IJG code, | ||||
| not just to the unmodified library.  If you use our work, you ought to | ||||
| acknowledge us. | ||||
| 
 | ||||
| Permission is NOT granted for the use of any IJG author's name or company name | ||||
| in advertising or publicity relating to this software or products derived from | ||||
| it.  This software may be referred to only as "the Independent JPEG Group's | ||||
| software". | ||||
| 
 | ||||
| We specifically permit and encourage the use of this software as the basis of | ||||
| commercial products, provided that all warranty or liability claims are | ||||
| assumed by the product vendor. | ||||
| 
 | ||||
| 
 | ||||
| ansi2knr.c is included in this distribution by permission of L. Peter Deutsch, | ||||
| sole proprietor of its copyright holder, Aladdin Enterprises of Menlo Park, CA. | ||||
| ansi2knr.c is NOT covered by the above copyright and conditions, but instead | ||||
| by the usual distribution terms of the Free Software Foundation; principally, | ||||
| that you must include source code if you redistribute it.  (See the file | ||||
| ansi2knr.c for full details.)  However, since ansi2knr.c is not needed as part | ||||
| of any program generated from the IJG code, this does not limit you more than | ||||
| the foregoing paragraphs do. | ||||
| 
 | ||||
| The Unix configuration script "configure" was produced with GNU Autoconf. | ||||
| It is copyright by the Free Software Foundation but is freely distributable. | ||||
| The same holds for its supporting scripts (config.guess, config.sub, | ||||
| ltconfig, ltmain.sh).  Another support script, install-sh, is copyright | ||||
| by M.I.T. but is also freely distributable. | ||||
| 
 | ||||
| It appears that the arithmetic coding option of the JPEG spec is covered by | ||||
| patents owned by IBM, AT&T, and Mitsubishi.  Hence arithmetic coding cannot | ||||
| legally be used without obtaining one or more licenses.  For this reason, | ||||
| support for arithmetic coding has been removed from the free JPEG software. | ||||
| (Since arithmetic coding provides only a marginal gain over the unpatented | ||||
| Huffman mode, it is unlikely that very many implementations will support it.) | ||||
| So far as we are aware, there are no patent restrictions on the remaining | ||||
| code. | ||||
| 
 | ||||
| The IJG distribution formerly included code to read and write GIF files. | ||||
| To avoid entanglement with the Unisys LZW patent, GIF reading support has | ||||
| been removed altogether, and the GIF writer has been simplified to produce | ||||
| "uncompressed GIFs".  This technique does not use the LZW algorithm; the | ||||
| resulting GIF files are larger than usual, but are readable by all standard | ||||
| GIF decoders. | ||||
| 
 | ||||
| We are required to state that | ||||
|     "The Graphics Interchange Format(c) is the Copyright property of | ||||
|     CompuServe Incorporated.  GIF(sm) is a Service Mark property of | ||||
|     CompuServe Incorporated." | ||||
| 
 | ||||
| 
 | ||||
| REFERENCES | ||||
| ========== | ||||
| 
 | ||||
| We highly recommend reading one or more of these references before trying to | ||||
| understand the innards of the JPEG software. | ||||
| 
 | ||||
| The best short technical introduction to the JPEG compression algorithm is | ||||
| 	Wallace, Gregory K.  "The JPEG Still Picture Compression Standard", | ||||
| 	Communications of the ACM, April 1991 (vol. 34 no. 4), pp. 30-44. | ||||
| (Adjacent articles in that issue discuss MPEG motion picture compression, | ||||
| applications of JPEG, and related topics.)  If you don't have the CACM issue | ||||
| handy, a PostScript file containing a revised version of Wallace's article is | ||||
| available at ftp://ftp.uu.net/graphics/jpeg/wallace.ps.gz.  The file (actually | ||||
| a preprint for an article that appeared in IEEE Trans. Consumer Electronics) | ||||
| omits the sample images that appeared in CACM, but it includes corrections | ||||
| and some added material.  Note: the Wallace article is copyright ACM and IEEE, | ||||
| and it may not be used for commercial purposes. | ||||
| 
 | ||||
| A somewhat less technical, more leisurely introduction to JPEG can be found in | ||||
| "The Data Compression Book" by Mark Nelson and Jean-loup Gailly, published by | ||||
| M&T Books (New York), 2nd ed. 1996, ISBN 1-55851-434-1.  This book provides | ||||
| good explanations and example C code for a multitude of compression methods | ||||
| including JPEG.  It is an excellent source if you are comfortable reading C | ||||
| code but don't know much about data compression in general.  The book's JPEG | ||||
| sample code is far from industrial-strength, but when you are ready to look | ||||
| at a full implementation, you've got one here... | ||||
| 
 | ||||
| The best full description of JPEG is the textbook "JPEG Still Image Data | ||||
| Compression Standard" by William B. Pennebaker and Joan L. Mitchell, published | ||||
| by Van Nostrand Reinhold, 1993, ISBN 0-442-01272-1.  Price US$59.95, 638 pp. | ||||
| The book includes the complete text of the ISO JPEG standards (DIS 10918-1 | ||||
| and draft DIS 10918-2).  This is by far the most complete exposition of JPEG | ||||
| in existence, and we highly recommend it. | ||||
| 
 | ||||
| The JPEG standard itself is not available electronically; you must order a | ||||
| paper copy through ISO or ITU.  (Unless you feel a need to own a certified | ||||
| official copy, we recommend buying the Pennebaker and Mitchell book instead; | ||||
| it's much cheaper and includes a great deal of useful explanatory material.) | ||||
| In the USA, copies of the standard may be ordered from ANSI Sales at (212) | ||||
| 642-4900, or from Global Engineering Documents at (800) 854-7179.  (ANSI | ||||
| doesn't take credit card orders, but Global does.)  It's not cheap: as of | ||||
| 1992, ANSI was charging $95 for Part 1 and $47 for Part 2, plus 7% | ||||
| shipping/handling.  The standard is divided into two parts, Part 1 being the | ||||
| actual specification, while Part 2 covers compliance testing methods.  Part 1 | ||||
| is titled "Digital Compression and Coding of Continuous-tone Still Images, | ||||
| Part 1: Requirements and guidelines" and has document numbers ISO/IEC IS | ||||
| 10918-1, ITU-T T.81.  Part 2 is titled "Digital Compression and Coding of | ||||
| Continuous-tone Still Images, Part 2: Compliance testing" and has document | ||||
| numbers ISO/IEC IS 10918-2, ITU-T T.83. | ||||
| 
 | ||||
| Some extensions to the original JPEG standard are defined in JPEG Part 3, | ||||
| a newer ISO standard numbered ISO/IEC IS 10918-3 and ITU-T T.84.  IJG | ||||
| currently does not support any Part 3 extensions. | ||||
| 
 | ||||
| The JPEG standard does not specify all details of an interchangeable file | ||||
| format.  For the omitted details we follow the "JFIF" conventions, revision | ||||
| 1.02.  A copy of the JFIF spec is available from: | ||||
| 	Literature Department | ||||
| 	C-Cube Microsystems, Inc. | ||||
| 	1778 McCarthy Blvd. | ||||
| 	Milpitas, CA 95035 | ||||
| 	phone (408) 944-6300,  fax (408) 944-6314 | ||||
| A PostScript version of this document is available by FTP at | ||||
| ftp://ftp.uu.net/graphics/jpeg/jfif.ps.gz.  There is also a plain text | ||||
| version at ftp://ftp.uu.net/graphics/jpeg/jfif.txt.gz, but it is missing | ||||
| the figures. | ||||
| 
 | ||||
| The TIFF 6.0 file format specification can be obtained by FTP from | ||||
| ftp://ftp.sgi.com/graphics/tiff/TIFF6.ps.gz.  The JPEG incorporation scheme | ||||
| found in the TIFF 6.0 spec of 3-June-92 has a number of serious problems. | ||||
| IJG does not recommend use of the TIFF 6.0 design (TIFF Compression tag 6). | ||||
| Instead, we recommend the JPEG design proposed by TIFF Technical Note #2 | ||||
| (Compression tag 7).  Copies of this Note can be obtained from ftp.sgi.com or | ||||
| from ftp://ftp.uu.net/graphics/jpeg/.  It is expected that the next revision | ||||
| of the TIFF spec will replace the 6.0 JPEG design with the Note's design. | ||||
| Although IJG's own code does not support TIFF/JPEG, the free libtiff library | ||||
| uses our library to implement TIFF/JPEG per the Note.  libtiff is available | ||||
| from ftp://ftp.sgi.com/graphics/tiff/. | ||||
| 
 | ||||
| 
 | ||||
| ARCHIVE LOCATIONS | ||||
| ================= | ||||
| 
 | ||||
| The "official" archive site for this software is ftp.uu.net (Internet | ||||
| address 192.48.96.9).  The most recent released version can always be found | ||||
| there in directory graphics/jpeg.  This particular version will be archived | ||||
| as ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz.  If you don't have | ||||
| direct Internet access, UUNET's archives are also available via UUCP; contact | ||||
| help@uunet.uu.net for information on retrieving files that way. | ||||
| 
 | ||||
| Numerous Internet sites maintain copies of the UUNET files.  However, only | ||||
| ftp.uu.net is guaranteed to have the latest official version. | ||||
| 
 | ||||
| You can also obtain this software in DOS-compatible "zip" archive format from | ||||
| the SimTel archives (ftp://ftp.simtel.net/pub/simtelnet/msdos/graphics/), or | ||||
| on CompuServe in the Graphics Support forum (GO CIS:GRAPHSUP), library 12 | ||||
| "JPEG Tools".  Again, these versions may sometimes lag behind the ftp.uu.net | ||||
| release. | ||||
| 
 | ||||
| The JPEG FAQ (Frequently Asked Questions) article is a useful source of | ||||
| general information about JPEG.  It is updated constantly and therefore is | ||||
| not included in this distribution.  The FAQ is posted every two weeks to | ||||
| Usenet newsgroups comp.graphics.misc, news.answers, and other groups. | ||||
| It is available on the World Wide Web at http://www.faqs.org/faqs/jpeg-faq/ | ||||
| and other news.answers archive sites, including the official news.answers | ||||
| archive at rtfm.mit.edu: ftp://rtfm.mit.edu/pub/usenet/news.answers/jpeg-faq/. | ||||
| If you don't have Web or FTP access, send e-mail to mail-server@rtfm.mit.edu | ||||
| with body | ||||
| 	send usenet/news.answers/jpeg-faq/part1 | ||||
| 	send usenet/news.answers/jpeg-faq/part2 | ||||
| 
 | ||||
| 
 | ||||
| RELATED SOFTWARE | ||||
| ================ | ||||
| 
 | ||||
| Numerous viewing and image manipulation programs now support JPEG.  (Quite a | ||||
| few of them use this library to do so.)  The JPEG FAQ described above lists | ||||
| some of the more popular free and shareware viewers, and tells where to | ||||
| obtain them on Internet. | ||||
| 
 | ||||
| If you are on a Unix machine, we highly recommend Jef Poskanzer's free | ||||
| PBMPLUS software, which provides many useful operations on PPM-format image | ||||
| files.  In particular, it can convert PPM images to and from a wide range of | ||||
| other formats, thus making cjpeg/djpeg considerably more useful.  The latest | ||||
| version is distributed by the NetPBM group, and is available from numerous | ||||
| sites, notably ftp://wuarchive.wustl.edu/graphics/graphics/packages/NetPBM/. | ||||
| Unfortunately PBMPLUS/NETPBM is not nearly as portable as the IJG software is; | ||||
| you are likely to have difficulty making it work on any non-Unix machine. | ||||
| 
 | ||||
| A different free JPEG implementation, written by the PVRG group at Stanford, | ||||
| is available from ftp://havefun.stanford.edu/pub/jpeg/.  This program | ||||
| is designed for research and experimentation rather than production use; | ||||
| it is slower, harder to use, and less portable than the IJG code, but it | ||||
| is easier to read and modify.  Also, the PVRG code supports lossless JPEG, | ||||
| which we do not.  (On the other hand, it doesn't do progressive JPEG.) | ||||
| 
 | ||||
| 
 | ||||
| FILE FORMAT WARS | ||||
| ================ | ||||
| 
 | ||||
| Some JPEG programs produce files that are not compatible with our library. | ||||
| The root of the problem is that the ISO JPEG committee failed to specify a | ||||
| concrete file format.  Some vendors "filled in the blanks" on their own, | ||||
| creating proprietary formats that no one else could read.  (For example, none | ||||
| of the early commercial JPEG implementations for the Macintosh were able to | ||||
| exchange compressed files.) | ||||
| 
 | ||||
| The file format we have adopted is called JFIF (see REFERENCES).  This format | ||||
| has been agreed to by a number of major commercial JPEG vendors, and it has | ||||
| become the de facto standard.  JFIF is a minimal or "low end" representation. | ||||
| We recommend the use of TIFF/JPEG (TIFF revision 6.0 as modified by TIFF | ||||
| Technical Note #2) for "high end" applications that need to record a lot of | ||||
| additional data about an image.  TIFF/JPEG is fairly new and not yet widely | ||||
| supported, unfortunately. | ||||
| 
 | ||||
| The upcoming JPEG Part 3 standard defines a file format called SPIFF. | ||||
| SPIFF is interoperable with JFIF, in the sense that most JFIF decoders should | ||||
| be able to read the most common variant of SPIFF.  SPIFF has some technical | ||||
| advantages over JFIF, but its major claim to fame is simply that it is an | ||||
| official standard rather than an informal one.  At this point it is unclear | ||||
| whether SPIFF will supersede JFIF or whether JFIF will remain the de-facto | ||||
| standard.  IJG intends to support SPIFF once the standard is frozen, but we | ||||
| have not decided whether it should become our default output format or not. | ||||
| (In any case, our decoder will remain capable of reading JFIF indefinitely.) | ||||
| 
 | ||||
| Various proprietary file formats incorporating JPEG compression also exist. | ||||
| We have little or no sympathy for the existence of these formats.  Indeed, | ||||
| one of the original reasons for developing this free software was to help | ||||
| force convergence on common, open format standards for JPEG files.  Don't | ||||
| use a proprietary file format! | ||||
| 
 | ||||
| 
 | ||||
| TO DO | ||||
| ===== | ||||
| 
 | ||||
| The major thrust for v7 will probably be improvement of visual quality. | ||||
| The current method for scaling the quantization tables is known not to be | ||||
| very good at low Q values.  We also intend to investigate block boundary | ||||
| smoothing, "poor man's variable quantization", and other means of improving | ||||
| quality-vs-file-size performance without sacrificing compatibility. | ||||
| 
 | ||||
| In future versions, we are considering supporting some of the upcoming JPEG | ||||
| Part 3 extensions --- principally, variable quantization and the SPIFF file | ||||
| format. | ||||
| 
 | ||||
| As always, speeding things up is of great interest. | ||||
| 
 | ||||
| Please send bug reports, offers of help, etc. to jpeg-info@uunet.uu.net. | ||||
|  | @ -0,0 +1,132 @@ | |||
| /*
 | ||||
|  * cderror.h | ||||
|  * | ||||
|  * Copyright (C) 1994-1997, 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 defines the error and message codes for the cjpeg/djpeg | ||||
|  * applications.  These strings are not needed as part of the JPEG library | ||||
|  * proper. | ||||
|  * Edit this file to add new codes, or to translate the message strings to | ||||
|  * some other language. | ||||
|  */ | ||||
| 
 | ||||
| /*
 | ||||
|  * To define the enum list of message codes, include this file without | ||||
|  * defining macro JMESSAGE.  To create a message string table, include it | ||||
|  * again with a suitable JMESSAGE definition (see jerror.c for an example). | ||||
|  */ | ||||
| #ifndef JMESSAGE | ||||
| #ifndef CDERROR_H | ||||
| #define CDERROR_H | ||||
| /* First time through, define the enum list */ | ||||
| #define JMAKE_ENUM_LIST | ||||
| #else | ||||
| /* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */ | ||||
| #define JMESSAGE(code,string) | ||||
| #endif /* CDERROR_H */ | ||||
| #endif /* JMESSAGE */ | ||||
| 
 | ||||
| #ifdef JMAKE_ENUM_LIST | ||||
| 
 | ||||
| typedef enum { | ||||
| 
 | ||||
| #define JMESSAGE(code,string)	code , | ||||
| 
 | ||||
| #endif /* JMAKE_ENUM_LIST */ | ||||
| 
 | ||||
| JMESSAGE(JMSG_FIRSTADDONCODE=1000, NULL) /* Must be first entry! */ | ||||
| 
 | ||||
| #ifdef BMP_SUPPORTED | ||||
| JMESSAGE(JERR_BMP_BADCMAP, "Unsupported BMP colormap format") | ||||
| JMESSAGE(JERR_BMP_BADDEPTH, "Only 8- and 24-bit BMP files are supported") | ||||
| JMESSAGE(JERR_BMP_BADHEADER, "Invalid BMP file: bad header length") | ||||
| JMESSAGE(JERR_BMP_BADPLANES, "Invalid BMP file: biPlanes not equal to 1") | ||||
| JMESSAGE(JERR_BMP_COLORSPACE, "BMP output must be grayscale or RGB") | ||||
| JMESSAGE(JERR_BMP_COMPRESSED, "Sorry, compressed BMPs not yet supported") | ||||
| JMESSAGE(JERR_BMP_NOT, "Not a BMP file - does not start with BM") | ||||
| JMESSAGE(JTRC_BMP, "%ux%u 24-bit BMP image") | ||||
| JMESSAGE(JTRC_BMP_MAPPED, "%ux%u 8-bit colormapped BMP image") | ||||
| JMESSAGE(JTRC_BMP_OS2, "%ux%u 24-bit OS2 BMP image") | ||||
| JMESSAGE(JTRC_BMP_OS2_MAPPED, "%ux%u 8-bit colormapped OS2 BMP image") | ||||
| #endif /* BMP_SUPPORTED */ | ||||
| 
 | ||||
| #ifdef GIF_SUPPORTED | ||||
| JMESSAGE(JERR_GIF_BUG, "GIF output got confused") | ||||
| JMESSAGE(JERR_GIF_CODESIZE, "Bogus GIF codesize %d") | ||||
| JMESSAGE(JERR_GIF_COLORSPACE, "GIF output must be grayscale or RGB") | ||||
| JMESSAGE(JERR_GIF_IMAGENOTFOUND, "Too few images in GIF file") | ||||
| JMESSAGE(JERR_GIF_NOT, "Not a GIF file") | ||||
| JMESSAGE(JTRC_GIF, "%ux%ux%d GIF image") | ||||
| JMESSAGE(JTRC_GIF_BADVERSION, | ||||
| 	 "Warning: unexpected GIF version number '%c%c%c'") | ||||
| JMESSAGE(JTRC_GIF_EXTENSION, "Ignoring GIF extension block of type 0x%02x") | ||||
| JMESSAGE(JTRC_GIF_NONSQUARE, "Caution: nonsquare pixels in input") | ||||
| JMESSAGE(JWRN_GIF_BADDATA, "Corrupt data in GIF file") | ||||
| JMESSAGE(JWRN_GIF_CHAR, "Bogus char 0x%02x in GIF file, ignoring") | ||||
| JMESSAGE(JWRN_GIF_ENDCODE, "Premature end of GIF image") | ||||
| JMESSAGE(JWRN_GIF_NOMOREDATA, "Ran out of GIF bits") | ||||
| #endif /* GIF_SUPPORTED */ | ||||
| 
 | ||||
| #ifdef PPM_SUPPORTED | ||||
| JMESSAGE(JERR_PPM_COLORSPACE, "PPM output must be grayscale or RGB") | ||||
| JMESSAGE(JERR_PPM_NONNUMERIC, "Nonnumeric data in PPM file") | ||||
| JMESSAGE(JERR_PPM_NOT, "Not a PPM/PGM file") | ||||
| JMESSAGE(JTRC_PGM, "%ux%u PGM image") | ||||
| JMESSAGE(JTRC_PGM_TEXT, "%ux%u text PGM image") | ||||
| JMESSAGE(JTRC_PPM, "%ux%u PPM image") | ||||
| JMESSAGE(JTRC_PPM_TEXT, "%ux%u text PPM image") | ||||
| #endif /* PPM_SUPPORTED */ | ||||
| 
 | ||||
| #ifdef RLE_SUPPORTED | ||||
| JMESSAGE(JERR_RLE_BADERROR, "Bogus error code from RLE library") | ||||
| JMESSAGE(JERR_RLE_COLORSPACE, "RLE output must be grayscale or RGB") | ||||
| JMESSAGE(JERR_RLE_DIMENSIONS, "Image dimensions (%ux%u) too large for RLE") | ||||
| JMESSAGE(JERR_RLE_EMPTY, "Empty RLE file") | ||||
| JMESSAGE(JERR_RLE_EOF, "Premature EOF in RLE header") | ||||
| JMESSAGE(JERR_RLE_MEM, "Insufficient memory for RLE header") | ||||
| JMESSAGE(JERR_RLE_NOT, "Not an RLE file") | ||||
| JMESSAGE(JERR_RLE_TOOMANYCHANNELS, "Cannot handle %d output channels for RLE") | ||||
| JMESSAGE(JERR_RLE_UNSUPPORTED, "Cannot handle this RLE setup") | ||||
| JMESSAGE(JTRC_RLE, "%ux%u full-color RLE file") | ||||
| JMESSAGE(JTRC_RLE_FULLMAP, "%ux%u full-color RLE file with map of length %d") | ||||
| JMESSAGE(JTRC_RLE_GRAY, "%ux%u grayscale RLE file") | ||||
| JMESSAGE(JTRC_RLE_MAPGRAY, "%ux%u grayscale RLE file with map of length %d") | ||||
| JMESSAGE(JTRC_RLE_MAPPED, "%ux%u colormapped RLE file with map of length %d") | ||||
| #endif /* RLE_SUPPORTED */ | ||||
| 
 | ||||
| #ifdef TARGA_SUPPORTED | ||||
| JMESSAGE(JERR_TGA_BADCMAP, "Unsupported Targa colormap format") | ||||
| JMESSAGE(JERR_TGA_BADPARMS, "Invalid or unsupported Targa file") | ||||
| JMESSAGE(JERR_TGA_COLORSPACE, "Targa output must be grayscale or RGB") | ||||
| JMESSAGE(JTRC_TGA, "%ux%u RGB Targa image") | ||||
| JMESSAGE(JTRC_TGA_GRAY, "%ux%u grayscale Targa image") | ||||
| JMESSAGE(JTRC_TGA_MAPPED, "%ux%u colormapped Targa image") | ||||
| #else | ||||
| JMESSAGE(JERR_TGA_NOTCOMP, "Targa support was not compiled") | ||||
| #endif /* TARGA_SUPPORTED */ | ||||
| 
 | ||||
| JMESSAGE(JERR_BAD_CMAP_FILE, | ||||
| 	 "Color map file is invalid or of unsupported format") | ||||
| JMESSAGE(JERR_TOO_MANY_COLORS, | ||||
| 	 "Output file format cannot handle %d colormap entries") | ||||
| JMESSAGE(JERR_UNGETC_FAILED, "ungetc failed") | ||||
| #ifdef TARGA_SUPPORTED | ||||
| JMESSAGE(JERR_UNKNOWN_FORMAT, | ||||
| 	 "Unrecognized input file format --- perhaps you need -targa") | ||||
| #else | ||||
| JMESSAGE(JERR_UNKNOWN_FORMAT, "Unrecognized input file format") | ||||
| #endif | ||||
| JMESSAGE(JERR_UNSUPPORTED_FORMAT, "Unsupported output file format") | ||||
| 
 | ||||
| #ifdef JMAKE_ENUM_LIST | ||||
| 
 | ||||
|   JMSG_LASTADDONCODE | ||||
| } ADDON_MESSAGE_CODE; | ||||
| 
 | ||||
| #undef JMAKE_ENUM_LIST | ||||
| #endif /* JMAKE_ENUM_LIST */ | ||||
| 
 | ||||
| /* Zap JMESSAGE macro so that future re-inclusions do nothing by default */ | ||||
| #undef JMESSAGE | ||||
|  | @ -0,0 +1,181 @@ | |||
| /*
 | ||||
|  * cdjpeg.c | ||||
|  * | ||||
|  * Copyright (C) 1991-1997, 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 common support routines used by the IJG application | ||||
|  * programs (cjpeg, djpeg, jpegtran). | ||||
|  */ | ||||
| 
 | ||||
| #include "cdjpeg.h"		/* Common decls for cjpeg/djpeg applications */ | ||||
| #include <ctype.h>		/* to declare isupper(), tolower() */ | ||||
| #ifdef NEED_SIGNAL_CATCHER | ||||
| #include <signal.h>		/* to declare signal() */ | ||||
| #endif | ||||
| #ifdef USE_SETMODE | ||||
| #include <fcntl.h>		/* to declare setmode()'s parameter macros */ | ||||
| /* If you have setmode() but not <io.h>, just delete this line: */ | ||||
| #include <io.h>			/* to declare setmode() */ | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Signal catcher to ensure that temporary files are removed before aborting. | ||||
|  * NB: for Amiga Manx C this is actually a global routine named _abort(); | ||||
|  * we put "#define signal_catcher _abort" in jconfig.h.  Talk about bogus... | ||||
|  */ | ||||
| 
 | ||||
| #ifdef NEED_SIGNAL_CATCHER | ||||
| 
 | ||||
| static j_common_ptr sig_cinfo; | ||||
| 
 | ||||
| void				/* must be global for Manx C */ | ||||
| signal_catcher (int signum) | ||||
| { | ||||
|   if (sig_cinfo != NULL) { | ||||
|     if (sig_cinfo->err != NULL) /* turn off trace output */ | ||||
|       sig_cinfo->err->trace_level = 0; | ||||
|     jpeg_destroy(sig_cinfo);	/* clean up memory allocation & temp files */ | ||||
|   } | ||||
|   exit(EXIT_FAILURE); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| enable_signal_catcher (j_common_ptr cinfo) | ||||
| { | ||||
|   sig_cinfo = cinfo; | ||||
| #ifdef SIGINT			/* not all systems have SIGINT */ | ||||
|   signal(SIGINT, signal_catcher); | ||||
| #endif | ||||
| #ifdef SIGTERM			/* not all systems have SIGTERM */ | ||||
|   signal(SIGTERM, signal_catcher); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Optional progress monitor: display a percent-done figure on stderr. | ||||
|  */ | ||||
| 
 | ||||
| #ifdef PROGRESS_REPORT | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| progress_monitor (j_common_ptr cinfo) | ||||
| { | ||||
|   cd_progress_ptr prog = (cd_progress_ptr) cinfo->progress; | ||||
|   int total_passes = prog->pub.total_passes + prog->total_extra_passes; | ||||
|   int percent_done = (int) (prog->pub.pass_counter*100L/prog->pub.pass_limit); | ||||
| 
 | ||||
|   if (percent_done != prog->percent_done) { | ||||
|     prog->percent_done = percent_done; | ||||
|     if (total_passes > 1) { | ||||
|       fprintf(stderr, "\rPass %d/%d: %3d%% ", | ||||
| 	      prog->pub.completed_passes + prog->completed_extra_passes + 1, | ||||
| 	      total_passes, percent_done); | ||||
|     } else { | ||||
|       fprintf(stderr, "\r %3d%% ", percent_done); | ||||
|     } | ||||
|     fflush(stderr); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| start_progress_monitor (j_common_ptr cinfo, cd_progress_ptr progress) | ||||
| { | ||||
|   /* Enable progress display, unless trace output is on */ | ||||
|   if (cinfo->err->trace_level == 0) { | ||||
|     progress->pub.progress_monitor = progress_monitor; | ||||
|     progress->completed_extra_passes = 0; | ||||
|     progress->total_extra_passes = 0; | ||||
|     progress->percent_done = -1; | ||||
|     cinfo->progress = &progress->pub; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| end_progress_monitor (j_common_ptr cinfo) | ||||
| { | ||||
|   /* Clear away progress display */ | ||||
|   if (cinfo->err->trace_level == 0) { | ||||
|     fprintf(stderr, "\r                \r"); | ||||
|     fflush(stderr); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Case-insensitive matching of possibly-abbreviated keyword switches. | ||||
|  * keyword is the constant keyword (must be lower case already), | ||||
|  * minchars is length of minimum legal abbreviation. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(boolean) | ||||
| keymatch (char * arg, const char * keyword, int minchars) | ||||
| { | ||||
|   register int ca, ck; | ||||
|   register int nmatched = 0; | ||||
| 
 | ||||
|   while ((ca = *arg++) != '\0') { | ||||
|     if ((ck = *keyword++) == '\0') | ||||
|       return FALSE;		/* arg longer than keyword, no good */ | ||||
|     if (isupper(ca))		/* force arg to lcase (assume ck is already) */ | ||||
|       ca = tolower(ca); | ||||
|     if (ca != ck) | ||||
|       return FALSE;		/* no good */ | ||||
|     nmatched++;			/* count matched characters */ | ||||
|   } | ||||
|   /* reached end of argument; fail if it's too short for unique abbrev */ | ||||
|   if (nmatched < minchars) | ||||
|     return FALSE; | ||||
|   return TRUE;			/* A-OK */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Routines to establish binary I/O mode for stdin and stdout. | ||||
|  * Non-Unix systems often require some hacking to get out of text mode. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(FILE *) | ||||
| read_stdin (void) | ||||
| { | ||||
|   FILE * input_file = stdin; | ||||
| 
 | ||||
| #ifdef USE_SETMODE		/* need to hack file mode? */ | ||||
|   setmode(fileno(stdin), O_BINARY); | ||||
| #endif | ||||
| #ifdef USE_FDOPEN		/* need to re-open in binary mode? */ | ||||
|   if ((input_file = fdopen(fileno(stdin), READ_BINARY)) == NULL) { | ||||
|     fprintf(stderr, "Cannot reopen stdin\n"); | ||||
|     exit(EXIT_FAILURE); | ||||
|   } | ||||
| #endif | ||||
|   return input_file; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GLOBAL(FILE *) | ||||
| write_stdout (void) | ||||
| { | ||||
|   FILE * output_file = stdout; | ||||
| 
 | ||||
| #ifdef USE_SETMODE		/* need to hack file mode? */ | ||||
|   setmode(fileno(stdout), O_BINARY); | ||||
| #endif | ||||
| #ifdef USE_FDOPEN		/* need to re-open in binary mode? */ | ||||
|   if ((output_file = fdopen(fileno(stdout), WRITE_BINARY)) == NULL) { | ||||
|     fprintf(stderr, "Cannot reopen stdout\n"); | ||||
|     exit(EXIT_FAILURE); | ||||
|   } | ||||
| #endif | ||||
|   return output_file; | ||||
| } | ||||
|  | @ -0,0 +1,184 @@ | |||
| /*
 | ||||
|  * cdjpeg.h | ||||
|  * | ||||
|  * Copyright (C) 1994-1997, 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 common declarations for the sample applications | ||||
|  * cjpeg and djpeg.  It is NOT used by the core JPEG library. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_CJPEG_DJPEG	/* define proper options in jconfig.h */ | ||||
| #define JPEG_INTERNAL_OPTIONS	/* cjpeg.c,djpeg.c need to see xxx_SUPPORTED */ | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| #include "jerror.h"		/* get library error codes too */ | ||||
| #include "cderror.h"		/* get application-specific error codes */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Object interface for cjpeg's source file decoding modules | ||||
|  */ | ||||
| 
 | ||||
| typedef struct cjpeg_source_struct * cjpeg_source_ptr; | ||||
| 
 | ||||
| struct cjpeg_source_struct { | ||||
|   JMETHOD(void, start_input, (j_compress_ptr cinfo, | ||||
| 			      cjpeg_source_ptr sinfo)); | ||||
|   JMETHOD(JDIMENSION, get_pixel_rows, (j_compress_ptr cinfo, | ||||
| 				       cjpeg_source_ptr sinfo)); | ||||
|   JMETHOD(void, finish_input, (j_compress_ptr cinfo, | ||||
| 			       cjpeg_source_ptr sinfo)); | ||||
| 
 | ||||
|   FILE *input_file; | ||||
| 
 | ||||
|   JSAMPARRAY buffer; | ||||
|   JDIMENSION buffer_height; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Object interface for djpeg's output file encoding modules | ||||
|  */ | ||||
| 
 | ||||
| typedef struct djpeg_dest_struct * djpeg_dest_ptr; | ||||
| 
 | ||||
| struct djpeg_dest_struct { | ||||
|   /* start_output is called after jpeg_start_decompress finishes.
 | ||||
|    * The color map will be ready at this time, if one is needed. | ||||
|    */ | ||||
|   JMETHOD(void, start_output, (j_decompress_ptr cinfo, | ||||
| 			       djpeg_dest_ptr dinfo)); | ||||
|   /* Emit the specified number of pixel rows from the buffer. */ | ||||
|   JMETHOD(void, put_pixel_rows, (j_decompress_ptr cinfo, | ||||
| 				 djpeg_dest_ptr dinfo, | ||||
| 				 JDIMENSION rows_supplied)); | ||||
|   /* Finish up at the end of the image. */ | ||||
|   JMETHOD(void, finish_output, (j_decompress_ptr cinfo, | ||||
| 				djpeg_dest_ptr dinfo)); | ||||
| 
 | ||||
|   /* Target file spec; filled in by djpeg.c after object is created. */ | ||||
|   FILE * output_file; | ||||
| 
 | ||||
|   /* Output pixel-row buffer.  Created by module init or start_output.
 | ||||
|    * Width is cinfo->output_width * cinfo->output_components; | ||||
|    * height is buffer_height. | ||||
|    */ | ||||
|   JSAMPARRAY buffer; | ||||
|   JDIMENSION buffer_height; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * cjpeg/djpeg may need to perform extra passes to convert to or from | ||||
|  * the source/destination file format.  The JPEG library does not know | ||||
|  * about these passes, but we'd like them to be counted by the progress | ||||
|  * monitor.  We use an expanded progress monitor object to hold the | ||||
|  * additional pass count. | ||||
|  */ | ||||
| 
 | ||||
| struct cdjpeg_progress_mgr { | ||||
|   struct jpeg_progress_mgr pub;	/* fields known to JPEG library */ | ||||
|   int completed_extra_passes;	/* extra passes completed */ | ||||
|   int total_extra_passes;	/* total extra */ | ||||
|   /* last printed percentage stored here to avoid multiple printouts */ | ||||
|   int percent_done; | ||||
| }; | ||||
| 
 | ||||
| typedef struct cdjpeg_progress_mgr * cd_progress_ptr; | ||||
| 
 | ||||
| 
 | ||||
| /* Short forms of external names for systems with brain-damaged linkers. */ | ||||
| 
 | ||||
| #ifdef NEED_SHORT_EXTERNAL_NAMES | ||||
| #define jinit_read_bmp		jIRdBMP | ||||
| #define jinit_write_bmp		jIWrBMP | ||||
| #define jinit_read_gif		jIRdGIF | ||||
| #define jinit_write_gif		jIWrGIF | ||||
| #define jinit_read_ppm		jIRdPPM | ||||
| #define jinit_write_ppm		jIWrPPM | ||||
| #define jinit_read_rle		jIRdRLE | ||||
| #define jinit_write_rle		jIWrRLE | ||||
| #define jinit_read_targa	jIRdTarga | ||||
| #define jinit_write_targa	jIWrTarga | ||||
| #define read_quant_tables	RdQTables | ||||
| #define read_scan_script	RdScnScript | ||||
| #define set_quant_slots		SetQSlots | ||||
| #define set_sample_factors	SetSFacts | ||||
| #define read_color_map		RdCMap | ||||
| #define enable_signal_catcher	EnSigCatcher | ||||
| #define start_progress_monitor	StProgMon | ||||
| #define end_progress_monitor	EnProgMon | ||||
| #define read_stdin		RdStdin | ||||
| #define write_stdout		WrStdout | ||||
| #endif /* NEED_SHORT_EXTERNAL_NAMES */ | ||||
| 
 | ||||
| /* Module selection routines for I/O modules. */ | ||||
| 
 | ||||
| EXTERN(cjpeg_source_ptr) jinit_read_bmp JPP((j_compress_ptr cinfo)); | ||||
| EXTERN(djpeg_dest_ptr) jinit_write_bmp JPP((j_decompress_ptr cinfo, | ||||
| 					    boolean is_os2)); | ||||
| EXTERN(cjpeg_source_ptr) jinit_read_gif JPP((j_compress_ptr cinfo)); | ||||
| EXTERN(djpeg_dest_ptr) jinit_write_gif JPP((j_decompress_ptr cinfo)); | ||||
| EXTERN(cjpeg_source_ptr) jinit_read_ppm JPP((j_compress_ptr cinfo)); | ||||
| EXTERN(djpeg_dest_ptr) jinit_write_ppm JPP((j_decompress_ptr cinfo)); | ||||
| EXTERN(cjpeg_source_ptr) jinit_read_rle JPP((j_compress_ptr cinfo)); | ||||
| EXTERN(djpeg_dest_ptr) jinit_write_rle JPP((j_decompress_ptr cinfo)); | ||||
| EXTERN(cjpeg_source_ptr) jinit_read_targa JPP((j_compress_ptr cinfo)); | ||||
| EXTERN(djpeg_dest_ptr) jinit_write_targa JPP((j_decompress_ptr cinfo)); | ||||
| 
 | ||||
| /* cjpeg support routines (in rdswitch.c) */ | ||||
| 
 | ||||
| EXTERN(boolean) read_quant_tables JPP((j_compress_ptr cinfo, char * filename, | ||||
| 				    int scale_factor, boolean force_baseline)); | ||||
| EXTERN(boolean) read_scan_script JPP((j_compress_ptr cinfo, char * filename)); | ||||
| EXTERN(boolean) set_quant_slots JPP((j_compress_ptr cinfo, char *arg)); | ||||
| EXTERN(boolean) set_sample_factors JPP((j_compress_ptr cinfo, char *arg)); | ||||
| 
 | ||||
| /* djpeg support routines (in rdcolmap.c) */ | ||||
| 
 | ||||
| EXTERN(void) read_color_map JPP((j_decompress_ptr cinfo, FILE * infile)); | ||||
| 
 | ||||
| /* common support routines (in cdjpeg.c) */ | ||||
| 
 | ||||
| EXTERN(void) enable_signal_catcher JPP((j_common_ptr cinfo)); | ||||
| EXTERN(void) start_progress_monitor JPP((j_common_ptr cinfo, | ||||
| 					 cd_progress_ptr progress)); | ||||
| EXTERN(void) end_progress_monitor JPP((j_common_ptr cinfo)); | ||||
| EXTERN(boolean) keymatch JPP((char * arg, const char * keyword, int minchars)); | ||||
| EXTERN(FILE *) read_stdin JPP((void)); | ||||
| EXTERN(FILE *) write_stdout JPP((void)); | ||||
| 
 | ||||
| /* miscellaneous useful macros */ | ||||
| 
 | ||||
| #ifdef DONT_USE_B_MODE		/* define mode parameters for fopen() */ | ||||
| #define READ_BINARY	"r" | ||||
| #define WRITE_BINARY	"w" | ||||
| #else | ||||
| #ifdef VMS			/* VMS is very nonstandard */ | ||||
| #define READ_BINARY	"rb", "ctx=stm" | ||||
| #define WRITE_BINARY	"wb", "ctx=stm" | ||||
| #else				/* standard ANSI-compliant case */ | ||||
| #define READ_BINARY	"rb" | ||||
| #define WRITE_BINARY	"wb" | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| #ifndef EXIT_FAILURE		/* define exit() codes if not provided */ | ||||
| #define EXIT_FAILURE  1 | ||||
| #endif | ||||
| #ifndef EXIT_SUCCESS | ||||
| #ifdef VMS | ||||
| #define EXIT_SUCCESS  1		/* VMS is very nonstandard */ | ||||
| #else | ||||
| #define EXIT_SUCCESS  0 | ||||
| #endif | ||||
| #endif | ||||
| #ifndef EXIT_WARNING | ||||
| #ifdef VMS | ||||
| #define EXIT_WARNING  1		/* VMS is very nonstandard */ | ||||
| #else | ||||
| #define EXIT_WARNING  2 | ||||
| #endif | ||||
| #endif | ||||
|  | @ -0,0 +1,217 @@ | |||
| CHANGE LOG for Independent JPEG Group's JPEG software | ||||
| 
 | ||||
| 
 | ||||
| Version 6b  27-Mar-1998 | ||||
| ----------------------- | ||||
| 
 | ||||
| jpegtran has new features for lossless image transformations (rotation | ||||
| and flipping) as well as "lossless" reduction to grayscale. | ||||
| 
 | ||||
| jpegtran now copies comments by default; it has a -copy switch to enable | ||||
| copying all APPn blocks as well, or to suppress comments.  (Formerly it | ||||
| always suppressed comments and APPn blocks.)  jpegtran now also preserves | ||||
| JFIF version and resolution information. | ||||
| 
 | ||||
| New decompressor library feature: COM and APPn markers found in the input | ||||
| file can be saved in memory for later use by the application.  (Before, | ||||
| you had to code this up yourself with a custom marker processor.) | ||||
| 
 | ||||
| There is an unused field "void * client_data" now in compress and decompress | ||||
| parameter structs; this may be useful in some applications. | ||||
| 
 | ||||
| JFIF version number information is now saved by the decoder and accepted by | ||||
| the encoder.  jpegtran uses this to copy the source file's version number, | ||||
| to ensure "jpegtran -copy all" won't create bogus files that contain JFXX | ||||
| extensions but claim to be version 1.01.  Applications that generate their | ||||
| own JFXX extension markers also (finally) have a supported way to cause the | ||||
| encoder to emit JFIF version number 1.02. | ||||
| 
 | ||||
| djpeg's trace mode reports JFIF 1.02 thumbnail images as such, rather | ||||
| than as unknown APP0 markers. | ||||
| 
 | ||||
| In -verbose mode, djpeg and rdjpgcom will try to print the contents of | ||||
| APP12 markers as text.  Some digital cameras store useful text information | ||||
| in APP12 markers. | ||||
| 
 | ||||
| Handling of truncated data streams is more robust: blocks beyond the one in | ||||
| which the error occurs will be output as uniform gray, or left unchanged | ||||
| if decoding a progressive JPEG.  The appearance no longer depends on the | ||||
| Huffman tables being used. | ||||
| 
 | ||||
| Huffman tables are checked for validity much more carefully than before. | ||||
| 
 | ||||
| To avoid the Unisys LZW patent, djpeg's GIF output capability has been | ||||
| changed to produce "uncompressed GIFs", and cjpeg's GIF input capability | ||||
| has been removed altogether.  We're not happy about it either, but there | ||||
| seems to be no good alternative. | ||||
| 
 | ||||
| The configure script now supports building libjpeg as a shared library | ||||
| on many flavors of Unix (all the ones that GNU libtool knows how to | ||||
| build shared libraries for).  Use "./configure --enable-shared" to | ||||
| try this out. | ||||
| 
 | ||||
| New jconfig file and makefiles for Microsoft Visual C++ and Developer Studio. | ||||
| Also, a jconfig file and a build script for Metrowerks CodeWarrior | ||||
| on Apple Macintosh.  makefile.dj has been updated for DJGPP v2, and there | ||||
| are miscellaneous other minor improvements in the makefiles. | ||||
| 
 | ||||
| jmemmac.c now knows how to create temporary files following Mac System 7 | ||||
| conventions. | ||||
| 
 | ||||
| djpeg's -map switch is now able to read raw-format PPM files reliably. | ||||
| 
 | ||||
| cjpeg -progressive -restart no longer generates any unnecessary DRI markers. | ||||
| 
 | ||||
| Multiple calls to jpeg_simple_progression for a single JPEG object | ||||
| no longer leak memory. | ||||
| 
 | ||||
| 
 | ||||
| Version 6a  7-Feb-96 | ||||
| -------------------- | ||||
| 
 | ||||
| Library initialization sequence modified to detect version mismatches | ||||
| and struct field packing mismatches between library and calling application. | ||||
| This change requires applications to be recompiled, but does not require | ||||
| any application source code change. | ||||
| 
 | ||||
| All routine declarations changed to the style "GLOBAL(type) name ...", | ||||
| that is, GLOBAL, LOCAL, METHODDEF, EXTERN are now macros taking the | ||||
| routine's return type as an argument.  This makes it possible to add | ||||
| Microsoft-style linkage keywords to all the routines by changing just | ||||
| these macros.  Note that any application code that was using these macros | ||||
| will have to be changed. | ||||
| 
 | ||||
| DCT coefficient quantization tables are now stored in normal array order | ||||
| rather than zigzag order.  Application code that calls jpeg_add_quant_table, | ||||
| or otherwise manipulates quantization tables directly, will need to be | ||||
| changed.  If you need to make such code work with either older or newer | ||||
| versions of the library, a test like "#if JPEG_LIB_VERSION >= 61" is | ||||
| recommended. | ||||
| 
 | ||||
| djpeg's trace capability now dumps DQT tables in natural order, not zigzag | ||||
| order.  This allows the trace output to be made into a "-qtables" file | ||||
| more easily. | ||||
| 
 | ||||
| New system-dependent memory manager module for use on Apple Macintosh. | ||||
| 
 | ||||
| Fix bug in cjpeg's -smooth option: last one or two scanlines would be | ||||
| duplicates of the prior line unless the image height mod 16 was 1 or 2. | ||||
| 
 | ||||
| Repair minor problems in VMS, BCC, MC6 makefiles. | ||||
| 
 | ||||
| New configure script based on latest GNU Autoconf. | ||||
| 
 | ||||
| Correct the list of include files needed by MetroWerks C for ccommand(). | ||||
| 
 | ||||
| Numerous small documentation updates. | ||||
| 
 | ||||
| 
 | ||||
| Version 6  2-Aug-95 | ||||
| ------------------- | ||||
| 
 | ||||
| Progressive JPEG support: library can read and write full progressive JPEG | ||||
| files.  A "buffered image" mode supports incremental decoding for on-the-fly | ||||
| display of progressive images.  Simply recompiling an existing IJG-v5-based | ||||
| decoder with v6 should allow it to read progressive files, though of course | ||||
| without any special progressive display. | ||||
| 
 | ||||
| New "jpegtran" application performs lossless transcoding between different | ||||
| JPEG formats; primarily, it can be used to convert baseline to progressive | ||||
| JPEG and vice versa.  In support of jpegtran, the library now allows lossless | ||||
| reading and writing of JPEG files as DCT coefficient arrays.  This ability | ||||
| may be of use in other applications. | ||||
| 
 | ||||
| Notes for programmers: | ||||
| * We changed jpeg_start_decompress() to be able to suspend; this makes all | ||||
| decoding modes available to suspending-input applications.  However, | ||||
| existing applications that use suspending input will need to be changed | ||||
| to check the return value from jpeg_start_decompress().  You don't need to | ||||
| do anything if you don't use a suspending data source. | ||||
| * We changed the interface to the virtual array routines: access_virt_array | ||||
| routines now take a count of the number of rows to access this time.  The | ||||
| last parameter to request_virt_array routines is now interpreted as the | ||||
| maximum number of rows that may be accessed at once, but not necessarily | ||||
| the height of every access. | ||||
| 
 | ||||
| 
 | ||||
| Version 5b  15-Mar-95 | ||||
| --------------------- | ||||
| 
 | ||||
| Correct bugs with grayscale images having v_samp_factor > 1. | ||||
| 
 | ||||
| jpeg_write_raw_data() now supports output suspension. | ||||
| 
 | ||||
| Correct bugs in "configure" script for case of compiling in | ||||
| a directory other than the one containing the source files. | ||||
| 
 | ||||
| Repair bug in jquant1.c: sometimes didn't use as many colors as it could. | ||||
| 
 | ||||
| Borland C makefile and jconfig file work under either MS-DOS or OS/2. | ||||
| 
 | ||||
| Miscellaneous improvements to documentation. | ||||
| 
 | ||||
| 
 | ||||
| Version 5a  7-Dec-94 | ||||
| -------------------- | ||||
| 
 | ||||
| Changed color conversion roundoff behavior so that grayscale values are | ||||
| represented exactly.  (This causes test image files to change.) | ||||
| 
 | ||||
| Make ordered dither use 16x16 instead of 4x4 pattern for a small quality | ||||
| improvement. | ||||
| 
 | ||||
| New configure script based on latest GNU Autoconf. | ||||
| Fix configure script to handle CFLAGS correctly. | ||||
| Rename *.auto files to *.cfg, so that configure script still works if | ||||
| file names have been truncated for DOS. | ||||
| 
 | ||||
| Fix bug in rdbmp.c: didn't allow for extra data between header and image. | ||||
| 
 | ||||
| Modify rdppm.c/wrppm.c to handle 2-byte raw PPM/PGM formats for 12-bit data. | ||||
| 
 | ||||
| Fix several bugs in rdrle.c. | ||||
| 
 | ||||
| NEED_SHORT_EXTERNAL_NAMES option was broken. | ||||
| 
 | ||||
| Revise jerror.h/jerror.c for more flexibility in message table. | ||||
| 
 | ||||
| Repair oversight in jmemname.c NO_MKTEMP case: file could be there | ||||
| but unreadable. | ||||
| 
 | ||||
| 
 | ||||
| Version 5  24-Sep-94 | ||||
| -------------------- | ||||
| 
 | ||||
| Version 5 represents a nearly complete redesign and rewrite of the IJG | ||||
| software.  Major user-visible changes include: | ||||
|   * Automatic configuration simplifies installation for most Unix systems. | ||||
|   * A range of speed vs. image quality tradeoffs are supported. | ||||
|     This includes resizing of an image during decompression: scaling down | ||||
|     by a factor of 1/2, 1/4, or 1/8 is handled very efficiently. | ||||
|   * New programs rdjpgcom and wrjpgcom allow insertion and extraction | ||||
|     of text comments in a JPEG file. | ||||
| 
 | ||||
| The application programmer's interface to the library has changed completely. | ||||
| Notable improvements include: | ||||
|   * We have eliminated the use of callback routines for handling the | ||||
|     uncompressed image data.  The application now sees the library as a | ||||
|     set of routines that it calls to read or write image data on a | ||||
|     scanline-by-scanline basis. | ||||
|   * The application image data is represented in a conventional interleaved- | ||||
|     pixel format, rather than as a separate array for each color channel. | ||||
|     This can save a copying step in many programs. | ||||
|   * The handling of compressed data has been cleaned up: the application can | ||||
|     supply routines to source or sink the compressed data.  It is possible to | ||||
|     suspend processing on source/sink buffer overrun, although this is not | ||||
|     supported in all operating modes. | ||||
|   * All static state has been eliminated from the library, so that multiple | ||||
|     instances of compression or decompression can be active concurrently. | ||||
|   * JPEG abbreviated datastream formats are supported, ie, quantization and | ||||
|     Huffman tables can be stored separately from the image data. | ||||
|   * And not only that, but the documentation of the library has improved | ||||
|     considerably! | ||||
| 
 | ||||
| 
 | ||||
| The last widely used release before the version 5 rewrite was version 4A of | ||||
| 18-Feb-93.  Change logs before that point have been discarded, since they | ||||
| are not of much interest after the rewrite. | ||||
|  | @ -0,0 +1,402 @@ | |||
| /*
 | ||||
|  * ckconfig.c | ||||
|  * | ||||
|  * Copyright (C) 1991-1994, 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 program is intended to help you determine how to configure the JPEG | ||||
|  * software for installation on a particular system.  The idea is to try to | ||||
|  * compile and execute this program.  If your compiler fails to compile the | ||||
|  * program, make changes as indicated in the comments below.  Once you can | ||||
|  * compile the program, run it, and it will produce a "jconfig.h" file for | ||||
|  * your system. | ||||
|  * | ||||
|  * As a general rule, each time you try to compile this program, | ||||
|  * pay attention only to the *first* error message you get from the compiler. | ||||
|  * Many C compilers will issue lots of spurious error messages once they | ||||
|  * have gotten confused.  Go to the line indicated in the first error message, | ||||
|  * and read the comments preceding that line to see what to change. | ||||
|  * | ||||
|  * Almost all of the edits you may need to make to this program consist of | ||||
|  * changing a line that reads "#define SOME_SYMBOL" to "#undef SOME_SYMBOL", | ||||
|  * or vice versa.  This is called defining or undefining that symbol. | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| /* First we must see if your system has the include files we need.
 | ||||
|  * We start out with the assumption that your system has all the ANSI-standard | ||||
|  * include files.  If you get any error trying to include one of these files, | ||||
|  * undefine the corresponding HAVE_xxx symbol. | ||||
|  */ | ||||
| 
 | ||||
| #define HAVE_STDDEF_H		/* replace 'define' by 'undef' if error here */ | ||||
| #ifdef HAVE_STDDEF_H		/* next line will be skipped if you undef... */ | ||||
| #include <stddef.h> | ||||
| #endif | ||||
| 
 | ||||
| #define HAVE_STDLIB_H		/* same thing for stdlib.h */ | ||||
| #ifdef HAVE_STDLIB_H | ||||
| #include <stdlib.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <stdio.h>		/* If you ain't got this, you ain't got C. */ | ||||
| 
 | ||||
| /* We have to see if your string functions are defined by
 | ||||
|  * strings.h (old BSD convention) or string.h (everybody else). | ||||
|  * We try the non-BSD convention first; define NEED_BSD_STRINGS | ||||
|  * if the compiler says it can't find string.h. | ||||
|  */ | ||||
| 
 | ||||
| #undef NEED_BSD_STRINGS | ||||
| 
 | ||||
| #ifdef NEED_BSD_STRINGS | ||||
| #include <strings.h> | ||||
| #else | ||||
| #include <string.h> | ||||
| #endif | ||||
| 
 | ||||
| /* On some systems (especially older Unix machines), type size_t is
 | ||||
|  * defined only in the include file <sys/types.h>.  If you get a failure | ||||
|  * on the size_t test below, try defining NEED_SYS_TYPES_H. | ||||
|  */ | ||||
| 
 | ||||
| #undef NEED_SYS_TYPES_H		/* start by assuming we don't need it */ | ||||
| #ifdef NEED_SYS_TYPES_H | ||||
| #include <sys/types.h> | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Usually type size_t is defined in one of the include files we've included
 | ||||
|  * above.  If not, you'll get an error on the "typedef size_t my_size_t;" line. | ||||
|  * In that case, first try defining NEED_SYS_TYPES_H just above. | ||||
|  * If that doesn't work, you'll have to search through your system library | ||||
|  * to figure out which include file defines "size_t".  Look for a line that | ||||
|  * says "typedef something-or-other size_t;".  Then, change the line below | ||||
|  * that says "#include <someincludefile.h>" to instead include the file | ||||
|  * you found size_t in, and define NEED_SPECIAL_INCLUDE.  If you can't find | ||||
|  * type size_t anywhere, try replacing "#include <someincludefile.h>" with | ||||
|  * "typedef unsigned int size_t;". | ||||
|  */ | ||||
| 
 | ||||
| #undef NEED_SPECIAL_INCLUDE	/* assume we DON'T need it, for starters */ | ||||
| 
 | ||||
| #ifdef NEED_SPECIAL_INCLUDE | ||||
| #include <someincludefile.h> | ||||
| #endif | ||||
| 
 | ||||
| typedef size_t my_size_t;	/* The payoff: do we have size_t now? */ | ||||
| 
 | ||||
| 
 | ||||
| /* The next question is whether your compiler supports ANSI-style function
 | ||||
|  * prototypes.  You need to know this in order to choose between using | ||||
|  * makefile.ansi and using makefile.unix. | ||||
|  * The #define line below is set to assume you have ANSI function prototypes. | ||||
|  * If you get an error in this group of lines, undefine HAVE_PROTOTYPES. | ||||
|  */ | ||||
| 
 | ||||
| #define HAVE_PROTOTYPES | ||||
| 
 | ||||
| #ifdef HAVE_PROTOTYPES | ||||
| int testfunction (int arg1, int * arg2); /* check prototypes */ | ||||
| 
 | ||||
| struct methods_struct {		/* check method-pointer declarations */ | ||||
|   int (*error_exit) (char *msgtext); | ||||
|   int (*trace_message) (char *msgtext); | ||||
|   int (*another_method) (void); | ||||
| }; | ||||
| 
 | ||||
| int testfunction (int arg1, int * arg2) /* check definitions */ | ||||
| { | ||||
|   return arg2[arg1]; | ||||
| } | ||||
| 
 | ||||
| int test2function (void)	/* check void arg list */ | ||||
| { | ||||
|   return 0; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Now we want to find out if your compiler knows what "unsigned char" means.
 | ||||
|  * If you get an error on the "unsigned char un_char;" line, | ||||
|  * then undefine HAVE_UNSIGNED_CHAR. | ||||
|  */ | ||||
| 
 | ||||
| #define HAVE_UNSIGNED_CHAR | ||||
| 
 | ||||
| #ifdef HAVE_UNSIGNED_CHAR | ||||
| unsigned char un_char; | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Now we want to find out if your compiler knows what "unsigned short" means.
 | ||||
|  * If you get an error on the "unsigned short un_short;" line, | ||||
|  * then undefine HAVE_UNSIGNED_SHORT. | ||||
|  */ | ||||
| 
 | ||||
| #define HAVE_UNSIGNED_SHORT | ||||
| 
 | ||||
| #ifdef HAVE_UNSIGNED_SHORT | ||||
| unsigned short un_short; | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Now we want to find out if your compiler understands type "void".
 | ||||
|  * If you get an error anywhere in here, undefine HAVE_VOID. | ||||
|  */ | ||||
| 
 | ||||
| #define HAVE_VOID | ||||
| 
 | ||||
| #ifdef HAVE_VOID | ||||
| /* Caution: a C++ compiler will insist on complete prototypes */ | ||||
| typedef void * void_ptr;	/* check void * */ | ||||
| #ifdef HAVE_PROTOTYPES		/* check ptr to function returning void */ | ||||
| typedef void (*void_func) (int a, int b); | ||||
| #else | ||||
| typedef void (*void_func) (); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAVE_PROTOTYPES		/* check void function result */ | ||||
| void test3function (void_ptr arg1, void_func arg2) | ||||
| #else | ||||
| void test3function (arg1, arg2) | ||||
|      void_ptr arg1; | ||||
|      void_func arg2; | ||||
| #endif | ||||
| { | ||||
|   char * locptr = (char *) arg1; /* check casting to and from void * */ | ||||
|   arg1 = (void *) locptr; | ||||
|   (*arg2) (1, 2);		/* check call of fcn returning void */ | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Now we want to find out if your compiler knows what "const" means.
 | ||||
|  * If you get an error here, undefine HAVE_CONST. | ||||
|  */ | ||||
| 
 | ||||
| #define HAVE_CONST | ||||
| 
 | ||||
| #ifdef HAVE_CONST | ||||
| static const int carray[3] = {1, 2, 3}; | ||||
| 
 | ||||
| #ifdef HAVE_PROTOTYPES | ||||
| int test4function (const int arg1) | ||||
| #else | ||||
| int test4function (arg1) | ||||
|      const int arg1; | ||||
| #endif | ||||
| { | ||||
|   return carray[arg1]; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* If you get an error or warning about this structure definition,
 | ||||
|  * define INCOMPLETE_TYPES_BROKEN. | ||||
|  */ | ||||
| 
 | ||||
| #undef INCOMPLETE_TYPES_BROKEN | ||||
| 
 | ||||
| #ifndef INCOMPLETE_TYPES_BROKEN | ||||
| typedef struct undefined_structure * undef_struct_ptr; | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* If you get an error about duplicate names,
 | ||||
|  * define NEED_SHORT_EXTERNAL_NAMES. | ||||
|  */ | ||||
| 
 | ||||
| #undef NEED_SHORT_EXTERNAL_NAMES | ||||
| 
 | ||||
| #ifndef NEED_SHORT_EXTERNAL_NAMES | ||||
| 
 | ||||
| int possibly_duplicate_function () | ||||
| { | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int possibly_dupli_function () | ||||
| { | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /************************************************************************
 | ||||
|  *  OK, that's it.  You should not have to change anything beyond this | ||||
|  *  point in order to compile and execute this program.  (You might get | ||||
|  *  some warnings, but you can ignore them.) | ||||
|  *  When you run the program, it will make a couple more tests that it | ||||
|  *  can do automatically, and then it will create jconfig.h and print out | ||||
|  *  any additional suggestions it has. | ||||
|  ************************************************************************ | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| #ifdef HAVE_PROTOTYPES | ||||
| int is_char_signed (int arg) | ||||
| #else | ||||
| int is_char_signed (arg) | ||||
|      int arg; | ||||
| #endif | ||||
| { | ||||
|   if (arg == 189) {		/* expected result for unsigned char */ | ||||
|     return 0;			/* type char is unsigned */ | ||||
|   } | ||||
|   else if (arg != -67) {	/* expected result for signed char */ | ||||
|     printf("Hmm, it seems 'char' is not eight bits wide on your machine.\n"); | ||||
|     printf("I fear the JPEG software will not work at all.\n\n"); | ||||
|   } | ||||
|   return 1;			/* assume char is signed otherwise */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef HAVE_PROTOTYPES | ||||
| int is_shifting_signed (long arg) | ||||
| #else | ||||
| int is_shifting_signed (arg) | ||||
|      long arg; | ||||
| #endif | ||||
| /* See whether right-shift on a long is signed or not. */ | ||||
| { | ||||
|   long res = arg >> 4; | ||||
| 
 | ||||
|   if (res == -0x7F7E80CL) {	/* expected result for signed shift */ | ||||
|     return 1;			/* right shift is signed */ | ||||
|   } | ||||
|   /* see if unsigned-shift hack will fix it. */ | ||||
|   /* we can't just test exact value since it depends on width of long... */ | ||||
|   res |= (~0L) << (32-4); | ||||
|   if (res == -0x7F7E80CL) {	/* expected result now? */ | ||||
|     return 0;			/* right shift is unsigned */ | ||||
|   } | ||||
|   printf("Right shift isn't acting as I expect it to.\n"); | ||||
|   printf("I fear the JPEG software will not work at all.\n\n"); | ||||
|   return 0;			/* try it with unsigned anyway */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef HAVE_PROTOTYPES | ||||
| int main (int argc, char ** argv) | ||||
| #else | ||||
| int main (argc, argv) | ||||
|      int argc; | ||||
|      char ** argv; | ||||
| #endif | ||||
| { | ||||
|   char signed_char_check = (char) (-67); | ||||
|   FILE *outfile; | ||||
| 
 | ||||
|   /* Attempt to write jconfig.h */ | ||||
|   if ((outfile = fopen("jconfig.h", "w")) == NULL) { | ||||
|     printf("Failed to write jconfig.h\n"); | ||||
|     return 1; | ||||
|   } | ||||
| 
 | ||||
|   /* Write out all the info */ | ||||
|   fprintf(outfile, "/* jconfig.h --- generated by ckconfig.c */\n"); | ||||
|   fprintf(outfile, "/* see jconfig.doc for explanations */\n\n"); | ||||
| #ifdef HAVE_PROTOTYPES | ||||
|   fprintf(outfile, "#define HAVE_PROTOTYPES\n"); | ||||
| #else | ||||
|   fprintf(outfile, "#undef HAVE_PROTOTYPES\n"); | ||||
| #endif | ||||
| #ifdef HAVE_UNSIGNED_CHAR | ||||
|   fprintf(outfile, "#define HAVE_UNSIGNED_CHAR\n"); | ||||
| #else | ||||
|   fprintf(outfile, "#undef HAVE_UNSIGNED_CHAR\n"); | ||||
| #endif | ||||
| #ifdef HAVE_UNSIGNED_SHORT | ||||
|   fprintf(outfile, "#define HAVE_UNSIGNED_SHORT\n"); | ||||
| #else | ||||
|   fprintf(outfile, "#undef HAVE_UNSIGNED_SHORT\n"); | ||||
| #endif | ||||
| #ifdef HAVE_VOID | ||||
|   fprintf(outfile, "/* #define void char */\n"); | ||||
| #else | ||||
|   fprintf(outfile, "#define void char\n"); | ||||
| #endif | ||||
| #ifdef HAVE_CONST | ||||
|   fprintf(outfile, "/* #define const */\n"); | ||||
| #else | ||||
|   fprintf(outfile, "#define const\n"); | ||||
| #endif | ||||
|   if (is_char_signed((int) signed_char_check)) | ||||
|     fprintf(outfile, "#undef CHAR_IS_UNSIGNED\n"); | ||||
|   else | ||||
|     fprintf(outfile, "#define CHAR_IS_UNSIGNED\n"); | ||||
| #ifdef HAVE_STDDEF_H | ||||
|   fprintf(outfile, "#define HAVE_STDDEF_H\n"); | ||||
| #else | ||||
|   fprintf(outfile, "#undef HAVE_STDDEF_H\n"); | ||||
| #endif | ||||
| #ifdef HAVE_STDLIB_H | ||||
|   fprintf(outfile, "#define HAVE_STDLIB_H\n"); | ||||
| #else | ||||
|   fprintf(outfile, "#undef HAVE_STDLIB_H\n"); | ||||
| #endif | ||||
| #ifdef NEED_BSD_STRINGS | ||||
|   fprintf(outfile, "#define NEED_BSD_STRINGS\n"); | ||||
| #else | ||||
|   fprintf(outfile, "#undef NEED_BSD_STRINGS\n"); | ||||
| #endif | ||||
| #ifdef NEED_SYS_TYPES_H | ||||
|   fprintf(outfile, "#define NEED_SYS_TYPES_H\n"); | ||||
| #else | ||||
|   fprintf(outfile, "#undef NEED_SYS_TYPES_H\n"); | ||||
| #endif | ||||
|   fprintf(outfile, "#undef NEED_FAR_POINTERS\n"); | ||||
| #ifdef NEED_SHORT_EXTERNAL_NAMES | ||||
|   fprintf(outfile, "#define NEED_SHORT_EXTERNAL_NAMES\n"); | ||||
| #else | ||||
|   fprintf(outfile, "#undef NEED_SHORT_EXTERNAL_NAMES\n"); | ||||
| #endif | ||||
| #ifdef INCOMPLETE_TYPES_BROKEN | ||||
|   fprintf(outfile, "#define INCOMPLETE_TYPES_BROKEN\n"); | ||||
| #else | ||||
|   fprintf(outfile, "#undef INCOMPLETE_TYPES_BROKEN\n"); | ||||
| #endif | ||||
|   fprintf(outfile, "\n#ifdef JPEG_INTERNALS\n\n"); | ||||
|   if (is_shifting_signed(-0x7F7E80B1L)) | ||||
|     fprintf(outfile, "#undef RIGHT_SHIFT_IS_UNSIGNED\n"); | ||||
|   else | ||||
|     fprintf(outfile, "#define RIGHT_SHIFT_IS_UNSIGNED\n"); | ||||
|   fprintf(outfile, "\n#endif /* JPEG_INTERNALS */\n"); | ||||
|   fprintf(outfile, "\n#ifdef JPEG_CJPEG_DJPEG\n\n"); | ||||
|   fprintf(outfile, "#define BMP_SUPPORTED		/* BMP image file format */\n"); | ||||
|   fprintf(outfile, "#define GIF_SUPPORTED		/* GIF image file format */\n"); | ||||
|   fprintf(outfile, "#define PPM_SUPPORTED		/* PBMPLUS PPM/PGM image file format */\n"); | ||||
|   fprintf(outfile, "#undef RLE_SUPPORTED		/* Utah RLE image file format */\n"); | ||||
|   fprintf(outfile, "#define TARGA_SUPPORTED		/* Targa image file format */\n\n"); | ||||
|   fprintf(outfile, "#undef TWO_FILE_COMMANDLINE	/* You may need this on non-Unix systems */\n"); | ||||
|   fprintf(outfile, "#undef NEED_SIGNAL_CATCHER	/* Define this if you use jmemname.c */\n"); | ||||
|   fprintf(outfile, "#undef DONT_USE_B_MODE\n"); | ||||
|   fprintf(outfile, "/* #define PROGRESS_REPORT */	/* optional */\n"); | ||||
|   fprintf(outfile, "\n#endif /* JPEG_CJPEG_DJPEG */\n"); | ||||
| 
 | ||||
|   /* Close the jconfig.h file */ | ||||
|   fclose(outfile); | ||||
| 
 | ||||
|   /* User report */ | ||||
|   printf("Configuration check for Independent JPEG Group's software done.\n"); | ||||
|   printf("\nI have written the jconfig.h file for you.\n\n"); | ||||
| #ifdef HAVE_PROTOTYPES | ||||
|   printf("You should use makefile.ansi as the starting point for your Makefile.\n"); | ||||
| #else | ||||
|   printf("You should use makefile.unix as the starting point for your Makefile.\n"); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef NEED_SPECIAL_INCLUDE | ||||
|   printf("\nYou'll need to change jconfig.h to include the system include file\n"); | ||||
|   printf("that you found type size_t in, or add a direct definition of type\n"); | ||||
|   printf("size_t if that's what you used.  Just add it to the end.\n"); | ||||
| #endif | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
|  | @ -0,0 +1,118 @@ | |||
| IJG JPEG LIBRARY:  CODING RULES | ||||
| 
 | ||||
| Copyright (C) 1991-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. | ||||
| 
 | ||||
| 
 | ||||
| Since numerous people will be contributing code and bug fixes, it's important | ||||
| to establish a common coding style.  The goal of using similar coding styles | ||||
| is much more important than the details of just what that style is. | ||||
| 
 | ||||
| In general we follow the recommendations of "Recommended C Style and Coding | ||||
| Standards" revision 6.1 (Cannon et al. as modified by Spencer, Keppel and | ||||
| Brader).  This document is available in the IJG FTP archive (see | ||||
| jpeg/doc/cstyle.ms.tbl.Z, or cstyle.txt.Z for those without nroff/tbl). | ||||
| 
 | ||||
| Block comments should be laid out thusly: | ||||
| 
 | ||||
| /* | ||||
|  *  Block comments in this style. | ||||
|  */ | ||||
| 
 | ||||
| We indent statements in K&R style, e.g., | ||||
| 	if (test) { | ||||
| 	  then-part; | ||||
| 	} else { | ||||
| 	  else-part; | ||||
| 	} | ||||
| with two spaces per indentation level.  (This indentation convention is | ||||
| handled automatically by GNU Emacs and many other text editors.) | ||||
| 
 | ||||
| Multi-word names should be written in lower case with underscores, e.g., | ||||
| multi_word_name (not multiWordName).  Preprocessor symbols and enum constants | ||||
| are similar but upper case (MULTI_WORD_NAME).  Names should be unique within | ||||
| the first fifteen characters.  (On some older systems, global names must be | ||||
| unique within six characters.  We accommodate this without cluttering the | ||||
| source code by using macros to substitute shorter names.) | ||||
| 
 | ||||
| We use function prototypes everywhere; we rely on automatic source code | ||||
| transformation to feed prototype-less C compilers.  Transformation is done | ||||
| by the simple and portable tool 'ansi2knr.c' (courtesy of Ghostscript). | ||||
| ansi2knr is not very bright, so it imposes a format requirement on function | ||||
| declarations: the function name MUST BEGIN IN COLUMN 1.  Thus all functions | ||||
| should be written in the following style: | ||||
| 
 | ||||
| LOCAL(int *) | ||||
| function_name (int a, char *b) | ||||
| { | ||||
|     code... | ||||
| } | ||||
| 
 | ||||
| Note that each function definition must begin with GLOBAL(type), LOCAL(type), | ||||
| or METHODDEF(type).  These macros expand to "static type" or just "type" as | ||||
| appropriate.  They provide a readable indication of the routine's usage and | ||||
| can readily be changed for special needs.  (For instance, special linkage | ||||
| keywords can be inserted for use in Windows DLLs.) | ||||
| 
 | ||||
| ansi2knr does not transform method declarations (function pointers in | ||||
| structs).  We handle these with a macro JMETHOD, defined as | ||||
| 	#ifdef HAVE_PROTOTYPES | ||||
| 	#define JMETHOD(type,methodname,arglist)  type (*methodname) arglist | ||||
| 	#else | ||||
| 	#define JMETHOD(type,methodname,arglist)  type (*methodname) () | ||||
| 	#endif | ||||
| which is used like this: | ||||
| 	struct function_pointers { | ||||
| 	  JMETHOD(void, init_entropy_encoder, (int somearg, jparms *jp)); | ||||
| 	  JMETHOD(void, term_entropy_encoder, (void)); | ||||
| 	}; | ||||
| Note the set of parentheses surrounding the parameter list. | ||||
| 
 | ||||
| A similar solution is used for forward and external function declarations | ||||
| (see the EXTERN and JPP macros). | ||||
| 
 | ||||
| If the code is to work on non-ANSI compilers, we cannot rely on a prototype | ||||
| declaration to coerce actual parameters into the right types.  Therefore, use | ||||
| explicit casts on actual parameters whenever the actual parameter type is not | ||||
| identical to the formal parameter.  Beware of implicit conversions to "int". | ||||
| 
 | ||||
| It seems there are some non-ANSI compilers in which the sizeof() operator | ||||
| is defined to return int, yet size_t is defined as long.  Needless to say, | ||||
| this is brain-damaged.  Always use the SIZEOF() macro in place of sizeof(), | ||||
| so that the result is guaranteed to be of type size_t. | ||||
| 
 | ||||
| 
 | ||||
| The JPEG library is intended to be used within larger programs.  Furthermore, | ||||
| we want it to be reentrant so that it can be used by applications that process | ||||
| multiple images concurrently.  The following rules support these requirements: | ||||
| 
 | ||||
| 1. Avoid direct use of file I/O, "malloc", error report printouts, etc; | ||||
| pass these through the common routines provided. | ||||
| 
 | ||||
| 2. Minimize global namespace pollution.  Functions should be declared static | ||||
| wherever possible.  (Note that our method-based calling conventions help this | ||||
| a lot: in many modules only the initialization function will ever need to be | ||||
| called directly, so only that function need be externally visible.)  All | ||||
| global function names should begin with "jpeg_", and should have an | ||||
| abbreviated name (unique in the first six characters) substituted by macro | ||||
| when NEED_SHORT_EXTERNAL_NAMES is set. | ||||
| 
 | ||||
| 3. Don't use global variables; anything that must be used in another module | ||||
| should be in the common data structures. | ||||
| 
 | ||||
| 4. Don't use static variables except for read-only constant tables.  Variables | ||||
| that should be private to a module can be placed into private structures (see | ||||
| the system architecture document, structure.doc). | ||||
| 
 | ||||
| 5. Source file names should begin with "j" for files that are part of the | ||||
| library proper; source files that are not part of the library, such as cjpeg.c | ||||
| and djpeg.c, do not begin with "j".  Keep source file names to eight | ||||
| characters (plus ".c" or ".h", etc) to make life easy for MS-DOSers.  Keep | ||||
| compression and decompression code in separate source files --- some | ||||
| applications may want only one half of the library. | ||||
| 
 | ||||
| Note: these rules (particularly #4) are not followed religiously in the | ||||
| modules that are used in cjpeg/djpeg but are not part of the JPEG library | ||||
| proper.  Those modules are not really intended to be used in other | ||||
| applications. | ||||
|  | @ -0,0 +1,433 @@ | |||
| /*
 | ||||
|  * example.c | ||||
|  * | ||||
|  * This file illustrates how to use the IJG code as a subroutine library | ||||
|  * to read or write JPEG image files.  You should look at this code in | ||||
|  * conjunction with the documentation file libjpeg.doc. | ||||
|  * | ||||
|  * This code will not do anything useful as-is, but it may be helpful as a | ||||
|  * skeleton for constructing routines that call the JPEG library.   | ||||
|  * | ||||
|  * We present these routines in the same coding style used in the JPEG code | ||||
|  * (ANSI function definitions, etc); but you are of course free to code your | ||||
|  * routines in a different style if you prefer. | ||||
|  */ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| /*
 | ||||
|  * Include file for users of JPEG library. | ||||
|  * You will need to have included system headers that define at least | ||||
|  * the typedefs FILE and size_t before you can include jpeglib.h. | ||||
|  * (stdio.h is sufficient on ANSI-conforming systems.) | ||||
|  * You may also wish to include "jerror.h". | ||||
|  */ | ||||
| 
 | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * <setjmp.h> is used for the optional error recovery mechanism shown in | ||||
|  * the second part of the example. | ||||
|  */ | ||||
| 
 | ||||
| #include <setjmp.h> | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /******************** JPEG COMPRESSION SAMPLE INTERFACE *******************/ | ||||
| 
 | ||||
| /* This half of the example shows how to feed data into the JPEG compressor.
 | ||||
|  * We present a minimal version that does not worry about refinements such | ||||
|  * as error recovery (the JPEG code will just exit() if it gets an error). | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * IMAGE DATA FORMATS: | ||||
|  * | ||||
|  * The standard input image format is a rectangular array of pixels, with | ||||
|  * each pixel having the same number of "component" values (color channels). | ||||
|  * Each pixel row is an array of JSAMPLEs (which typically are unsigned chars). | ||||
|  * If you are working with color data, then the color values for each pixel | ||||
|  * must be adjacent in the row; for example, R,G,B,R,G,B,R,G,B,... for 24-bit | ||||
|  * RGB color. | ||||
|  * | ||||
|  * For this example, we'll assume that this data structure matches the way | ||||
|  * our application has stored the image in memory, so we can just pass a | ||||
|  * pointer to our image buffer.  In particular, let's say that the image is | ||||
|  * RGB color and is described by: | ||||
|  */ | ||||
| 
 | ||||
| extern JSAMPLE * image_buffer;	/* Points to large array of R,G,B-order data */ | ||||
| extern int image_height;	/* Number of rows in image */ | ||||
| extern int image_width;		/* Number of columns in image */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Sample routine for JPEG compression.  We assume that the target file name | ||||
|  * and a compression quality factor are passed in. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| write_JPEG_file (char * filename, int quality) | ||||
| { | ||||
|   /* This struct contains the JPEG compression parameters and pointers to
 | ||||
|    * working space (which is allocated as needed by the JPEG library). | ||||
|    * It is possible to have several such structures, representing multiple | ||||
|    * compression/decompression processes, in existence at once.  We refer | ||||
|    * to any one struct (and its associated working data) as a "JPEG object". | ||||
|    */ | ||||
|   struct jpeg_compress_struct cinfo; | ||||
|   /* This struct represents a JPEG error handler.  It is declared separately
 | ||||
|    * because applications often want to supply a specialized error handler | ||||
|    * (see the second half of this file for an example).  But here we just | ||||
|    * take the easy way out and use the standard error handler, which will | ||||
|    * print a message on stderr and call exit() if compression fails. | ||||
|    * Note that this struct must live as long as the main JPEG parameter | ||||
|    * struct, to avoid dangling-pointer problems. | ||||
|    */ | ||||
|   struct jpeg_error_mgr jerr; | ||||
|   /* More stuff */ | ||||
|   FILE * outfile;		/* target file */ | ||||
|   JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */ | ||||
|   int row_stride;		/* physical row width in image buffer */ | ||||
| 
 | ||||
|   /* Step 1: allocate and initialize JPEG compression object */ | ||||
| 
 | ||||
|   /* We have to set up the error handler first, in case the initialization
 | ||||
|    * step fails.  (Unlikely, but it could happen if you are out of memory.) | ||||
|    * This routine fills in the contents of struct jerr, and returns jerr's | ||||
|    * address which we place into the link field in cinfo. | ||||
|    */ | ||||
|   cinfo.err = jpeg_std_error(&jerr); | ||||
|   /* Now we can initialize the JPEG compression object. */ | ||||
|   jpeg_create_compress(&cinfo); | ||||
| 
 | ||||
|   /* Step 2: specify data destination (eg, a file) */ | ||||
|   /* Note: steps 2 and 3 can be done in either order. */ | ||||
| 
 | ||||
|   /* Here we use the library-supplied code to send compressed data to a
 | ||||
|    * stdio stream.  You can also write your own code to do something else. | ||||
|    * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that | ||||
|    * requires it in order to write binary files. | ||||
|    */ | ||||
|   if ((outfile = fopen(filename, "wb")) == NULL) { | ||||
|     fprintf(stderr, "can't open %s\n", filename); | ||||
|     exit(1); | ||||
|   } | ||||
|   jpeg_stdio_dest(&cinfo, outfile); | ||||
| 
 | ||||
|   /* Step 3: set parameters for compression */ | ||||
| 
 | ||||
|   /* First we supply a description of the input image.
 | ||||
|    * Four fields of the cinfo struct must be filled in: | ||||
|    */ | ||||
|   cinfo.image_width = image_width; 	/* image width and height, in pixels */ | ||||
|   cinfo.image_height = image_height; | ||||
|   cinfo.input_components = 3;		/* # of color components per pixel */ | ||||
|   cinfo.in_color_space = JCS_RGB; 	/* colorspace of input image */ | ||||
|   /* Now use the library's routine to set default compression parameters.
 | ||||
|    * (You must set at least cinfo.in_color_space before calling this, | ||||
|    * since the defaults depend on the source color space.) | ||||
|    */ | ||||
|   jpeg_set_defaults(&cinfo); | ||||
|   /* Now you can set any non-default parameters you wish to.
 | ||||
|    * Here we just illustrate the use of quality (quantization table) scaling: | ||||
|    */ | ||||
|   jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); | ||||
| 
 | ||||
|   /* Step 4: Start compressor */ | ||||
| 
 | ||||
|   /* TRUE ensures that we will write a complete interchange-JPEG file.
 | ||||
|    * Pass TRUE unless you are very sure of what you're doing. | ||||
|    */ | ||||
|   jpeg_start_compress(&cinfo, TRUE); | ||||
| 
 | ||||
|   /* Step 5: while (scan lines remain to be written) */ | ||||
|   /*           jpeg_write_scanlines(...); */ | ||||
| 
 | ||||
|   /* Here we use the library's state variable cinfo.next_scanline as the
 | ||||
|    * loop counter, so that we don't have to keep track ourselves. | ||||
|    * To keep things simple, we pass one scanline per call; you can pass | ||||
|    * more if you wish, though. | ||||
|    */ | ||||
|   row_stride = image_width * 3;	/* JSAMPLEs per row in image_buffer */ | ||||
| 
 | ||||
|   while (cinfo.next_scanline < cinfo.image_height) { | ||||
|     /* jpeg_write_scanlines expects an array of pointers to scanlines.
 | ||||
|      * Here the array is only one element long, but you could pass | ||||
|      * more than one scanline at a time if that's more convenient. | ||||
|      */ | ||||
|     row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride]; | ||||
|     (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); | ||||
|   } | ||||
| 
 | ||||
|   /* Step 6: Finish compression */ | ||||
| 
 | ||||
|   jpeg_finish_compress(&cinfo); | ||||
|   /* After finish_compress, we can close the output file. */ | ||||
|   fclose(outfile); | ||||
| 
 | ||||
|   /* Step 7: release JPEG compression object */ | ||||
| 
 | ||||
|   /* This is an important step since it will release a good deal of memory. */ | ||||
|   jpeg_destroy_compress(&cinfo); | ||||
| 
 | ||||
|   /* And we're done! */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * SOME FINE POINTS: | ||||
|  * | ||||
|  * In the above loop, we ignored the return value of jpeg_write_scanlines, | ||||
|  * which is the number of scanlines actually written.  We could get away | ||||
|  * with this because we were only relying on the value of cinfo.next_scanline, | ||||
|  * which will be incremented correctly.  If you maintain additional loop | ||||
|  * variables then you should be careful to increment them properly. | ||||
|  * Actually, for output to a stdio stream you needn't worry, because | ||||
|  * then jpeg_write_scanlines will write all the lines passed (or else exit | ||||
|  * with a fatal error).  Partial writes can only occur if you use a data | ||||
|  * destination module that can demand suspension of the compressor. | ||||
|  * (If you don't know what that's for, you don't need it.) | ||||
|  * | ||||
|  * If the compressor requires full-image buffers (for entropy-coding | ||||
|  * optimization or a multi-scan JPEG file), it will create temporary | ||||
|  * files for anything that doesn't fit within the maximum-memory setting. | ||||
|  * (Note that temp files are NOT needed if you use the default parameters.) | ||||
|  * On some systems you may need to set up a signal handler to ensure that | ||||
|  * temporary files are deleted if the program is interrupted.  See libjpeg.doc. | ||||
|  * | ||||
|  * Scanlines MUST be supplied in top-to-bottom order if you want your JPEG | ||||
|  * files to be compatible with everyone else's.  If you cannot readily read | ||||
|  * your data in that order, you'll need an intermediate array to hold the | ||||
|  * image.  See rdtarga.c or rdbmp.c for examples of handling bottom-to-top | ||||
|  * source data using the JPEG code's internal virtual-array mechanisms. | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/ | ||||
| 
 | ||||
| /* This half of the example shows how to read data from the JPEG decompressor.
 | ||||
|  * It's a bit more refined than the above, in that we show: | ||||
|  *   (a) how to modify the JPEG library's standard error-reporting behavior; | ||||
|  *   (b) how to allocate workspace using the library's memory manager. | ||||
|  * | ||||
|  * Just to make this example a little different from the first one, we'll | ||||
|  * assume that we do not intend to put the whole image into an in-memory | ||||
|  * buffer, but to send it line-by-line someplace else.  We need a one- | ||||
|  * scanline-high JSAMPLE array as a work buffer, and we will let the JPEG | ||||
|  * memory manager allocate it for us.  This approach is actually quite useful | ||||
|  * because we don't need to remember to deallocate the buffer separately: it | ||||
|  * will go away automatically when the JPEG object is cleaned up. | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * ERROR HANDLING: | ||||
|  * | ||||
|  * The JPEG library's standard error handler (jerror.c) is divided into | ||||
|  * several "methods" which you can override individually.  This lets you | ||||
|  * adjust the behavior without duplicating a lot of code, which you might | ||||
|  * have to update with each future release. | ||||
|  * | ||||
|  * Our example here shows how to override the "error_exit" method so that | ||||
|  * control is returned to the library's caller when a fatal error occurs, | ||||
|  * rather than calling exit() as the standard error_exit method does. | ||||
|  * | ||||
|  * We use C's setjmp/longjmp facility to return control.  This means that the | ||||
|  * routine which calls the JPEG library must first execute a setjmp() call to | ||||
|  * establish the return point.  We want the replacement error_exit to do a | ||||
|  * longjmp().  But we need to make the setjmp buffer accessible to the | ||||
|  * error_exit routine.  To do this, we make a private extension of the | ||||
|  * standard JPEG error handler object.  (If we were using C++, we'd say we | ||||
|  * were making a subclass of the regular error handler.) | ||||
|  * | ||||
|  * Here's the extended error handler struct: | ||||
|  */ | ||||
| 
 | ||||
| struct my_error_mgr { | ||||
|   struct jpeg_error_mgr pub;	/* "public" fields */ | ||||
| 
 | ||||
|   jmp_buf setjmp_buffer;	/* for return to caller */ | ||||
| }; | ||||
| 
 | ||||
| typedef struct my_error_mgr * my_error_ptr; | ||||
| 
 | ||||
| /*
 | ||||
|  * Here's the routine that will replace the standard error_exit method: | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| my_error_exit (j_common_ptr cinfo) | ||||
| { | ||||
|   /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ | ||||
|   my_error_ptr myerr = (my_error_ptr) cinfo->err; | ||||
| 
 | ||||
|   /* Always display the message. */ | ||||
|   /* We could postpone this until after returning, if we chose. */ | ||||
|   (*cinfo->err->output_message) (cinfo); | ||||
| 
 | ||||
|   /* Return control to the setjmp point */ | ||||
|   longjmp(myerr->setjmp_buffer, 1); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Sample routine for JPEG decompression.  We assume that the source file name | ||||
|  * is passed in.  We want to return 1 on success, 0 on error. | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| GLOBAL(int) | ||||
| read_JPEG_file (char * filename) | ||||
| { | ||||
|   /* This struct contains the JPEG decompression parameters and pointers to
 | ||||
|    * working space (which is allocated as needed by the JPEG library). | ||||
|    */ | ||||
|   struct jpeg_decompress_struct cinfo; | ||||
|   /* We use our private extension JPEG error handler.
 | ||||
|    * Note that this struct must live as long as the main JPEG parameter | ||||
|    * struct, to avoid dangling-pointer problems. | ||||
|    */ | ||||
|   struct my_error_mgr jerr; | ||||
|   /* More stuff */ | ||||
|   FILE * infile;		/* source file */ | ||||
|   JSAMPARRAY buffer;		/* Output row buffer */ | ||||
|   int row_stride;		/* physical row width in output buffer */ | ||||
| 
 | ||||
|   /* In this example we want to open the input file before doing anything else,
 | ||||
|    * so that the setjmp() error recovery below can assume the file is open. | ||||
|    * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that | ||||
|    * requires it in order to read binary files. | ||||
|    */ | ||||
| 
 | ||||
|   if ((infile = fopen(filename, "rb")) == NULL) { | ||||
|     fprintf(stderr, "can't open %s\n", filename); | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   /* Step 1: allocate and initialize JPEG decompression object */ | ||||
| 
 | ||||
|   /* We set up the normal JPEG error routines, then override error_exit. */ | ||||
|   cinfo.err = jpeg_std_error(&jerr.pub); | ||||
|   jerr.pub.error_exit = my_error_exit; | ||||
|   /* Establish the setjmp return context for my_error_exit to use. */ | ||||
|   if (setjmp(jerr.setjmp_buffer)) { | ||||
|     /* If we get here, the JPEG code has signaled an error.
 | ||||
|      * We need to clean up the JPEG object, close the input file, and return. | ||||
|      */ | ||||
|     jpeg_destroy_decompress(&cinfo); | ||||
|     fclose(infile); | ||||
|     return 0; | ||||
|   } | ||||
|   /* Now we can initialize the JPEG decompression object. */ | ||||
|   jpeg_create_decompress(&cinfo); | ||||
| 
 | ||||
|   /* Step 2: specify data source (eg, a file) */ | ||||
| 
 | ||||
|   jpeg_stdio_src(&cinfo, infile); | ||||
| 
 | ||||
|   /* Step 3: read file parameters with jpeg_read_header() */ | ||||
| 
 | ||||
|   (void) jpeg_read_header(&cinfo, TRUE); | ||||
|   /* We can ignore the return value from jpeg_read_header since
 | ||||
|    *   (a) suspension is not possible with the stdio data source, and | ||||
|    *   (b) we passed TRUE to reject a tables-only JPEG file as an error. | ||||
|    * See libjpeg.doc for more info. | ||||
|    */ | ||||
| 
 | ||||
|   /* Step 4: set parameters for decompression */ | ||||
| 
 | ||||
|   /* In this example, we don't need to change any of the defaults set by
 | ||||
|    * jpeg_read_header(), so we do nothing here. | ||||
|    */ | ||||
| 
 | ||||
|   /* Step 5: Start decompressor */ | ||||
| 
 | ||||
|   (void) jpeg_start_decompress(&cinfo); | ||||
|   /* We can ignore the return value since suspension is not possible
 | ||||
|    * with the stdio data source. | ||||
|    */ | ||||
| 
 | ||||
|   /* We may need to do some setup of our own at this point before reading
 | ||||
|    * the data.  After jpeg_start_decompress() we have the correct scaled | ||||
|    * output image dimensions available, as well as the output colormap | ||||
|    * if we asked for color quantization. | ||||
|    * In this example, we need to make an output work buffer of the right size. | ||||
|    */  | ||||
|   /* JSAMPLEs per row in output buffer */ | ||||
|   row_stride = cinfo.output_width * cinfo.output_components; | ||||
|   /* Make a one-row-high sample array that will go away when done with image */ | ||||
|   buffer = (*cinfo.mem->alloc_sarray) | ||||
| 		((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); | ||||
| 
 | ||||
|   /* Step 6: while (scan lines remain to be read) */ | ||||
|   /*           jpeg_read_scanlines(...); */ | ||||
| 
 | ||||
|   /* Here we use the library's state variable cinfo.output_scanline as the
 | ||||
|    * loop counter, so that we don't have to keep track ourselves. | ||||
|    */ | ||||
|   while (cinfo.output_scanline < cinfo.output_height) { | ||||
|     /* jpeg_read_scanlines expects an array of pointers to scanlines.
 | ||||
|      * Here the array is only one element long, but you could ask for | ||||
|      * more than one scanline at a time if that's more convenient. | ||||
|      */ | ||||
|     (void) jpeg_read_scanlines(&cinfo, buffer, 1); | ||||
|     /* Assume put_scanline_someplace wants a pointer and sample count. */ | ||||
|     put_scanline_someplace(buffer[0], row_stride); | ||||
|   } | ||||
| 
 | ||||
|   /* Step 7: Finish decompression */ | ||||
| 
 | ||||
|   (void) jpeg_finish_decompress(&cinfo); | ||||
|   /* We can ignore the return value since suspension is not possible
 | ||||
|    * with the stdio data source. | ||||
|    */ | ||||
| 
 | ||||
|   /* Step 8: Release JPEG decompression object */ | ||||
| 
 | ||||
|   /* This is an important step since it will release a good deal of memory. */ | ||||
|   jpeg_destroy_decompress(&cinfo); | ||||
| 
 | ||||
|   /* After finish_decompress, we can close the input file.
 | ||||
|    * Here we postpone it until after no more JPEG errors are possible, | ||||
|    * so as to simplify the setjmp error logic above.  (Actually, I don't | ||||
|    * think that jpeg_destroy can do an error exit, but why assume anything...) | ||||
|    */ | ||||
|   fclose(infile); | ||||
| 
 | ||||
|   /* At this point you may want to check to see whether any corrupt-data
 | ||||
|    * warnings occurred (test whether jerr.pub.num_warnings is nonzero). | ||||
|    */ | ||||
| 
 | ||||
|   /* And we're done! */ | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * SOME FINE POINTS: | ||||
|  * | ||||
|  * In the above code, we ignored the return value of jpeg_read_scanlines, | ||||
|  * which is the number of scanlines actually read.  We could get away with | ||||
|  * this because we asked for only one line at a time and we weren't using | ||||
|  * a suspending data source.  See libjpeg.doc for more info. | ||||
|  * | ||||
|  * We cheated a bit by calling alloc_sarray() after jpeg_start_decompress(); | ||||
|  * we should have done it beforehand to ensure that the space would be | ||||
|  * counted against the JPEG max_memory setting.  In some systems the above | ||||
|  * code would risk an out-of-memory error.  However, in general we don't | ||||
|  * know the output image dimensions before jpeg_start_decompress(), unless we | ||||
|  * call jpeg_calc_output_dimensions().  See libjpeg.doc for more about this. | ||||
|  * | ||||
|  * Scanlines are returned in the same order as they appear in the JPEG file, | ||||
|  * which is standardly top-to-bottom.  If you must emit data bottom-to-top, | ||||
|  * you can use one of the virtual arrays provided by the JPEG memory manager | ||||
|  * to invert the data.  See wrbmp.c for an example. | ||||
|  * | ||||
|  * As with compression, some operating modes may require temporary files. | ||||
|  * On some systems you may need to set up a signal handler to ensure that | ||||
|  * temporary files are deleted if the program is interrupted.  See libjpeg.doc. | ||||
|  */ | ||||
|  | @ -0,0 +1,210 @@ | |||
| IJG JPEG LIBRARY:  FILE LIST | ||||
| 
 | ||||
| Copyright (C) 1994-1998, 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. | ||||
| 
 | ||||
| 
 | ||||
| Here is a road map to the files in the IJG JPEG distribution.  The | ||||
| distribution includes the JPEG library proper, plus two application | ||||
| programs ("cjpeg" and "djpeg") which use the library to convert JPEG | ||||
| files to and from some other popular image formats.  A third application | ||||
| "jpegtran" uses the library to do lossless conversion between different | ||||
| variants of JPEG.  There are also two stand-alone applications, | ||||
| "rdjpgcom" and "wrjpgcom". | ||||
| 
 | ||||
| 
 | ||||
| THE JPEG LIBRARY | ||||
| ================ | ||||
| 
 | ||||
| Include files: | ||||
| 
 | ||||
| jpeglib.h	JPEG library's exported data and function declarations. | ||||
| jconfig.h	Configuration declarations.  Note: this file is not present | ||||
| 		in the distribution; it is generated during installation. | ||||
| jmorecfg.h	Additional configuration declarations; need not be changed | ||||
| 		for a standard installation. | ||||
| jerror.h	Declares JPEG library's error and trace message codes. | ||||
| jinclude.h	Central include file used by all IJG .c files to reference | ||||
| 		system include files. | ||||
| jpegint.h	JPEG library's internal data structures. | ||||
| jchuff.h	Private declarations for Huffman encoder modules. | ||||
| jdhuff.h	Private declarations for Huffman decoder modules. | ||||
| jdct.h		Private declarations for forward & reverse DCT subsystems. | ||||
| jmemsys.h	Private declarations for memory management subsystem. | ||||
| jversion.h	Version information. | ||||
| 
 | ||||
| Applications using the library should include jpeglib.h (which in turn | ||||
| includes jconfig.h and jmorecfg.h).  Optionally, jerror.h may be included | ||||
| if the application needs to reference individual JPEG error codes.  The | ||||
| other include files are intended for internal use and would not normally | ||||
| be included by an application program.  (cjpeg/djpeg/etc do use jinclude.h, | ||||
| since its function is to improve portability of the whole IJG distribution. | ||||
| Most other applications will directly include the system include files they | ||||
| want, and hence won't need jinclude.h.) | ||||
| 
 | ||||
| 
 | ||||
| C source code files: | ||||
| 
 | ||||
| These files contain most of the functions intended to be called directly by | ||||
| an application program: | ||||
| 
 | ||||
| jcapimin.c	Application program interface: core routines for compression. | ||||
| jcapistd.c	Application program interface: standard compression. | ||||
| jdapimin.c	Application program interface: core routines for decompression. | ||||
| jdapistd.c	Application program interface: standard decompression. | ||||
| jcomapi.c	Application program interface routines common to compression | ||||
| 		and decompression. | ||||
| jcparam.c	Compression parameter setting helper routines. | ||||
| jctrans.c	API and library routines for transcoding compression. | ||||
| jdtrans.c	API and library routines for transcoding decompression. | ||||
| 
 | ||||
| Compression side of the library: | ||||
| 
 | ||||
| jcinit.c	Initialization: determines which other modules to use. | ||||
| jcmaster.c	Master control: setup and inter-pass sequencing logic. | ||||
| jcmainct.c	Main buffer controller (preprocessor => JPEG compressor). | ||||
| jcprepct.c	Preprocessor buffer controller. | ||||
| jccoefct.c	Buffer controller for DCT coefficient buffer. | ||||
| jccolor.c	Color space conversion. | ||||
| jcsample.c	Downsampling. | ||||
| jcdctmgr.c	DCT manager (DCT implementation selection & control). | ||||
| jfdctint.c	Forward DCT using slow-but-accurate integer method. | ||||
| jfdctfst.c	Forward DCT using faster, less accurate integer method. | ||||
| jfdctflt.c	Forward DCT using floating-point arithmetic. | ||||
| jchuff.c	Huffman entropy coding for sequential JPEG. | ||||
| jcphuff.c	Huffman entropy coding for progressive JPEG. | ||||
| jcmarker.c	JPEG marker writing. | ||||
| jdatadst.c	Data destination manager for stdio output. | ||||
| 
 | ||||
| Decompression side of the library: | ||||
| 
 | ||||
| jdmaster.c	Master control: determines which other modules to use. | ||||
| jdinput.c	Input controller: controls input processing modules. | ||||
| jdmainct.c	Main buffer controller (JPEG decompressor => postprocessor). | ||||
| jdcoefct.c	Buffer controller for DCT coefficient buffer. | ||||
| jdpostct.c	Postprocessor buffer controller. | ||||
| jdmarker.c	JPEG marker reading. | ||||
| jdhuff.c	Huffman entropy decoding for sequential JPEG. | ||||
| jdphuff.c	Huffman entropy decoding for progressive JPEG. | ||||
| jddctmgr.c	IDCT manager (IDCT implementation selection & control). | ||||
| jidctint.c	Inverse DCT using slow-but-accurate integer method. | ||||
| jidctfst.c	Inverse DCT using faster, less accurate integer method. | ||||
| jidctflt.c	Inverse DCT using floating-point arithmetic. | ||||
| jidctred.c	Inverse DCTs with reduced-size outputs. | ||||
| jdsample.c	Upsampling. | ||||
| jdcolor.c	Color space conversion. | ||||
| jdmerge.c	Merged upsampling/color conversion (faster, lower quality). | ||||
| jquant1.c	One-pass color quantization using a fixed-spacing colormap. | ||||
| jquant2.c	Two-pass color quantization using a custom-generated colormap. | ||||
| 		Also handles one-pass quantization to an externally given map. | ||||
| jdatasrc.c	Data source manager for stdio input. | ||||
| 
 | ||||
| Support files for both compression and decompression: | ||||
| 
 | ||||
| jerror.c	Standard error handling routines (application replaceable). | ||||
| jmemmgr.c	System-independent (more or less) memory management code. | ||||
| jutils.c	Miscellaneous utility routines. | ||||
| 
 | ||||
| jmemmgr.c relies on a system-dependent memory management module.  The IJG | ||||
| distribution includes the following implementations of the system-dependent | ||||
| module: | ||||
| 
 | ||||
| jmemnobs.c	"No backing store": assumes adequate virtual memory exists. | ||||
| jmemansi.c	Makes temporary files with ANSI-standard routine tmpfile(). | ||||
| jmemname.c	Makes temporary files with program-generated file names. | ||||
| jmemdos.c	Custom implementation for MS-DOS (16-bit environment only): | ||||
| 		can use extended and expanded memory as well as temp files. | ||||
| jmemmac.c	Custom implementation for Apple Macintosh. | ||||
| 
 | ||||
| Exactly one of the system-dependent modules should be configured into an | ||||
| installed JPEG library (see install.doc for hints about which one to use). | ||||
| On unusual systems you may find it worthwhile to make a special | ||||
| system-dependent memory manager. | ||||
| 
 | ||||
| 
 | ||||
| Non-C source code files: | ||||
| 
 | ||||
| jmemdosa.asm	80x86 assembly code support for jmemdos.c; used only in | ||||
| 		MS-DOS-specific configurations of the JPEG library. | ||||
| 
 | ||||
| 
 | ||||
| CJPEG/DJPEG/JPEGTRAN | ||||
| ==================== | ||||
| 
 | ||||
| Include files: | ||||
| 
 | ||||
| cdjpeg.h	Declarations shared by cjpeg/djpeg/jpegtran modules. | ||||
| cderror.h	Additional error and trace message codes for cjpeg et al. | ||||
| transupp.h	Declarations for jpegtran support routines in transupp.c. | ||||
| 
 | ||||
| C source code files: | ||||
| 
 | ||||
| cjpeg.c		Main program for cjpeg. | ||||
| djpeg.c		Main program for djpeg. | ||||
| jpegtran.c	Main program for jpegtran. | ||||
| cdjpeg.c	Utility routines used by all three programs. | ||||
| rdcolmap.c	Code to read a colormap file for djpeg's "-map" switch. | ||||
| rdswitch.c	Code to process some of cjpeg's more complex switches. | ||||
| 		Also used by jpegtran. | ||||
| transupp.c	Support code for jpegtran: lossless image manipulations. | ||||
| 
 | ||||
| Image file reader modules for cjpeg: | ||||
| 
 | ||||
| rdbmp.c		BMP file input. | ||||
| rdgif.c		GIF file input (now just a stub). | ||||
| rdppm.c		PPM/PGM file input. | ||||
| rdrle.c		Utah RLE file input. | ||||
| rdtarga.c	Targa file input. | ||||
| 
 | ||||
| Image file writer modules for djpeg: | ||||
| 
 | ||||
| wrbmp.c		BMP file output. | ||||
| wrgif.c		GIF file output (a mere shadow of its former self). | ||||
| wrppm.c		PPM/PGM file output. | ||||
| wrrle.c		Utah RLE file output. | ||||
| wrtarga.c	Targa file output. | ||||
| 
 | ||||
| 
 | ||||
| RDJPGCOM/WRJPGCOM | ||||
| ================= | ||||
| 
 | ||||
| C source code files: | ||||
| 
 | ||||
| rdjpgcom.c	Stand-alone rdjpgcom application. | ||||
| wrjpgcom.c	Stand-alone wrjpgcom application. | ||||
| 
 | ||||
| These programs do not depend on the IJG library.  They do use | ||||
| jconfig.h and jinclude.h, only to improve portability. | ||||
| 
 | ||||
| 
 | ||||
| ADDITIONAL FILES | ||||
| ================ | ||||
| 
 | ||||
| Documentation (see README for a guide to the documentation files): | ||||
| 
 | ||||
| README		Master documentation file. | ||||
| *.doc		Other documentation files. | ||||
| *.1		Documentation in Unix man page format. | ||||
| change.log	Version-to-version change highlights. | ||||
| example.c	Sample code for calling JPEG library. | ||||
| 
 | ||||
| Configuration/installation files and programs (see install.doc for more info): | ||||
| 
 | ||||
| configure	Unix shell script to perform automatic configuration. | ||||
| ltconfig	Support scripts for configure (from GNU libtool). | ||||
| ltmain.sh | ||||
| config.guess | ||||
| config.sub | ||||
| install-sh	Install shell script for those Unix systems lacking one. | ||||
| ckconfig.c	Program to generate jconfig.h on non-Unix systems. | ||||
| jconfig.doc	Template for making jconfig.h by hand. | ||||
| makefile.*	Sample makefiles for particular systems. | ||||
| jconfig.*	Sample jconfig.h for particular systems. | ||||
| ansi2knr.c	De-ANSIfier for pre-ANSI C compilers (courtesy of | ||||
| 		L. Peter Deutsch and Aladdin Enterprises). | ||||
| 
 | ||||
| Test files (see install.doc for test procedure): | ||||
| 
 | ||||
| test*.*		Source and comparison files for confidence test. | ||||
| 		These are binary image files, NOT text files. | ||||
|  | @ -0,0 +1,280 @@ | |||
| /*
 | ||||
|  * jcapimin.c | ||||
|  * | ||||
|  * Copyright (C) 1994-1998, 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 application interface code for the compression half | ||||
|  * of the JPEG library.  These are the "minimum" API routines that may be | ||||
|  * needed in either the normal full-compression case or the transcoding-only | ||||
|  * case. | ||||
|  * | ||||
|  * Most of the routines intended to be called directly by an application | ||||
|  * are in this file or in jcapistd.c.  But also see jcparam.c for | ||||
|  * parameter-setup helper routines, jcomapi.c for routines shared by | ||||
|  * compression and decompression, and jctrans.c for the transcoding case. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialization of a JPEG compression object. | ||||
|  * The error manager must already be set up (in case memory manager fails). | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_CreateCompress (j_compress_ptr cinfo, int version, size_t structsize) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   /* Guard against version mismatches between library and caller. */ | ||||
|   cinfo->mem = NULL;		/* so jpeg_destroy knows mem mgr not called */ | ||||
|   if (version != JPEG_LIB_VERSION) | ||||
|     ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); | ||||
|   if (structsize != SIZEOF(struct jpeg_compress_struct)) | ||||
|     ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,  | ||||
| 	     (int) SIZEOF(struct jpeg_compress_struct), (int) structsize); | ||||
| 
 | ||||
|   /* For debugging purposes, we zero the whole master structure.
 | ||||
|    * But the application has already set the err pointer, and may have set | ||||
|    * client_data, so we have to save and restore those fields. | ||||
|    * Note: if application hasn't set client_data, tools like Purify may | ||||
|    * complain here. | ||||
|    */ | ||||
|   { | ||||
|     struct jpeg_error_mgr * err = cinfo->err; | ||||
|     void * client_data = cinfo->client_data; /* ignore Purify complaint here */ | ||||
|     MEMZERO(cinfo, SIZEOF(struct jpeg_compress_struct)); | ||||
|     cinfo->err = err; | ||||
|     cinfo->client_data = client_data; | ||||
|   } | ||||
|   cinfo->is_decompressor = FALSE; | ||||
| 
 | ||||
|   /* Initialize a memory manager instance for this object */ | ||||
|   jinit_memory_mgr((j_common_ptr) cinfo); | ||||
| 
 | ||||
|   /* Zero out pointers to permanent structures. */ | ||||
|   cinfo->progress = NULL; | ||||
|   cinfo->dest = NULL; | ||||
| 
 | ||||
|   cinfo->comp_info = NULL; | ||||
| 
 | ||||
|   for (i = 0; i < NUM_QUANT_TBLS; i++) | ||||
|     cinfo->quant_tbl_ptrs[i] = NULL; | ||||
| 
 | ||||
|   for (i = 0; i < NUM_HUFF_TBLS; i++) { | ||||
|     cinfo->dc_huff_tbl_ptrs[i] = NULL; | ||||
|     cinfo->ac_huff_tbl_ptrs[i] = NULL; | ||||
|   } | ||||
| 
 | ||||
|   cinfo->script_space = NULL; | ||||
| 
 | ||||
|   cinfo->input_gamma = 1.0;	/* in case application forgets */ | ||||
| 
 | ||||
|   /* OK, I'm ready */ | ||||
|   cinfo->global_state = CSTATE_START; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Destruction of a JPEG compression object | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_destroy_compress (j_compress_ptr cinfo) | ||||
| { | ||||
|   jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Abort processing of a JPEG compression operation, | ||||
|  * but don't destroy the object itself. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_abort_compress (j_compress_ptr cinfo) | ||||
| { | ||||
|   jpeg_abort((j_common_ptr) cinfo); /* use common routine */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Forcibly suppress or un-suppress all quantization and Huffman tables. | ||||
|  * Marks all currently defined tables as already written (if suppress) | ||||
|  * or not written (if !suppress).  This will control whether they get emitted | ||||
|  * by a subsequent jpeg_start_compress call. | ||||
|  * | ||||
|  * This routine is exported for use by applications that want to produce | ||||
|  * abbreviated JPEG datastreams.  It logically belongs in jcparam.c, but | ||||
|  * since it is called by jpeg_start_compress, we put it here --- otherwise | ||||
|  * jcparam.o would be linked whether the application used it or not. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_suppress_tables (j_compress_ptr cinfo, boolean suppress) | ||||
| { | ||||
|   int i; | ||||
|   JQUANT_TBL * qtbl; | ||||
|   JHUFF_TBL * htbl; | ||||
| 
 | ||||
|   for (i = 0; i < NUM_QUANT_TBLS; i++) { | ||||
|     if ((qtbl = cinfo->quant_tbl_ptrs[i]) != NULL) | ||||
|       qtbl->sent_table = suppress; | ||||
|   } | ||||
| 
 | ||||
|   for (i = 0; i < NUM_HUFF_TBLS; i++) { | ||||
|     if ((htbl = cinfo->dc_huff_tbl_ptrs[i]) != NULL) | ||||
|       htbl->sent_table = suppress; | ||||
|     if ((htbl = cinfo->ac_huff_tbl_ptrs[i]) != NULL) | ||||
|       htbl->sent_table = suppress; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Finish JPEG compression. | ||||
|  * | ||||
|  * If a multipass operating mode was selected, this may do a great deal of | ||||
|  * work including most of the actual output. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_finish_compress (j_compress_ptr cinfo) | ||||
| { | ||||
|   JDIMENSION iMCU_row; | ||||
| 
 | ||||
|   if (cinfo->global_state == CSTATE_SCANNING || | ||||
|       cinfo->global_state == CSTATE_RAW_OK) { | ||||
|     /* Terminate first pass */ | ||||
|     if (cinfo->next_scanline < cinfo->image_height) | ||||
|       ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); | ||||
|     (*cinfo->master->finish_pass) (cinfo); | ||||
|   } else if (cinfo->global_state != CSTATE_WRCOEFS) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   /* Perform any remaining passes */ | ||||
|   while (! cinfo->master->is_last_pass) { | ||||
|     (*cinfo->master->prepare_for_pass) (cinfo); | ||||
|     for (iMCU_row = 0; iMCU_row < cinfo->total_iMCU_rows; iMCU_row++) { | ||||
|       if (cinfo->progress != NULL) { | ||||
| 	cinfo->progress->pass_counter = (long) iMCU_row; | ||||
| 	cinfo->progress->pass_limit = (long) cinfo->total_iMCU_rows; | ||||
| 	(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); | ||||
|       } | ||||
|       /* We bypass the main controller and invoke coef controller directly;
 | ||||
|        * all work is being done from the coefficient buffer. | ||||
|        */ | ||||
|       if (! (*cinfo->coef->compress_data) (cinfo, (JSAMPIMAGE) NULL)) | ||||
| 	ERREXIT(cinfo, JERR_CANT_SUSPEND); | ||||
|     } | ||||
|     (*cinfo->master->finish_pass) (cinfo); | ||||
|   } | ||||
|   /* Write EOI, do final cleanup */ | ||||
|   (*cinfo->marker->write_file_trailer) (cinfo); | ||||
|   (*cinfo->dest->term_destination) (cinfo); | ||||
|   /* We can use jpeg_abort to release memory and reset global_state */ | ||||
|   jpeg_abort((j_common_ptr) cinfo); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Write a special marker. | ||||
|  * This is only recommended for writing COM or APPn markers. | ||||
|  * Must be called after jpeg_start_compress() and before | ||||
|  * first call to jpeg_write_scanlines() or jpeg_write_raw_data(). | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_write_marker (j_compress_ptr cinfo, int marker, | ||||
| 		   const JOCTET *dataptr, unsigned int datalen) | ||||
| { | ||||
|   JMETHOD(void, write_marker_byte, (j_compress_ptr info, int val)); | ||||
| 
 | ||||
|   if (cinfo->next_scanline != 0 || | ||||
|       (cinfo->global_state != CSTATE_SCANNING && | ||||
|        cinfo->global_state != CSTATE_RAW_OK && | ||||
|        cinfo->global_state != CSTATE_WRCOEFS)) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
| 
 | ||||
|   (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); | ||||
|   write_marker_byte = cinfo->marker->write_marker_byte;	/* copy for speed */ | ||||
|   while (datalen--) { | ||||
|     (*write_marker_byte) (cinfo, *dataptr); | ||||
|     dataptr++; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| /* Same, but piecemeal. */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_write_m_header (j_compress_ptr cinfo, int marker, unsigned int datalen) | ||||
| { | ||||
|   if (cinfo->next_scanline != 0 || | ||||
|       (cinfo->global_state != CSTATE_SCANNING && | ||||
|        cinfo->global_state != CSTATE_RAW_OK && | ||||
|        cinfo->global_state != CSTATE_WRCOEFS)) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
| 
 | ||||
|   (*cinfo->marker->write_marker_header) (cinfo, marker, datalen); | ||||
| } | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_write_m_byte (j_compress_ptr cinfo, int val) | ||||
| { | ||||
|   (*cinfo->marker->write_marker_byte) (cinfo, val); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Alternate compression function: just write an abbreviated table file. | ||||
|  * Before calling this, all parameters and a data destination must be set up. | ||||
|  * | ||||
|  * To produce a pair of files containing abbreviated tables and abbreviated | ||||
|  * image data, one would proceed as follows: | ||||
|  * | ||||
|  *		initialize JPEG object | ||||
|  *		set JPEG parameters | ||||
|  *		set destination to table file | ||||
|  *		jpeg_write_tables(cinfo); | ||||
|  *		set destination to image file | ||||
|  *		jpeg_start_compress(cinfo, FALSE); | ||||
|  *		write data... | ||||
|  *		jpeg_finish_compress(cinfo); | ||||
|  * | ||||
|  * jpeg_write_tables has the side effect of marking all tables written | ||||
|  * (same as jpeg_suppress_tables(..., TRUE)).  Thus a subsequent start_compress | ||||
|  * will not re-emit the tables unless it is passed write_all_tables=TRUE. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_write_tables (j_compress_ptr cinfo) | ||||
| { | ||||
|   if (cinfo->global_state != CSTATE_START) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
| 
 | ||||
|   /* (Re)initialize error mgr and destination modules */ | ||||
|   (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); | ||||
|   (*cinfo->dest->init_destination) (cinfo); | ||||
|   /* Initialize the marker writer ... bit of a crock to do it here. */ | ||||
|   jinit_marker_writer(cinfo); | ||||
|   /* Write them tables! */ | ||||
|   (*cinfo->marker->write_tables_only) (cinfo); | ||||
|   /* And clean up. */ | ||||
|   (*cinfo->dest->term_destination) (cinfo); | ||||
|   /*
 | ||||
|    * In library releases up through v6a, we called jpeg_abort() here to free | ||||
|    * any working memory allocated by the destination manager and marker | ||||
|    * writer.  Some applications had a problem with that: they allocated space | ||||
|    * of their own from the library memory manager, and didn't want it to go | ||||
|    * away during write_tables.  So now we do nothing.  This will cause a | ||||
|    * memory leak if an app calls write_tables repeatedly without doing a full | ||||
|    * compression cycle or otherwise resetting the JPEG object.  However, that | ||||
|    * seems less bad than unexpectedly freeing memory in the normal case. | ||||
|    * An app that prefers the old behavior can call jpeg_abort for itself after | ||||
|    * each call to jpeg_write_tables(). | ||||
|    */ | ||||
| } | ||||
|  | @ -0,0 +1,161 @@ | |||
| /*
 | ||||
|  * jcapistd.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 application interface code for the compression half | ||||
|  * of the JPEG library.  These are the "standard" API routines that are | ||||
|  * used in the normal full-compression case.  They are not used by a | ||||
|  * transcoding-only application.  Note that if an application links in | ||||
|  * jpeg_start_compress, it will end up linking in the entire compressor. | ||||
|  * We thus must separate this file from jcapimin.c to avoid linking the | ||||
|  * whole compression library into a transcoder. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Compression initialization. | ||||
|  * Before calling this, all parameters and a data destination must be set up. | ||||
|  * | ||||
|  * We require a write_all_tables parameter as a failsafe check when writing | ||||
|  * multiple datastreams from the same compression object.  Since prior runs | ||||
|  * will have left all the tables marked sent_table=TRUE, a subsequent run | ||||
|  * would emit an abbreviated stream (no tables) by default.  This may be what | ||||
|  * is wanted, but for safety's sake it should not be the default behavior: | ||||
|  * programmers should have to make a deliberate choice to emit abbreviated | ||||
|  * images.  Therefore the documentation and examples should encourage people | ||||
|  * to pass write_all_tables=TRUE; then it will take active thought to do the | ||||
|  * wrong thing. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_start_compress (j_compress_ptr cinfo, boolean write_all_tables) | ||||
| { | ||||
|   if (cinfo->global_state != CSTATE_START) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
| 
 | ||||
|   if (write_all_tables) | ||||
|     jpeg_suppress_tables(cinfo, FALSE);	/* mark all tables to be written */ | ||||
| 
 | ||||
|   /* (Re)initialize error mgr and destination modules */ | ||||
|   (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); | ||||
|   (*cinfo->dest->init_destination) (cinfo); | ||||
|   /* Perform master selection of active modules */ | ||||
|   jinit_compress_master(cinfo); | ||||
|   /* Set up for the first pass */ | ||||
|   (*cinfo->master->prepare_for_pass) (cinfo); | ||||
|   /* Ready for application to drive first pass through jpeg_write_scanlines
 | ||||
|    * or jpeg_write_raw_data. | ||||
|    */ | ||||
|   cinfo->next_scanline = 0; | ||||
|   cinfo->global_state = (cinfo->raw_data_in ? CSTATE_RAW_OK : CSTATE_SCANNING); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Write some scanlines of data to the JPEG compressor. | ||||
|  * | ||||
|  * The return value will be the number of lines actually written. | ||||
|  * This should be less than the supplied num_lines only in case that | ||||
|  * the data destination module has requested suspension of the compressor, | ||||
|  * or if more than image_height scanlines are passed in. | ||||
|  * | ||||
|  * Note: we warn about excess calls to jpeg_write_scanlines() since | ||||
|  * this likely signals an application programmer error.  However, | ||||
|  * excess scanlines passed in the last valid call are *silently* ignored, | ||||
|  * so that the application need not adjust num_lines for end-of-image | ||||
|  * when using a multiple-scanline buffer. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(JDIMENSION) | ||||
| jpeg_write_scanlines (j_compress_ptr cinfo, JSAMPARRAY scanlines, | ||||
| 		      JDIMENSION num_lines) | ||||
| { | ||||
|   JDIMENSION row_ctr, rows_left; | ||||
| 
 | ||||
|   if (cinfo->global_state != CSTATE_SCANNING) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   if (cinfo->next_scanline >= cinfo->image_height) | ||||
|     WARNMS(cinfo, JWRN_TOO_MUCH_DATA); | ||||
| 
 | ||||
|   /* Call progress monitor hook if present */ | ||||
|   if (cinfo->progress != NULL) { | ||||
|     cinfo->progress->pass_counter = (long) cinfo->next_scanline; | ||||
|     cinfo->progress->pass_limit = (long) cinfo->image_height; | ||||
|     (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); | ||||
|   } | ||||
| 
 | ||||
|   /* Give master control module another chance if this is first call to
 | ||||
|    * jpeg_write_scanlines.  This lets output of the frame/scan headers be | ||||
|    * delayed so that application can write COM, etc, markers between | ||||
|    * jpeg_start_compress and jpeg_write_scanlines. | ||||
|    */ | ||||
|   if (cinfo->master->call_pass_startup) | ||||
|     (*cinfo->master->pass_startup) (cinfo); | ||||
| 
 | ||||
|   /* Ignore any extra scanlines at bottom of image. */ | ||||
|   rows_left = cinfo->image_height - cinfo->next_scanline; | ||||
|   if (num_lines > rows_left) | ||||
|     num_lines = rows_left; | ||||
| 
 | ||||
|   row_ctr = 0; | ||||
|   (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, num_lines); | ||||
|   cinfo->next_scanline += row_ctr; | ||||
|   return row_ctr; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Alternate entry point to write raw data. | ||||
|  * Processes exactly one iMCU row per call, unless suspended. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(JDIMENSION) | ||||
| jpeg_write_raw_data (j_compress_ptr cinfo, JSAMPIMAGE data, | ||||
| 		     JDIMENSION num_lines) | ||||
| { | ||||
|   JDIMENSION lines_per_iMCU_row; | ||||
| 
 | ||||
|   if (cinfo->global_state != CSTATE_RAW_OK) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   if (cinfo->next_scanline >= cinfo->image_height) { | ||||
|     WARNMS(cinfo, JWRN_TOO_MUCH_DATA); | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   /* Call progress monitor hook if present */ | ||||
|   if (cinfo->progress != NULL) { | ||||
|     cinfo->progress->pass_counter = (long) cinfo->next_scanline; | ||||
|     cinfo->progress->pass_limit = (long) cinfo->image_height; | ||||
|     (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); | ||||
|   } | ||||
| 
 | ||||
|   /* Give master control module another chance if this is first call to
 | ||||
|    * jpeg_write_raw_data.  This lets output of the frame/scan headers be | ||||
|    * delayed so that application can write COM, etc, markers between | ||||
|    * jpeg_start_compress and jpeg_write_raw_data. | ||||
|    */ | ||||
|   if (cinfo->master->call_pass_startup) | ||||
|     (*cinfo->master->pass_startup) (cinfo); | ||||
| 
 | ||||
|   /* Verify that at least one iMCU row has been passed. */ | ||||
|   lines_per_iMCU_row = cinfo->max_v_samp_factor * DCTSIZE; | ||||
|   if (num_lines < lines_per_iMCU_row) | ||||
|     ERREXIT(cinfo, JERR_BUFFER_SIZE); | ||||
| 
 | ||||
|   /* Directly compress the row. */ | ||||
|   if (! (*cinfo->coef->compress_data) (cinfo, data)) { | ||||
|     /* If compressor did not consume the whole row, suspend processing. */ | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   /* OK, we processed one iMCU row. */ | ||||
|   cinfo->next_scanline += lines_per_iMCU_row; | ||||
|   return lines_per_iMCU_row; | ||||
| } | ||||
|  | @ -0,0 +1,449 @@ | |||
| /*
 | ||||
|  * jccoefct.c | ||||
|  * | ||||
|  * Copyright (C) 1994-1997, 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 the coefficient buffer controller for compression. | ||||
|  * This controller is the top level of the JPEG compressor proper. | ||||
|  * The coefficient buffer lies between forward-DCT and entropy encoding steps. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /* We use a full-image coefficient buffer when doing Huffman optimization,
 | ||||
|  * and also for writing multiple-scan JPEG files.  In all cases, the DCT | ||||
|  * step is run during the first pass, and subsequent passes need only read | ||||
|  * the buffered coefficients. | ||||
|  */ | ||||
| #ifdef ENTROPY_OPT_SUPPORTED | ||||
| #define FULL_COEF_BUFFER_SUPPORTED | ||||
| #else | ||||
| #ifdef C_MULTISCAN_FILES_SUPPORTED | ||||
| #define FULL_COEF_BUFFER_SUPPORTED | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* Private buffer controller object */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_c_coef_controller pub; /* public fields */ | ||||
| 
 | ||||
|   JDIMENSION iMCU_row_num;	/* iMCU row # within image */ | ||||
|   JDIMENSION mcu_ctr;		/* counts MCUs processed in current row */ | ||||
|   int MCU_vert_offset;		/* counts MCU rows within iMCU row */ | ||||
|   int MCU_rows_per_iMCU_row;	/* number of such rows needed */ | ||||
| 
 | ||||
|   /* For single-pass compression, it's sufficient to buffer just one MCU
 | ||||
|    * (although this may prove a bit slow in practice).  We allocate a | ||||
|    * workspace of C_MAX_BLOCKS_IN_MCU coefficient blocks, and reuse it for each | ||||
|    * MCU constructed and sent.  (On 80x86, the workspace is FAR even though | ||||
|    * it's not really very big; this is to keep the module interfaces unchanged | ||||
|    * when a large coefficient buffer is necessary.) | ||||
|    * In multi-pass modes, this array points to the current MCU's blocks | ||||
|    * within the virtual arrays. | ||||
|    */ | ||||
|   JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; | ||||
| 
 | ||||
|   /* In multi-pass modes, we need a virtual block array for each component. */ | ||||
|   jvirt_barray_ptr whole_image[MAX_COMPONENTS]; | ||||
| } my_coef_controller; | ||||
| 
 | ||||
| typedef my_coef_controller * my_coef_ptr; | ||||
| 
 | ||||
| 
 | ||||
| /* Forward declarations */ | ||||
| METHODDEF(boolean) compress_data | ||||
|     JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); | ||||
| #ifdef FULL_COEF_BUFFER_SUPPORTED | ||||
| METHODDEF(boolean) compress_first_pass | ||||
|     JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); | ||||
| METHODDEF(boolean) compress_output | ||||
|     JPP((j_compress_ptr cinfo, JSAMPIMAGE input_buf)); | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| start_iMCU_row (j_compress_ptr cinfo) | ||||
| /* Reset within-iMCU-row counters for a new row */ | ||||
| { | ||||
|   my_coef_ptr coef = (my_coef_ptr) cinfo->coef; | ||||
| 
 | ||||
|   /* In an interleaved scan, an MCU row is the same as an iMCU row.
 | ||||
|    * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. | ||||
|    * But at the bottom of the image, process only what's left. | ||||
|    */ | ||||
|   if (cinfo->comps_in_scan > 1) { | ||||
|     coef->MCU_rows_per_iMCU_row = 1; | ||||
|   } else { | ||||
|     if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) | ||||
|       coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; | ||||
|     else | ||||
|       coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; | ||||
|   } | ||||
| 
 | ||||
|   coef->mcu_ctr = 0; | ||||
|   coef->MCU_vert_offset = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize for a processing pass. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) | ||||
| { | ||||
|   my_coef_ptr coef = (my_coef_ptr) cinfo->coef; | ||||
| 
 | ||||
|   coef->iMCU_row_num = 0; | ||||
|   start_iMCU_row(cinfo); | ||||
| 
 | ||||
|   switch (pass_mode) { | ||||
|   case JBUF_PASS_THRU: | ||||
|     if (coef->whole_image[0] != NULL) | ||||
|       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
|     coef->pub.compress_data = compress_data; | ||||
|     break; | ||||
| #ifdef FULL_COEF_BUFFER_SUPPORTED | ||||
|   case JBUF_SAVE_AND_PASS: | ||||
|     if (coef->whole_image[0] == NULL) | ||||
|       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
|     coef->pub.compress_data = compress_first_pass; | ||||
|     break; | ||||
|   case JBUF_CRANK_DEST: | ||||
|     if (coef->whole_image[0] == NULL) | ||||
|       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
|     coef->pub.compress_data = compress_output; | ||||
|     break; | ||||
| #endif | ||||
|   default: | ||||
|     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
|     break; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Process some data in the single-pass case. | ||||
|  * We process the equivalent of one fully interleaved MCU row ("iMCU" row) | ||||
|  * per call, ie, v_samp_factor block rows for each component in the image. | ||||
|  * Returns TRUE if the iMCU row is completed, FALSE if suspended. | ||||
|  * | ||||
|  * NB: input_buf contains a plane for each component in image, | ||||
|  * which we index according to the component's SOF position. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(boolean) | ||||
| compress_data (j_compress_ptr cinfo, JSAMPIMAGE input_buf) | ||||
| { | ||||
|   my_coef_ptr coef = (my_coef_ptr) cinfo->coef; | ||||
|   JDIMENSION MCU_col_num;	/* index of current MCU within row */ | ||||
|   JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; | ||||
|   JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; | ||||
|   int blkn, bi, ci, yindex, yoffset, blockcnt; | ||||
|   JDIMENSION ypos, xpos; | ||||
|   jpeg_component_info *compptr; | ||||
| 
 | ||||
|   /* Loop to write as much as one whole iMCU row */ | ||||
|   for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; | ||||
|        yoffset++) { | ||||
|     for (MCU_col_num = coef->mcu_ctr; MCU_col_num <= last_MCU_col; | ||||
| 	 MCU_col_num++) { | ||||
|       /* Determine where data comes from in input_buf and do the DCT thing.
 | ||||
|        * Each call on forward_DCT processes a horizontal row of DCT blocks | ||||
|        * as wide as an MCU; we rely on having allocated the MCU_buffer[] blocks | ||||
|        * sequentially.  Dummy blocks at the right or bottom edge are filled in | ||||
|        * specially.  The data in them does not matter for image reconstruction, | ||||
|        * so we fill them with values that will encode to the smallest amount of | ||||
|        * data, viz: all zeroes in the AC entries, DC entries equal to previous | ||||
|        * block's DC value.  (Thanks to Thomas Kinsman for this idea.) | ||||
|        */ | ||||
|       blkn = 0; | ||||
|       for (ci = 0; ci < cinfo->comps_in_scan; ci++) { | ||||
| 	compptr = cinfo->cur_comp_info[ci]; | ||||
| 	blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width | ||||
| 						: compptr->last_col_width; | ||||
| 	xpos = MCU_col_num * compptr->MCU_sample_width; | ||||
| 	ypos = yoffset * DCTSIZE; /* ypos == (yoffset+yindex) * DCTSIZE */ | ||||
| 	for (yindex = 0; yindex < compptr->MCU_height; yindex++) { | ||||
| 	  if (coef->iMCU_row_num < last_iMCU_row || | ||||
| 	      yoffset+yindex < compptr->last_row_height) { | ||||
| 	    (*cinfo->fdct->forward_DCT) (cinfo, compptr, | ||||
| 					 input_buf[compptr->component_index], | ||||
| 					 coef->MCU_buffer[blkn], | ||||
| 					 ypos, xpos, (JDIMENSION) blockcnt); | ||||
| 	    if (blockcnt < compptr->MCU_width) { | ||||
| 	      /* Create some dummy blocks at the right edge of the image. */ | ||||
| 	      jzero_far((void FAR *) coef->MCU_buffer[blkn + blockcnt], | ||||
| 			(compptr->MCU_width - blockcnt) * SIZEOF(JBLOCK)); | ||||
| 	      for (bi = blockcnt; bi < compptr->MCU_width; bi++) { | ||||
| 		coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn+bi-1][0][0]; | ||||
| 	      } | ||||
| 	    } | ||||
| 	  } else { | ||||
| 	    /* Create a row of dummy blocks at the bottom of the image. */ | ||||
| 	    jzero_far((void FAR *) coef->MCU_buffer[blkn], | ||||
| 		      compptr->MCU_width * SIZEOF(JBLOCK)); | ||||
| 	    for (bi = 0; bi < compptr->MCU_width; bi++) { | ||||
| 	      coef->MCU_buffer[blkn+bi][0][0] = coef->MCU_buffer[blkn-1][0][0]; | ||||
| 	    } | ||||
| 	  } | ||||
| 	  blkn += compptr->MCU_width; | ||||
| 	  ypos += DCTSIZE; | ||||
| 	} | ||||
|       } | ||||
|       /* Try to write the MCU.  In event of a suspension failure, we will
 | ||||
|        * re-DCT the MCU on restart (a bit inefficient, could be fixed...) | ||||
|        */ | ||||
|       if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { | ||||
| 	/* Suspension forced; update state counters and exit */ | ||||
| 	coef->MCU_vert_offset = yoffset; | ||||
| 	coef->mcu_ctr = MCU_col_num; | ||||
| 	return FALSE; | ||||
|       } | ||||
|     } | ||||
|     /* Completed an MCU row, but perhaps not an iMCU row */ | ||||
|     coef->mcu_ctr = 0; | ||||
|   } | ||||
|   /* Completed the iMCU row, advance counters for next one */ | ||||
|   coef->iMCU_row_num++; | ||||
|   start_iMCU_row(cinfo); | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef FULL_COEF_BUFFER_SUPPORTED | ||||
| 
 | ||||
| /*
 | ||||
|  * Process some data in the first pass of a multi-pass case. | ||||
|  * We process the equivalent of one fully interleaved MCU row ("iMCU" row) | ||||
|  * per call, ie, v_samp_factor block rows for each component in the image. | ||||
|  * This amount of data is read from the source buffer, DCT'd and quantized, | ||||
|  * and saved into the virtual arrays.  We also generate suitable dummy blocks | ||||
|  * as needed at the right and lower edges.  (The dummy blocks are constructed | ||||
|  * in the virtual arrays, which have been padded appropriately.)  This makes | ||||
|  * it possible for subsequent passes not to worry about real vs. dummy blocks. | ||||
|  * | ||||
|  * We must also emit the data to the entropy encoder.  This is conveniently | ||||
|  * done by calling compress_output() after we've loaded the current strip | ||||
|  * of the virtual arrays. | ||||
|  * | ||||
|  * NB: input_buf contains a plane for each component in image.  All | ||||
|  * components are DCT'd and loaded into the virtual arrays in this pass. | ||||
|  * However, it may be that only a subset of the components are emitted to | ||||
|  * the entropy encoder during this first pass; be careful about looking | ||||
|  * at the scan-dependent variables (MCU dimensions, etc). | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(boolean) | ||||
| compress_first_pass (j_compress_ptr cinfo, JSAMPIMAGE input_buf) | ||||
| { | ||||
|   my_coef_ptr coef = (my_coef_ptr) cinfo->coef; | ||||
|   JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; | ||||
|   JDIMENSION blocks_across, MCUs_across, MCUindex; | ||||
|   int bi, ci, h_samp_factor, block_row, block_rows, ndummy; | ||||
|   JCOEF lastDC; | ||||
|   jpeg_component_info *compptr; | ||||
|   JBLOCKARRAY buffer; | ||||
|   JBLOCKROW thisblockrow, lastblockrow; | ||||
| 
 | ||||
|   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
|        ci++, compptr++) { | ||||
|     /* Align the virtual buffer for this component. */ | ||||
|     buffer = (*cinfo->mem->access_virt_barray) | ||||
|       ((j_common_ptr) cinfo, coef->whole_image[ci], | ||||
|        coef->iMCU_row_num * compptr->v_samp_factor, | ||||
|        (JDIMENSION) compptr->v_samp_factor, TRUE); | ||||
|     /* Count non-dummy DCT block rows in this iMCU row. */ | ||||
|     if (coef->iMCU_row_num < last_iMCU_row) | ||||
|       block_rows = compptr->v_samp_factor; | ||||
|     else { | ||||
|       /* NB: can't use last_row_height here, since may not be set! */ | ||||
|       block_rows = (int) (compptr->height_in_blocks % compptr->v_samp_factor); | ||||
|       if (block_rows == 0) block_rows = compptr->v_samp_factor; | ||||
|     } | ||||
|     blocks_across = compptr->width_in_blocks; | ||||
|     h_samp_factor = compptr->h_samp_factor; | ||||
|     /* Count number of dummy blocks to be added at the right margin. */ | ||||
|     ndummy = (int) (blocks_across % h_samp_factor); | ||||
|     if (ndummy > 0) | ||||
|       ndummy = h_samp_factor - ndummy; | ||||
|     /* Perform DCT for all non-dummy blocks in this iMCU row.  Each call
 | ||||
|      * on forward_DCT processes a complete horizontal row of DCT blocks. | ||||
|      */ | ||||
|     for (block_row = 0; block_row < block_rows; block_row++) { | ||||
|       thisblockrow = buffer[block_row]; | ||||
|       (*cinfo->fdct->forward_DCT) (cinfo, compptr, | ||||
| 				   input_buf[ci], thisblockrow, | ||||
| 				   (JDIMENSION) (block_row * DCTSIZE), | ||||
| 				   (JDIMENSION) 0, blocks_across); | ||||
|       if (ndummy > 0) { | ||||
| 	/* Create dummy blocks at the right edge of the image. */ | ||||
| 	thisblockrow += blocks_across; /* => first dummy block */ | ||||
| 	jzero_far((void FAR *) thisblockrow, ndummy * SIZEOF(JBLOCK)); | ||||
| 	lastDC = thisblockrow[-1][0]; | ||||
| 	for (bi = 0; bi < ndummy; bi++) { | ||||
| 	  thisblockrow[bi][0] = lastDC; | ||||
| 	} | ||||
|       } | ||||
|     } | ||||
|     /* If at end of image, create dummy block rows as needed.
 | ||||
|      * The tricky part here is that within each MCU, we want the DC values | ||||
|      * of the dummy blocks to match the last real block's DC value. | ||||
|      * This squeezes a few more bytes out of the resulting file... | ||||
|      */ | ||||
|     if (coef->iMCU_row_num == last_iMCU_row) { | ||||
|       blocks_across += ndummy;	/* include lower right corner */ | ||||
|       MCUs_across = blocks_across / h_samp_factor; | ||||
|       for (block_row = block_rows; block_row < compptr->v_samp_factor; | ||||
| 	   block_row++) { | ||||
| 	thisblockrow = buffer[block_row]; | ||||
| 	lastblockrow = buffer[block_row-1]; | ||||
| 	jzero_far((void FAR *) thisblockrow, | ||||
| 		  (size_t) (blocks_across * SIZEOF(JBLOCK))); | ||||
| 	for (MCUindex = 0; MCUindex < MCUs_across; MCUindex++) { | ||||
| 	  lastDC = lastblockrow[h_samp_factor-1][0]; | ||||
| 	  for (bi = 0; bi < h_samp_factor; bi++) { | ||||
| 	    thisblockrow[bi][0] = lastDC; | ||||
| 	  } | ||||
| 	  thisblockrow += h_samp_factor; /* advance to next MCU in row */ | ||||
| 	  lastblockrow += h_samp_factor; | ||||
| 	} | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   /* NB: compress_output will increment iMCU_row_num if successful.
 | ||||
|    * A suspension return will result in redoing all the work above next time. | ||||
|    */ | ||||
| 
 | ||||
|   /* Emit data to the entropy encoder, sharing code with subsequent passes */ | ||||
|   return compress_output(cinfo, input_buf); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Process some data in subsequent passes of a multi-pass case. | ||||
|  * We process the equivalent of one fully interleaved MCU row ("iMCU" row) | ||||
|  * per call, ie, v_samp_factor block rows for each component in the scan. | ||||
|  * The data is obtained from the virtual arrays and fed to the entropy coder. | ||||
|  * Returns TRUE if the iMCU row is completed, FALSE if suspended. | ||||
|  * | ||||
|  * NB: input_buf is ignored; it is likely to be a NULL pointer. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(boolean) | ||||
| compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) | ||||
| { | ||||
|   my_coef_ptr coef = (my_coef_ptr) cinfo->coef; | ||||
|   JDIMENSION MCU_col_num;	/* index of current MCU within row */ | ||||
|   int blkn, ci, xindex, yindex, yoffset; | ||||
|   JDIMENSION start_col; | ||||
|   JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; | ||||
|   JBLOCKROW buffer_ptr; | ||||
|   jpeg_component_info *compptr; | ||||
| 
 | ||||
|   /* Align the virtual buffers for the components used in this scan.
 | ||||
|    * NB: during first pass, this is safe only because the buffers will | ||||
|    * already be aligned properly, so jmemmgr.c won't need to do any I/O. | ||||
|    */ | ||||
|   for (ci = 0; ci < cinfo->comps_in_scan; ci++) { | ||||
|     compptr = cinfo->cur_comp_info[ci]; | ||||
|     buffer[ci] = (*cinfo->mem->access_virt_barray) | ||||
|       ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], | ||||
|        coef->iMCU_row_num * compptr->v_samp_factor, | ||||
|        (JDIMENSION) compptr->v_samp_factor, FALSE); | ||||
|   } | ||||
| 
 | ||||
|   /* Loop to process one whole iMCU row */ | ||||
|   for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; | ||||
|        yoffset++) { | ||||
|     for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; | ||||
| 	 MCU_col_num++) { | ||||
|       /* Construct list of pointers to DCT blocks belonging to this MCU */ | ||||
|       blkn = 0;			/* index of current DCT block within MCU */ | ||||
|       for (ci = 0; ci < cinfo->comps_in_scan; ci++) { | ||||
| 	compptr = cinfo->cur_comp_info[ci]; | ||||
| 	start_col = MCU_col_num * compptr->MCU_width; | ||||
| 	for (yindex = 0; yindex < compptr->MCU_height; yindex++) { | ||||
| 	  buffer_ptr = buffer[ci][yindex+yoffset] + start_col; | ||||
| 	  for (xindex = 0; xindex < compptr->MCU_width; xindex++) { | ||||
| 	    coef->MCU_buffer[blkn++] = buffer_ptr++; | ||||
| 	  } | ||||
| 	} | ||||
|       } | ||||
|       /* Try to write the MCU. */ | ||||
|       if (! (*cinfo->entropy->encode_mcu) (cinfo, coef->MCU_buffer)) { | ||||
| 	/* Suspension forced; update state counters and exit */ | ||||
| 	coef->MCU_vert_offset = yoffset; | ||||
| 	coef->mcu_ctr = MCU_col_num; | ||||
| 	return FALSE; | ||||
|       } | ||||
|     } | ||||
|     /* Completed an MCU row, but perhaps not an iMCU row */ | ||||
|     coef->mcu_ctr = 0; | ||||
|   } | ||||
|   /* Completed the iMCU row, advance counters for next one */ | ||||
|   coef->iMCU_row_num++; | ||||
|   start_iMCU_row(cinfo); | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| #endif /* FULL_COEF_BUFFER_SUPPORTED */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize coefficient buffer controller. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jinit_c_coef_controller (j_compress_ptr cinfo, boolean need_full_buffer) | ||||
| { | ||||
|   my_coef_ptr coef; | ||||
| 
 | ||||
|   coef = (my_coef_ptr) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				SIZEOF(my_coef_controller)); | ||||
|   cinfo->coef = (struct jpeg_c_coef_controller *) coef; | ||||
|   coef->pub.start_pass = start_pass_coef; | ||||
| 
 | ||||
|   /* Create the coefficient buffer. */ | ||||
|   if (need_full_buffer) { | ||||
| #ifdef FULL_COEF_BUFFER_SUPPORTED | ||||
|     /* Allocate a full-image virtual array for each component, */ | ||||
|     /* padded to a multiple of samp_factor DCT blocks in each direction. */ | ||||
|     int ci; | ||||
|     jpeg_component_info *compptr; | ||||
| 
 | ||||
|     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
| 	 ci++, compptr++) { | ||||
|       coef->whole_image[ci] = (*cinfo->mem->request_virt_barray) | ||||
| 	((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, | ||||
| 	 (JDIMENSION) jround_up((long) compptr->width_in_blocks, | ||||
| 				(long) compptr->h_samp_factor), | ||||
| 	 (JDIMENSION) jround_up((long) compptr->height_in_blocks, | ||||
| 				(long) compptr->v_samp_factor), | ||||
| 	 (JDIMENSION) compptr->v_samp_factor); | ||||
|     } | ||||
| #else | ||||
|     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
| #endif | ||||
|   } else { | ||||
|     /* We only need a single-MCU buffer. */ | ||||
|     JBLOCKROW buffer; | ||||
|     int i; | ||||
| 
 | ||||
|     buffer = (JBLOCKROW) | ||||
|       (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				  C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); | ||||
|     for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { | ||||
|       coef->MCU_buffer[i] = buffer + i; | ||||
|     } | ||||
|     coef->whole_image[0] = NULL; /* flag for no virtual arrays */ | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,459 @@ | |||
| /*
 | ||||
|  * jccolor.c | ||||
|  * | ||||
|  * Copyright (C) 1991-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 input colorspace conversion routines. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Private subobject */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_color_converter pub; /* public fields */ | ||||
| 
 | ||||
|   /* Private state for RGB->YCC conversion */ | ||||
|   INT32 * rgb_ycc_tab;		/* => table for RGB to YCbCr conversion */ | ||||
| } my_color_converter; | ||||
| 
 | ||||
| typedef my_color_converter * my_cconvert_ptr; | ||||
| 
 | ||||
| 
 | ||||
| /**************** RGB -> YCbCr conversion: most common case **************/ | ||||
| 
 | ||||
| /*
 | ||||
|  * YCbCr is defined per CCIR 601-1, except that Cb and Cr are | ||||
|  * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. | ||||
|  * The conversion equations to be implemented are therefore | ||||
|  *	Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B | ||||
|  *	Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B  + CENTERJSAMPLE | ||||
|  *	Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B  + CENTERJSAMPLE | ||||
|  * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) | ||||
|  * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2, | ||||
|  * rather than CENTERJSAMPLE, for Cb and Cr.  This gave equal positive and | ||||
|  * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0) | ||||
|  * were not represented exactly.  Now we sacrifice exact representation of | ||||
|  * maximum red and maximum blue in order to get exact grayscales. | ||||
|  * | ||||
|  * To avoid floating-point arithmetic, we represent the fractional constants | ||||
|  * as integers scaled up by 2^16 (about 4 digits precision); we have to divide | ||||
|  * the products by 2^16, with appropriate rounding, to get the correct answer. | ||||
|  * | ||||
|  * For even more speed, we avoid doing any multiplications in the inner loop | ||||
|  * by precalculating the constants times R,G,B for all possible values. | ||||
|  * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); | ||||
|  * for 12-bit samples it is still acceptable.  It's not very reasonable for | ||||
|  * 16-bit samples, but if you want lossless storage you shouldn't be changing | ||||
|  * colorspace anyway. | ||||
|  * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included | ||||
|  * in the tables to save adding them separately in the inner loop. | ||||
|  */ | ||||
| 
 | ||||
| #define SCALEBITS	16	/* speediest right-shift on some machines */ | ||||
| #define CBCR_OFFSET	((INT32) CENTERJSAMPLE << SCALEBITS) | ||||
| #define ONE_HALF	((INT32) 1 << (SCALEBITS-1)) | ||||
| #define FIX(x)		((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) | ||||
| 
 | ||||
| /* We allocate one big table and divide it up into eight parts, instead of
 | ||||
|  * doing eight alloc_small requests.  This lets us use a single table base | ||||
|  * address, which can be held in a register in the inner loops on many | ||||
|  * machines (more than can hold all eight addresses, anyway). | ||||
|  */ | ||||
| 
 | ||||
| #define R_Y_OFF		0			/* offset to R => Y section */ | ||||
| #define G_Y_OFF		(1*(MAXJSAMPLE+1))	/* offset to G => Y section */ | ||||
| #define B_Y_OFF		(2*(MAXJSAMPLE+1))	/* etc. */ | ||||
| #define R_CB_OFF	(3*(MAXJSAMPLE+1)) | ||||
| #define G_CB_OFF	(4*(MAXJSAMPLE+1)) | ||||
| #define B_CB_OFF	(5*(MAXJSAMPLE+1)) | ||||
| #define R_CR_OFF	B_CB_OFF		/* B=>Cb, R=>Cr are the same */ | ||||
| #define G_CR_OFF	(6*(MAXJSAMPLE+1)) | ||||
| #define B_CR_OFF	(7*(MAXJSAMPLE+1)) | ||||
| #define TABLE_SIZE	(8*(MAXJSAMPLE+1)) | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize for RGB->YCC colorspace conversion. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| rgb_ycc_start (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; | ||||
|   INT32 * rgb_ycc_tab; | ||||
|   INT32 i; | ||||
| 
 | ||||
|   /* Allocate and fill in the conversion tables. */ | ||||
|   cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				(TABLE_SIZE * SIZEOF(INT32))); | ||||
| 
 | ||||
|   for (i = 0; i <= MAXJSAMPLE; i++) { | ||||
|     rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i; | ||||
|     rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i; | ||||
|     rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i     + ONE_HALF; | ||||
|     rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i; | ||||
|     rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i; | ||||
|     /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
 | ||||
|      * This ensures that the maximum output will round to MAXJSAMPLE | ||||
|      * not MAXJSAMPLE+1, and thus that we don't have to range-limit. | ||||
|      */ | ||||
|     rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i    + CBCR_OFFSET + ONE_HALF-1; | ||||
| /*  B=>Cb and R=>Cr tables are the same
 | ||||
|     rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i    + CBCR_OFFSET + ONE_HALF-1; | ||||
| */ | ||||
|     rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i; | ||||
|     rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Convert some rows of samples to the JPEG colorspace. | ||||
|  * | ||||
|  * Note that we change from the application's interleaved-pixel format | ||||
|  * to our internal noninterleaved, one-plane-per-component format. | ||||
|  * The input buffer is therefore three times as wide as the output buffer. | ||||
|  * | ||||
|  * A starting row offset is provided only for the output buffer.  The caller | ||||
|  * can easily adjust the passed input_buf value to accommodate any row | ||||
|  * offset required on that side. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| rgb_ycc_convert (j_compress_ptr cinfo, | ||||
| 		 JSAMPARRAY input_buf, JSAMPIMAGE output_buf, | ||||
| 		 JDIMENSION output_row, int num_rows) | ||||
| { | ||||
|   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; | ||||
|   register int r, g, b; | ||||
|   register INT32 * ctab = cconvert->rgb_ycc_tab; | ||||
|   register JSAMPROW inptr; | ||||
|   register JSAMPROW outptr0, outptr1, outptr2; | ||||
|   register JDIMENSION col; | ||||
|   JDIMENSION num_cols = cinfo->image_width; | ||||
| 
 | ||||
|   while (--num_rows >= 0) { | ||||
|     inptr = *input_buf++; | ||||
|     outptr0 = output_buf[0][output_row]; | ||||
|     outptr1 = output_buf[1][output_row]; | ||||
|     outptr2 = output_buf[2][output_row]; | ||||
|     output_row++; | ||||
|     for (col = 0; col < num_cols; col++) { | ||||
|       r = GETJSAMPLE(inptr[RGB_RED]); | ||||
|       g = GETJSAMPLE(inptr[RGB_GREEN]); | ||||
|       b = GETJSAMPLE(inptr[RGB_BLUE]); | ||||
|       inptr += RGB_PIXELSIZE; | ||||
|       /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
 | ||||
|        * must be too; we do not need an explicit range-limiting operation. | ||||
|        * Hence the value being shifted is never negative, and we don't | ||||
|        * need the general RIGHT_SHIFT macro. | ||||
|        */ | ||||
|       /* Y */ | ||||
|       outptr0[col] = (JSAMPLE) | ||||
| 		((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) | ||||
| 		 >> SCALEBITS); | ||||
|       /* Cb */ | ||||
|       outptr1[col] = (JSAMPLE) | ||||
| 		((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) | ||||
| 		 >> SCALEBITS); | ||||
|       /* Cr */ | ||||
|       outptr2[col] = (JSAMPLE) | ||||
| 		((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) | ||||
| 		 >> SCALEBITS); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /**************** Cases other than RGB -> YCbCr **************/ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Convert some rows of samples to the JPEG colorspace. | ||||
|  * This version handles RGB->grayscale conversion, which is the same | ||||
|  * as the RGB->Y portion of RGB->YCbCr. | ||||
|  * We assume rgb_ycc_start has been called (we only use the Y tables). | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| rgb_gray_convert (j_compress_ptr cinfo, | ||||
| 		  JSAMPARRAY input_buf, JSAMPIMAGE output_buf, | ||||
| 		  JDIMENSION output_row, int num_rows) | ||||
| { | ||||
|   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; | ||||
|   register int r, g, b; | ||||
|   register INT32 * ctab = cconvert->rgb_ycc_tab; | ||||
|   register JSAMPROW inptr; | ||||
|   register JSAMPROW outptr; | ||||
|   register JDIMENSION col; | ||||
|   JDIMENSION num_cols = cinfo->image_width; | ||||
| 
 | ||||
|   while (--num_rows >= 0) { | ||||
|     inptr = *input_buf++; | ||||
|     outptr = output_buf[0][output_row]; | ||||
|     output_row++; | ||||
|     for (col = 0; col < num_cols; col++) { | ||||
|       r = GETJSAMPLE(inptr[RGB_RED]); | ||||
|       g = GETJSAMPLE(inptr[RGB_GREEN]); | ||||
|       b = GETJSAMPLE(inptr[RGB_BLUE]); | ||||
|       inptr += RGB_PIXELSIZE; | ||||
|       /* Y */ | ||||
|       outptr[col] = (JSAMPLE) | ||||
| 		((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) | ||||
| 		 >> SCALEBITS); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Convert some rows of samples to the JPEG colorspace. | ||||
|  * This version handles Adobe-style CMYK->YCCK conversion, | ||||
|  * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same | ||||
|  * conversion as above, while passing K (black) unchanged. | ||||
|  * We assume rgb_ycc_start has been called. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| cmyk_ycck_convert (j_compress_ptr cinfo, | ||||
| 		   JSAMPARRAY input_buf, JSAMPIMAGE output_buf, | ||||
| 		   JDIMENSION output_row, int num_rows) | ||||
| { | ||||
|   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; | ||||
|   register int r, g, b; | ||||
|   register INT32 * ctab = cconvert->rgb_ycc_tab; | ||||
|   register JSAMPROW inptr; | ||||
|   register JSAMPROW outptr0, outptr1, outptr2, outptr3; | ||||
|   register JDIMENSION col; | ||||
|   JDIMENSION num_cols = cinfo->image_width; | ||||
| 
 | ||||
|   while (--num_rows >= 0) { | ||||
|     inptr = *input_buf++; | ||||
|     outptr0 = output_buf[0][output_row]; | ||||
|     outptr1 = output_buf[1][output_row]; | ||||
|     outptr2 = output_buf[2][output_row]; | ||||
|     outptr3 = output_buf[3][output_row]; | ||||
|     output_row++; | ||||
|     for (col = 0; col < num_cols; col++) { | ||||
|       r = MAXJSAMPLE - GETJSAMPLE(inptr[0]); | ||||
|       g = MAXJSAMPLE - GETJSAMPLE(inptr[1]); | ||||
|       b = MAXJSAMPLE - GETJSAMPLE(inptr[2]); | ||||
|       /* K passes through as-is */ | ||||
|       outptr3[col] = inptr[3];	/* don't need GETJSAMPLE here */ | ||||
|       inptr += 4; | ||||
|       /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
 | ||||
|        * must be too; we do not need an explicit range-limiting operation. | ||||
|        * Hence the value being shifted is never negative, and we don't | ||||
|        * need the general RIGHT_SHIFT macro. | ||||
|        */ | ||||
|       /* Y */ | ||||
|       outptr0[col] = (JSAMPLE) | ||||
| 		((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) | ||||
| 		 >> SCALEBITS); | ||||
|       /* Cb */ | ||||
|       outptr1[col] = (JSAMPLE) | ||||
| 		((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF]) | ||||
| 		 >> SCALEBITS); | ||||
|       /* Cr */ | ||||
|       outptr2[col] = (JSAMPLE) | ||||
| 		((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF]) | ||||
| 		 >> SCALEBITS); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Convert some rows of samples to the JPEG colorspace. | ||||
|  * This version handles grayscale output with no conversion. | ||||
|  * The source can be either plain grayscale or YCbCr (since Y == gray). | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| grayscale_convert (j_compress_ptr cinfo, | ||||
| 		   JSAMPARRAY input_buf, JSAMPIMAGE output_buf, | ||||
| 		   JDIMENSION output_row, int num_rows) | ||||
| { | ||||
|   register JSAMPROW inptr; | ||||
|   register JSAMPROW outptr; | ||||
|   register JDIMENSION col; | ||||
|   JDIMENSION num_cols = cinfo->image_width; | ||||
|   int instride = cinfo->input_components; | ||||
| 
 | ||||
|   while (--num_rows >= 0) { | ||||
|     inptr = *input_buf++; | ||||
|     outptr = output_buf[0][output_row]; | ||||
|     output_row++; | ||||
|     for (col = 0; col < num_cols; col++) { | ||||
|       outptr[col] = inptr[0];	/* don't need GETJSAMPLE() here */ | ||||
|       inptr += instride; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Convert some rows of samples to the JPEG colorspace. | ||||
|  * This version handles multi-component colorspaces without conversion. | ||||
|  * We assume input_components == num_components. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| null_convert (j_compress_ptr cinfo, | ||||
| 	      JSAMPARRAY input_buf, JSAMPIMAGE output_buf, | ||||
| 	      JDIMENSION output_row, int num_rows) | ||||
| { | ||||
|   register JSAMPROW inptr; | ||||
|   register JSAMPROW outptr; | ||||
|   register JDIMENSION col; | ||||
|   register int ci; | ||||
|   int nc = cinfo->num_components; | ||||
|   JDIMENSION num_cols = cinfo->image_width; | ||||
| 
 | ||||
|   while (--num_rows >= 0) { | ||||
|     /* It seems fastest to make a separate pass for each component. */ | ||||
|     for (ci = 0; ci < nc; ci++) { | ||||
|       inptr = *input_buf; | ||||
|       outptr = output_buf[ci][output_row]; | ||||
|       for (col = 0; col < num_cols; col++) { | ||||
| 	outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */ | ||||
| 	inptr += nc; | ||||
|       } | ||||
|     } | ||||
|     input_buf++; | ||||
|     output_row++; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Empty method for start_pass. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| null_method (j_compress_ptr cinfo) | ||||
| { | ||||
|   /* no work needed */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Module initialization routine for input colorspace conversion. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jinit_color_converter (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_cconvert_ptr cconvert; | ||||
| 
 | ||||
|   cconvert = (my_cconvert_ptr) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				SIZEOF(my_color_converter)); | ||||
|   cinfo->cconvert = (struct jpeg_color_converter *) cconvert; | ||||
|   /* set start_pass to null method until we find out differently */ | ||||
|   cconvert->pub.start_pass = null_method; | ||||
| 
 | ||||
|   /* Make sure input_components agrees with in_color_space */ | ||||
|   switch (cinfo->in_color_space) { | ||||
|   case JCS_GRAYSCALE: | ||||
|     if (cinfo->input_components != 1) | ||||
|       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); | ||||
|     break; | ||||
| 
 | ||||
|   case JCS_RGB: | ||||
| #if RGB_PIXELSIZE != 3 | ||||
|     if (cinfo->input_components != RGB_PIXELSIZE) | ||||
|       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); | ||||
|     break; | ||||
| #endif /* else share code with YCbCr */ | ||||
| 
 | ||||
|   case JCS_YCbCr: | ||||
|     if (cinfo->input_components != 3) | ||||
|       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); | ||||
|     break; | ||||
| 
 | ||||
|   case JCS_CMYK: | ||||
|   case JCS_YCCK: | ||||
|     if (cinfo->input_components != 4) | ||||
|       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); | ||||
|     break; | ||||
| 
 | ||||
|   default:			/* JCS_UNKNOWN can be anything */ | ||||
|     if (cinfo->input_components < 1) | ||||
|       ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); | ||||
|     break; | ||||
|   } | ||||
| 
 | ||||
|   /* Check num_components, set conversion method based on requested space */ | ||||
|   switch (cinfo->jpeg_color_space) { | ||||
|   case JCS_GRAYSCALE: | ||||
|     if (cinfo->num_components != 1) | ||||
|       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); | ||||
|     if (cinfo->in_color_space == JCS_GRAYSCALE) | ||||
|       cconvert->pub.color_convert = grayscale_convert; | ||||
|     else if (cinfo->in_color_space == JCS_RGB) { | ||||
|       cconvert->pub.start_pass = rgb_ycc_start; | ||||
|       cconvert->pub.color_convert = rgb_gray_convert; | ||||
|     } else if (cinfo->in_color_space == JCS_YCbCr) | ||||
|       cconvert->pub.color_convert = grayscale_convert; | ||||
|     else | ||||
|       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); | ||||
|     break; | ||||
| 
 | ||||
|   case JCS_RGB: | ||||
|     if (cinfo->num_components != 3) | ||||
|       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); | ||||
|     if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3) | ||||
|       cconvert->pub.color_convert = null_convert; | ||||
|     else | ||||
|       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); | ||||
|     break; | ||||
| 
 | ||||
|   case JCS_YCbCr: | ||||
|     if (cinfo->num_components != 3) | ||||
|       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); | ||||
|     if (cinfo->in_color_space == JCS_RGB) { | ||||
|       cconvert->pub.start_pass = rgb_ycc_start; | ||||
|       cconvert->pub.color_convert = rgb_ycc_convert; | ||||
|     } else if (cinfo->in_color_space == JCS_YCbCr) | ||||
|       cconvert->pub.color_convert = null_convert; | ||||
|     else | ||||
|       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); | ||||
|     break; | ||||
| 
 | ||||
|   case JCS_CMYK: | ||||
|     if (cinfo->num_components != 4) | ||||
|       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); | ||||
|     if (cinfo->in_color_space == JCS_CMYK) | ||||
|       cconvert->pub.color_convert = null_convert; | ||||
|     else | ||||
|       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); | ||||
|     break; | ||||
| 
 | ||||
|   case JCS_YCCK: | ||||
|     if (cinfo->num_components != 4) | ||||
|       ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); | ||||
|     if (cinfo->in_color_space == JCS_CMYK) { | ||||
|       cconvert->pub.start_pass = rgb_ycc_start; | ||||
|       cconvert->pub.color_convert = cmyk_ycck_convert; | ||||
|     } else if (cinfo->in_color_space == JCS_YCCK) | ||||
|       cconvert->pub.color_convert = null_convert; | ||||
|     else | ||||
|       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); | ||||
|     break; | ||||
| 
 | ||||
|   default:			/* allow null conversion of JCS_UNKNOWN */ | ||||
|     if (cinfo->jpeg_color_space != cinfo->in_color_space || | ||||
| 	cinfo->num_components != cinfo->input_components) | ||||
|       ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); | ||||
|     cconvert->pub.color_convert = null_convert; | ||||
|     break; | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,387 @@ | |||
| /*
 | ||||
|  * jcdctmgr.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 the forward-DCT management logic. | ||||
|  * This code selects a particular DCT implementation to be used, | ||||
|  * and it performs related housekeeping chores including coefficient | ||||
|  * quantization. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| #include "jdct.h"		/* Private declarations for DCT subsystem */ | ||||
| 
 | ||||
| 
 | ||||
| /* Private subobject for this module */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_forward_dct pub;	/* public fields */ | ||||
| 
 | ||||
|   /* Pointer to the DCT routine actually in use */ | ||||
|   forward_DCT_method_ptr do_dct; | ||||
| 
 | ||||
|   /* The actual post-DCT divisors --- not identical to the quant table
 | ||||
|    * entries, because of scaling (especially for an unnormalized DCT). | ||||
|    * Each table is given in normal array order. | ||||
|    */ | ||||
|   DCTELEM * divisors[NUM_QUANT_TBLS]; | ||||
| 
 | ||||
| #ifdef DCT_FLOAT_SUPPORTED | ||||
|   /* Same as above for the floating-point case. */ | ||||
|   float_DCT_method_ptr do_float_dct; | ||||
|   FAST_FLOAT * float_divisors[NUM_QUANT_TBLS]; | ||||
| #endif | ||||
| } my_fdct_controller; | ||||
| 
 | ||||
| typedef my_fdct_controller * my_fdct_ptr; | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize for a processing pass. | ||||
|  * Verify that all referenced Q-tables are present, and set up | ||||
|  * the divisor table for each one. | ||||
|  * In the current implementation, DCT of all components is done during | ||||
|  * the first pass, even if only some components will be output in the | ||||
|  * first scan.  Hence all components should be examined here. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| start_pass_fdctmgr (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; | ||||
|   int ci, qtblno, i; | ||||
|   jpeg_component_info *compptr; | ||||
|   JQUANT_TBL * qtbl; | ||||
|   DCTELEM * dtbl; | ||||
| 
 | ||||
|   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
|        ci++, compptr++) { | ||||
|     qtblno = compptr->quant_tbl_no; | ||||
|     /* Make sure specified quantization table is present */ | ||||
|     if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS || | ||||
| 	cinfo->quant_tbl_ptrs[qtblno] == NULL) | ||||
|       ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno); | ||||
|     qtbl = cinfo->quant_tbl_ptrs[qtblno]; | ||||
|     /* Compute divisors for this quant table */ | ||||
|     /* We may do this more than once for same table, but it's not a big deal */ | ||||
|     switch (cinfo->dct_method) { | ||||
| #ifdef DCT_ISLOW_SUPPORTED | ||||
|     case JDCT_ISLOW: | ||||
|       /* For LL&M IDCT method, divisors are equal to raw quantization
 | ||||
|        * coefficients multiplied by 8 (to counteract scaling). | ||||
|        */ | ||||
|       if (fdct->divisors[qtblno] == NULL) { | ||||
| 	fdct->divisors[qtblno] = (DCTELEM *) | ||||
| 	  (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				      DCTSIZE2 * SIZEOF(DCTELEM)); | ||||
|       } | ||||
|       dtbl = fdct->divisors[qtblno]; | ||||
|       for (i = 0; i < DCTSIZE2; i++) { | ||||
| 	dtbl[i] = ((DCTELEM) qtbl->quantval[i]) << 3; | ||||
|       } | ||||
|       break; | ||||
| #endif | ||||
| #ifdef DCT_IFAST_SUPPORTED | ||||
|     case JDCT_IFAST: | ||||
|       { | ||||
| 	/* For AA&N IDCT method, divisors are equal to quantization
 | ||||
| 	 * coefficients scaled by scalefactor[row]*scalefactor[col], where | ||||
| 	 *   scalefactor[0] = 1 | ||||
| 	 *   scalefactor[k] = cos(k*PI/16) * sqrt(2)    for k=1..7 | ||||
| 	 * We apply a further scale factor of 8. | ||||
| 	 */ | ||||
| #define CONST_BITS 14 | ||||
| 	static const INT16 aanscales[DCTSIZE2] = { | ||||
| 	  /* precomputed values scaled up by 14 bits */ | ||||
| 	  16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520, | ||||
| 	  22725, 31521, 29692, 26722, 22725, 17855, 12299,  6270, | ||||
| 	  21407, 29692, 27969, 25172, 21407, 16819, 11585,  5906, | ||||
| 	  19266, 26722, 25172, 22654, 19266, 15137, 10426,  5315, | ||||
| 	  16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520, | ||||
| 	  12873, 17855, 16819, 15137, 12873, 10114,  6967,  3552, | ||||
| 	   8867, 12299, 11585, 10426,  8867,  6967,  4799,  2446, | ||||
| 	   4520,  6270,  5906,  5315,  4520,  3552,  2446,  1247 | ||||
| 	}; | ||||
| 	SHIFT_TEMPS | ||||
| 
 | ||||
| 	if (fdct->divisors[qtblno] == NULL) { | ||||
| 	  fdct->divisors[qtblno] = (DCTELEM *) | ||||
| 	    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 					DCTSIZE2 * SIZEOF(DCTELEM)); | ||||
| 	} | ||||
| 	dtbl = fdct->divisors[qtblno]; | ||||
| 	for (i = 0; i < DCTSIZE2; i++) { | ||||
| 	  dtbl[i] = (DCTELEM) | ||||
| 	    DESCALE(MULTIPLY16V16((INT32) qtbl->quantval[i], | ||||
| 				  (INT32) aanscales[i]), | ||||
| 		    CONST_BITS-3); | ||||
| 	} | ||||
|       } | ||||
|       break; | ||||
| #endif | ||||
| #ifdef DCT_FLOAT_SUPPORTED | ||||
|     case JDCT_FLOAT: | ||||
|       { | ||||
| 	/* For float AA&N IDCT method, divisors are equal to quantization
 | ||||
| 	 * coefficients scaled by scalefactor[row]*scalefactor[col], where | ||||
| 	 *   scalefactor[0] = 1 | ||||
| 	 *   scalefactor[k] = cos(k*PI/16) * sqrt(2)    for k=1..7 | ||||
| 	 * We apply a further scale factor of 8. | ||||
| 	 * What's actually stored is 1/divisor so that the inner loop can | ||||
| 	 * use a multiplication rather than a division. | ||||
| 	 */ | ||||
| 	FAST_FLOAT * fdtbl; | ||||
| 	int row, col; | ||||
| 	static const double aanscalefactor[DCTSIZE] = { | ||||
| 	  1.0, 1.387039845, 1.306562965, 1.175875602, | ||||
| 	  1.0, 0.785694958, 0.541196100, 0.275899379 | ||||
| 	}; | ||||
| 
 | ||||
| 	if (fdct->float_divisors[qtblno] == NULL) { | ||||
| 	  fdct->float_divisors[qtblno] = (FAST_FLOAT *) | ||||
| 	    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 					DCTSIZE2 * SIZEOF(FAST_FLOAT)); | ||||
| 	} | ||||
| 	fdtbl = fdct->float_divisors[qtblno]; | ||||
| 	i = 0; | ||||
| 	for (row = 0; row < DCTSIZE; row++) { | ||||
| 	  for (col = 0; col < DCTSIZE; col++) { | ||||
| 	    fdtbl[i] = (FAST_FLOAT) | ||||
| 	      (1.0 / (((double) qtbl->quantval[i] * | ||||
| 		       aanscalefactor[row] * aanscalefactor[col] * 8.0))); | ||||
| 	    i++; | ||||
| 	  } | ||||
| 	} | ||||
|       } | ||||
|       break; | ||||
| #endif | ||||
|     default: | ||||
|       ERREXIT(cinfo, JERR_NOT_COMPILED); | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Perform forward DCT on one or more blocks of a component. | ||||
|  * | ||||
|  * The input samples are taken from the sample_data[] array starting at | ||||
|  * position start_row/start_col, and moving to the right for any additional | ||||
|  * blocks. The quantized coefficients are returned in coef_blocks[]. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| forward_DCT (j_compress_ptr cinfo, jpeg_component_info * compptr, | ||||
| 	     JSAMPARRAY sample_data, JBLOCKROW coef_blocks, | ||||
| 	     JDIMENSION start_row, JDIMENSION start_col, | ||||
| 	     JDIMENSION num_blocks) | ||||
| /* This version is used for integer DCT implementations. */ | ||||
| { | ||||
|   /* This routine is heavily used, so it's worth coding it tightly. */ | ||||
|   my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; | ||||
|   forward_DCT_method_ptr do_dct = fdct->do_dct; | ||||
|   DCTELEM * divisors = fdct->divisors[compptr->quant_tbl_no]; | ||||
|   DCTELEM workspace[DCTSIZE2];	/* work area for FDCT subroutine */ | ||||
|   JDIMENSION bi; | ||||
| 
 | ||||
|   sample_data += start_row;	/* fold in the vertical offset once */ | ||||
| 
 | ||||
|   for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { | ||||
|     /* Load data into workspace, applying unsigned->signed conversion */ | ||||
|     { register DCTELEM *workspaceptr; | ||||
|       register JSAMPROW elemptr; | ||||
|       register int elemr; | ||||
| 
 | ||||
|       workspaceptr = workspace; | ||||
|       for (elemr = 0; elemr < DCTSIZE; elemr++) { | ||||
| 	elemptr = sample_data[elemr] + start_col; | ||||
| #if DCTSIZE == 8		/* unroll the inner loop */ | ||||
| 	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; | ||||
| 	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; | ||||
| 	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; | ||||
| 	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; | ||||
| 	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; | ||||
| 	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; | ||||
| 	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; | ||||
| 	*workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; | ||||
| #else | ||||
| 	{ register int elemc; | ||||
| 	  for (elemc = DCTSIZE; elemc > 0; elemc--) { | ||||
| 	    *workspaceptr++ = GETJSAMPLE(*elemptr++) - CENTERJSAMPLE; | ||||
| 	  } | ||||
| 	} | ||||
| #endif | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     /* Perform the DCT */ | ||||
|     (*do_dct) (workspace); | ||||
| 
 | ||||
|     /* Quantize/descale the coefficients, and store into coef_blocks[] */ | ||||
|     { register DCTELEM temp, qval; | ||||
|       register int i; | ||||
|       register JCOEFPTR output_ptr = coef_blocks[bi]; | ||||
| 
 | ||||
|       for (i = 0; i < DCTSIZE2; i++) { | ||||
| 	qval = divisors[i]; | ||||
| 	temp = workspace[i]; | ||||
| 	/* Divide the coefficient value by qval, ensuring proper rounding.
 | ||||
| 	 * Since C does not specify the direction of rounding for negative | ||||
| 	 * quotients, we have to force the dividend positive for portability. | ||||
| 	 * | ||||
| 	 * In most files, at least half of the output values will be zero | ||||
| 	 * (at default quantization settings, more like three-quarters...) | ||||
| 	 * so we should ensure that this case is fast.  On many machines, | ||||
| 	 * a comparison is enough cheaper than a divide to make a special test | ||||
| 	 * a win.  Since both inputs will be nonnegative, we need only test | ||||
| 	 * for a < b to discover whether a/b is 0. | ||||
| 	 * If your machine's division is fast enough, define FAST_DIVIDE. | ||||
| 	 */ | ||||
| #ifdef FAST_DIVIDE | ||||
| #define DIVIDE_BY(a,b)	a /= b | ||||
| #else | ||||
| #define DIVIDE_BY(a,b)	if (a >= b) a /= b; else a = 0 | ||||
| #endif | ||||
| 	if (temp < 0) { | ||||
| 	  temp = -temp; | ||||
| 	  temp += qval>>1;	/* for rounding */ | ||||
| 	  DIVIDE_BY(temp, qval); | ||||
| 	  temp = -temp; | ||||
| 	} else { | ||||
| 	  temp += qval>>1;	/* for rounding */ | ||||
| 	  DIVIDE_BY(temp, qval); | ||||
| 	} | ||||
| 	output_ptr[i] = (JCOEF) temp; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef DCT_FLOAT_SUPPORTED | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| forward_DCT_float (j_compress_ptr cinfo, jpeg_component_info * compptr, | ||||
| 		   JSAMPARRAY sample_data, JBLOCKROW coef_blocks, | ||||
| 		   JDIMENSION start_row, JDIMENSION start_col, | ||||
| 		   JDIMENSION num_blocks) | ||||
| /* This version is used for floating-point DCT implementations. */ | ||||
| { | ||||
|   /* This routine is heavily used, so it's worth coding it tightly. */ | ||||
|   my_fdct_ptr fdct = (my_fdct_ptr) cinfo->fdct; | ||||
|   float_DCT_method_ptr do_dct = fdct->do_float_dct; | ||||
|   FAST_FLOAT * divisors = fdct->float_divisors[compptr->quant_tbl_no]; | ||||
|   FAST_FLOAT workspace[DCTSIZE2]; /* work area for FDCT subroutine */ | ||||
|   JDIMENSION bi; | ||||
| 
 | ||||
|   sample_data += start_row;	/* fold in the vertical offset once */ | ||||
| 
 | ||||
|   for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) { | ||||
|     /* Load data into workspace, applying unsigned->signed conversion */ | ||||
|     { register FAST_FLOAT *workspaceptr; | ||||
|       register JSAMPROW elemptr; | ||||
|       register int elemr; | ||||
| 
 | ||||
|       workspaceptr = workspace; | ||||
|       for (elemr = 0; elemr < DCTSIZE; elemr++) { | ||||
| 	elemptr = sample_data[elemr] + start_col; | ||||
| #if DCTSIZE == 8		/* unroll the inner loop */ | ||||
| 	*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); | ||||
| 	*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); | ||||
| 	*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); | ||||
| 	*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); | ||||
| 	*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); | ||||
| 	*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); | ||||
| 	*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); | ||||
| 	*workspaceptr++ = (FAST_FLOAT)(GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); | ||||
| #else | ||||
| 	{ register int elemc; | ||||
| 	  for (elemc = DCTSIZE; elemc > 0; elemc--) { | ||||
| 	    *workspaceptr++ = (FAST_FLOAT) | ||||
| 	      (GETJSAMPLE(*elemptr++) - CENTERJSAMPLE); | ||||
| 	  } | ||||
| 	} | ||||
| #endif | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     /* Perform the DCT */ | ||||
|     (*do_dct) (workspace); | ||||
| 
 | ||||
|     /* Quantize/descale the coefficients, and store into coef_blocks[] */ | ||||
|     { register FAST_FLOAT temp; | ||||
|       register int i; | ||||
|       register JCOEFPTR output_ptr = coef_blocks[bi]; | ||||
| 
 | ||||
|       for (i = 0; i < DCTSIZE2; i++) { | ||||
| 	/* Apply the quantization and scaling factor */ | ||||
| 	temp = workspace[i] * divisors[i]; | ||||
| 	/* Round to nearest integer.
 | ||||
| 	 * Since C does not specify the direction of rounding for negative | ||||
| 	 * quotients, we have to force the dividend positive for portability. | ||||
| 	 * The maximum coefficient size is +-16K (for 12-bit data), so this | ||||
| 	 * code should work for either 16-bit or 32-bit ints. | ||||
| 	 */ | ||||
| 	output_ptr[i] = (JCOEF) ((int) (temp + (FAST_FLOAT) 16384.5) - 16384); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #endif /* DCT_FLOAT_SUPPORTED */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize FDCT manager. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jinit_forward_dct (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_fdct_ptr fdct; | ||||
|   int i; | ||||
| 
 | ||||
|   fdct = (my_fdct_ptr) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				SIZEOF(my_fdct_controller)); | ||||
|   cinfo->fdct = (struct jpeg_forward_dct *) fdct; | ||||
|   fdct->pub.start_pass = start_pass_fdctmgr; | ||||
| 
 | ||||
|   switch (cinfo->dct_method) { | ||||
| #ifdef DCT_ISLOW_SUPPORTED | ||||
|   case JDCT_ISLOW: | ||||
|     fdct->pub.forward_DCT = forward_DCT; | ||||
|     fdct->do_dct = jpeg_fdct_islow; | ||||
|     break; | ||||
| #endif | ||||
| #ifdef DCT_IFAST_SUPPORTED | ||||
|   case JDCT_IFAST: | ||||
|     fdct->pub.forward_DCT = forward_DCT; | ||||
|     fdct->do_dct = jpeg_fdct_ifast; | ||||
|     break; | ||||
| #endif | ||||
| #ifdef DCT_FLOAT_SUPPORTED | ||||
|   case JDCT_FLOAT: | ||||
|     fdct->pub.forward_DCT = forward_DCT_float; | ||||
|     fdct->do_float_dct = jpeg_fdct_float; | ||||
|     break; | ||||
| #endif | ||||
|   default: | ||||
|     ERREXIT(cinfo, JERR_NOT_COMPILED); | ||||
|     break; | ||||
|   } | ||||
| 
 | ||||
|   /* Mark divisor tables unallocated */ | ||||
|   for (i = 0; i < NUM_QUANT_TBLS; i++) { | ||||
|     fdct->divisors[i] = NULL; | ||||
| #ifdef DCT_FLOAT_SUPPORTED | ||||
|     fdct->float_divisors[i] = NULL; | ||||
| #endif | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,909 @@ | |||
| /*
 | ||||
|  * jchuff.c | ||||
|  * | ||||
|  * Copyright (C) 1991-1997, 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 Huffman entropy encoding routines. | ||||
|  * | ||||
|  * Much of the complexity here has to do with supporting output suspension. | ||||
|  * If the data destination module demands suspension, we want to be able to | ||||
|  * back up to the start of the current MCU.  To do this, we copy state | ||||
|  * variables into local working storage, and update them back to the | ||||
|  * permanent JPEG objects only upon successful completion of an MCU. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| #include "jchuff.h"		/* Declarations shared with jcphuff.c */ | ||||
| 
 | ||||
| 
 | ||||
| /* Expanded entropy encoder object for Huffman encoding.
 | ||||
|  * | ||||
|  * The savable_state subrecord contains fields that change within an MCU, | ||||
|  * but must not be updated permanently until we complete the MCU. | ||||
|  */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   INT32 put_buffer;		/* current bit-accumulation buffer */ | ||||
|   int put_bits;			/* # of bits now in it */ | ||||
|   int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ | ||||
| } savable_state; | ||||
| 
 | ||||
| /* This macro is to work around compilers with missing or broken
 | ||||
|  * structure assignment.  You'll need to fix this code if you have | ||||
|  * such a compiler and you change MAX_COMPS_IN_SCAN. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef NO_STRUCT_ASSIGN | ||||
| #define ASSIGN_STATE(dest,src)  ((dest) = (src)) | ||||
| #else | ||||
| #if MAX_COMPS_IN_SCAN == 4 | ||||
| #define ASSIGN_STATE(dest,src)  \ | ||||
| 	((dest).put_buffer = (src).put_buffer, \ | ||||
| 	 (dest).put_bits = (src).put_bits, \ | ||||
| 	 (dest).last_dc_val[0] = (src).last_dc_val[0], \ | ||||
| 	 (dest).last_dc_val[1] = (src).last_dc_val[1], \ | ||||
| 	 (dest).last_dc_val[2] = (src).last_dc_val[2], \ | ||||
| 	 (dest).last_dc_val[3] = (src).last_dc_val[3]) | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_entropy_encoder pub; /* public fields */ | ||||
| 
 | ||||
|   savable_state saved;		/* Bit buffer & DC state at start of MCU */ | ||||
| 
 | ||||
|   /* These fields are NOT loaded into local working state. */ | ||||
|   unsigned int restarts_to_go;	/* MCUs left in this restart interval */ | ||||
|   int next_restart_num;		/* next restart number to write (0-7) */ | ||||
| 
 | ||||
|   /* Pointers to derived tables (these workspaces have image lifespan) */ | ||||
|   c_derived_tbl * dc_derived_tbls[NUM_HUFF_TBLS]; | ||||
|   c_derived_tbl * ac_derived_tbls[NUM_HUFF_TBLS]; | ||||
| 
 | ||||
| #ifdef ENTROPY_OPT_SUPPORTED	/* Statistics tables for optimization */ | ||||
|   long * dc_count_ptrs[NUM_HUFF_TBLS]; | ||||
|   long * ac_count_ptrs[NUM_HUFF_TBLS]; | ||||
| #endif | ||||
| } huff_entropy_encoder; | ||||
| 
 | ||||
| typedef huff_entropy_encoder * huff_entropy_ptr; | ||||
| 
 | ||||
| /* Working state while writing an MCU.
 | ||||
|  * This struct contains all the fields that are needed by subroutines. | ||||
|  */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   JOCTET * next_output_byte;	/* => next byte to write in buffer */ | ||||
|   size_t free_in_buffer;	/* # of byte spaces remaining in buffer */ | ||||
|   savable_state cur;		/* Current bit buffer & DC state */ | ||||
|   j_compress_ptr cinfo;		/* dump_buffer needs access to this */ | ||||
| } working_state; | ||||
| 
 | ||||
| 
 | ||||
| /* Forward declarations */ | ||||
| METHODDEF(boolean) encode_mcu_huff JPP((j_compress_ptr cinfo, | ||||
| 					JBLOCKROW *MCU_data)); | ||||
| METHODDEF(void) finish_pass_huff JPP((j_compress_ptr cinfo)); | ||||
| #ifdef ENTROPY_OPT_SUPPORTED | ||||
| METHODDEF(boolean) encode_mcu_gather JPP((j_compress_ptr cinfo, | ||||
| 					  JBLOCKROW *MCU_data)); | ||||
| METHODDEF(void) finish_pass_gather JPP((j_compress_ptr cinfo)); | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize for a Huffman-compressed scan. | ||||
|  * If gather_statistics is TRUE, we do not output anything during the scan, | ||||
|  * just count the Huffman symbols used and generate Huffman code tables. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| start_pass_huff (j_compress_ptr cinfo, boolean gather_statistics) | ||||
| { | ||||
|   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; | ||||
|   int ci, dctbl, actbl; | ||||
|   jpeg_component_info * compptr; | ||||
| 
 | ||||
|   if (gather_statistics) { | ||||
| #ifdef ENTROPY_OPT_SUPPORTED | ||||
|     entropy->pub.encode_mcu = encode_mcu_gather; | ||||
|     entropy->pub.finish_pass = finish_pass_gather; | ||||
| #else | ||||
|     ERREXIT(cinfo, JERR_NOT_COMPILED); | ||||
| #endif | ||||
|   } else { | ||||
|     entropy->pub.encode_mcu = encode_mcu_huff; | ||||
|     entropy->pub.finish_pass = finish_pass_huff; | ||||
|   } | ||||
| 
 | ||||
|   for (ci = 0; ci < cinfo->comps_in_scan; ci++) { | ||||
|     compptr = cinfo->cur_comp_info[ci]; | ||||
|     dctbl = compptr->dc_tbl_no; | ||||
|     actbl = compptr->ac_tbl_no; | ||||
|     if (gather_statistics) { | ||||
| #ifdef ENTROPY_OPT_SUPPORTED | ||||
|       /* Check for invalid table indexes */ | ||||
|       /* (make_c_derived_tbl does this in the other path) */ | ||||
|       if (dctbl < 0 || dctbl >= NUM_HUFF_TBLS) | ||||
| 	ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, dctbl); | ||||
|       if (actbl < 0 || actbl >= NUM_HUFF_TBLS) | ||||
| 	ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, actbl); | ||||
|       /* Allocate and zero the statistics tables */ | ||||
|       /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ | ||||
|       if (entropy->dc_count_ptrs[dctbl] == NULL) | ||||
| 	entropy->dc_count_ptrs[dctbl] = (long *) | ||||
| 	  (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				      257 * SIZEOF(long)); | ||||
|       MEMZERO(entropy->dc_count_ptrs[dctbl], 257 * SIZEOF(long)); | ||||
|       if (entropy->ac_count_ptrs[actbl] == NULL) | ||||
| 	entropy->ac_count_ptrs[actbl] = (long *) | ||||
| 	  (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				      257 * SIZEOF(long)); | ||||
|       MEMZERO(entropy->ac_count_ptrs[actbl], 257 * SIZEOF(long)); | ||||
| #endif | ||||
|     } else { | ||||
|       /* Compute derived values for Huffman tables */ | ||||
|       /* We may do this more than once for a table, but it's not expensive */ | ||||
|       jpeg_make_c_derived_tbl(cinfo, TRUE, dctbl, | ||||
| 			      & entropy->dc_derived_tbls[dctbl]); | ||||
|       jpeg_make_c_derived_tbl(cinfo, FALSE, actbl, | ||||
| 			      & entropy->ac_derived_tbls[actbl]); | ||||
|     } | ||||
|     /* Initialize DC predictions to 0 */ | ||||
|     entropy->saved.last_dc_val[ci] = 0; | ||||
|   } | ||||
| 
 | ||||
|   /* Initialize bit buffer to empty */ | ||||
|   entropy->saved.put_buffer = 0; | ||||
|   entropy->saved.put_bits = 0; | ||||
| 
 | ||||
|   /* Initialize restart stuff */ | ||||
|   entropy->restarts_to_go = cinfo->restart_interval; | ||||
|   entropy->next_restart_num = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Compute the derived values for a Huffman table. | ||||
|  * This routine also performs some validation checks on the table. | ||||
|  * | ||||
|  * Note this is also used by jcphuff.c. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_make_c_derived_tbl (j_compress_ptr cinfo, boolean isDC, int tblno, | ||||
| 			 c_derived_tbl ** pdtbl) | ||||
| { | ||||
|   JHUFF_TBL *htbl; | ||||
|   c_derived_tbl *dtbl; | ||||
|   int p, i, l, lastp, si, maxsymbol; | ||||
|   char huffsize[257]; | ||||
|   unsigned int huffcode[257]; | ||||
|   unsigned int code; | ||||
| 
 | ||||
|   /* Note that huffsize[] and huffcode[] are filled in code-length order,
 | ||||
|    * paralleling the order of the symbols themselves in htbl->huffval[]. | ||||
|    */ | ||||
| 
 | ||||
|   /* Find the input Huffman table */ | ||||
|   if (tblno < 0 || tblno >= NUM_HUFF_TBLS) | ||||
|     ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); | ||||
|   htbl = | ||||
|     isDC ? cinfo->dc_huff_tbl_ptrs[tblno] : cinfo->ac_huff_tbl_ptrs[tblno]; | ||||
|   if (htbl == NULL) | ||||
|     ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tblno); | ||||
| 
 | ||||
|   /* Allocate a workspace if we haven't already done so. */ | ||||
|   if (*pdtbl == NULL) | ||||
|     *pdtbl = (c_derived_tbl *) | ||||
|       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				  SIZEOF(c_derived_tbl)); | ||||
|   dtbl = *pdtbl; | ||||
|    | ||||
|   /* Figure C.1: make table of Huffman code length for each symbol */ | ||||
| 
 | ||||
|   p = 0; | ||||
|   for (l = 1; l <= 16; l++) { | ||||
|     i = (int) htbl->bits[l]; | ||||
|     if (i < 0 || p + i > 256)	/* protect against table overrun */ | ||||
|       ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); | ||||
|     while (i--) | ||||
|       huffsize[p++] = (char) l; | ||||
|   } | ||||
|   huffsize[p] = 0; | ||||
|   lastp = p; | ||||
|    | ||||
|   /* Figure C.2: generate the codes themselves */ | ||||
|   /* We also validate that the counts represent a legal Huffman code tree. */ | ||||
| 
 | ||||
|   code = 0; | ||||
|   si = huffsize[0]; | ||||
|   p = 0; | ||||
|   while (huffsize[p]) { | ||||
|     while (((int) huffsize[p]) == si) { | ||||
|       huffcode[p++] = code; | ||||
|       code++; | ||||
|     } | ||||
|     /* code is now 1 more than the last code used for codelength si; but
 | ||||
|      * it must still fit in si bits, since no code is allowed to be all ones. | ||||
|      */ | ||||
|     if (((INT32) code) >= (((INT32) 1) << si)) | ||||
|       ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); | ||||
|     code <<= 1; | ||||
|     si++; | ||||
|   } | ||||
|    | ||||
|   /* Figure C.3: generate encoding tables */ | ||||
|   /* These are code and size indexed by symbol value */ | ||||
| 
 | ||||
|   /* Set all codeless symbols to have code length 0;
 | ||||
|    * this lets us detect duplicate VAL entries here, and later | ||||
|    * allows emit_bits to detect any attempt to emit such symbols. | ||||
|    */ | ||||
|   MEMZERO(dtbl->ehufsi, SIZEOF(dtbl->ehufsi)); | ||||
| 
 | ||||
|   /* This is also a convenient place to check for out-of-range
 | ||||
|    * and duplicated VAL entries.  We allow 0..255 for AC symbols | ||||
|    * but only 0..15 for DC.  (We could constrain them further | ||||
|    * based on data depth and mode, but this seems enough.) | ||||
|    */ | ||||
|   maxsymbol = isDC ? 15 : 255; | ||||
| 
 | ||||
|   for (p = 0; p < lastp; p++) { | ||||
|     i = htbl->huffval[p]; | ||||
|     if (i < 0 || i > maxsymbol || dtbl->ehufsi[i]) | ||||
|       ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); | ||||
|     dtbl->ehufco[i] = huffcode[p]; | ||||
|     dtbl->ehufsi[i] = huffsize[p]; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Outputting bytes to the file */ | ||||
| 
 | ||||
| /* Emit a byte, taking 'action' if must suspend. */ | ||||
| #define emit_byte(state,val,action)  \ | ||||
| 	{ *(state)->next_output_byte++ = (JOCTET) (val);  \ | ||||
| 	  if (--(state)->free_in_buffer == 0)  \ | ||||
| 	    if (! dump_buffer(state))  \ | ||||
| 	      { action; } } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(boolean) | ||||
| dump_buffer (working_state * state) | ||||
| /* Empty the output buffer; return TRUE if successful, FALSE if must suspend */ | ||||
| { | ||||
|   struct jpeg_destination_mgr * dest = state->cinfo->dest; | ||||
| 
 | ||||
|   if (! (*dest->empty_output_buffer) (state->cinfo)) | ||||
|     return FALSE; | ||||
|   /* After a successful buffer dump, must reset buffer pointers */ | ||||
|   state->next_output_byte = dest->next_output_byte; | ||||
|   state->free_in_buffer = dest->free_in_buffer; | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Outputting bits to the file */ | ||||
| 
 | ||||
| /* Only the right 24 bits of put_buffer are used; the valid bits are
 | ||||
|  * left-justified in this part.  At most 16 bits can be passed to emit_bits | ||||
|  * in one call, and we never retain more than 7 bits in put_buffer | ||||
|  * between calls, so 24 bits are sufficient. | ||||
|  */ | ||||
| 
 | ||||
| INLINE | ||||
| LOCAL(boolean) | ||||
| emit_bits (working_state * state, unsigned int code, int size) | ||||
| /* Emit some bits; return TRUE if successful, FALSE if must suspend */ | ||||
| { | ||||
|   /* This routine is heavily used, so it's worth coding tightly. */ | ||||
|   register INT32 put_buffer = (INT32) code; | ||||
|   register int put_bits = state->cur.put_bits; | ||||
| 
 | ||||
|   /* if size is 0, caller used an invalid Huffman table entry */ | ||||
|   if (size == 0) | ||||
|     ERREXIT(state->cinfo, JERR_HUFF_MISSING_CODE); | ||||
| 
 | ||||
|   put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */ | ||||
|    | ||||
|   put_bits += size;		/* new number of bits in buffer */ | ||||
|    | ||||
|   put_buffer <<= 24 - put_bits; /* align incoming bits */ | ||||
| 
 | ||||
|   put_buffer |= state->cur.put_buffer; /* and merge with old buffer contents */ | ||||
|    | ||||
|   while (put_bits >= 8) { | ||||
|     int c = (int) ((put_buffer >> 16) & 0xFF); | ||||
|      | ||||
|     emit_byte(state, c, return FALSE); | ||||
|     if (c == 0xFF) {		/* need to stuff a zero byte? */ | ||||
|       emit_byte(state, 0, return FALSE); | ||||
|     } | ||||
|     put_buffer <<= 8; | ||||
|     put_bits -= 8; | ||||
|   } | ||||
| 
 | ||||
|   state->cur.put_buffer = put_buffer; /* update state variables */ | ||||
|   state->cur.put_bits = put_bits; | ||||
| 
 | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(boolean) | ||||
| flush_bits (working_state * state) | ||||
| { | ||||
|   if (! emit_bits(state, 0x7F, 7)) /* fill any partial byte with ones */ | ||||
|     return FALSE; | ||||
|   state->cur.put_buffer = 0;	/* and reset bit-buffer to empty */ | ||||
|   state->cur.put_bits = 0; | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Encode a single block's worth of coefficients */ | ||||
| 
 | ||||
| LOCAL(boolean) | ||||
| encode_one_block (working_state * state, JCOEFPTR block, int last_dc_val, | ||||
| 		  c_derived_tbl *dctbl, c_derived_tbl *actbl) | ||||
| { | ||||
|   register int temp, temp2; | ||||
|   register int nbits; | ||||
|   register int k, r, i; | ||||
|    | ||||
|   /* Encode the DC coefficient difference per section F.1.2.1 */ | ||||
|    | ||||
|   temp = temp2 = block[0] - last_dc_val; | ||||
| 
 | ||||
|   if (temp < 0) { | ||||
|     temp = -temp;		/* temp is abs value of input */ | ||||
|     /* For a negative input, want temp2 = bitwise complement of abs(input) */ | ||||
|     /* This code assumes we are on a two's complement machine */ | ||||
|     temp2--; | ||||
|   } | ||||
|    | ||||
|   /* Find the number of bits needed for the magnitude of the coefficient */ | ||||
|   nbits = 0; | ||||
|   while (temp) { | ||||
|     nbits++; | ||||
|     temp >>= 1; | ||||
|   } | ||||
|   /* Check for out-of-range coefficient values.
 | ||||
|    * Since we're encoding a difference, the range limit is twice as much. | ||||
|    */ | ||||
|   if (nbits > MAX_COEF_BITS+1) | ||||
|     ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); | ||||
|    | ||||
|   /* Emit the Huffman-coded symbol for the number of bits */ | ||||
|   if (! emit_bits(state, dctbl->ehufco[nbits], dctbl->ehufsi[nbits])) | ||||
|     return FALSE; | ||||
| 
 | ||||
|   /* Emit that number of bits of the value, if positive, */ | ||||
|   /* or the complement of its magnitude, if negative. */ | ||||
|   if (nbits)			/* emit_bits rejects calls with size 0 */ | ||||
|     if (! emit_bits(state, (unsigned int) temp2, nbits)) | ||||
|       return FALSE; | ||||
| 
 | ||||
|   /* Encode the AC coefficients per section F.1.2.2 */ | ||||
|    | ||||
|   r = 0;			/* r = run length of zeros */ | ||||
|    | ||||
|   for (k = 1; k < DCTSIZE2; k++) { | ||||
|     if ((temp = block[jpeg_natural_order[k]]) == 0) { | ||||
|       r++; | ||||
|     } else { | ||||
|       /* if run length > 15, must emit special run-length-16 codes (0xF0) */ | ||||
|       while (r > 15) { | ||||
| 	if (! emit_bits(state, actbl->ehufco[0xF0], actbl->ehufsi[0xF0])) | ||||
| 	  return FALSE; | ||||
| 	r -= 16; | ||||
|       } | ||||
| 
 | ||||
|       temp2 = temp; | ||||
|       if (temp < 0) { | ||||
| 	temp = -temp;		/* temp is abs value of input */ | ||||
| 	/* This code assumes we are on a two's complement machine */ | ||||
| 	temp2--; | ||||
|       } | ||||
|        | ||||
|       /* Find the number of bits needed for the magnitude of the coefficient */ | ||||
|       nbits = 1;		/* there must be at least one 1 bit */ | ||||
|       while ((temp >>= 1)) | ||||
| 	nbits++; | ||||
|       /* Check for out-of-range coefficient values */ | ||||
|       if (nbits > MAX_COEF_BITS) | ||||
| 	ERREXIT(state->cinfo, JERR_BAD_DCT_COEF); | ||||
|        | ||||
|       /* Emit Huffman symbol for run length / number of bits */ | ||||
|       i = (r << 4) + nbits; | ||||
|       if (! emit_bits(state, actbl->ehufco[i], actbl->ehufsi[i])) | ||||
| 	return FALSE; | ||||
| 
 | ||||
|       /* Emit that number of bits of the value, if positive, */ | ||||
|       /* or the complement of its magnitude, if negative. */ | ||||
|       if (! emit_bits(state, (unsigned int) temp2, nbits)) | ||||
| 	return FALSE; | ||||
|        | ||||
|       r = 0; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* If the last coef(s) were zero, emit an end-of-block code */ | ||||
|   if (r > 0) | ||||
|     if (! emit_bits(state, actbl->ehufco[0], actbl->ehufsi[0])) | ||||
|       return FALSE; | ||||
| 
 | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Emit a restart marker & resynchronize predictions. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(boolean) | ||||
| emit_restart (working_state * state, int restart_num) | ||||
| { | ||||
|   int ci; | ||||
| 
 | ||||
|   if (! flush_bits(state)) | ||||
|     return FALSE; | ||||
| 
 | ||||
|   emit_byte(state, 0xFF, return FALSE); | ||||
|   emit_byte(state, JPEG_RST0 + restart_num, return FALSE); | ||||
| 
 | ||||
|   /* Re-initialize DC predictions to 0 */ | ||||
|   for (ci = 0; ci < state->cinfo->comps_in_scan; ci++) | ||||
|     state->cur.last_dc_val[ci] = 0; | ||||
| 
 | ||||
|   /* The restart counter is not updated until we successfully write the MCU. */ | ||||
| 
 | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Encode and output one MCU's worth of Huffman-compressed coefficients. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(boolean) | ||||
| encode_mcu_huff (j_compress_ptr cinfo, JBLOCKROW *MCU_data) | ||||
| { | ||||
|   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; | ||||
|   working_state state; | ||||
|   int blkn, ci; | ||||
|   jpeg_component_info * compptr; | ||||
| 
 | ||||
|   /* Load up working state */ | ||||
|   state.next_output_byte = cinfo->dest->next_output_byte; | ||||
|   state.free_in_buffer = cinfo->dest->free_in_buffer; | ||||
|   ASSIGN_STATE(state.cur, entropy->saved); | ||||
|   state.cinfo = cinfo; | ||||
| 
 | ||||
|   /* Emit restart marker if needed */ | ||||
|   if (cinfo->restart_interval) { | ||||
|     if (entropy->restarts_to_go == 0) | ||||
|       if (! emit_restart(&state, entropy->next_restart_num)) | ||||
| 	return FALSE; | ||||
|   } | ||||
| 
 | ||||
|   /* Encode the MCU data blocks */ | ||||
|   for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { | ||||
|     ci = cinfo->MCU_membership[blkn]; | ||||
|     compptr = cinfo->cur_comp_info[ci]; | ||||
|     if (! encode_one_block(&state, | ||||
| 			   MCU_data[blkn][0], state.cur.last_dc_val[ci], | ||||
| 			   entropy->dc_derived_tbls[compptr->dc_tbl_no], | ||||
| 			   entropy->ac_derived_tbls[compptr->ac_tbl_no])) | ||||
|       return FALSE; | ||||
|     /* Update last_dc_val */ | ||||
|     state.cur.last_dc_val[ci] = MCU_data[blkn][0][0]; | ||||
|   } | ||||
| 
 | ||||
|   /* Completed MCU, so update state */ | ||||
|   cinfo->dest->next_output_byte = state.next_output_byte; | ||||
|   cinfo->dest->free_in_buffer = state.free_in_buffer; | ||||
|   ASSIGN_STATE(entropy->saved, state.cur); | ||||
| 
 | ||||
|   /* Update restart-interval state too */ | ||||
|   if (cinfo->restart_interval) { | ||||
|     if (entropy->restarts_to_go == 0) { | ||||
|       entropy->restarts_to_go = cinfo->restart_interval; | ||||
|       entropy->next_restart_num++; | ||||
|       entropy->next_restart_num &= 7; | ||||
|     } | ||||
|     entropy->restarts_to_go--; | ||||
|   } | ||||
| 
 | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Finish up at the end of a Huffman-compressed scan. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| finish_pass_huff (j_compress_ptr cinfo) | ||||
| { | ||||
|   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; | ||||
|   working_state state; | ||||
| 
 | ||||
|   /* Load up working state ... flush_bits needs it */ | ||||
|   state.next_output_byte = cinfo->dest->next_output_byte; | ||||
|   state.free_in_buffer = cinfo->dest->free_in_buffer; | ||||
|   ASSIGN_STATE(state.cur, entropy->saved); | ||||
|   state.cinfo = cinfo; | ||||
| 
 | ||||
|   /* Flush out the last data */ | ||||
|   if (! flush_bits(&state)) | ||||
|     ERREXIT(cinfo, JERR_CANT_SUSPEND); | ||||
| 
 | ||||
|   /* Update state */ | ||||
|   cinfo->dest->next_output_byte = state.next_output_byte; | ||||
|   cinfo->dest->free_in_buffer = state.free_in_buffer; | ||||
|   ASSIGN_STATE(entropy->saved, state.cur); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Huffman coding optimization. | ||||
|  * | ||||
|  * We first scan the supplied data and count the number of uses of each symbol | ||||
|  * that is to be Huffman-coded. (This process MUST agree with the code above.) | ||||
|  * Then we build a Huffman coding tree for the observed counts. | ||||
|  * Symbols which are not needed at all for the particular image are not | ||||
|  * assigned any code, which saves space in the DHT marker as well as in | ||||
|  * the compressed data. | ||||
|  */ | ||||
| 
 | ||||
| #ifdef ENTROPY_OPT_SUPPORTED | ||||
| 
 | ||||
| 
 | ||||
| /* Process a single block's worth of coefficients */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| htest_one_block (j_compress_ptr cinfo, JCOEFPTR block, int last_dc_val, | ||||
| 		 long dc_counts[], long ac_counts[]) | ||||
| { | ||||
|   register int temp; | ||||
|   register int nbits; | ||||
|   register int k, r; | ||||
|    | ||||
|   /* Encode the DC coefficient difference per section F.1.2.1 */ | ||||
|    | ||||
|   temp = block[0] - last_dc_val; | ||||
|   if (temp < 0) | ||||
|     temp = -temp; | ||||
|    | ||||
|   /* Find the number of bits needed for the magnitude of the coefficient */ | ||||
|   nbits = 0; | ||||
|   while (temp) { | ||||
|     nbits++; | ||||
|     temp >>= 1; | ||||
|   } | ||||
|   /* Check for out-of-range coefficient values.
 | ||||
|    * Since we're encoding a difference, the range limit is twice as much. | ||||
|    */ | ||||
|   if (nbits > MAX_COEF_BITS+1) | ||||
|     ERREXIT(cinfo, JERR_BAD_DCT_COEF); | ||||
| 
 | ||||
|   /* Count the Huffman symbol for the number of bits */ | ||||
|   dc_counts[nbits]++; | ||||
|    | ||||
|   /* Encode the AC coefficients per section F.1.2.2 */ | ||||
|    | ||||
|   r = 0;			/* r = run length of zeros */ | ||||
|    | ||||
|   for (k = 1; k < DCTSIZE2; k++) { | ||||
|     if ((temp = block[jpeg_natural_order[k]]) == 0) { | ||||
|       r++; | ||||
|     } else { | ||||
|       /* if run length > 15, must emit special run-length-16 codes (0xF0) */ | ||||
|       while (r > 15) { | ||||
| 	ac_counts[0xF0]++; | ||||
| 	r -= 16; | ||||
|       } | ||||
|        | ||||
|       /* Find the number of bits needed for the magnitude of the coefficient */ | ||||
|       if (temp < 0) | ||||
| 	temp = -temp; | ||||
|        | ||||
|       /* Find the number of bits needed for the magnitude of the coefficient */ | ||||
|       nbits = 1;		/* there must be at least one 1 bit */ | ||||
|       while ((temp >>= 1)) | ||||
| 	nbits++; | ||||
|       /* Check for out-of-range coefficient values */ | ||||
|       if (nbits > MAX_COEF_BITS) | ||||
| 	ERREXIT(cinfo, JERR_BAD_DCT_COEF); | ||||
|        | ||||
|       /* Count Huffman symbol for run length / number of bits */ | ||||
|       ac_counts[(r << 4) + nbits]++; | ||||
|        | ||||
|       r = 0; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* If the last coef(s) were zero, emit an end-of-block code */ | ||||
|   if (r > 0) | ||||
|     ac_counts[0]++; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Trial-encode one MCU's worth of Huffman-compressed coefficients. | ||||
|  * No data is actually output, so no suspension return is possible. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(boolean) | ||||
| encode_mcu_gather (j_compress_ptr cinfo, JBLOCKROW *MCU_data) | ||||
| { | ||||
|   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; | ||||
|   int blkn, ci; | ||||
|   jpeg_component_info * compptr; | ||||
| 
 | ||||
|   /* Take care of restart intervals if needed */ | ||||
|   if (cinfo->restart_interval) { | ||||
|     if (entropy->restarts_to_go == 0) { | ||||
|       /* Re-initialize DC predictions to 0 */ | ||||
|       for (ci = 0; ci < cinfo->comps_in_scan; ci++) | ||||
| 	entropy->saved.last_dc_val[ci] = 0; | ||||
|       /* Update restart state */ | ||||
|       entropy->restarts_to_go = cinfo->restart_interval; | ||||
|     } | ||||
|     entropy->restarts_to_go--; | ||||
|   } | ||||
| 
 | ||||
|   for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { | ||||
|     ci = cinfo->MCU_membership[blkn]; | ||||
|     compptr = cinfo->cur_comp_info[ci]; | ||||
|     htest_one_block(cinfo, MCU_data[blkn][0], entropy->saved.last_dc_val[ci], | ||||
| 		    entropy->dc_count_ptrs[compptr->dc_tbl_no], | ||||
| 		    entropy->ac_count_ptrs[compptr->ac_tbl_no]); | ||||
|     entropy->saved.last_dc_val[ci] = MCU_data[blkn][0][0]; | ||||
|   } | ||||
| 
 | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Generate the best Huffman code table for the given counts, fill htbl. | ||||
|  * Note this is also used by jcphuff.c. | ||||
|  * | ||||
|  * The JPEG standard requires that no symbol be assigned a codeword of all | ||||
|  * one bits (so that padding bits added at the end of a compressed segment | ||||
|  * can't look like a valid code).  Because of the canonical ordering of | ||||
|  * codewords, this just means that there must be an unused slot in the | ||||
|  * longest codeword length category.  Section K.2 of the JPEG spec suggests | ||||
|  * reserving such a slot by pretending that symbol 256 is a valid symbol | ||||
|  * with count 1.  In theory that's not optimal; giving it count zero but | ||||
|  * including it in the symbol set anyway should give a better Huffman code. | ||||
|  * But the theoretically better code actually seems to come out worse in | ||||
|  * practice, because it produces more all-ones bytes (which incur stuffed | ||||
|  * zero bytes in the final file).  In any case the difference is tiny. | ||||
|  * | ||||
|  * The JPEG standard requires Huffman codes to be no more than 16 bits long. | ||||
|  * If some symbols have a very small but nonzero probability, the Huffman tree | ||||
|  * must be adjusted to meet the code length restriction.  We currently use | ||||
|  * the adjustment method suggested in JPEG section K.2.  This method is *not* | ||||
|  * optimal; it may not choose the best possible limited-length code.  But | ||||
|  * typically only very-low-frequency symbols will be given less-than-optimal | ||||
|  * lengths, so the code is almost optimal.  Experimental comparisons against | ||||
|  * an optimal limited-length-code algorithm indicate that the difference is | ||||
|  * microscopic --- usually less than a hundredth of a percent of total size. | ||||
|  * So the extra complexity of an optimal algorithm doesn't seem worthwhile. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_gen_optimal_table (j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[]) | ||||
| { | ||||
| #define MAX_CLEN 32		/* assumed maximum initial code length */ | ||||
|   UINT8 bits[MAX_CLEN+1];	/* bits[k] = # of symbols with code length k */ | ||||
|   int codesize[257];		/* codesize[k] = code length of symbol k */ | ||||
|   int others[257];		/* next symbol in current branch of tree */ | ||||
|   int c1, c2; | ||||
|   int p, i, j; | ||||
|   long v; | ||||
| 
 | ||||
|   /* This algorithm is explained in section K.2 of the JPEG standard */ | ||||
| 
 | ||||
|   MEMZERO(bits, SIZEOF(bits)); | ||||
|   MEMZERO(codesize, SIZEOF(codesize)); | ||||
|   for (i = 0; i < 257; i++) | ||||
|     others[i] = -1;		/* init links to empty */ | ||||
|    | ||||
|   freq[256] = 1;		/* make sure 256 has a nonzero count */ | ||||
|   /* Including the pseudo-symbol 256 in the Huffman procedure guarantees
 | ||||
|    * that no real symbol is given code-value of all ones, because 256 | ||||
|    * will be placed last in the largest codeword category. | ||||
|    */ | ||||
| 
 | ||||
|   /* Huffman's basic algorithm to assign optimal code lengths to symbols */ | ||||
| 
 | ||||
|   for (;;) { | ||||
|     /* Find the smallest nonzero frequency, set c1 = its symbol */ | ||||
|     /* In case of ties, take the larger symbol number */ | ||||
|     c1 = -1; | ||||
|     v = 1000000000L; | ||||
|     for (i = 0; i <= 256; i++) { | ||||
|       if (freq[i] && freq[i] <= v) { | ||||
| 	v = freq[i]; | ||||
| 	c1 = i; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     /* Find the next smallest nonzero frequency, set c2 = its symbol */ | ||||
|     /* In case of ties, take the larger symbol number */ | ||||
|     c2 = -1; | ||||
|     v = 1000000000L; | ||||
|     for (i = 0; i <= 256; i++) { | ||||
|       if (freq[i] && freq[i] <= v && i != c1) { | ||||
| 	v = freq[i]; | ||||
| 	c2 = i; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     /* Done if we've merged everything into one frequency */ | ||||
|     if (c2 < 0) | ||||
|       break; | ||||
|      | ||||
|     /* Else merge the two counts/trees */ | ||||
|     freq[c1] += freq[c2]; | ||||
|     freq[c2] = 0; | ||||
| 
 | ||||
|     /* Increment the codesize of everything in c1's tree branch */ | ||||
|     codesize[c1]++; | ||||
|     while (others[c1] >= 0) { | ||||
|       c1 = others[c1]; | ||||
|       codesize[c1]++; | ||||
|     } | ||||
|      | ||||
|     others[c1] = c2;		/* chain c2 onto c1's tree branch */ | ||||
|      | ||||
|     /* Increment the codesize of everything in c2's tree branch */ | ||||
|     codesize[c2]++; | ||||
|     while (others[c2] >= 0) { | ||||
|       c2 = others[c2]; | ||||
|       codesize[c2]++; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Now count the number of symbols of each code length */ | ||||
|   for (i = 0; i <= 256; i++) { | ||||
|     if (codesize[i]) { | ||||
|       /* The JPEG standard seems to think that this can't happen, */ | ||||
|       /* but I'm paranoid... */ | ||||
|       if (codesize[i] > MAX_CLEN) | ||||
| 	ERREXIT(cinfo, JERR_HUFF_CLEN_OVERFLOW); | ||||
| 
 | ||||
|       bits[codesize[i]]++; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure
 | ||||
|    * Huffman procedure assigned any such lengths, we must adjust the coding. | ||||
|    * Here is what the JPEG spec says about how this next bit works: | ||||
|    * Since symbols are paired for the longest Huffman code, the symbols are | ||||
|    * removed from this length category two at a time.  The prefix for the pair | ||||
|    * (which is one bit shorter) is allocated to one of the pair; then, | ||||
|    * skipping the BITS entry for that prefix length, a code word from the next | ||||
|    * shortest nonzero BITS entry is converted into a prefix for two code words | ||||
|    * one bit longer. | ||||
|    */ | ||||
|    | ||||
|   for (i = MAX_CLEN; i > 16; i--) { | ||||
|     while (bits[i] > 0) { | ||||
|       j = i - 2;		/* find length of new prefix to be used */ | ||||
|       while (bits[j] == 0) | ||||
| 	j--; | ||||
|        | ||||
|       bits[i] -= 2;		/* remove two symbols */ | ||||
|       bits[i-1]++;		/* one goes in this length */ | ||||
|       bits[j+1] += 2;		/* two new symbols in this length */ | ||||
|       bits[j]--;		/* symbol of this length is now a prefix */ | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Remove the count for the pseudo-symbol 256 from the largest codelength */ | ||||
|   while (bits[i] == 0)		/* find largest codelength still in use */ | ||||
|     i--; | ||||
|   bits[i]--; | ||||
|    | ||||
|   /* Return final symbol counts (only for lengths 0..16) */ | ||||
|   MEMCOPY(htbl->bits, bits, SIZEOF(htbl->bits)); | ||||
|    | ||||
|   /* Return a list of the symbols sorted by code length */ | ||||
|   /* It's not real clear to me why we don't need to consider the codelength
 | ||||
|    * changes made above, but the JPEG spec seems to think this works. | ||||
|    */ | ||||
|   p = 0; | ||||
|   for (i = 1; i <= MAX_CLEN; i++) { | ||||
|     for (j = 0; j <= 255; j++) { | ||||
|       if (codesize[j] == i) { | ||||
| 	htbl->huffval[p] = (UINT8) j; | ||||
| 	p++; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Set sent_table FALSE so updated table will be written to JPEG file. */ | ||||
|   htbl->sent_table = FALSE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Finish up a statistics-gathering pass and create the new Huffman tables. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| finish_pass_gather (j_compress_ptr cinfo) | ||||
| { | ||||
|   huff_entropy_ptr entropy = (huff_entropy_ptr) cinfo->entropy; | ||||
|   int ci, dctbl, actbl; | ||||
|   jpeg_component_info * compptr; | ||||
|   JHUFF_TBL **htblptr; | ||||
|   boolean did_dc[NUM_HUFF_TBLS]; | ||||
|   boolean did_ac[NUM_HUFF_TBLS]; | ||||
| 
 | ||||
|   /* It's important not to apply jpeg_gen_optimal_table more than once
 | ||||
|    * per table, because it clobbers the input frequency counts! | ||||
|    */ | ||||
|   MEMZERO(did_dc, SIZEOF(did_dc)); | ||||
|   MEMZERO(did_ac, SIZEOF(did_ac)); | ||||
| 
 | ||||
|   for (ci = 0; ci < cinfo->comps_in_scan; ci++) { | ||||
|     compptr = cinfo->cur_comp_info[ci]; | ||||
|     dctbl = compptr->dc_tbl_no; | ||||
|     actbl = compptr->ac_tbl_no; | ||||
|     if (! did_dc[dctbl]) { | ||||
|       htblptr = & cinfo->dc_huff_tbl_ptrs[dctbl]; | ||||
|       if (*htblptr == NULL) | ||||
| 	*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); | ||||
|       jpeg_gen_optimal_table(cinfo, *htblptr, entropy->dc_count_ptrs[dctbl]); | ||||
|       did_dc[dctbl] = TRUE; | ||||
|     } | ||||
|     if (! did_ac[actbl]) { | ||||
|       htblptr = & cinfo->ac_huff_tbl_ptrs[actbl]; | ||||
|       if (*htblptr == NULL) | ||||
| 	*htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); | ||||
|       jpeg_gen_optimal_table(cinfo, *htblptr, entropy->ac_count_ptrs[actbl]); | ||||
|       did_ac[actbl] = TRUE; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #endif /* ENTROPY_OPT_SUPPORTED */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Module initialization routine for Huffman entropy encoding. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jinit_huff_encoder (j_compress_ptr cinfo) | ||||
| { | ||||
|   huff_entropy_ptr entropy; | ||||
|   int i; | ||||
| 
 | ||||
|   entropy = (huff_entropy_ptr) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				SIZEOF(huff_entropy_encoder)); | ||||
|   cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; | ||||
|   entropy->pub.start_pass = start_pass_huff; | ||||
| 
 | ||||
|   /* Mark tables unallocated */ | ||||
|   for (i = 0; i < NUM_HUFF_TBLS; i++) { | ||||
|     entropy->dc_derived_tbls[i] = entropy->ac_derived_tbls[i] = NULL; | ||||
| #ifdef ENTROPY_OPT_SUPPORTED | ||||
|     entropy->dc_count_ptrs[i] = entropy->ac_count_ptrs[i] = NULL; | ||||
| #endif | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,47 @@ | |||
| /*
 | ||||
|  * jchuff.h | ||||
|  * | ||||
|  * Copyright (C) 1991-1997, 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 declarations for Huffman entropy encoding routines | ||||
|  * that are shared between the sequential encoder (jchuff.c) and the | ||||
|  * progressive encoder (jcphuff.c).  No other modules need to see these. | ||||
|  */ | ||||
| 
 | ||||
| /* The legal range of a DCT coefficient is
 | ||||
|  *  -1024 .. +1023  for 8-bit data; | ||||
|  * -16384 .. +16383 for 12-bit data. | ||||
|  * Hence the magnitude should always fit in 10 or 14 bits respectively. | ||||
|  */ | ||||
| 
 | ||||
| #if BITS_IN_JSAMPLE == 8 | ||||
| #define MAX_COEF_BITS 10 | ||||
| #else | ||||
| #define MAX_COEF_BITS 14 | ||||
| #endif | ||||
| 
 | ||||
| /* Derived data constructed for each Huffman table */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   unsigned int ehufco[256];	/* code for each symbol */ | ||||
|   char ehufsi[256];		/* length of code for each symbol */ | ||||
|   /* If no code has been allocated for a symbol S, ehufsi[S] contains 0 */ | ||||
| } c_derived_tbl; | ||||
| 
 | ||||
| /* Short forms of external names for systems with brain-damaged linkers. */ | ||||
| 
 | ||||
| #ifdef NEED_SHORT_EXTERNAL_NAMES | ||||
| #define jpeg_make_c_derived_tbl	jMkCDerived | ||||
| #define jpeg_gen_optimal_table	jGenOptTbl | ||||
| #endif /* NEED_SHORT_EXTERNAL_NAMES */ | ||||
| 
 | ||||
| /* Expand a Huffman table definition into the derived format */ | ||||
| EXTERN(void) jpeg_make_c_derived_tbl | ||||
| 	JPP((j_compress_ptr cinfo, boolean isDC, int tblno, | ||||
| 	     c_derived_tbl ** pdtbl)); | ||||
| 
 | ||||
| /* Generate an optimal table definition given the specified counts */ | ||||
| EXTERN(void) jpeg_gen_optimal_table | ||||
| 	JPP((j_compress_ptr cinfo, JHUFF_TBL * htbl, long freq[])); | ||||
|  | @ -0,0 +1,72 @@ | |||
| /*
 | ||||
|  * jcinit.c | ||||
|  * | ||||
|  * Copyright (C) 1991-1997, 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 initialization logic for the JPEG compressor. | ||||
|  * This routine is in charge of selecting the modules to be executed and | ||||
|  * making an initialization call to each one. | ||||
|  * | ||||
|  * Logically, this code belongs in jcmaster.c.  It's split out because | ||||
|  * linking this routine implies linking the entire compression library. | ||||
|  * For a transcoding-only application, we want to be able to use jcmaster.c | ||||
|  * without linking in the whole library. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Master selection of compression modules. | ||||
|  * This is done once at the start of processing an image.  We determine | ||||
|  * which modules will be used and give them appropriate initialization calls. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jinit_compress_master (j_compress_ptr cinfo) | ||||
| { | ||||
|   /* Initialize master control (includes parameter checking/processing) */ | ||||
|   jinit_c_master_control(cinfo, FALSE /* full compression */); | ||||
| 
 | ||||
|   /* Preprocessing */ | ||||
|   if (! cinfo->raw_data_in) { | ||||
|     jinit_color_converter(cinfo); | ||||
|     jinit_downsampler(cinfo); | ||||
|     jinit_c_prep_controller(cinfo, FALSE /* never need full buffer here */); | ||||
|   } | ||||
|   /* Forward DCT */ | ||||
|   jinit_forward_dct(cinfo); | ||||
|   /* Entropy encoding: either Huffman or arithmetic coding. */ | ||||
|   if (cinfo->arith_code) { | ||||
|     ERREXIT(cinfo, JERR_ARITH_NOTIMPL); | ||||
|   } else { | ||||
|     if (cinfo->progressive_mode) { | ||||
| #ifdef C_PROGRESSIVE_SUPPORTED | ||||
|       jinit_phuff_encoder(cinfo); | ||||
| #else | ||||
|       ERREXIT(cinfo, JERR_NOT_COMPILED); | ||||
| #endif | ||||
|     } else | ||||
|       jinit_huff_encoder(cinfo); | ||||
|   } | ||||
| 
 | ||||
|   /* Need a full-image coefficient buffer in any multi-pass mode. */ | ||||
|   jinit_c_coef_controller(cinfo, | ||||
| 		(boolean) (cinfo->num_scans > 1 || cinfo->optimize_coding)); | ||||
|   jinit_c_main_controller(cinfo, FALSE /* never need full buffer here */); | ||||
| 
 | ||||
|   jinit_marker_writer(cinfo); | ||||
| 
 | ||||
|   /* We can now tell the memory manager to allocate virtual arrays. */ | ||||
|   (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); | ||||
| 
 | ||||
|   /* Write the datastream header (SOI) immediately.
 | ||||
|    * Frame and scan headers are postponed till later. | ||||
|    * This lets application insert special markers after the SOI. | ||||
|    */ | ||||
|   (*cinfo->marker->write_file_header) (cinfo); | ||||
| } | ||||
|  | @ -0,0 +1,293 @@ | |||
| /*
 | ||||
|  * jcmainct.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 the main buffer controller for compression. | ||||
|  * The main buffer lies between the pre-processor and the JPEG | ||||
|  * compressor proper; it holds downsampled data in the JPEG colorspace. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Note: currently, there is no operating mode in which a full-image buffer
 | ||||
|  * is needed at this step.  If there were, that mode could not be used with | ||||
|  * "raw data" input, since this module is bypassed in that case.  However, | ||||
|  * we've left the code here for possible use in special applications. | ||||
|  */ | ||||
| #undef FULL_MAIN_BUFFER_SUPPORTED | ||||
| 
 | ||||
| 
 | ||||
| /* Private buffer controller object */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_c_main_controller pub; /* public fields */ | ||||
| 
 | ||||
|   JDIMENSION cur_iMCU_row;	/* number of current iMCU row */ | ||||
|   JDIMENSION rowgroup_ctr;	/* counts row groups received in iMCU row */ | ||||
|   boolean suspended;		/* remember if we suspended output */ | ||||
|   J_BUF_MODE pass_mode;		/* current operating mode */ | ||||
| 
 | ||||
|   /* If using just a strip buffer, this points to the entire set of buffers
 | ||||
|    * (we allocate one for each component).  In the full-image case, this | ||||
|    * points to the currently accessible strips of the virtual arrays. | ||||
|    */ | ||||
|   JSAMPARRAY buffer[MAX_COMPONENTS]; | ||||
| 
 | ||||
| #ifdef FULL_MAIN_BUFFER_SUPPORTED | ||||
|   /* If using full-image storage, this array holds pointers to virtual-array
 | ||||
|    * control blocks for each component.  Unused if not full-image storage. | ||||
|    */ | ||||
|   jvirt_sarray_ptr whole_image[MAX_COMPONENTS]; | ||||
| #endif | ||||
| } my_main_controller; | ||||
| 
 | ||||
| typedef my_main_controller * my_main_ptr; | ||||
| 
 | ||||
| 
 | ||||
| /* Forward declarations */ | ||||
| METHODDEF(void) process_data_simple_main | ||||
| 	JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, | ||||
| 	     JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); | ||||
| #ifdef FULL_MAIN_BUFFER_SUPPORTED | ||||
| METHODDEF(void) process_data_buffer_main | ||||
| 	JPP((j_compress_ptr cinfo, JSAMPARRAY input_buf, | ||||
| 	     JDIMENSION *in_row_ctr, JDIMENSION in_rows_avail)); | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize for a processing pass. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| start_pass_main (j_compress_ptr cinfo, J_BUF_MODE pass_mode) | ||||
| { | ||||
|   my_main_ptr main = (my_main_ptr) cinfo->main; | ||||
| 
 | ||||
|   /* Do nothing in raw-data mode. */ | ||||
|   if (cinfo->raw_data_in) | ||||
|     return; | ||||
| 
 | ||||
|   main->cur_iMCU_row = 0;	/* initialize counters */ | ||||
|   main->rowgroup_ctr = 0; | ||||
|   main->suspended = FALSE; | ||||
|   main->pass_mode = pass_mode;	/* save mode for use by process_data */ | ||||
| 
 | ||||
|   switch (pass_mode) { | ||||
|   case JBUF_PASS_THRU: | ||||
| #ifdef FULL_MAIN_BUFFER_SUPPORTED | ||||
|     if (main->whole_image[0] != NULL) | ||||
|       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
| #endif | ||||
|     main->pub.process_data = process_data_simple_main; | ||||
|     break; | ||||
| #ifdef FULL_MAIN_BUFFER_SUPPORTED | ||||
|   case JBUF_SAVE_SOURCE: | ||||
|   case JBUF_CRANK_DEST: | ||||
|   case JBUF_SAVE_AND_PASS: | ||||
|     if (main->whole_image[0] == NULL) | ||||
|       ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
|     main->pub.process_data = process_data_buffer_main; | ||||
|     break; | ||||
| #endif | ||||
|   default: | ||||
|     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
|     break; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Process some data. | ||||
|  * This routine handles the simple pass-through mode, | ||||
|  * where we have only a strip buffer. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| process_data_simple_main (j_compress_ptr cinfo, | ||||
| 			  JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, | ||||
| 			  JDIMENSION in_rows_avail) | ||||
| { | ||||
|   my_main_ptr main = (my_main_ptr) cinfo->main; | ||||
| 
 | ||||
|   while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { | ||||
|     /* Read input data if we haven't filled the main buffer yet */ | ||||
|     if (main->rowgroup_ctr < DCTSIZE) | ||||
|       (*cinfo->prep->pre_process_data) (cinfo, | ||||
| 					input_buf, in_row_ctr, in_rows_avail, | ||||
| 					main->buffer, &main->rowgroup_ctr, | ||||
| 					(JDIMENSION) DCTSIZE); | ||||
| 
 | ||||
|     /* If we don't have a full iMCU row buffered, return to application for
 | ||||
|      * more data.  Note that preprocessor will always pad to fill the iMCU row | ||||
|      * at the bottom of the image. | ||||
|      */ | ||||
|     if (main->rowgroup_ctr != DCTSIZE) | ||||
|       return; | ||||
| 
 | ||||
|     /* Send the completed row to the compressor */ | ||||
|     if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { | ||||
|       /* If compressor did not consume the whole row, then we must need to
 | ||||
|        * suspend processing and return to the application.  In this situation | ||||
|        * we pretend we didn't yet consume the last input row; otherwise, if | ||||
|        * it happened to be the last row of the image, the application would | ||||
|        * think we were done. | ||||
|        */ | ||||
|       if (! main->suspended) { | ||||
| 	(*in_row_ctr)--; | ||||
| 	main->suspended = TRUE; | ||||
|       } | ||||
|       return; | ||||
|     } | ||||
|     /* We did finish the row.  Undo our little suspension hack if a previous
 | ||||
|      * call suspended; then mark the main buffer empty. | ||||
|      */ | ||||
|     if (main->suspended) { | ||||
|       (*in_row_ctr)++; | ||||
|       main->suspended = FALSE; | ||||
|     } | ||||
|     main->rowgroup_ctr = 0; | ||||
|     main->cur_iMCU_row++; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef FULL_MAIN_BUFFER_SUPPORTED | ||||
| 
 | ||||
| /*
 | ||||
|  * Process some data. | ||||
|  * This routine handles all of the modes that use a full-size buffer. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| process_data_buffer_main (j_compress_ptr cinfo, | ||||
| 			  JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, | ||||
| 			  JDIMENSION in_rows_avail) | ||||
| { | ||||
|   my_main_ptr main = (my_main_ptr) cinfo->main; | ||||
|   int ci; | ||||
|   jpeg_component_info *compptr; | ||||
|   boolean writing = (main->pass_mode != JBUF_CRANK_DEST); | ||||
| 
 | ||||
|   while (main->cur_iMCU_row < cinfo->total_iMCU_rows) { | ||||
|     /* Realign the virtual buffers if at the start of an iMCU row. */ | ||||
|     if (main->rowgroup_ctr == 0) { | ||||
|       for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
| 	   ci++, compptr++) { | ||||
| 	main->buffer[ci] = (*cinfo->mem->access_virt_sarray) | ||||
| 	  ((j_common_ptr) cinfo, main->whole_image[ci], | ||||
| 	   main->cur_iMCU_row * (compptr->v_samp_factor * DCTSIZE), | ||||
| 	   (JDIMENSION) (compptr->v_samp_factor * DCTSIZE), writing); | ||||
|       } | ||||
|       /* In a read pass, pretend we just read some source data. */ | ||||
|       if (! writing) { | ||||
| 	*in_row_ctr += cinfo->max_v_samp_factor * DCTSIZE; | ||||
| 	main->rowgroup_ctr = DCTSIZE; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     /* If a write pass, read input data until the current iMCU row is full. */ | ||||
|     /* Note: preprocessor will pad if necessary to fill the last iMCU row. */ | ||||
|     if (writing) { | ||||
|       (*cinfo->prep->pre_process_data) (cinfo, | ||||
| 					input_buf, in_row_ctr, in_rows_avail, | ||||
| 					main->buffer, &main->rowgroup_ctr, | ||||
| 					(JDIMENSION) DCTSIZE); | ||||
|       /* Return to application if we need more data to fill the iMCU row. */ | ||||
|       if (main->rowgroup_ctr < DCTSIZE) | ||||
| 	return; | ||||
|     } | ||||
| 
 | ||||
|     /* Emit data, unless this is a sink-only pass. */ | ||||
|     if (main->pass_mode != JBUF_SAVE_SOURCE) { | ||||
|       if (! (*cinfo->coef->compress_data) (cinfo, main->buffer)) { | ||||
| 	/* If compressor did not consume the whole row, then we must need to
 | ||||
| 	 * suspend processing and return to the application.  In this situation | ||||
| 	 * we pretend we didn't yet consume the last input row; otherwise, if | ||||
| 	 * it happened to be the last row of the image, the application would | ||||
| 	 * think we were done. | ||||
| 	 */ | ||||
| 	if (! main->suspended) { | ||||
| 	  (*in_row_ctr)--; | ||||
| 	  main->suspended = TRUE; | ||||
| 	} | ||||
| 	return; | ||||
|       } | ||||
|       /* We did finish the row.  Undo our little suspension hack if a previous
 | ||||
|        * call suspended; then mark the main buffer empty. | ||||
|        */ | ||||
|       if (main->suspended) { | ||||
| 	(*in_row_ctr)++; | ||||
| 	main->suspended = FALSE; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     /* If get here, we are done with this iMCU row.  Mark buffer empty. */ | ||||
|     main->rowgroup_ctr = 0; | ||||
|     main->cur_iMCU_row++; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #endif /* FULL_MAIN_BUFFER_SUPPORTED */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize main buffer controller. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jinit_c_main_controller (j_compress_ptr cinfo, boolean need_full_buffer) | ||||
| { | ||||
|   my_main_ptr main; | ||||
|   int ci; | ||||
|   jpeg_component_info *compptr; | ||||
| 
 | ||||
|   main = (my_main_ptr) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				SIZEOF(my_main_controller)); | ||||
|   cinfo->main = (struct jpeg_c_main_controller *) main; | ||||
|   main->pub.start_pass = start_pass_main; | ||||
| 
 | ||||
|   /* We don't need to create a buffer in raw-data mode. */ | ||||
|   if (cinfo->raw_data_in) | ||||
|     return; | ||||
| 
 | ||||
|   /* Create the buffer.  It holds downsampled data, so each component
 | ||||
|    * may be of a different size. | ||||
|    */ | ||||
|   if (need_full_buffer) { | ||||
| #ifdef FULL_MAIN_BUFFER_SUPPORTED | ||||
|     /* Allocate a full-image virtual array for each component */ | ||||
|     /* Note we pad the bottom to a multiple of the iMCU height */ | ||||
|     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
| 	 ci++, compptr++) { | ||||
|       main->whole_image[ci] = (*cinfo->mem->request_virt_sarray) | ||||
| 	((j_common_ptr) cinfo, JPOOL_IMAGE, FALSE, | ||||
| 	 compptr->width_in_blocks * DCTSIZE, | ||||
| 	 (JDIMENSION) jround_up((long) compptr->height_in_blocks, | ||||
| 				(long) compptr->v_samp_factor) * DCTSIZE, | ||||
| 	 (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); | ||||
|     } | ||||
| #else | ||||
|     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
| #endif | ||||
|   } else { | ||||
| #ifdef FULL_MAIN_BUFFER_SUPPORTED | ||||
|     main->whole_image[0] = NULL; /* flag for no virtual arrays */ | ||||
| #endif | ||||
|     /* Allocate a strip buffer for each component */ | ||||
|     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
| 	 ci++, compptr++) { | ||||
|       main->buffer[ci] = (*cinfo->mem->alloc_sarray) | ||||
| 	((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 	 compptr->width_in_blocks * DCTSIZE, | ||||
| 	 (JDIMENSION) (compptr->v_samp_factor * DCTSIZE)); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,664 @@ | |||
| /*
 | ||||
|  * jcmarker.c | ||||
|  * | ||||
|  * Copyright (C) 1991-1998, 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 routines to write JPEG datastream markers. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| typedef enum {			/* JPEG marker codes */ | ||||
|   M_SOF0  = 0xc0, | ||||
|   M_SOF1  = 0xc1, | ||||
|   M_SOF2  = 0xc2, | ||||
|   M_SOF3  = 0xc3, | ||||
|    | ||||
|   M_SOF5  = 0xc5, | ||||
|   M_SOF6  = 0xc6, | ||||
|   M_SOF7  = 0xc7, | ||||
|    | ||||
|   M_JPG   = 0xc8, | ||||
|   M_SOF9  = 0xc9, | ||||
|   M_SOF10 = 0xca, | ||||
|   M_SOF11 = 0xcb, | ||||
|    | ||||
|   M_SOF13 = 0xcd, | ||||
|   M_SOF14 = 0xce, | ||||
|   M_SOF15 = 0xcf, | ||||
|    | ||||
|   M_DHT   = 0xc4, | ||||
|    | ||||
|   M_DAC   = 0xcc, | ||||
|    | ||||
|   M_RST0  = 0xd0, | ||||
|   M_RST1  = 0xd1, | ||||
|   M_RST2  = 0xd2, | ||||
|   M_RST3  = 0xd3, | ||||
|   M_RST4  = 0xd4, | ||||
|   M_RST5  = 0xd5, | ||||
|   M_RST6  = 0xd6, | ||||
|   M_RST7  = 0xd7, | ||||
|    | ||||
|   M_SOI   = 0xd8, | ||||
|   M_EOI   = 0xd9, | ||||
|   M_SOS   = 0xda, | ||||
|   M_DQT   = 0xdb, | ||||
|   M_DNL   = 0xdc, | ||||
|   M_DRI   = 0xdd, | ||||
|   M_DHP   = 0xde, | ||||
|   M_EXP   = 0xdf, | ||||
|    | ||||
|   M_APP0  = 0xe0, | ||||
|   M_APP1  = 0xe1, | ||||
|   M_APP2  = 0xe2, | ||||
|   M_APP3  = 0xe3, | ||||
|   M_APP4  = 0xe4, | ||||
|   M_APP5  = 0xe5, | ||||
|   M_APP6  = 0xe6, | ||||
|   M_APP7  = 0xe7, | ||||
|   M_APP8  = 0xe8, | ||||
|   M_APP9  = 0xe9, | ||||
|   M_APP10 = 0xea, | ||||
|   M_APP11 = 0xeb, | ||||
|   M_APP12 = 0xec, | ||||
|   M_APP13 = 0xed, | ||||
|   M_APP14 = 0xee, | ||||
|   M_APP15 = 0xef, | ||||
|    | ||||
|   M_JPG0  = 0xf0, | ||||
|   M_JPG13 = 0xfd, | ||||
|   M_COM   = 0xfe, | ||||
|    | ||||
|   M_TEM   = 0x01, | ||||
|    | ||||
|   M_ERROR = 0x100 | ||||
| } JPEG_MARKER; | ||||
| 
 | ||||
| 
 | ||||
| /* Private state */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_marker_writer pub; /* public fields */ | ||||
| 
 | ||||
|   unsigned int last_restart_interval; /* last DRI value emitted; 0 after SOI */ | ||||
| } my_marker_writer; | ||||
| 
 | ||||
| typedef my_marker_writer * my_marker_ptr; | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Basic output routines. | ||||
|  * | ||||
|  * Note that we do not support suspension while writing a marker. | ||||
|  * Therefore, an application using suspension must ensure that there is | ||||
|  * enough buffer space for the initial markers (typ. 600-700 bytes) before | ||||
|  * calling jpeg_start_compress, and enough space to write the trailing EOI | ||||
|  * (a few bytes) before calling jpeg_finish_compress.  Multipass compression | ||||
|  * modes are not supported at all with suspension, so those two are the only | ||||
|  * points where markers will be written. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_byte (j_compress_ptr cinfo, int val) | ||||
| /* Emit a byte */ | ||||
| { | ||||
|   struct jpeg_destination_mgr * dest = cinfo->dest; | ||||
| 
 | ||||
|   *(dest->next_output_byte)++ = (JOCTET) val; | ||||
|   if (--dest->free_in_buffer == 0) { | ||||
|     if (! (*dest->empty_output_buffer) (cinfo)) | ||||
|       ERREXIT(cinfo, JERR_CANT_SUSPEND); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_marker (j_compress_ptr cinfo, JPEG_MARKER mark) | ||||
| /* Emit a marker code */ | ||||
| { | ||||
|   emit_byte(cinfo, 0xFF); | ||||
|   emit_byte(cinfo, (int) mark); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_2bytes (j_compress_ptr cinfo, int value) | ||||
| /* Emit a 2-byte integer; these are always MSB first in JPEG files */ | ||||
| { | ||||
|   emit_byte(cinfo, (value >> 8) & 0xFF); | ||||
|   emit_byte(cinfo, value & 0xFF); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Routines to write specific marker types. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(int) | ||||
| emit_dqt (j_compress_ptr cinfo, int index) | ||||
| /* Emit a DQT marker */ | ||||
| /* Returns the precision used (0 = 8bits, 1 = 16bits) for baseline checking */ | ||||
| { | ||||
|   JQUANT_TBL * qtbl = cinfo->quant_tbl_ptrs[index]; | ||||
|   int prec; | ||||
|   int i; | ||||
| 
 | ||||
|   if (qtbl == NULL) | ||||
|     ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, index); | ||||
| 
 | ||||
|   prec = 0; | ||||
|   for (i = 0; i < DCTSIZE2; i++) { | ||||
|     if (qtbl->quantval[i] > 255) | ||||
|       prec = 1; | ||||
|   } | ||||
| 
 | ||||
|   if (! qtbl->sent_table) { | ||||
|     emit_marker(cinfo, M_DQT); | ||||
| 
 | ||||
|     emit_2bytes(cinfo, prec ? DCTSIZE2*2 + 1 + 2 : DCTSIZE2 + 1 + 2); | ||||
| 
 | ||||
|     emit_byte(cinfo, index + (prec<<4)); | ||||
| 
 | ||||
|     for (i = 0; i < DCTSIZE2; i++) { | ||||
|       /* The table entries must be emitted in zigzag order. */ | ||||
|       unsigned int qval = qtbl->quantval[jpeg_natural_order[i]]; | ||||
|       if (prec) | ||||
| 	emit_byte(cinfo, (int) (qval >> 8)); | ||||
|       emit_byte(cinfo, (int) (qval & 0xFF)); | ||||
|     } | ||||
| 
 | ||||
|     qtbl->sent_table = TRUE; | ||||
|   } | ||||
| 
 | ||||
|   return prec; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_dht (j_compress_ptr cinfo, int index, boolean is_ac) | ||||
| /* Emit a DHT marker */ | ||||
| { | ||||
|   JHUFF_TBL * htbl; | ||||
|   int length, i; | ||||
|    | ||||
|   if (is_ac) { | ||||
|     htbl = cinfo->ac_huff_tbl_ptrs[index]; | ||||
|     index += 0x10;		/* output index has AC bit set */ | ||||
|   } else { | ||||
|     htbl = cinfo->dc_huff_tbl_ptrs[index]; | ||||
|   } | ||||
| 
 | ||||
|   if (htbl == NULL) | ||||
|     ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, index); | ||||
|    | ||||
|   if (! htbl->sent_table) { | ||||
|     emit_marker(cinfo, M_DHT); | ||||
|      | ||||
|     length = 0; | ||||
|     for (i = 1; i <= 16; i++) | ||||
|       length += htbl->bits[i]; | ||||
|      | ||||
|     emit_2bytes(cinfo, length + 2 + 1 + 16); | ||||
|     emit_byte(cinfo, index); | ||||
|      | ||||
|     for (i = 1; i <= 16; i++) | ||||
|       emit_byte(cinfo, htbl->bits[i]); | ||||
|      | ||||
|     for (i = 0; i < length; i++) | ||||
|       emit_byte(cinfo, htbl->huffval[i]); | ||||
|      | ||||
|     htbl->sent_table = TRUE; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_dac (j_compress_ptr cinfo) | ||||
| /* Emit a DAC marker */ | ||||
| /* Since the useful info is so small, we want to emit all the tables in */ | ||||
| /* one DAC marker.  Therefore this routine does its own scan of the table. */ | ||||
| { | ||||
| #ifdef C_ARITH_CODING_SUPPORTED | ||||
|   char dc_in_use[NUM_ARITH_TBLS]; | ||||
|   char ac_in_use[NUM_ARITH_TBLS]; | ||||
|   int length, i; | ||||
|   jpeg_component_info *compptr; | ||||
|    | ||||
|   for (i = 0; i < NUM_ARITH_TBLS; i++) | ||||
|     dc_in_use[i] = ac_in_use[i] = 0; | ||||
|    | ||||
|   for (i = 0; i < cinfo->comps_in_scan; i++) { | ||||
|     compptr = cinfo->cur_comp_info[i]; | ||||
|     dc_in_use[compptr->dc_tbl_no] = 1; | ||||
|     ac_in_use[compptr->ac_tbl_no] = 1; | ||||
|   } | ||||
|    | ||||
|   length = 0; | ||||
|   for (i = 0; i < NUM_ARITH_TBLS; i++) | ||||
|     length += dc_in_use[i] + ac_in_use[i]; | ||||
|    | ||||
|   emit_marker(cinfo, M_DAC); | ||||
|    | ||||
|   emit_2bytes(cinfo, length*2 + 2); | ||||
|    | ||||
|   for (i = 0; i < NUM_ARITH_TBLS; i++) { | ||||
|     if (dc_in_use[i]) { | ||||
|       emit_byte(cinfo, i); | ||||
|       emit_byte(cinfo, cinfo->arith_dc_L[i] + (cinfo->arith_dc_U[i]<<4)); | ||||
|     } | ||||
|     if (ac_in_use[i]) { | ||||
|       emit_byte(cinfo, i + 0x10); | ||||
|       emit_byte(cinfo, cinfo->arith_ac_K[i]); | ||||
|     } | ||||
|   } | ||||
| #endif /* C_ARITH_CODING_SUPPORTED */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_dri (j_compress_ptr cinfo) | ||||
| /* Emit a DRI marker */ | ||||
| { | ||||
|   emit_marker(cinfo, M_DRI); | ||||
|    | ||||
|   emit_2bytes(cinfo, 4);	/* fixed length */ | ||||
| 
 | ||||
|   emit_2bytes(cinfo, (int) cinfo->restart_interval); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_sof (j_compress_ptr cinfo, JPEG_MARKER code) | ||||
| /* Emit a SOF marker */ | ||||
| { | ||||
|   int ci; | ||||
|   jpeg_component_info *compptr; | ||||
|    | ||||
|   emit_marker(cinfo, code); | ||||
|    | ||||
|   emit_2bytes(cinfo, 3 * cinfo->num_components + 2 + 5 + 1); /* length */ | ||||
| 
 | ||||
|   /* Make sure image isn't bigger than SOF field can handle */ | ||||
|   if ((long) cinfo->image_height > 65535L || | ||||
|       (long) cinfo->image_width > 65535L) | ||||
|     ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) 65535); | ||||
| 
 | ||||
|   emit_byte(cinfo, cinfo->data_precision); | ||||
|   emit_2bytes(cinfo, (int) cinfo->image_height); | ||||
|   emit_2bytes(cinfo, (int) cinfo->image_width); | ||||
| 
 | ||||
|   emit_byte(cinfo, cinfo->num_components); | ||||
| 
 | ||||
|   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
|        ci++, compptr++) { | ||||
|     emit_byte(cinfo, compptr->component_id); | ||||
|     emit_byte(cinfo, (compptr->h_samp_factor << 4) + compptr->v_samp_factor); | ||||
|     emit_byte(cinfo, compptr->quant_tbl_no); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_sos (j_compress_ptr cinfo) | ||||
| /* Emit a SOS marker */ | ||||
| { | ||||
|   int i, td, ta; | ||||
|   jpeg_component_info *compptr; | ||||
|    | ||||
|   emit_marker(cinfo, M_SOS); | ||||
|    | ||||
|   emit_2bytes(cinfo, 2 * cinfo->comps_in_scan + 2 + 1 + 3); /* length */ | ||||
|    | ||||
|   emit_byte(cinfo, cinfo->comps_in_scan); | ||||
|    | ||||
|   for (i = 0; i < cinfo->comps_in_scan; i++) { | ||||
|     compptr = cinfo->cur_comp_info[i]; | ||||
|     emit_byte(cinfo, compptr->component_id); | ||||
|     td = compptr->dc_tbl_no; | ||||
|     ta = compptr->ac_tbl_no; | ||||
|     if (cinfo->progressive_mode) { | ||||
|       /* Progressive mode: only DC or only AC tables are used in one scan;
 | ||||
|        * furthermore, Huffman coding of DC refinement uses no table at all. | ||||
|        * We emit 0 for unused field(s); this is recommended by the P&M text | ||||
|        * but does not seem to be specified in the standard. | ||||
|        */ | ||||
|       if (cinfo->Ss == 0) { | ||||
| 	ta = 0;			/* DC scan */ | ||||
| 	if (cinfo->Ah != 0 && !cinfo->arith_code) | ||||
| 	  td = 0;		/* no DC table either */ | ||||
|       } else { | ||||
| 	td = 0;			/* AC scan */ | ||||
|       } | ||||
|     } | ||||
|     emit_byte(cinfo, (td << 4) + ta); | ||||
|   } | ||||
| 
 | ||||
|   emit_byte(cinfo, cinfo->Ss); | ||||
|   emit_byte(cinfo, cinfo->Se); | ||||
|   emit_byte(cinfo, (cinfo->Ah << 4) + cinfo->Al); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_jfif_app0 (j_compress_ptr cinfo) | ||||
| /* Emit a JFIF-compliant APP0 marker */ | ||||
| { | ||||
|   /*
 | ||||
|    * Length of APP0 block	(2 bytes) | ||||
|    * Block ID			(4 bytes - ASCII "JFIF") | ||||
|    * Zero byte			(1 byte to terminate the ID string) | ||||
|    * Version Major, Minor	(2 bytes - major first) | ||||
|    * Units			(1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) | ||||
|    * Xdpu			(2 bytes - dots per unit horizontal) | ||||
|    * Ydpu			(2 bytes - dots per unit vertical) | ||||
|    * Thumbnail X size		(1 byte) | ||||
|    * Thumbnail Y size		(1 byte) | ||||
|    */ | ||||
|    | ||||
|   emit_marker(cinfo, M_APP0); | ||||
|    | ||||
|   emit_2bytes(cinfo, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ | ||||
| 
 | ||||
|   emit_byte(cinfo, 0x4A);	/* Identifier: ASCII "JFIF" */ | ||||
|   emit_byte(cinfo, 0x46); | ||||
|   emit_byte(cinfo, 0x49); | ||||
|   emit_byte(cinfo, 0x46); | ||||
|   emit_byte(cinfo, 0); | ||||
|   emit_byte(cinfo, cinfo->JFIF_major_version); /* Version fields */ | ||||
|   emit_byte(cinfo, cinfo->JFIF_minor_version); | ||||
|   emit_byte(cinfo, cinfo->density_unit); /* Pixel size information */ | ||||
|   emit_2bytes(cinfo, (int) cinfo->X_density); | ||||
|   emit_2bytes(cinfo, (int) cinfo->Y_density); | ||||
|   emit_byte(cinfo, 0);		/* No thumbnail image */ | ||||
|   emit_byte(cinfo, 0); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_adobe_app14 (j_compress_ptr cinfo) | ||||
| /* Emit an Adobe APP14 marker */ | ||||
| { | ||||
|   /*
 | ||||
|    * Length of APP14 block	(2 bytes) | ||||
|    * Block ID			(5 bytes - ASCII "Adobe") | ||||
|    * Version Number		(2 bytes - currently 100) | ||||
|    * Flags0			(2 bytes - currently 0) | ||||
|    * Flags1			(2 bytes - currently 0) | ||||
|    * Color transform		(1 byte) | ||||
|    * | ||||
|    * Although Adobe TN 5116 mentions Version = 101, all the Adobe files | ||||
|    * now in circulation seem to use Version = 100, so that's what we write. | ||||
|    * | ||||
|    * We write the color transform byte as 1 if the JPEG color space is | ||||
|    * YCbCr, 2 if it's YCCK, 0 otherwise.  Adobe's definition has to do with | ||||
|    * whether the encoder performed a transformation, which is pretty useless. | ||||
|    */ | ||||
|    | ||||
|   emit_marker(cinfo, M_APP14); | ||||
|    | ||||
|   emit_2bytes(cinfo, 2 + 5 + 2 + 2 + 2 + 1); /* length */ | ||||
| 
 | ||||
|   emit_byte(cinfo, 0x41);	/* Identifier: ASCII "Adobe" */ | ||||
|   emit_byte(cinfo, 0x64); | ||||
|   emit_byte(cinfo, 0x6F); | ||||
|   emit_byte(cinfo, 0x62); | ||||
|   emit_byte(cinfo, 0x65); | ||||
|   emit_2bytes(cinfo, 100);	/* Version */ | ||||
|   emit_2bytes(cinfo, 0);	/* Flags0 */ | ||||
|   emit_2bytes(cinfo, 0);	/* Flags1 */ | ||||
|   switch (cinfo->jpeg_color_space) { | ||||
|   case JCS_YCbCr: | ||||
|     emit_byte(cinfo, 1);	/* Color transform = 1 */ | ||||
|     break; | ||||
|   case JCS_YCCK: | ||||
|     emit_byte(cinfo, 2);	/* Color transform = 2 */ | ||||
|     break; | ||||
|   default: | ||||
|     emit_byte(cinfo, 0);	/* Color transform = 0 */ | ||||
|     break; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * These routines allow writing an arbitrary marker with parameters. | ||||
|  * The only intended use is to emit COM or APPn markers after calling | ||||
|  * write_file_header and before calling write_frame_header. | ||||
|  * Other uses are not guaranteed to produce desirable results. | ||||
|  * Counting the parameter bytes properly is the caller's responsibility. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| write_marker_header (j_compress_ptr cinfo, int marker, unsigned int datalen) | ||||
| /* Emit an arbitrary marker header */ | ||||
| { | ||||
|   if (datalen > (unsigned int) 65533)		/* safety check */ | ||||
|     ERREXIT(cinfo, JERR_BAD_LENGTH); | ||||
| 
 | ||||
|   emit_marker(cinfo, (JPEG_MARKER) marker); | ||||
| 
 | ||||
|   emit_2bytes(cinfo, (int) (datalen + 2));	/* total length */ | ||||
| } | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| write_marker_byte (j_compress_ptr cinfo, int val) | ||||
| /* Emit one byte of marker parameters following write_marker_header */ | ||||
| { | ||||
|   emit_byte(cinfo, val); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Write datastream header. | ||||
|  * This consists of an SOI and optional APPn markers. | ||||
|  * We recommend use of the JFIF marker, but not the Adobe marker, | ||||
|  * when using YCbCr or grayscale data.  The JFIF marker should NOT | ||||
|  * be used for any other JPEG colorspace.  The Adobe marker is helpful | ||||
|  * to distinguish RGB, CMYK, and YCCK colorspaces. | ||||
|  * Note that an application can write additional header markers after | ||||
|  * jpeg_start_compress returns. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| write_file_header (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_marker_ptr marker = (my_marker_ptr) cinfo->marker; | ||||
| 
 | ||||
|   emit_marker(cinfo, M_SOI);	/* first the SOI */ | ||||
| 
 | ||||
|   /* SOI is defined to reset restart interval to 0 */ | ||||
|   marker->last_restart_interval = 0; | ||||
| 
 | ||||
|   if (cinfo->write_JFIF_header)	/* next an optional JFIF APP0 */ | ||||
|     emit_jfif_app0(cinfo); | ||||
|   if (cinfo->write_Adobe_marker) /* next an optional Adobe APP14 */ | ||||
|     emit_adobe_app14(cinfo); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Write frame header. | ||||
|  * This consists of DQT and SOFn markers. | ||||
|  * Note that we do not emit the SOF until we have emitted the DQT(s). | ||||
|  * This avoids compatibility problems with incorrect implementations that | ||||
|  * try to error-check the quant table numbers as soon as they see the SOF. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| write_frame_header (j_compress_ptr cinfo) | ||||
| { | ||||
|   int ci, prec; | ||||
|   boolean is_baseline; | ||||
|   jpeg_component_info *compptr; | ||||
|    | ||||
|   /* Emit DQT for each quantization table.
 | ||||
|    * Note that emit_dqt() suppresses any duplicate tables. | ||||
|    */ | ||||
|   prec = 0; | ||||
|   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
|        ci++, compptr++) { | ||||
|     prec += emit_dqt(cinfo, compptr->quant_tbl_no); | ||||
|   } | ||||
|   /* now prec is nonzero iff there are any 16-bit quant tables. */ | ||||
| 
 | ||||
|   /* Check for a non-baseline specification.
 | ||||
|    * Note we assume that Huffman table numbers won't be changed later. | ||||
|    */ | ||||
|   if (cinfo->arith_code || cinfo->progressive_mode || | ||||
|       cinfo->data_precision != 8) { | ||||
|     is_baseline = FALSE; | ||||
|   } else { | ||||
|     is_baseline = TRUE; | ||||
|     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
| 	 ci++, compptr++) { | ||||
|       if (compptr->dc_tbl_no > 1 || compptr->ac_tbl_no > 1) | ||||
| 	is_baseline = FALSE; | ||||
|     } | ||||
|     if (prec && is_baseline) { | ||||
|       is_baseline = FALSE; | ||||
|       /* If it's baseline except for quantizer size, warn the user */ | ||||
|       TRACEMS(cinfo, 0, JTRC_16BIT_TABLES); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Emit the proper SOF marker */ | ||||
|   if (cinfo->arith_code) { | ||||
|     emit_sof(cinfo, M_SOF9);	/* SOF code for arithmetic coding */ | ||||
|   } else { | ||||
|     if (cinfo->progressive_mode) | ||||
|       emit_sof(cinfo, M_SOF2);	/* SOF code for progressive Huffman */ | ||||
|     else if (is_baseline) | ||||
|       emit_sof(cinfo, M_SOF0);	/* SOF code for baseline implementation */ | ||||
|     else | ||||
|       emit_sof(cinfo, M_SOF1);	/* SOF code for non-baseline Huffman file */ | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Write scan header. | ||||
|  * This consists of DHT or DAC markers, optional DRI, and SOS. | ||||
|  * Compressed data will be written following the SOS. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| write_scan_header (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_marker_ptr marker = (my_marker_ptr) cinfo->marker; | ||||
|   int i; | ||||
|   jpeg_component_info *compptr; | ||||
| 
 | ||||
|   if (cinfo->arith_code) { | ||||
|     /* Emit arith conditioning info.  We may have some duplication
 | ||||
|      * if the file has multiple scans, but it's so small it's hardly | ||||
|      * worth worrying about. | ||||
|      */ | ||||
|     emit_dac(cinfo); | ||||
|   } else { | ||||
|     /* Emit Huffman tables.
 | ||||
|      * Note that emit_dht() suppresses any duplicate tables. | ||||
|      */ | ||||
|     for (i = 0; i < cinfo->comps_in_scan; i++) { | ||||
|       compptr = cinfo->cur_comp_info[i]; | ||||
|       if (cinfo->progressive_mode) { | ||||
| 	/* Progressive mode: only DC or only AC tables are used in one scan */ | ||||
| 	if (cinfo->Ss == 0) { | ||||
| 	  if (cinfo->Ah == 0)	/* DC needs no table for refinement scan */ | ||||
| 	    emit_dht(cinfo, compptr->dc_tbl_no, FALSE); | ||||
| 	} else { | ||||
| 	  emit_dht(cinfo, compptr->ac_tbl_no, TRUE); | ||||
| 	} | ||||
|       } else { | ||||
| 	/* Sequential mode: need both DC and AC tables */ | ||||
| 	emit_dht(cinfo, compptr->dc_tbl_no, FALSE); | ||||
| 	emit_dht(cinfo, compptr->ac_tbl_no, TRUE); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Emit DRI if required --- note that DRI value could change for each scan.
 | ||||
|    * We avoid wasting space with unnecessary DRIs, however. | ||||
|    */ | ||||
|   if (cinfo->restart_interval != marker->last_restart_interval) { | ||||
|     emit_dri(cinfo); | ||||
|     marker->last_restart_interval = cinfo->restart_interval; | ||||
|   } | ||||
| 
 | ||||
|   emit_sos(cinfo); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Write datastream trailer. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| write_file_trailer (j_compress_ptr cinfo) | ||||
| { | ||||
|   emit_marker(cinfo, M_EOI); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Write an abbreviated table-specification datastream. | ||||
|  * This consists of SOI, DQT and DHT tables, and EOI. | ||||
|  * Any table that is defined and not marked sent_table = TRUE will be | ||||
|  * emitted.  Note that all tables will be marked sent_table = TRUE at exit. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| write_tables_only (j_compress_ptr cinfo) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   emit_marker(cinfo, M_SOI); | ||||
| 
 | ||||
|   for (i = 0; i < NUM_QUANT_TBLS; i++) { | ||||
|     if (cinfo->quant_tbl_ptrs[i] != NULL) | ||||
|       (void) emit_dqt(cinfo, i); | ||||
|   } | ||||
| 
 | ||||
|   if (! cinfo->arith_code) { | ||||
|     for (i = 0; i < NUM_HUFF_TBLS; i++) { | ||||
|       if (cinfo->dc_huff_tbl_ptrs[i] != NULL) | ||||
| 	emit_dht(cinfo, i, FALSE); | ||||
|       if (cinfo->ac_huff_tbl_ptrs[i] != NULL) | ||||
| 	emit_dht(cinfo, i, TRUE); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   emit_marker(cinfo, M_EOI); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize the marker writer module. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jinit_marker_writer (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_marker_ptr marker; | ||||
| 
 | ||||
|   /* Create the subobject */ | ||||
|   marker = (my_marker_ptr) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				SIZEOF(my_marker_writer)); | ||||
|   cinfo->marker = (struct jpeg_marker_writer *) marker; | ||||
|   /* Initialize method pointers */ | ||||
|   marker->pub.write_file_header = write_file_header; | ||||
|   marker->pub.write_frame_header = write_frame_header; | ||||
|   marker->pub.write_scan_header = write_scan_header; | ||||
|   marker->pub.write_file_trailer = write_file_trailer; | ||||
|   marker->pub.write_tables_only = write_tables_only; | ||||
|   marker->pub.write_marker_header = write_marker_header; | ||||
|   marker->pub.write_marker_byte = write_marker_byte; | ||||
|   /* Initialize private state */ | ||||
|   marker->last_restart_interval = 0; | ||||
| } | ||||
|  | @ -0,0 +1,590 @@ | |||
| /*
 | ||||
|  * jcmaster.c | ||||
|  * | ||||
|  * Copyright (C) 1991-1997, 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 master control logic for the JPEG compressor. | ||||
|  * These routines are concerned with parameter validation, initial setup, | ||||
|  * and inter-pass control (determining the number of passes and the work  | ||||
|  * to be done in each pass). | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Private state */ | ||||
| 
 | ||||
| typedef enum { | ||||
| 	main_pass,		/* input data, also do first output step */ | ||||
| 	huff_opt_pass,		/* Huffman code optimization pass */ | ||||
| 	output_pass		/* data output pass */ | ||||
| } c_pass_type; | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_comp_master pub;	/* public fields */ | ||||
| 
 | ||||
|   c_pass_type pass_type;	/* the type of the current pass */ | ||||
| 
 | ||||
|   int pass_number;		/* # of passes completed */ | ||||
|   int total_passes;		/* total # of passes needed */ | ||||
| 
 | ||||
|   int scan_number;		/* current index in scan_info[] */ | ||||
| } my_comp_master; | ||||
| 
 | ||||
| typedef my_comp_master * my_master_ptr; | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Support routines that do various essential calculations. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| initial_setup (j_compress_ptr cinfo) | ||||
| /* Do computations that are needed before master selection phase */ | ||||
| { | ||||
|   int ci; | ||||
|   jpeg_component_info *compptr; | ||||
|   long samplesperrow; | ||||
|   JDIMENSION jd_samplesperrow; | ||||
| 
 | ||||
|   /* Sanity check on image dimensions */ | ||||
|   if (cinfo->image_height <= 0 || cinfo->image_width <= 0 | ||||
|       || cinfo->num_components <= 0 || cinfo->input_components <= 0) | ||||
|     ERREXIT(cinfo, JERR_EMPTY_IMAGE); | ||||
| 
 | ||||
|   /* Make sure image isn't bigger than I can handle */ | ||||
|   if ((long) cinfo->image_height > (long) JPEG_MAX_DIMENSION || | ||||
|       (long) cinfo->image_width > (long) JPEG_MAX_DIMENSION) | ||||
|     ERREXIT1(cinfo, JERR_IMAGE_TOO_BIG, (unsigned int) JPEG_MAX_DIMENSION); | ||||
| 
 | ||||
|   /* Width of an input scanline must be representable as JDIMENSION. */ | ||||
|   samplesperrow = (long) cinfo->image_width * (long) cinfo->input_components; | ||||
|   jd_samplesperrow = (JDIMENSION) samplesperrow; | ||||
|   if ((long) jd_samplesperrow != samplesperrow) | ||||
|     ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); | ||||
| 
 | ||||
|   /* For now, precision must match compiled-in value... */ | ||||
|   if (cinfo->data_precision != BITS_IN_JSAMPLE) | ||||
|     ERREXIT1(cinfo, JERR_BAD_PRECISION, cinfo->data_precision); | ||||
| 
 | ||||
|   /* Check that number of components won't exceed internal array sizes */ | ||||
|   if (cinfo->num_components > MAX_COMPONENTS) | ||||
|     ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, | ||||
| 	     MAX_COMPONENTS); | ||||
| 
 | ||||
|   /* Compute maximum sampling factors; check factor validity */ | ||||
|   cinfo->max_h_samp_factor = 1; | ||||
|   cinfo->max_v_samp_factor = 1; | ||||
|   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
|        ci++, compptr++) { | ||||
|     if (compptr->h_samp_factor<=0 || compptr->h_samp_factor>MAX_SAMP_FACTOR || | ||||
| 	compptr->v_samp_factor<=0 || compptr->v_samp_factor>MAX_SAMP_FACTOR) | ||||
|       ERREXIT(cinfo, JERR_BAD_SAMPLING); | ||||
|     cinfo->max_h_samp_factor = MAX(cinfo->max_h_samp_factor, | ||||
| 				   compptr->h_samp_factor); | ||||
|     cinfo->max_v_samp_factor = MAX(cinfo->max_v_samp_factor, | ||||
| 				   compptr->v_samp_factor); | ||||
|   } | ||||
| 
 | ||||
|   /* Compute dimensions of components */ | ||||
|   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
|        ci++, compptr++) { | ||||
|     /* Fill in the correct component_index value; don't rely on application */ | ||||
|     compptr->component_index = ci; | ||||
|     /* For compression, we never do DCT scaling. */ | ||||
|     compptr->DCT_scaled_size = DCTSIZE; | ||||
|     /* Size in DCT blocks */ | ||||
|     compptr->width_in_blocks = (JDIMENSION) | ||||
|       jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, | ||||
| 		    (long) (cinfo->max_h_samp_factor * DCTSIZE)); | ||||
|     compptr->height_in_blocks = (JDIMENSION) | ||||
|       jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, | ||||
| 		    (long) (cinfo->max_v_samp_factor * DCTSIZE)); | ||||
|     /* Size in samples */ | ||||
|     compptr->downsampled_width = (JDIMENSION) | ||||
|       jdiv_round_up((long) cinfo->image_width * (long) compptr->h_samp_factor, | ||||
| 		    (long) cinfo->max_h_samp_factor); | ||||
|     compptr->downsampled_height = (JDIMENSION) | ||||
|       jdiv_round_up((long) cinfo->image_height * (long) compptr->v_samp_factor, | ||||
| 		    (long) cinfo->max_v_samp_factor); | ||||
|     /* Mark component needed (this flag isn't actually used for compression) */ | ||||
|     compptr->component_needed = TRUE; | ||||
|   } | ||||
| 
 | ||||
|   /* Compute number of fully interleaved MCU rows (number of times that
 | ||||
|    * main controller will call coefficient controller). | ||||
|    */ | ||||
|   cinfo->total_iMCU_rows = (JDIMENSION) | ||||
|     jdiv_round_up((long) cinfo->image_height, | ||||
| 		  (long) (cinfo->max_v_samp_factor*DCTSIZE)); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef C_MULTISCAN_FILES_SUPPORTED | ||||
| 
 | ||||
| LOCAL(void) | ||||
| validate_script (j_compress_ptr cinfo) | ||||
| /* Verify that the scan script in cinfo->scan_info[] is valid; also
 | ||||
|  * determine whether it uses progressive JPEG, and set cinfo->progressive_mode. | ||||
|  */ | ||||
| { | ||||
|   const jpeg_scan_info * scanptr; | ||||
|   int scanno, ncomps, ci, coefi, thisi; | ||||
|   int Ss, Se, Ah, Al; | ||||
|   boolean component_sent[MAX_COMPONENTS]; | ||||
| #ifdef C_PROGRESSIVE_SUPPORTED | ||||
|   int * last_bitpos_ptr; | ||||
|   int last_bitpos[MAX_COMPONENTS][DCTSIZE2]; | ||||
|   /* -1 until that coefficient has been seen; then last Al for it */ | ||||
| #endif | ||||
| 
 | ||||
|   if (cinfo->num_scans <= 0) | ||||
|     ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, 0); | ||||
| 
 | ||||
|   /* For sequential JPEG, all scans must have Ss=0, Se=DCTSIZE2-1;
 | ||||
|    * for progressive JPEG, no scan can have this. | ||||
|    */ | ||||
|   scanptr = cinfo->scan_info; | ||||
|   if (scanptr->Ss != 0 || scanptr->Se != DCTSIZE2-1) { | ||||
| #ifdef C_PROGRESSIVE_SUPPORTED | ||||
|     cinfo->progressive_mode = TRUE; | ||||
|     last_bitpos_ptr = & last_bitpos[0][0]; | ||||
|     for (ci = 0; ci < cinfo->num_components; ci++)  | ||||
|       for (coefi = 0; coefi < DCTSIZE2; coefi++) | ||||
| 	*last_bitpos_ptr++ = -1; | ||||
| #else | ||||
|     ERREXIT(cinfo, JERR_NOT_COMPILED); | ||||
| #endif | ||||
|   } else { | ||||
|     cinfo->progressive_mode = FALSE; | ||||
|     for (ci = 0; ci < cinfo->num_components; ci++)  | ||||
|       component_sent[ci] = FALSE; | ||||
|   } | ||||
| 
 | ||||
|   for (scanno = 1; scanno <= cinfo->num_scans; scanptr++, scanno++) { | ||||
|     /* Validate component indexes */ | ||||
|     ncomps = scanptr->comps_in_scan; | ||||
|     if (ncomps <= 0 || ncomps > MAX_COMPS_IN_SCAN) | ||||
|       ERREXIT2(cinfo, JERR_COMPONENT_COUNT, ncomps, MAX_COMPS_IN_SCAN); | ||||
|     for (ci = 0; ci < ncomps; ci++) { | ||||
|       thisi = scanptr->component_index[ci]; | ||||
|       if (thisi < 0 || thisi >= cinfo->num_components) | ||||
| 	ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); | ||||
|       /* Components must appear in SOF order within each scan */ | ||||
|       if (ci > 0 && thisi <= scanptr->component_index[ci-1]) | ||||
| 	ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); | ||||
|     } | ||||
|     /* Validate progression parameters */ | ||||
|     Ss = scanptr->Ss; | ||||
|     Se = scanptr->Se; | ||||
|     Ah = scanptr->Ah; | ||||
|     Al = scanptr->Al; | ||||
|     if (cinfo->progressive_mode) { | ||||
| #ifdef C_PROGRESSIVE_SUPPORTED | ||||
|       /* The JPEG spec simply gives the ranges 0..13 for Ah and Al, but that
 | ||||
|        * seems wrong: the upper bound ought to depend on data precision. | ||||
|        * Perhaps they really meant 0..N+1 for N-bit precision. | ||||
|        * Here we allow 0..10 for 8-bit data; Al larger than 10 results in | ||||
|        * out-of-range reconstructed DC values during the first DC scan, | ||||
|        * which might cause problems for some decoders. | ||||
|        */ | ||||
| #if BITS_IN_JSAMPLE == 8 | ||||
| #define MAX_AH_AL 10 | ||||
| #else | ||||
| #define MAX_AH_AL 13 | ||||
| #endif | ||||
|       if (Ss < 0 || Ss >= DCTSIZE2 || Se < Ss || Se >= DCTSIZE2 || | ||||
| 	  Ah < 0 || Ah > MAX_AH_AL || Al < 0 || Al > MAX_AH_AL) | ||||
| 	ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); | ||||
|       if (Ss == 0) { | ||||
| 	if (Se != 0)		/* DC and AC together not OK */ | ||||
| 	  ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); | ||||
|       } else { | ||||
| 	if (ncomps != 1)	/* AC scans must be for only one component */ | ||||
| 	  ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); | ||||
|       } | ||||
|       for (ci = 0; ci < ncomps; ci++) { | ||||
| 	last_bitpos_ptr = & last_bitpos[scanptr->component_index[ci]][0]; | ||||
| 	if (Ss != 0 && last_bitpos_ptr[0] < 0) /* AC without prior DC scan */ | ||||
| 	  ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); | ||||
| 	for (coefi = Ss; coefi <= Se; coefi++) { | ||||
| 	  if (last_bitpos_ptr[coefi] < 0) { | ||||
| 	    /* first scan of this coefficient */ | ||||
| 	    if (Ah != 0) | ||||
| 	      ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); | ||||
| 	  } else { | ||||
| 	    /* not first scan */ | ||||
| 	    if (Ah != last_bitpos_ptr[coefi] || Al != Ah-1) | ||||
| 	      ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); | ||||
| 	  } | ||||
| 	  last_bitpos_ptr[coefi] = Al; | ||||
| 	} | ||||
|       } | ||||
| #endif | ||||
|     } else { | ||||
|       /* For sequential JPEG, all progression parameters must be these: */ | ||||
|       if (Ss != 0 || Se != DCTSIZE2-1 || Ah != 0 || Al != 0) | ||||
| 	ERREXIT1(cinfo, JERR_BAD_PROG_SCRIPT, scanno); | ||||
|       /* Make sure components are not sent twice */ | ||||
|       for (ci = 0; ci < ncomps; ci++) { | ||||
| 	thisi = scanptr->component_index[ci]; | ||||
| 	if (component_sent[thisi]) | ||||
| 	  ERREXIT1(cinfo, JERR_BAD_SCAN_SCRIPT, scanno); | ||||
| 	component_sent[thisi] = TRUE; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Now verify that everything got sent. */ | ||||
|   if (cinfo->progressive_mode) { | ||||
| #ifdef C_PROGRESSIVE_SUPPORTED | ||||
|     /* For progressive mode, we only check that at least some DC data
 | ||||
|      * got sent for each component; the spec does not require that all bits | ||||
|      * of all coefficients be transmitted.  Would it be wiser to enforce | ||||
|      * transmission of all coefficient bits?? | ||||
|      */ | ||||
|     for (ci = 0; ci < cinfo->num_components; ci++) { | ||||
|       if (last_bitpos[ci][0] < 0) | ||||
| 	ERREXIT(cinfo, JERR_MISSING_DATA); | ||||
|     } | ||||
| #endif | ||||
|   } else { | ||||
|     for (ci = 0; ci < cinfo->num_components; ci++) { | ||||
|       if (! component_sent[ci]) | ||||
| 	ERREXIT(cinfo, JERR_MISSING_DATA); | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #endif /* C_MULTISCAN_FILES_SUPPORTED */ | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| select_scan_parameters (j_compress_ptr cinfo) | ||||
| /* Set up the scan parameters for the current scan */ | ||||
| { | ||||
|   int ci; | ||||
| 
 | ||||
| #ifdef C_MULTISCAN_FILES_SUPPORTED | ||||
|   if (cinfo->scan_info != NULL) { | ||||
|     /* Prepare for current scan --- the script is already validated */ | ||||
|     my_master_ptr master = (my_master_ptr) cinfo->master; | ||||
|     const jpeg_scan_info * scanptr = cinfo->scan_info + master->scan_number; | ||||
| 
 | ||||
|     cinfo->comps_in_scan = scanptr->comps_in_scan; | ||||
|     for (ci = 0; ci < scanptr->comps_in_scan; ci++) { | ||||
|       cinfo->cur_comp_info[ci] = | ||||
| 	&cinfo->comp_info[scanptr->component_index[ci]]; | ||||
|     } | ||||
|     cinfo->Ss = scanptr->Ss; | ||||
|     cinfo->Se = scanptr->Se; | ||||
|     cinfo->Ah = scanptr->Ah; | ||||
|     cinfo->Al = scanptr->Al; | ||||
|   } | ||||
|   else | ||||
| #endif | ||||
|   { | ||||
|     /* Prepare for single sequential-JPEG scan containing all components */ | ||||
|     if (cinfo->num_components > MAX_COMPS_IN_SCAN) | ||||
|       ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, | ||||
| 	       MAX_COMPS_IN_SCAN); | ||||
|     cinfo->comps_in_scan = cinfo->num_components; | ||||
|     for (ci = 0; ci < cinfo->num_components; ci++) { | ||||
|       cinfo->cur_comp_info[ci] = &cinfo->comp_info[ci]; | ||||
|     } | ||||
|     cinfo->Ss = 0; | ||||
|     cinfo->Se = DCTSIZE2-1; | ||||
|     cinfo->Ah = 0; | ||||
|     cinfo->Al = 0; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| per_scan_setup (j_compress_ptr cinfo) | ||||
| /* Do computations that are needed before processing a JPEG scan */ | ||||
| /* cinfo->comps_in_scan and cinfo->cur_comp_info[] are already set */ | ||||
| { | ||||
|   int ci, mcublks, tmp; | ||||
|   jpeg_component_info *compptr; | ||||
|    | ||||
|   if (cinfo->comps_in_scan == 1) { | ||||
|      | ||||
|     /* Noninterleaved (single-component) scan */ | ||||
|     compptr = cinfo->cur_comp_info[0]; | ||||
|      | ||||
|     /* Overall image size in MCUs */ | ||||
|     cinfo->MCUs_per_row = compptr->width_in_blocks; | ||||
|     cinfo->MCU_rows_in_scan = compptr->height_in_blocks; | ||||
|      | ||||
|     /* For noninterleaved scan, always one block per MCU */ | ||||
|     compptr->MCU_width = 1; | ||||
|     compptr->MCU_height = 1; | ||||
|     compptr->MCU_blocks = 1; | ||||
|     compptr->MCU_sample_width = DCTSIZE; | ||||
|     compptr->last_col_width = 1; | ||||
|     /* For noninterleaved scans, it is convenient to define last_row_height
 | ||||
|      * as the number of block rows present in the last iMCU row. | ||||
|      */ | ||||
|     tmp = (int) (compptr->height_in_blocks % compptr->v_samp_factor); | ||||
|     if (tmp == 0) tmp = compptr->v_samp_factor; | ||||
|     compptr->last_row_height = tmp; | ||||
|      | ||||
|     /* Prepare array describing MCU composition */ | ||||
|     cinfo->blocks_in_MCU = 1; | ||||
|     cinfo->MCU_membership[0] = 0; | ||||
|      | ||||
|   } else { | ||||
|      | ||||
|     /* Interleaved (multi-component) scan */ | ||||
|     if (cinfo->comps_in_scan <= 0 || cinfo->comps_in_scan > MAX_COMPS_IN_SCAN) | ||||
|       ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->comps_in_scan, | ||||
| 	       MAX_COMPS_IN_SCAN); | ||||
|      | ||||
|     /* Overall image size in MCUs */ | ||||
|     cinfo->MCUs_per_row = (JDIMENSION) | ||||
|       jdiv_round_up((long) cinfo->image_width, | ||||
| 		    (long) (cinfo->max_h_samp_factor*DCTSIZE)); | ||||
|     cinfo->MCU_rows_in_scan = (JDIMENSION) | ||||
|       jdiv_round_up((long) cinfo->image_height, | ||||
| 		    (long) (cinfo->max_v_samp_factor*DCTSIZE)); | ||||
|      | ||||
|     cinfo->blocks_in_MCU = 0; | ||||
|      | ||||
|     for (ci = 0; ci < cinfo->comps_in_scan; ci++) { | ||||
|       compptr = cinfo->cur_comp_info[ci]; | ||||
|       /* Sampling factors give # of blocks of component in each MCU */ | ||||
|       compptr->MCU_width = compptr->h_samp_factor; | ||||
|       compptr->MCU_height = compptr->v_samp_factor; | ||||
|       compptr->MCU_blocks = compptr->MCU_width * compptr->MCU_height; | ||||
|       compptr->MCU_sample_width = compptr->MCU_width * DCTSIZE; | ||||
|       /* Figure number of non-dummy blocks in last MCU column & row */ | ||||
|       tmp = (int) (compptr->width_in_blocks % compptr->MCU_width); | ||||
|       if (tmp == 0) tmp = compptr->MCU_width; | ||||
|       compptr->last_col_width = tmp; | ||||
|       tmp = (int) (compptr->height_in_blocks % compptr->MCU_height); | ||||
|       if (tmp == 0) tmp = compptr->MCU_height; | ||||
|       compptr->last_row_height = tmp; | ||||
|       /* Prepare array describing MCU composition */ | ||||
|       mcublks = compptr->MCU_blocks; | ||||
|       if (cinfo->blocks_in_MCU + mcublks > C_MAX_BLOCKS_IN_MCU) | ||||
| 	ERREXIT(cinfo, JERR_BAD_MCU_SIZE); | ||||
|       while (mcublks-- > 0) { | ||||
| 	cinfo->MCU_membership[cinfo->blocks_in_MCU++] = ci; | ||||
|       } | ||||
|     } | ||||
|      | ||||
|   } | ||||
| 
 | ||||
|   /* Convert restart specified in rows to actual MCU count. */ | ||||
|   /* Note that count must fit in 16 bits, so we provide limiting. */ | ||||
|   if (cinfo->restart_in_rows > 0) { | ||||
|     long nominal = (long) cinfo->restart_in_rows * (long) cinfo->MCUs_per_row; | ||||
|     cinfo->restart_interval = (unsigned int) MIN(nominal, 65535L); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Per-pass setup. | ||||
|  * This is called at the beginning of each pass.  We determine which modules | ||||
|  * will be active during this pass and give them appropriate start_pass calls. | ||||
|  * We also set is_last_pass to indicate whether any more passes will be | ||||
|  * required. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| prepare_for_pass (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_master_ptr master = (my_master_ptr) cinfo->master; | ||||
| 
 | ||||
|   switch (master->pass_type) { | ||||
|   case main_pass: | ||||
|     /* Initial pass: will collect input data, and do either Huffman
 | ||||
|      * optimization or data output for the first scan. | ||||
|      */ | ||||
|     select_scan_parameters(cinfo); | ||||
|     per_scan_setup(cinfo); | ||||
|     if (! cinfo->raw_data_in) { | ||||
|       (*cinfo->cconvert->start_pass) (cinfo); | ||||
|       (*cinfo->downsample->start_pass) (cinfo); | ||||
|       (*cinfo->prep->start_pass) (cinfo, JBUF_PASS_THRU); | ||||
|     } | ||||
|     (*cinfo->fdct->start_pass) (cinfo); | ||||
|     (*cinfo->entropy->start_pass) (cinfo, cinfo->optimize_coding); | ||||
|     (*cinfo->coef->start_pass) (cinfo, | ||||
| 				(master->total_passes > 1 ? | ||||
| 				 JBUF_SAVE_AND_PASS : JBUF_PASS_THRU)); | ||||
|     (*cinfo->main->start_pass) (cinfo, JBUF_PASS_THRU); | ||||
|     if (cinfo->optimize_coding) { | ||||
|       /* No immediate data output; postpone writing frame/scan headers */ | ||||
|       master->pub.call_pass_startup = FALSE; | ||||
|     } else { | ||||
|       /* Will write frame/scan headers at first jpeg_write_scanlines call */ | ||||
|       master->pub.call_pass_startup = TRUE; | ||||
|     } | ||||
|     break; | ||||
| #ifdef ENTROPY_OPT_SUPPORTED | ||||
|   case huff_opt_pass: | ||||
|     /* Do Huffman optimization for a scan after the first one. */ | ||||
|     select_scan_parameters(cinfo); | ||||
|     per_scan_setup(cinfo); | ||||
|     if (cinfo->Ss != 0 || cinfo->Ah == 0 || cinfo->arith_code) { | ||||
|       (*cinfo->entropy->start_pass) (cinfo, TRUE); | ||||
|       (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); | ||||
|       master->pub.call_pass_startup = FALSE; | ||||
|       break; | ||||
|     } | ||||
|     /* Special case: Huffman DC refinement scans need no Huffman table
 | ||||
|      * and therefore we can skip the optimization pass for them. | ||||
|      */ | ||||
|     master->pass_type = output_pass; | ||||
|     master->pass_number++; | ||||
|     /*FALLTHROUGH*/ | ||||
| #endif | ||||
|   case output_pass: | ||||
|     /* Do a data-output pass. */ | ||||
|     /* We need not repeat per-scan setup if prior optimization pass did it. */ | ||||
|     if (! cinfo->optimize_coding) { | ||||
|       select_scan_parameters(cinfo); | ||||
|       per_scan_setup(cinfo); | ||||
|     } | ||||
|     (*cinfo->entropy->start_pass) (cinfo, FALSE); | ||||
|     (*cinfo->coef->start_pass) (cinfo, JBUF_CRANK_DEST); | ||||
|     /* We emit frame/scan headers now */ | ||||
|     if (master->scan_number == 0) | ||||
|       (*cinfo->marker->write_frame_header) (cinfo); | ||||
|     (*cinfo->marker->write_scan_header) (cinfo); | ||||
|     master->pub.call_pass_startup = FALSE; | ||||
|     break; | ||||
|   default: | ||||
|     ERREXIT(cinfo, JERR_NOT_COMPILED); | ||||
|   } | ||||
| 
 | ||||
|   master->pub.is_last_pass = (master->pass_number == master->total_passes-1); | ||||
| 
 | ||||
|   /* Set up progress monitor's pass info if present */ | ||||
|   if (cinfo->progress != NULL) { | ||||
|     cinfo->progress->completed_passes = master->pass_number; | ||||
|     cinfo->progress->total_passes = master->total_passes; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Special start-of-pass hook. | ||||
|  * This is called by jpeg_write_scanlines if call_pass_startup is TRUE. | ||||
|  * In single-pass processing, we need this hook because we don't want to | ||||
|  * write frame/scan headers during jpeg_start_compress; we want to let the | ||||
|  * application write COM markers etc. between jpeg_start_compress and the | ||||
|  * jpeg_write_scanlines loop. | ||||
|  * In multi-pass processing, this routine is not used. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| pass_startup (j_compress_ptr cinfo) | ||||
| { | ||||
|   cinfo->master->call_pass_startup = FALSE; /* reset flag so call only once */ | ||||
| 
 | ||||
|   (*cinfo->marker->write_frame_header) (cinfo); | ||||
|   (*cinfo->marker->write_scan_header) (cinfo); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Finish up at end of pass. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| finish_pass_master (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_master_ptr master = (my_master_ptr) cinfo->master; | ||||
| 
 | ||||
|   /* The entropy coder always needs an end-of-pass call,
 | ||||
|    * either to analyze statistics or to flush its output buffer. | ||||
|    */ | ||||
|   (*cinfo->entropy->finish_pass) (cinfo); | ||||
| 
 | ||||
|   /* Update state for next pass */ | ||||
|   switch (master->pass_type) { | ||||
|   case main_pass: | ||||
|     /* next pass is either output of scan 0 (after optimization)
 | ||||
|      * or output of scan 1 (if no optimization). | ||||
|      */ | ||||
|     master->pass_type = output_pass; | ||||
|     if (! cinfo->optimize_coding) | ||||
|       master->scan_number++; | ||||
|     break; | ||||
|   case huff_opt_pass: | ||||
|     /* next pass is always output of current scan */ | ||||
|     master->pass_type = output_pass; | ||||
|     break; | ||||
|   case output_pass: | ||||
|     /* next pass is either optimization or output of next scan */ | ||||
|     if (cinfo->optimize_coding) | ||||
|       master->pass_type = huff_opt_pass; | ||||
|     master->scan_number++; | ||||
|     break; | ||||
|   } | ||||
| 
 | ||||
|   master->pass_number++; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize master compression control. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jinit_c_master_control (j_compress_ptr cinfo, boolean transcode_only) | ||||
| { | ||||
|   my_master_ptr master; | ||||
| 
 | ||||
|   master = (my_master_ptr) | ||||
|       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				  SIZEOF(my_comp_master)); | ||||
|   cinfo->master = (struct jpeg_comp_master *) master; | ||||
|   master->pub.prepare_for_pass = prepare_for_pass; | ||||
|   master->pub.pass_startup = pass_startup; | ||||
|   master->pub.finish_pass = finish_pass_master; | ||||
|   master->pub.is_last_pass = FALSE; | ||||
| 
 | ||||
|   /* Validate parameters, determine derived values */ | ||||
|   initial_setup(cinfo); | ||||
| 
 | ||||
|   if (cinfo->scan_info != NULL) { | ||||
| #ifdef C_MULTISCAN_FILES_SUPPORTED | ||||
|     validate_script(cinfo); | ||||
| #else | ||||
|     ERREXIT(cinfo, JERR_NOT_COMPILED); | ||||
| #endif | ||||
|   } else { | ||||
|     cinfo->progressive_mode = FALSE; | ||||
|     cinfo->num_scans = 1; | ||||
|   } | ||||
| 
 | ||||
|   if (cinfo->progressive_mode)	/*  TEMPORARY HACK ??? */ | ||||
|     cinfo->optimize_coding = TRUE; /* assume default tables no good for progressive mode */ | ||||
| 
 | ||||
|   /* Initialize my private state */ | ||||
|   if (transcode_only) { | ||||
|     /* no main pass in transcoding */ | ||||
|     if (cinfo->optimize_coding) | ||||
|       master->pass_type = huff_opt_pass; | ||||
|     else | ||||
|       master->pass_type = output_pass; | ||||
|   } else { | ||||
|     /* for normal compression, first pass is always this type: */ | ||||
|     master->pass_type = main_pass; | ||||
|   } | ||||
|   master->scan_number = 0; | ||||
|   master->pass_number = 0; | ||||
|   if (cinfo->optimize_coding) | ||||
|     master->total_passes = cinfo->num_scans * 2; | ||||
|   else | ||||
|     master->total_passes = cinfo->num_scans; | ||||
| } | ||||
|  | @ -0,0 +1,106 @@ | |||
| /*
 | ||||
|  * jcomapi.c | ||||
|  * | ||||
|  * Copyright (C) 1994-1997, 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 application interface routines that are used for both | ||||
|  * compression and decompression. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Abort processing of a JPEG compression or decompression operation, | ||||
|  * but don't destroy the object itself. | ||||
|  * | ||||
|  * For this, we merely clean up all the nonpermanent memory pools. | ||||
|  * Note that temp files (virtual arrays) are not allowed to belong to | ||||
|  * the permanent pool, so we will be able to close all temp files here. | ||||
|  * Closing a data source or destination, if necessary, is the application's | ||||
|  * responsibility. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_abort (j_common_ptr cinfo) | ||||
| { | ||||
|   int pool; | ||||
| 
 | ||||
|   /* Do nothing if called on a not-initialized or destroyed JPEG object. */ | ||||
|   if (cinfo->mem == NULL) | ||||
|     return; | ||||
| 
 | ||||
|   /* Releasing pools in reverse order might help avoid fragmentation
 | ||||
|    * with some (brain-damaged) malloc libraries. | ||||
|    */ | ||||
|   for (pool = JPOOL_NUMPOOLS-1; pool > JPOOL_PERMANENT; pool--) { | ||||
|     (*cinfo->mem->free_pool) (cinfo, pool); | ||||
|   } | ||||
| 
 | ||||
|   /* Reset overall state for possible reuse of object */ | ||||
|   if (cinfo->is_decompressor) { | ||||
|     cinfo->global_state = DSTATE_START; | ||||
|     /* Try to keep application from accessing now-deleted marker list.
 | ||||
|      * A bit kludgy to do it here, but this is the most central place. | ||||
|      */ | ||||
|     ((j_decompress_ptr) cinfo)->marker_list = NULL; | ||||
|   } else { | ||||
|     cinfo->global_state = CSTATE_START; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Destruction of a JPEG object. | ||||
|  * | ||||
|  * Everything gets deallocated except the master jpeg_compress_struct itself | ||||
|  * and the error manager struct.  Both of these are supplied by the application | ||||
|  * and must be freed, if necessary, by the application.  (Often they are on | ||||
|  * the stack and so don't need to be freed anyway.) | ||||
|  * Closing a data source or destination, if necessary, is the application's | ||||
|  * responsibility. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_destroy (j_common_ptr cinfo) | ||||
| { | ||||
|   /* We need only tell the memory manager to release everything. */ | ||||
|   /* NB: mem pointer is NULL if memory mgr failed to initialize. */ | ||||
|   if (cinfo->mem != NULL) | ||||
|     (*cinfo->mem->self_destruct) (cinfo); | ||||
|   cinfo->mem = NULL;		/* be safe if jpeg_destroy is called twice */ | ||||
|   cinfo->global_state = 0;	/* mark it destroyed */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Convenience routines for allocating quantization and Huffman tables. | ||||
|  * (Would jutils.c be a more reasonable place to put these?) | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(JQUANT_TBL *) | ||||
| jpeg_alloc_quant_table (j_common_ptr cinfo) | ||||
| { | ||||
|   JQUANT_TBL *tbl; | ||||
| 
 | ||||
|   tbl = (JQUANT_TBL *) | ||||
|     (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JQUANT_TBL)); | ||||
|   tbl->sent_table = FALSE;	/* make sure this is false in any new table */ | ||||
|   return tbl; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GLOBAL(JHUFF_TBL *) | ||||
| jpeg_alloc_huff_table (j_common_ptr cinfo) | ||||
| { | ||||
|   JHUFF_TBL *tbl; | ||||
| 
 | ||||
|   tbl = (JHUFF_TBL *) | ||||
|     (*cinfo->mem->alloc_small) (cinfo, JPOOL_PERMANENT, SIZEOF(JHUFF_TBL)); | ||||
|   tbl->sent_table = FALSE;	/* make sure this is false in any new table */ | ||||
|   return tbl; | ||||
| } | ||||
|  | @ -0,0 +1,155 @@ | |||
| /* | ||||
|  * jconfig.doc | ||||
|  * | ||||
|  * Copyright (C) 1991-1994, 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 documents the configuration options that are required to | ||||
|  * customize the JPEG software for a particular system. | ||||
|  * | ||||
|  * The actual configuration options for a particular installation are stored | ||||
|  * in jconfig.h.  On many machines, jconfig.h can be generated automatically | ||||
|  * or copied from one of the "canned" jconfig files that we supply.  But if | ||||
|  * you need to generate a jconfig.h file by hand, this file tells you how. | ||||
|  * | ||||
|  * DO NOT EDIT THIS FILE --- IT WON'T ACCOMPLISH ANYTHING. | ||||
|  * EDIT A COPY NAMED JCONFIG.H. | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
|  * These symbols indicate the properties of your machine or compiler. | ||||
|  * #define the symbol if yes, #undef it if no. | ||||
|  */ | ||||
| 
 | ||||
| /* Does your compiler support function prototypes? | ||||
|  * (If not, you also need to use ansi2knr, see install.doc) | ||||
|  */ | ||||
| #define HAVE_PROTOTYPES | ||||
| 
 | ||||
| /* Does your compiler support the declaration "unsigned char" ? | ||||
|  * How about "unsigned short" ? | ||||
|  */ | ||||
| #define HAVE_UNSIGNED_CHAR | ||||
| #define HAVE_UNSIGNED_SHORT | ||||
| 
 | ||||
| /* Define "void" as "char" if your compiler doesn't know about type void. | ||||
|  * NOTE: be sure to define void such that "void *" represents the most general | ||||
|  * pointer type, e.g., that returned by malloc(). | ||||
|  */ | ||||
| /* #define void char */ | ||||
| 
 | ||||
| /* Define "const" as empty if your compiler doesn't know the "const" keyword. | ||||
|  */ | ||||
| /* #define const */ | ||||
| 
 | ||||
| /* Define this if an ordinary "char" type is unsigned. | ||||
|  * If you're not sure, leaving it undefined will work at some cost in speed. | ||||
|  * If you defined HAVE_UNSIGNED_CHAR then the speed difference is minimal. | ||||
|  */ | ||||
| #undef CHAR_IS_UNSIGNED | ||||
| 
 | ||||
| /* Define this if your system has an ANSI-conforming <stddef.h> file. | ||||
|  */ | ||||
| #define HAVE_STDDEF_H | ||||
| 
 | ||||
| /* Define this if your system has an ANSI-conforming <stdlib.h> file. | ||||
|  */ | ||||
| #define HAVE_STDLIB_H | ||||
| 
 | ||||
| /* Define this if your system does not have an ANSI/SysV <string.h>, | ||||
|  * but does have a BSD-style <strings.h>. | ||||
|  */ | ||||
| #undef NEED_BSD_STRINGS | ||||
| 
 | ||||
| /* Define this if your system does not provide typedef size_t in any of the | ||||
|  * ANSI-standard places (stddef.h, stdlib.h, or stdio.h), but places it in | ||||
|  * <sys/types.h> instead. | ||||
|  */ | ||||
| #undef NEED_SYS_TYPES_H | ||||
| 
 | ||||
| /* For 80x86 machines, you need to define NEED_FAR_POINTERS, | ||||
|  * unless you are using a large-data memory model or 80386 flat-memory mode. | ||||
|  * On less brain-damaged CPUs this symbol must not be defined. | ||||
|  * (Defining this symbol causes large data structures to be referenced through | ||||
|  * "far" pointers and to be allocated with a special version of malloc.) | ||||
|  */ | ||||
| #undef NEED_FAR_POINTERS | ||||
| 
 | ||||
| /* Define this if your linker needs global names to be unique in less | ||||
|  * than the first 15 characters. | ||||
|  */ | ||||
| #undef NEED_SHORT_EXTERNAL_NAMES | ||||
| 
 | ||||
| /* Although a real ANSI C compiler can deal perfectly well with pointers to | ||||
|  * unspecified structures (see "incomplete types" in the spec), a few pre-ANSI | ||||
|  * and pseudo-ANSI compilers get confused.  To keep one of these bozos happy, | ||||
|  * define INCOMPLETE_TYPES_BROKEN.  This is not recommended unless you | ||||
|  * actually get "missing structure definition" warnings or errors while | ||||
|  * compiling the JPEG code. | ||||
|  */ | ||||
| #undef INCOMPLETE_TYPES_BROKEN | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
|  * The following options affect code selection within the JPEG library, | ||||
|  * but they don't need to be visible to applications using the library. | ||||
|  * To minimize application namespace pollution, the symbols won't be | ||||
|  * defined unless JPEG_INTERNALS has been defined. | ||||
|  */ | ||||
| 
 | ||||
| #ifdef JPEG_INTERNALS | ||||
| 
 | ||||
| /* Define this if your compiler implements ">>" on signed values as a logical | ||||
|  * (unsigned) shift; leave it undefined if ">>" is a signed (arithmetic) shift, | ||||
|  * which is the normal and rational definition. | ||||
|  */ | ||||
| #undef RIGHT_SHIFT_IS_UNSIGNED | ||||
| 
 | ||||
| 
 | ||||
| #endif /* JPEG_INTERNALS */ | ||||
| 
 | ||||
| 
 | ||||
| /* | ||||
|  * The remaining options do not affect the JPEG library proper, | ||||
|  * but only the sample applications cjpeg/djpeg (see cjpeg.c, djpeg.c). | ||||
|  * Other applications can ignore these. | ||||
|  */ | ||||
| 
 | ||||
| #ifdef JPEG_CJPEG_DJPEG | ||||
| 
 | ||||
| /* These defines indicate which image (non-JPEG) file formats are allowed. */ | ||||
| 
 | ||||
| #define BMP_SUPPORTED		/* BMP image file format */ | ||||
| #define GIF_SUPPORTED		/* GIF image file format */ | ||||
| #define PPM_SUPPORTED		/* PBMPLUS PPM/PGM image file format */ | ||||
| #undef RLE_SUPPORTED		/* Utah RLE image file format */ | ||||
| #define TARGA_SUPPORTED		/* Targa image file format */ | ||||
| 
 | ||||
| /* Define this if you want to name both input and output files on the command | ||||
|  * line, rather than using stdout and optionally stdin.  You MUST do this if | ||||
|  * your system can't cope with binary I/O to stdin/stdout.  See comments at | ||||
|  * head of cjpeg.c or djpeg.c. | ||||
|  */ | ||||
| #undef TWO_FILE_COMMANDLINE | ||||
| 
 | ||||
| /* Define this if your system needs explicit cleanup of temporary files. | ||||
|  * This is crucial under MS-DOS, where the temporary "files" may be areas | ||||
|  * of extended memory; on most other systems it's not as important. | ||||
|  */ | ||||
| #undef NEED_SIGNAL_CATCHER | ||||
| 
 | ||||
| /* By default, we open image files with fopen(...,"rb") or fopen(...,"wb"). | ||||
|  * This is necessary on systems that distinguish text files from binary files, | ||||
|  * and is harmless on most systems that don't.  If you have one of the rare | ||||
|  * systems that complains about the "b" spec, define this symbol. | ||||
|  */ | ||||
| #undef DONT_USE_B_MODE | ||||
| 
 | ||||
| /* Define this if you want percent-done progress reports from cjpeg/djpeg. | ||||
|  */ | ||||
| #undef PROGRESS_REPORT | ||||
| 
 | ||||
| 
 | ||||
| #endif /* JPEG_CJPEG_DJPEG */ | ||||
|  | @ -0,0 +1,45 @@ | |||
| /* jconfig.h.  Generated automatically by configure.  */ | ||||
| /* jconfig.cfg --- source file edited by configure script */ | ||||
| /* see jconfig.doc for explanations */ | ||||
| 
 | ||||
| #define HAVE_PROTOTYPES  | ||||
| #define HAVE_UNSIGNED_CHAR  | ||||
| #define HAVE_UNSIGNED_SHORT  | ||||
| #undef void | ||||
| #undef const | ||||
| #undef CHAR_IS_UNSIGNED | ||||
| #define HAVE_STDDEF_H  | ||||
| #define HAVE_STDLIB_H  | ||||
| #undef NEED_BSD_STRINGS | ||||
| #undef NEED_SYS_TYPES_H | ||||
| #undef NEED_FAR_POINTERS | ||||
| #undef NEED_SHORT_EXTERNAL_NAMES | ||||
| /* Define this if you get warnings about undefined structures. */ | ||||
| #undef INCOMPLETE_TYPES_BROKEN | ||||
| 
 | ||||
| #ifdef JPEG_INTERNALS | ||||
| 
 | ||||
| #undef RIGHT_SHIFT_IS_UNSIGNED | ||||
| #define INLINE __inline__ | ||||
| /* These are for configuring the JPEG memory manager. */ | ||||
| #undef DEFAULT_MAX_MEM | ||||
| #undef NO_MKTEMP | ||||
| 
 | ||||
| #endif /* JPEG_INTERNALS */ | ||||
| 
 | ||||
| #ifdef JPEG_CJPEG_DJPEG | ||||
| 
 | ||||
| #define BMP_SUPPORTED		/* BMP image file format */ | ||||
| #define GIF_SUPPORTED		/* GIF image file format */ | ||||
| #define PPM_SUPPORTED		/* PBMPLUS PPM/PGM image file format */ | ||||
| #undef RLE_SUPPORTED		/* Utah RLE image file format */ | ||||
| #define TARGA_SUPPORTED		/* Targa image file format */ | ||||
| 
 | ||||
| #undef TWO_FILE_COMMANDLINE | ||||
| #undef NEED_SIGNAL_CATCHER | ||||
| #undef DONT_USE_B_MODE | ||||
| 
 | ||||
| /* Define this if you want percent-done progress reports from cjpeg/djpeg. */ | ||||
| #undef PROGRESS_REPORT | ||||
| 
 | ||||
| #endif /* JPEG_CJPEG_DJPEG */ | ||||
|  | @ -0,0 +1,610 @@ | |||
| /*
 | ||||
|  * jcparam.c | ||||
|  * | ||||
|  * Copyright (C) 1991-1998, 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 optional default-setting code for the JPEG compressor. | ||||
|  * Applications do not have to use this file, but those that don't use it | ||||
|  * must know a lot more about the innards of the JPEG code. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Quantization table setup routines | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_add_quant_table (j_compress_ptr cinfo, int which_tbl, | ||||
| 		      const unsigned int *basic_table, | ||||
| 		      int scale_factor, boolean force_baseline) | ||||
| /* Define a quantization table equal to the basic_table times
 | ||||
|  * a scale factor (given as a percentage). | ||||
|  * If force_baseline is TRUE, the computed quantization table entries | ||||
|  * are limited to 1..255 for JPEG baseline compatibility. | ||||
|  */ | ||||
| { | ||||
|   JQUANT_TBL ** qtblptr; | ||||
|   int i; | ||||
|   long temp; | ||||
| 
 | ||||
|   /* Safety check to ensure start_compress not called yet. */ | ||||
|   if (cinfo->global_state != CSTATE_START) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
| 
 | ||||
|   if (which_tbl < 0 || which_tbl >= NUM_QUANT_TBLS) | ||||
|     ERREXIT1(cinfo, JERR_DQT_INDEX, which_tbl); | ||||
| 
 | ||||
|   qtblptr = & cinfo->quant_tbl_ptrs[which_tbl]; | ||||
| 
 | ||||
|   if (*qtblptr == NULL) | ||||
|     *qtblptr = jpeg_alloc_quant_table((j_common_ptr) cinfo); | ||||
| 
 | ||||
|   for (i = 0; i < DCTSIZE2; i++) { | ||||
|     temp = ((long) basic_table[i] * scale_factor + 50L) / 100L; | ||||
|     /* limit the values to the valid range */ | ||||
|     if (temp <= 0L) temp = 1L; | ||||
|     if (temp > 32767L) temp = 32767L; /* max quantizer needed for 12 bits */ | ||||
|     if (force_baseline && temp > 255L) | ||||
|       temp = 255L;		/* limit to baseline range if requested */ | ||||
|     (*qtblptr)->quantval[i] = (UINT16) temp; | ||||
|   } | ||||
| 
 | ||||
|   /* Initialize sent_table FALSE so table will be written to JPEG file. */ | ||||
|   (*qtblptr)->sent_table = FALSE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_set_linear_quality (j_compress_ptr cinfo, int scale_factor, | ||||
| 			 boolean force_baseline) | ||||
| /* Set or change the 'quality' (quantization) setting, using default tables
 | ||||
|  * and a straight percentage-scaling quality scale.  In most cases it's better | ||||
|  * to use jpeg_set_quality (below); this entry point is provided for | ||||
|  * applications that insist on a linear percentage scaling. | ||||
|  */ | ||||
| { | ||||
|   /* These are the sample quantization tables given in JPEG spec section K.1.
 | ||||
|    * The spec says that the values given produce "good" quality, and | ||||
|    * when divided by 2, "very good" quality. | ||||
|    */ | ||||
|   static const unsigned int std_luminance_quant_tbl[DCTSIZE2] = { | ||||
|     16,  11,  10,  16,  24,  40,  51,  61, | ||||
|     12,  12,  14,  19,  26,  58,  60,  55, | ||||
|     14,  13,  16,  24,  40,  57,  69,  56, | ||||
|     14,  17,  22,  29,  51,  87,  80,  62, | ||||
|     18,  22,  37,  56,  68, 109, 103,  77, | ||||
|     24,  35,  55,  64,  81, 104, 113,  92, | ||||
|     49,  64,  78,  87, 103, 121, 120, 101, | ||||
|     72,  92,  95,  98, 112, 100, 103,  99 | ||||
|   }; | ||||
|   static const unsigned int std_chrominance_quant_tbl[DCTSIZE2] = { | ||||
|     17,  18,  24,  47,  99,  99,  99,  99, | ||||
|     18,  21,  26,  66,  99,  99,  99,  99, | ||||
|     24,  26,  56,  99,  99,  99,  99,  99, | ||||
|     47,  66,  99,  99,  99,  99,  99,  99, | ||||
|     99,  99,  99,  99,  99,  99,  99,  99, | ||||
|     99,  99,  99,  99,  99,  99,  99,  99, | ||||
|     99,  99,  99,  99,  99,  99,  99,  99, | ||||
|     99,  99,  99,  99,  99,  99,  99,  99 | ||||
|   }; | ||||
| 
 | ||||
|   /* Set up two quantization tables using the specified scaling */ | ||||
|   jpeg_add_quant_table(cinfo, 0, std_luminance_quant_tbl, | ||||
| 		       scale_factor, force_baseline); | ||||
|   jpeg_add_quant_table(cinfo, 1, std_chrominance_quant_tbl, | ||||
| 		       scale_factor, force_baseline); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GLOBAL(int) | ||||
| jpeg_quality_scaling (int quality) | ||||
| /* Convert a user-specified quality rating to a percentage scaling factor
 | ||||
|  * for an underlying quantization table, using our recommended scaling curve. | ||||
|  * The input 'quality' factor should be 0 (terrible) to 100 (very good). | ||||
|  */ | ||||
| { | ||||
|   /* Safety limit on quality factor.  Convert 0 to 1 to avoid zero divide. */ | ||||
|   if (quality <= 0) quality = 1; | ||||
|   if (quality > 100) quality = 100; | ||||
| 
 | ||||
|   /* The basic table is used as-is (scaling 100) for a quality of 50.
 | ||||
|    * Qualities 50..100 are converted to scaling percentage 200 - 2*Q; | ||||
|    * note that at Q=100 the scaling is 0, which will cause jpeg_add_quant_table | ||||
|    * to make all the table entries 1 (hence, minimum quantization loss). | ||||
|    * Qualities 1..50 are converted to scaling percentage 5000/Q. | ||||
|    */ | ||||
|   if (quality < 50) | ||||
|     quality = 5000 / quality; | ||||
|   else | ||||
|     quality = 200 - quality*2; | ||||
| 
 | ||||
|   return quality; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_set_quality (j_compress_ptr cinfo, int quality, boolean force_baseline) | ||||
| /* Set or change the 'quality' (quantization) setting, using default tables.
 | ||||
|  * This is the standard quality-adjusting entry point for typical user | ||||
|  * interfaces; only those who want detailed control over quantization tables | ||||
|  * would use the preceding three routines directly. | ||||
|  */ | ||||
| { | ||||
|   /* Convert user 0-100 rating to percentage scaling */ | ||||
|   quality = jpeg_quality_scaling(quality); | ||||
| 
 | ||||
|   /* Set up standard quality tables */ | ||||
|   jpeg_set_linear_quality(cinfo, quality, force_baseline); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Huffman table setup routines | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| add_huff_table (j_compress_ptr cinfo, | ||||
| 		JHUFF_TBL **htblptr, const UINT8 *bits, const UINT8 *val) | ||||
| /* Define a Huffman table */ | ||||
| { | ||||
|   int nsymbols, len; | ||||
| 
 | ||||
|   if (*htblptr == NULL) | ||||
|     *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); | ||||
| 
 | ||||
|   /* Copy the number-of-symbols-of-each-code-length counts */ | ||||
|   MEMCOPY((*htblptr)->bits, bits, SIZEOF((*htblptr)->bits)); | ||||
| 
 | ||||
|   /* Validate the counts.  We do this here mainly so we can copy the right
 | ||||
|    * number of symbols from the val[] array, without risking marching off | ||||
|    * the end of memory.  jchuff.c will do a more thorough test later. | ||||
|    */ | ||||
|   nsymbols = 0; | ||||
|   for (len = 1; len <= 16; len++) | ||||
|     nsymbols += bits[len]; | ||||
|   if (nsymbols < 1 || nsymbols > 256) | ||||
|     ERREXIT(cinfo, JERR_BAD_HUFF_TABLE); | ||||
| 
 | ||||
|   MEMCOPY((*htblptr)->huffval, val, nsymbols * SIZEOF(UINT8)); | ||||
| 
 | ||||
|   /* Initialize sent_table FALSE so table will be written to JPEG file. */ | ||||
|   (*htblptr)->sent_table = FALSE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| std_huff_tables (j_compress_ptr cinfo) | ||||
| /* Set up the standard Huffman tables (cf. JPEG standard section K.3) */ | ||||
| /* IMPORTANT: these are only valid for 8-bit data precision! */ | ||||
| { | ||||
|   static const UINT8 bits_dc_luminance[17] = | ||||
|     { /* 0-base */ 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; | ||||
|   static const UINT8 val_dc_luminance[] = | ||||
|     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; | ||||
|    | ||||
|   static const UINT8 bits_dc_chrominance[17] = | ||||
|     { /* 0-base */ 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0 }; | ||||
|   static const UINT8 val_dc_chrominance[] = | ||||
|     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; | ||||
|    | ||||
|   static const UINT8 bits_ac_luminance[17] = | ||||
|     { /* 0-base */ 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d }; | ||||
|   static const UINT8 val_ac_luminance[] = | ||||
|     { 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, | ||||
|       0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, | ||||
|       0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, | ||||
|       0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, | ||||
|       0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, | ||||
|       0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, | ||||
|       0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, | ||||
|       0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, | ||||
|       0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, | ||||
|       0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, | ||||
|       0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, | ||||
|       0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, | ||||
|       0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, | ||||
|       0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, | ||||
|       0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, | ||||
|       0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, | ||||
|       0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, | ||||
|       0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, | ||||
|       0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, | ||||
|       0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, | ||||
|       0xf9, 0xfa }; | ||||
|    | ||||
|   static const UINT8 bits_ac_chrominance[17] = | ||||
|     { /* 0-base */ 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77 }; | ||||
|   static const UINT8 val_ac_chrominance[] = | ||||
|     { 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, | ||||
|       0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, | ||||
|       0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, | ||||
|       0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, | ||||
|       0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, | ||||
|       0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, | ||||
|       0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, | ||||
|       0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, | ||||
|       0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, | ||||
|       0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, | ||||
|       0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, | ||||
|       0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, | ||||
|       0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, | ||||
|       0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, | ||||
|       0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, | ||||
|       0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, | ||||
|       0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, | ||||
|       0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, | ||||
|       0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, | ||||
|       0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, | ||||
|       0xf9, 0xfa }; | ||||
|    | ||||
|   add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[0], | ||||
| 		 bits_dc_luminance, val_dc_luminance); | ||||
|   add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[0], | ||||
| 		 bits_ac_luminance, val_ac_luminance); | ||||
|   add_huff_table(cinfo, &cinfo->dc_huff_tbl_ptrs[1], | ||||
| 		 bits_dc_chrominance, val_dc_chrominance); | ||||
|   add_huff_table(cinfo, &cinfo->ac_huff_tbl_ptrs[1], | ||||
| 		 bits_ac_chrominance, val_ac_chrominance); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Default parameter setup for compression. | ||||
|  * | ||||
|  * Applications that don't choose to use this routine must do their | ||||
|  * own setup of all these parameters.  Alternately, you can call this | ||||
|  * to establish defaults and then alter parameters selectively.  This | ||||
|  * is the recommended approach since, if we add any new parameters, | ||||
|  * your code will still work (they'll be set to reasonable defaults). | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_set_defaults (j_compress_ptr cinfo) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   /* Safety check to ensure start_compress not called yet. */ | ||||
|   if (cinfo->global_state != CSTATE_START) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
| 
 | ||||
|   /* Allocate comp_info array large enough for maximum component count.
 | ||||
|    * Array is made permanent in case application wants to compress | ||||
|    * multiple images at same param settings. | ||||
|    */ | ||||
|   if (cinfo->comp_info == NULL) | ||||
|     cinfo->comp_info = (jpeg_component_info *) | ||||
|       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, | ||||
| 				  MAX_COMPONENTS * SIZEOF(jpeg_component_info)); | ||||
| 
 | ||||
|   /* Initialize everything not dependent on the color space */ | ||||
| 
 | ||||
|   cinfo->data_precision = BITS_IN_JSAMPLE; | ||||
|   /* Set up two quantization tables using default quality of 75 */ | ||||
|   jpeg_set_quality(cinfo, 75, TRUE); | ||||
|   /* Set up two Huffman tables */ | ||||
|   std_huff_tables(cinfo); | ||||
| 
 | ||||
|   /* Initialize default arithmetic coding conditioning */ | ||||
|   for (i = 0; i < NUM_ARITH_TBLS; i++) { | ||||
|     cinfo->arith_dc_L[i] = 0; | ||||
|     cinfo->arith_dc_U[i] = 1; | ||||
|     cinfo->arith_ac_K[i] = 5; | ||||
|   } | ||||
| 
 | ||||
|   /* Default is no multiple-scan output */ | ||||
|   cinfo->scan_info = NULL; | ||||
|   cinfo->num_scans = 0; | ||||
| 
 | ||||
|   /* Expect normal source image, not raw downsampled data */ | ||||
|   cinfo->raw_data_in = FALSE; | ||||
| 
 | ||||
|   /* Use Huffman coding, not arithmetic coding, by default */ | ||||
|   cinfo->arith_code = FALSE; | ||||
| 
 | ||||
|   /* By default, don't do extra passes to optimize entropy coding */ | ||||
|   cinfo->optimize_coding = FALSE; | ||||
|   /* The standard Huffman tables are only valid for 8-bit data precision.
 | ||||
|    * If the precision is higher, force optimization on so that usable | ||||
|    * tables will be computed.  This test can be removed if default tables | ||||
|    * are supplied that are valid for the desired precision. | ||||
|    */ | ||||
|   if (cinfo->data_precision > 8) | ||||
|     cinfo->optimize_coding = TRUE; | ||||
| 
 | ||||
|   /* By default, use the simpler non-cosited sampling alignment */ | ||||
|   cinfo->CCIR601_sampling = FALSE; | ||||
| 
 | ||||
|   /* No input smoothing */ | ||||
|   cinfo->smoothing_factor = 0; | ||||
| 
 | ||||
|   /* DCT algorithm preference */ | ||||
|   cinfo->dct_method = JDCT_DEFAULT; | ||||
| 
 | ||||
|   /* No restart markers */ | ||||
|   cinfo->restart_interval = 0; | ||||
|   cinfo->restart_in_rows = 0; | ||||
| 
 | ||||
|   /* Fill in default JFIF marker parameters.  Note that whether the marker
 | ||||
|    * will actually be written is determined by jpeg_set_colorspace. | ||||
|    * | ||||
|    * By default, the library emits JFIF version code 1.01. | ||||
|    * An application that wants to emit JFIF 1.02 extension markers should set | ||||
|    * JFIF_minor_version to 2.  We could probably get away with just defaulting | ||||
|    * to 1.02, but there may still be some decoders in use that will complain | ||||
|    * about that; saying 1.01 should minimize compatibility problems. | ||||
|    */ | ||||
|   cinfo->JFIF_major_version = 1; /* Default JFIF version = 1.01 */ | ||||
|   cinfo->JFIF_minor_version = 1; | ||||
|   cinfo->density_unit = 0;	/* Pixel size is unknown by default */ | ||||
|   cinfo->X_density = 1;		/* Pixel aspect ratio is square by default */ | ||||
|   cinfo->Y_density = 1; | ||||
| 
 | ||||
|   /* Choose JPEG colorspace based on input space, set defaults accordingly */ | ||||
| 
 | ||||
|   jpeg_default_colorspace(cinfo); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Select an appropriate JPEG colorspace for in_color_space. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_default_colorspace (j_compress_ptr cinfo) | ||||
| { | ||||
|   switch (cinfo->in_color_space) { | ||||
|   case JCS_GRAYSCALE: | ||||
|     jpeg_set_colorspace(cinfo, JCS_GRAYSCALE); | ||||
|     break; | ||||
|   case JCS_RGB: | ||||
|     jpeg_set_colorspace(cinfo, JCS_YCbCr); | ||||
|     break; | ||||
|   case JCS_YCbCr: | ||||
|     jpeg_set_colorspace(cinfo, JCS_YCbCr); | ||||
|     break; | ||||
|   case JCS_CMYK: | ||||
|     jpeg_set_colorspace(cinfo, JCS_CMYK); /* By default, no translation */ | ||||
|     break; | ||||
|   case JCS_YCCK: | ||||
|     jpeg_set_colorspace(cinfo, JCS_YCCK); | ||||
|     break; | ||||
|   case JCS_UNKNOWN: | ||||
|     jpeg_set_colorspace(cinfo, JCS_UNKNOWN); | ||||
|     break; | ||||
|   default: | ||||
|     ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Set the JPEG colorspace, and choose colorspace-dependent default values. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_set_colorspace (j_compress_ptr cinfo, J_COLOR_SPACE colorspace) | ||||
| { | ||||
|   jpeg_component_info * compptr; | ||||
|   int ci; | ||||
| 
 | ||||
| #define SET_COMP(index,id,hsamp,vsamp,quant,dctbl,actbl)  \ | ||||
|   (compptr = &cinfo->comp_info[index], \ | ||||
|    compptr->component_id = (id), \ | ||||
|    compptr->h_samp_factor = (hsamp), \ | ||||
|    compptr->v_samp_factor = (vsamp), \ | ||||
|    compptr->quant_tbl_no = (quant), \ | ||||
|    compptr->dc_tbl_no = (dctbl), \ | ||||
|    compptr->ac_tbl_no = (actbl) ) | ||||
| 
 | ||||
|   /* Safety check to ensure start_compress not called yet. */ | ||||
|   if (cinfo->global_state != CSTATE_START) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
| 
 | ||||
|   /* For all colorspaces, we use Q and Huff tables 0 for luminance components,
 | ||||
|    * tables 1 for chrominance components. | ||||
|    */ | ||||
| 
 | ||||
|   cinfo->jpeg_color_space = colorspace; | ||||
| 
 | ||||
|   cinfo->write_JFIF_header = FALSE; /* No marker for non-JFIF colorspaces */ | ||||
|   cinfo->write_Adobe_marker = FALSE; /* write no Adobe marker by default */ | ||||
| 
 | ||||
|   switch (colorspace) { | ||||
|   case JCS_GRAYSCALE: | ||||
|     cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ | ||||
|     cinfo->num_components = 1; | ||||
|     /* JFIF specifies component ID 1 */ | ||||
|     SET_COMP(0, 1, 1,1, 0, 0,0); | ||||
|     break; | ||||
|   case JCS_RGB: | ||||
|     cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag RGB */ | ||||
|     cinfo->num_components = 3; | ||||
|     SET_COMP(0, 0x52 /* 'R' */, 1,1, 0, 0,0); | ||||
|     SET_COMP(1, 0x47 /* 'G' */, 1,1, 0, 0,0); | ||||
|     SET_COMP(2, 0x42 /* 'B' */, 1,1, 0, 0,0); | ||||
|     break; | ||||
|   case JCS_YCbCr: | ||||
|     cinfo->write_JFIF_header = TRUE; /* Write a JFIF marker */ | ||||
|     cinfo->num_components = 3; | ||||
|     /* JFIF specifies component IDs 1,2,3 */ | ||||
|     /* We default to 2x2 subsamples of chrominance */ | ||||
|     SET_COMP(0, 1, 2,2, 0, 0,0); | ||||
|     SET_COMP(1, 2, 1,1, 1, 1,1); | ||||
|     SET_COMP(2, 3, 1,1, 1, 1,1); | ||||
|     break; | ||||
|   case JCS_CMYK: | ||||
|     cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag CMYK */ | ||||
|     cinfo->num_components = 4; | ||||
|     SET_COMP(0, 0x43 /* 'C' */, 1,1, 0, 0,0); | ||||
|     SET_COMP(1, 0x4D /* 'M' */, 1,1, 0, 0,0); | ||||
|     SET_COMP(2, 0x59 /* 'Y' */, 1,1, 0, 0,0); | ||||
|     SET_COMP(3, 0x4B /* 'K' */, 1,1, 0, 0,0); | ||||
|     break; | ||||
|   case JCS_YCCK: | ||||
|     cinfo->write_Adobe_marker = TRUE; /* write Adobe marker to flag YCCK */ | ||||
|     cinfo->num_components = 4; | ||||
|     SET_COMP(0, 1, 2,2, 0, 0,0); | ||||
|     SET_COMP(1, 2, 1,1, 1, 1,1); | ||||
|     SET_COMP(2, 3, 1,1, 1, 1,1); | ||||
|     SET_COMP(3, 4, 2,2, 0, 0,0); | ||||
|     break; | ||||
|   case JCS_UNKNOWN: | ||||
|     cinfo->num_components = cinfo->input_components; | ||||
|     if (cinfo->num_components < 1 || cinfo->num_components > MAX_COMPONENTS) | ||||
|       ERREXIT2(cinfo, JERR_COMPONENT_COUNT, cinfo->num_components, | ||||
| 	       MAX_COMPONENTS); | ||||
|     for (ci = 0; ci < cinfo->num_components; ci++) { | ||||
|       SET_COMP(ci, ci, 1,1, 0, 0,0); | ||||
|     } | ||||
|     break; | ||||
|   default: | ||||
|     ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef C_PROGRESSIVE_SUPPORTED | ||||
| 
 | ||||
| LOCAL(jpeg_scan_info *) | ||||
| fill_a_scan (jpeg_scan_info * scanptr, int ci, | ||||
| 	     int Ss, int Se, int Ah, int Al) | ||||
| /* Support routine: generate one scan for specified component */ | ||||
| { | ||||
|   scanptr->comps_in_scan = 1; | ||||
|   scanptr->component_index[0] = ci; | ||||
|   scanptr->Ss = Ss; | ||||
|   scanptr->Se = Se; | ||||
|   scanptr->Ah = Ah; | ||||
|   scanptr->Al = Al; | ||||
|   scanptr++; | ||||
|   return scanptr; | ||||
| } | ||||
| 
 | ||||
| LOCAL(jpeg_scan_info *) | ||||
| fill_scans (jpeg_scan_info * scanptr, int ncomps, | ||||
| 	    int Ss, int Se, int Ah, int Al) | ||||
| /* Support routine: generate one scan for each component */ | ||||
| { | ||||
|   int ci; | ||||
| 
 | ||||
|   for (ci = 0; ci < ncomps; ci++) { | ||||
|     scanptr->comps_in_scan = 1; | ||||
|     scanptr->component_index[0] = ci; | ||||
|     scanptr->Ss = Ss; | ||||
|     scanptr->Se = Se; | ||||
|     scanptr->Ah = Ah; | ||||
|     scanptr->Al = Al; | ||||
|     scanptr++; | ||||
|   } | ||||
|   return scanptr; | ||||
| } | ||||
| 
 | ||||
| LOCAL(jpeg_scan_info *) | ||||
| fill_dc_scans (jpeg_scan_info * scanptr, int ncomps, int Ah, int Al) | ||||
| /* Support routine: generate interleaved DC scan if possible, else N scans */ | ||||
| { | ||||
|   int ci; | ||||
| 
 | ||||
|   if (ncomps <= MAX_COMPS_IN_SCAN) { | ||||
|     /* Single interleaved DC scan */ | ||||
|     scanptr->comps_in_scan = ncomps; | ||||
|     for (ci = 0; ci < ncomps; ci++) | ||||
|       scanptr->component_index[ci] = ci; | ||||
|     scanptr->Ss = scanptr->Se = 0; | ||||
|     scanptr->Ah = Ah; | ||||
|     scanptr->Al = Al; | ||||
|     scanptr++; | ||||
|   } else { | ||||
|     /* Noninterleaved DC scan for each component */ | ||||
|     scanptr = fill_scans(scanptr, ncomps, 0, 0, Ah, Al); | ||||
|   } | ||||
|   return scanptr; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Create a recommended progressive-JPEG script. | ||||
|  * cinfo->num_components and cinfo->jpeg_color_space must be correct. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_simple_progression (j_compress_ptr cinfo) | ||||
| { | ||||
|   int ncomps = cinfo->num_components; | ||||
|   int nscans; | ||||
|   jpeg_scan_info * scanptr; | ||||
| 
 | ||||
|   /* Safety check to ensure start_compress not called yet. */ | ||||
|   if (cinfo->global_state != CSTATE_START) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
| 
 | ||||
|   /* Figure space needed for script.  Calculation must match code below! */ | ||||
|   if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { | ||||
|     /* Custom script for YCbCr color images. */ | ||||
|     nscans = 10; | ||||
|   } else { | ||||
|     /* All-purpose script for other color spaces. */ | ||||
|     if (ncomps > MAX_COMPS_IN_SCAN) | ||||
|       nscans = 6 * ncomps;	/* 2 DC + 4 AC scans per component */ | ||||
|     else | ||||
|       nscans = 2 + 4 * ncomps;	/* 2 DC scans; 4 AC scans per component */ | ||||
|   } | ||||
| 
 | ||||
|   /* Allocate space for script.
 | ||||
|    * We need to put it in the permanent pool in case the application performs | ||||
|    * multiple compressions without changing the settings.  To avoid a memory | ||||
|    * leak if jpeg_simple_progression is called repeatedly for the same JPEG | ||||
|    * object, we try to re-use previously allocated space, and we allocate | ||||
|    * enough space to handle YCbCr even if initially asked for grayscale. | ||||
|    */ | ||||
|   if (cinfo->script_space == NULL || cinfo->script_space_size < nscans) { | ||||
|     cinfo->script_space_size = MAX(nscans, 10); | ||||
|     cinfo->script_space = (jpeg_scan_info *) | ||||
|       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, | ||||
| 			cinfo->script_space_size * SIZEOF(jpeg_scan_info)); | ||||
|   } | ||||
|   scanptr = cinfo->script_space; | ||||
|   cinfo->scan_info = scanptr; | ||||
|   cinfo->num_scans = nscans; | ||||
| 
 | ||||
|   if (ncomps == 3 && cinfo->jpeg_color_space == JCS_YCbCr) { | ||||
|     /* Custom script for YCbCr color images. */ | ||||
|     /* Initial DC scan */ | ||||
|     scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); | ||||
|     /* Initial AC scan: get some luma data out in a hurry */ | ||||
|     scanptr = fill_a_scan(scanptr, 0, 1, 5, 0, 2); | ||||
|     /* Chroma data is too small to be worth expending many scans on */ | ||||
|     scanptr = fill_a_scan(scanptr, 2, 1, 63, 0, 1); | ||||
|     scanptr = fill_a_scan(scanptr, 1, 1, 63, 0, 1); | ||||
|     /* Complete spectral selection for luma AC */ | ||||
|     scanptr = fill_a_scan(scanptr, 0, 6, 63, 0, 2); | ||||
|     /* Refine next bit of luma AC */ | ||||
|     scanptr = fill_a_scan(scanptr, 0, 1, 63, 2, 1); | ||||
|     /* Finish DC successive approximation */ | ||||
|     scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); | ||||
|     /* Finish AC successive approximation */ | ||||
|     scanptr = fill_a_scan(scanptr, 2, 1, 63, 1, 0); | ||||
|     scanptr = fill_a_scan(scanptr, 1, 1, 63, 1, 0); | ||||
|     /* Luma bottom bit comes last since it's usually largest scan */ | ||||
|     scanptr = fill_a_scan(scanptr, 0, 1, 63, 1, 0); | ||||
|   } else { | ||||
|     /* All-purpose script for other color spaces. */ | ||||
|     /* Successive approximation first pass */ | ||||
|     scanptr = fill_dc_scans(scanptr, ncomps, 0, 1); | ||||
|     scanptr = fill_scans(scanptr, ncomps, 1, 5, 0, 2); | ||||
|     scanptr = fill_scans(scanptr, ncomps, 6, 63, 0, 2); | ||||
|     /* Successive approximation second pass */ | ||||
|     scanptr = fill_scans(scanptr, ncomps, 1, 63, 2, 1); | ||||
|     /* Successive approximation final pass */ | ||||
|     scanptr = fill_dc_scans(scanptr, ncomps, 1, 0); | ||||
|     scanptr = fill_scans(scanptr, ncomps, 1, 63, 1, 0); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #endif /* C_PROGRESSIVE_SUPPORTED */ | ||||
|  | @ -0,0 +1,833 @@ | |||
| /*
 | ||||
|  * jcphuff.c | ||||
|  * | ||||
|  * Copyright (C) 1995-1997, 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 Huffman entropy encoding routines for progressive JPEG. | ||||
|  * | ||||
|  * We do not support output suspension in this module, since the library | ||||
|  * currently does not allow multiple-scan files to be written with output | ||||
|  * suspension. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| #include "jchuff.h"		/* Declarations shared with jchuff.c */ | ||||
| 
 | ||||
| #ifdef C_PROGRESSIVE_SUPPORTED | ||||
| 
 | ||||
| /* Expanded entropy encoder object for progressive Huffman encoding. */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_entropy_encoder pub; /* public fields */ | ||||
| 
 | ||||
|   /* Mode flag: TRUE for optimization, FALSE for actual data output */ | ||||
|   boolean gather_statistics; | ||||
| 
 | ||||
|   /* Bit-level coding status.
 | ||||
|    * next_output_byte/free_in_buffer are local copies of cinfo->dest fields. | ||||
|    */ | ||||
|   JOCTET * next_output_byte;	/* => next byte to write in buffer */ | ||||
|   size_t free_in_buffer;	/* # of byte spaces remaining in buffer */ | ||||
|   INT32 put_buffer;		/* current bit-accumulation buffer */ | ||||
|   int put_bits;			/* # of bits now in it */ | ||||
|   j_compress_ptr cinfo;		/* link to cinfo (needed for dump_buffer) */ | ||||
| 
 | ||||
|   /* Coding status for DC components */ | ||||
|   int last_dc_val[MAX_COMPS_IN_SCAN]; /* last DC coef for each component */ | ||||
| 
 | ||||
|   /* Coding status for AC components */ | ||||
|   int ac_tbl_no;		/* the table number of the single component */ | ||||
|   unsigned int EOBRUN;		/* run length of EOBs */ | ||||
|   unsigned int BE;		/* # of buffered correction bits before MCU */ | ||||
|   char * bit_buffer;		/* buffer for correction bits (1 per char) */ | ||||
|   /* packing correction bits tightly would save some space but cost time... */ | ||||
| 
 | ||||
|   unsigned int restarts_to_go;	/* MCUs left in this restart interval */ | ||||
|   int next_restart_num;		/* next restart number to write (0-7) */ | ||||
| 
 | ||||
|   /* Pointers to derived tables (these workspaces have image lifespan).
 | ||||
|    * Since any one scan codes only DC or only AC, we only need one set | ||||
|    * of tables, not one for DC and one for AC. | ||||
|    */ | ||||
|   c_derived_tbl * derived_tbls[NUM_HUFF_TBLS]; | ||||
| 
 | ||||
|   /* Statistics tables for optimization; again, one set is enough */ | ||||
|   long * count_ptrs[NUM_HUFF_TBLS]; | ||||
| } phuff_entropy_encoder; | ||||
| 
 | ||||
| typedef phuff_entropy_encoder * phuff_entropy_ptr; | ||||
| 
 | ||||
| /* MAX_CORR_BITS is the number of bits the AC refinement correction-bit
 | ||||
|  * buffer can hold.  Larger sizes may slightly improve compression, but | ||||
|  * 1000 is already well into the realm of overkill. | ||||
|  * The minimum safe size is 64 bits. | ||||
|  */ | ||||
| 
 | ||||
| #define MAX_CORR_BITS  1000	/* Max # of correction bits I can buffer */ | ||||
| 
 | ||||
| /* IRIGHT_SHIFT is like RIGHT_SHIFT, but works on int rather than INT32.
 | ||||
|  * We assume that int right shift is unsigned if INT32 right shift is, | ||||
|  * which should be safe. | ||||
|  */ | ||||
| 
 | ||||
| #ifdef RIGHT_SHIFT_IS_UNSIGNED | ||||
| #define ISHIFT_TEMPS	int ishift_temp; | ||||
| #define IRIGHT_SHIFT(x,shft)  \ | ||||
| 	((ishift_temp = (x)) < 0 ? \ | ||||
| 	 (ishift_temp >> (shft)) | ((~0) << (16-(shft))) : \ | ||||
| 	 (ishift_temp >> (shft))) | ||||
| #else | ||||
| #define ISHIFT_TEMPS | ||||
| #define IRIGHT_SHIFT(x,shft)	((x) >> (shft)) | ||||
| #endif | ||||
| 
 | ||||
| /* Forward declarations */ | ||||
| METHODDEF(boolean) encode_mcu_DC_first JPP((j_compress_ptr cinfo, | ||||
| 					    JBLOCKROW *MCU_data)); | ||||
| METHODDEF(boolean) encode_mcu_AC_first JPP((j_compress_ptr cinfo, | ||||
| 					    JBLOCKROW *MCU_data)); | ||||
| METHODDEF(boolean) encode_mcu_DC_refine JPP((j_compress_ptr cinfo, | ||||
| 					     JBLOCKROW *MCU_data)); | ||||
| METHODDEF(boolean) encode_mcu_AC_refine JPP((j_compress_ptr cinfo, | ||||
| 					     JBLOCKROW *MCU_data)); | ||||
| METHODDEF(void) finish_pass_phuff JPP((j_compress_ptr cinfo)); | ||||
| METHODDEF(void) finish_pass_gather_phuff JPP((j_compress_ptr cinfo)); | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize for a Huffman-compressed scan using progressive JPEG. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| start_pass_phuff (j_compress_ptr cinfo, boolean gather_statistics) | ||||
| {   | ||||
|   phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; | ||||
|   boolean is_DC_band; | ||||
|   int ci, tbl; | ||||
|   jpeg_component_info * compptr; | ||||
| 
 | ||||
|   entropy->cinfo = cinfo; | ||||
|   entropy->gather_statistics = gather_statistics; | ||||
| 
 | ||||
|   is_DC_band = (cinfo->Ss == 0); | ||||
| 
 | ||||
|   /* We assume jcmaster.c already validated the scan parameters. */ | ||||
| 
 | ||||
|   /* Select execution routines */ | ||||
|   if (cinfo->Ah == 0) { | ||||
|     if (is_DC_band) | ||||
|       entropy->pub.encode_mcu = encode_mcu_DC_first; | ||||
|     else | ||||
|       entropy->pub.encode_mcu = encode_mcu_AC_first; | ||||
|   } else { | ||||
|     if (is_DC_band) | ||||
|       entropy->pub.encode_mcu = encode_mcu_DC_refine; | ||||
|     else { | ||||
|       entropy->pub.encode_mcu = encode_mcu_AC_refine; | ||||
|       /* AC refinement needs a correction bit buffer */ | ||||
|       if (entropy->bit_buffer == NULL) | ||||
| 	entropy->bit_buffer = (char *) | ||||
| 	  (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				      MAX_CORR_BITS * SIZEOF(char)); | ||||
|     } | ||||
|   } | ||||
|   if (gather_statistics) | ||||
|     entropy->pub.finish_pass = finish_pass_gather_phuff; | ||||
|   else | ||||
|     entropy->pub.finish_pass = finish_pass_phuff; | ||||
| 
 | ||||
|   /* Only DC coefficients may be interleaved, so cinfo->comps_in_scan = 1
 | ||||
|    * for AC coefficients. | ||||
|    */ | ||||
|   for (ci = 0; ci < cinfo->comps_in_scan; ci++) { | ||||
|     compptr = cinfo->cur_comp_info[ci]; | ||||
|     /* Initialize DC predictions to 0 */ | ||||
|     entropy->last_dc_val[ci] = 0; | ||||
|     /* Get table index */ | ||||
|     if (is_DC_band) { | ||||
|       if (cinfo->Ah != 0)	/* DC refinement needs no table */ | ||||
| 	continue; | ||||
|       tbl = compptr->dc_tbl_no; | ||||
|     } else { | ||||
|       entropy->ac_tbl_no = tbl = compptr->ac_tbl_no; | ||||
|     } | ||||
|     if (gather_statistics) { | ||||
|       /* Check for invalid table index */ | ||||
|       /* (make_c_derived_tbl does this in the other path) */ | ||||
|       if (tbl < 0 || tbl >= NUM_HUFF_TBLS) | ||||
|         ERREXIT1(cinfo, JERR_NO_HUFF_TABLE, tbl); | ||||
|       /* Allocate and zero the statistics tables */ | ||||
|       /* Note that jpeg_gen_optimal_table expects 257 entries in each table! */ | ||||
|       if (entropy->count_ptrs[tbl] == NULL) | ||||
| 	entropy->count_ptrs[tbl] = (long *) | ||||
| 	  (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				      257 * SIZEOF(long)); | ||||
|       MEMZERO(entropy->count_ptrs[tbl], 257 * SIZEOF(long)); | ||||
|     } else { | ||||
|       /* Compute derived values for Huffman table */ | ||||
|       /* We may do this more than once for a table, but it's not expensive */ | ||||
|       jpeg_make_c_derived_tbl(cinfo, is_DC_band, tbl, | ||||
| 			      & entropy->derived_tbls[tbl]); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   /* Initialize AC stuff */ | ||||
|   entropy->EOBRUN = 0; | ||||
|   entropy->BE = 0; | ||||
| 
 | ||||
|   /* Initialize bit buffer to empty */ | ||||
|   entropy->put_buffer = 0; | ||||
|   entropy->put_bits = 0; | ||||
| 
 | ||||
|   /* Initialize restart stuff */ | ||||
|   entropy->restarts_to_go = cinfo->restart_interval; | ||||
|   entropy->next_restart_num = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Outputting bytes to the file.
 | ||||
|  * NB: these must be called only when actually outputting, | ||||
|  * that is, entropy->gather_statistics == FALSE. | ||||
|  */ | ||||
| 
 | ||||
| /* Emit a byte */ | ||||
| #define emit_byte(entropy,val)  \ | ||||
| 	{ *(entropy)->next_output_byte++ = (JOCTET) (val);  \ | ||||
| 	  if (--(entropy)->free_in_buffer == 0)  \ | ||||
| 	    dump_buffer(entropy); } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| dump_buffer (phuff_entropy_ptr entropy) | ||||
| /* Empty the output buffer; we do not support suspension in this module. */ | ||||
| { | ||||
|   struct jpeg_destination_mgr * dest = entropy->cinfo->dest; | ||||
| 
 | ||||
|   if (! (*dest->empty_output_buffer) (entropy->cinfo)) | ||||
|     ERREXIT(entropy->cinfo, JERR_CANT_SUSPEND); | ||||
|   /* After a successful buffer dump, must reset buffer pointers */ | ||||
|   entropy->next_output_byte = dest->next_output_byte; | ||||
|   entropy->free_in_buffer = dest->free_in_buffer; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Outputting bits to the file */ | ||||
| 
 | ||||
| /* Only the right 24 bits of put_buffer are used; the valid bits are
 | ||||
|  * left-justified in this part.  At most 16 bits can be passed to emit_bits | ||||
|  * in one call, and we never retain more than 7 bits in put_buffer | ||||
|  * between calls, so 24 bits are sufficient. | ||||
|  */ | ||||
| 
 | ||||
| INLINE | ||||
| LOCAL(void) | ||||
| emit_bits (phuff_entropy_ptr entropy, unsigned int code, int size) | ||||
| /* Emit some bits, unless we are in gather mode */ | ||||
| { | ||||
|   /* This routine is heavily used, so it's worth coding tightly. */ | ||||
|   register INT32 put_buffer = (INT32) code; | ||||
|   register int put_bits = entropy->put_bits; | ||||
| 
 | ||||
|   /* if size is 0, caller used an invalid Huffman table entry */ | ||||
|   if (size == 0) | ||||
|     ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); | ||||
| 
 | ||||
|   if (entropy->gather_statistics) | ||||
|     return;			/* do nothing if we're only getting stats */ | ||||
| 
 | ||||
|   put_buffer &= (((INT32) 1)<<size) - 1; /* mask off any extra bits in code */ | ||||
|    | ||||
|   put_bits += size;		/* new number of bits in buffer */ | ||||
|    | ||||
|   put_buffer <<= 24 - put_bits; /* align incoming bits */ | ||||
| 
 | ||||
|   put_buffer |= entropy->put_buffer; /* and merge with old buffer contents */ | ||||
| 
 | ||||
|   while (put_bits >= 8) { | ||||
|     int c = (int) ((put_buffer >> 16) & 0xFF); | ||||
|      | ||||
|     emit_byte(entropy, c); | ||||
|     if (c == 0xFF) {		/* need to stuff a zero byte? */ | ||||
|       emit_byte(entropy, 0); | ||||
|     } | ||||
|     put_buffer <<= 8; | ||||
|     put_bits -= 8; | ||||
|   } | ||||
| 
 | ||||
|   entropy->put_buffer = put_buffer; /* update variables */ | ||||
|   entropy->put_bits = put_bits; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| flush_bits (phuff_entropy_ptr entropy) | ||||
| { | ||||
|   emit_bits(entropy, 0x7F, 7); /* fill any partial byte with ones */ | ||||
|   entropy->put_buffer = 0;     /* and reset bit-buffer to empty */ | ||||
|   entropy->put_bits = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Emit (or just count) a Huffman symbol. | ||||
|  */ | ||||
| 
 | ||||
| INLINE | ||||
| LOCAL(void) | ||||
| emit_symbol (phuff_entropy_ptr entropy, int tbl_no, int symbol) | ||||
| { | ||||
|   if (entropy->gather_statistics) | ||||
|     entropy->count_ptrs[tbl_no][symbol]++; | ||||
|   else { | ||||
|     c_derived_tbl * tbl = entropy->derived_tbls[tbl_no]; | ||||
|     emit_bits(entropy, tbl->ehufco[symbol], tbl->ehufsi[symbol]); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Emit bits from a correction bit buffer. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_buffered_bits (phuff_entropy_ptr entropy, char * bufstart, | ||||
| 		    unsigned int nbits) | ||||
| { | ||||
|   if (entropy->gather_statistics) | ||||
|     return;			/* no real work */ | ||||
| 
 | ||||
|   while (nbits > 0) { | ||||
|     emit_bits(entropy, (unsigned int) (*bufstart), 1); | ||||
|     bufstart++; | ||||
|     nbits--; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Emit any pending EOBRUN symbol. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_eobrun (phuff_entropy_ptr entropy) | ||||
| { | ||||
|   register int temp, nbits; | ||||
| 
 | ||||
|   if (entropy->EOBRUN > 0) {	/* if there is any pending EOBRUN */ | ||||
|     temp = entropy->EOBRUN; | ||||
|     nbits = 0; | ||||
|     while ((temp >>= 1)) | ||||
|       nbits++; | ||||
|     /* safety check: shouldn't happen given limited correction-bit buffer */ | ||||
|     if (nbits > 14) | ||||
|       ERREXIT(entropy->cinfo, JERR_HUFF_MISSING_CODE); | ||||
| 
 | ||||
|     emit_symbol(entropy, entropy->ac_tbl_no, nbits << 4); | ||||
|     if (nbits) | ||||
|       emit_bits(entropy, entropy->EOBRUN, nbits); | ||||
| 
 | ||||
|     entropy->EOBRUN = 0; | ||||
| 
 | ||||
|     /* Emit any buffered correction bits */ | ||||
|     emit_buffered_bits(entropy, entropy->bit_buffer, entropy->BE); | ||||
|     entropy->BE = 0; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Emit a restart marker & resynchronize predictions. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| emit_restart (phuff_entropy_ptr entropy, int restart_num) | ||||
| { | ||||
|   int ci; | ||||
| 
 | ||||
|   emit_eobrun(entropy); | ||||
| 
 | ||||
|   if (! entropy->gather_statistics) { | ||||
|     flush_bits(entropy); | ||||
|     emit_byte(entropy, 0xFF); | ||||
|     emit_byte(entropy, JPEG_RST0 + restart_num); | ||||
|   } | ||||
| 
 | ||||
|   if (entropy->cinfo->Ss == 0) { | ||||
|     /* Re-initialize DC predictions to 0 */ | ||||
|     for (ci = 0; ci < entropy->cinfo->comps_in_scan; ci++) | ||||
|       entropy->last_dc_val[ci] = 0; | ||||
|   } else { | ||||
|     /* Re-initialize all AC-related fields to 0 */ | ||||
|     entropy->EOBRUN = 0; | ||||
|     entropy->BE = 0; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * MCU encoding for DC initial scan (either spectral selection, | ||||
|  * or first pass of successive approximation). | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(boolean) | ||||
| encode_mcu_DC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) | ||||
| { | ||||
|   phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; | ||||
|   register int temp, temp2; | ||||
|   register int nbits; | ||||
|   int blkn, ci; | ||||
|   int Al = cinfo->Al; | ||||
|   JBLOCKROW block; | ||||
|   jpeg_component_info * compptr; | ||||
|   ISHIFT_TEMPS | ||||
| 
 | ||||
|   entropy->next_output_byte = cinfo->dest->next_output_byte; | ||||
|   entropy->free_in_buffer = cinfo->dest->free_in_buffer; | ||||
| 
 | ||||
|   /* Emit restart marker if needed */ | ||||
|   if (cinfo->restart_interval) | ||||
|     if (entropy->restarts_to_go == 0) | ||||
|       emit_restart(entropy, entropy->next_restart_num); | ||||
| 
 | ||||
|   /* Encode the MCU data blocks */ | ||||
|   for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { | ||||
|     block = MCU_data[blkn]; | ||||
|     ci = cinfo->MCU_membership[blkn]; | ||||
|     compptr = cinfo->cur_comp_info[ci]; | ||||
| 
 | ||||
|     /* Compute the DC value after the required point transform by Al.
 | ||||
|      * This is simply an arithmetic right shift. | ||||
|      */ | ||||
|     temp2 = IRIGHT_SHIFT((int) ((*block)[0]), Al); | ||||
| 
 | ||||
|     /* DC differences are figured on the point-transformed values. */ | ||||
|     temp = temp2 - entropy->last_dc_val[ci]; | ||||
|     entropy->last_dc_val[ci] = temp2; | ||||
| 
 | ||||
|     /* Encode the DC coefficient difference per section G.1.2.1 */ | ||||
|     temp2 = temp; | ||||
|     if (temp < 0) { | ||||
|       temp = -temp;		/* temp is abs value of input */ | ||||
|       /* For a negative input, want temp2 = bitwise complement of abs(input) */ | ||||
|       /* This code assumes we are on a two's complement machine */ | ||||
|       temp2--; | ||||
|     } | ||||
|      | ||||
|     /* Find the number of bits needed for the magnitude of the coefficient */ | ||||
|     nbits = 0; | ||||
|     while (temp) { | ||||
|       nbits++; | ||||
|       temp >>= 1; | ||||
|     } | ||||
|     /* Check for out-of-range coefficient values.
 | ||||
|      * Since we're encoding a difference, the range limit is twice as much. | ||||
|      */ | ||||
|     if (nbits > MAX_COEF_BITS+1) | ||||
|       ERREXIT(cinfo, JERR_BAD_DCT_COEF); | ||||
|      | ||||
|     /* Count/emit the Huffman-coded symbol for the number of bits */ | ||||
|     emit_symbol(entropy, compptr->dc_tbl_no, nbits); | ||||
|      | ||||
|     /* Emit that number of bits of the value, if positive, */ | ||||
|     /* or the complement of its magnitude, if negative. */ | ||||
|     if (nbits)			/* emit_bits rejects calls with size 0 */ | ||||
|       emit_bits(entropy, (unsigned int) temp2, nbits); | ||||
|   } | ||||
| 
 | ||||
|   cinfo->dest->next_output_byte = entropy->next_output_byte; | ||||
|   cinfo->dest->free_in_buffer = entropy->free_in_buffer; | ||||
| 
 | ||||
|   /* Update restart-interval state too */ | ||||
|   if (cinfo->restart_interval) { | ||||
|     if (entropy->restarts_to_go == 0) { | ||||
|       entropy->restarts_to_go = cinfo->restart_interval; | ||||
|       entropy->next_restart_num++; | ||||
|       entropy->next_restart_num &= 7; | ||||
|     } | ||||
|     entropy->restarts_to_go--; | ||||
|   } | ||||
| 
 | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * MCU encoding for AC initial scan (either spectral selection, | ||||
|  * or first pass of successive approximation). | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(boolean) | ||||
| encode_mcu_AC_first (j_compress_ptr cinfo, JBLOCKROW *MCU_data) | ||||
| { | ||||
|   phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; | ||||
|   register int temp, temp2; | ||||
|   register int nbits; | ||||
|   register int r, k; | ||||
|   int Se = cinfo->Se; | ||||
|   int Al = cinfo->Al; | ||||
|   JBLOCKROW block; | ||||
| 
 | ||||
|   entropy->next_output_byte = cinfo->dest->next_output_byte; | ||||
|   entropy->free_in_buffer = cinfo->dest->free_in_buffer; | ||||
| 
 | ||||
|   /* Emit restart marker if needed */ | ||||
|   if (cinfo->restart_interval) | ||||
|     if (entropy->restarts_to_go == 0) | ||||
|       emit_restart(entropy, entropy->next_restart_num); | ||||
| 
 | ||||
|   /* Encode the MCU data block */ | ||||
|   block = MCU_data[0]; | ||||
| 
 | ||||
|   /* Encode the AC coefficients per section G.1.2.2, fig. G.3 */ | ||||
|    | ||||
|   r = 0;			/* r = run length of zeros */ | ||||
|     | ||||
|   for (k = cinfo->Ss; k <= Se; k++) { | ||||
|     if ((temp = (*block)[jpeg_natural_order[k]]) == 0) { | ||||
|       r++; | ||||
|       continue; | ||||
|     } | ||||
|     /* We must apply the point transform by Al.  For AC coefficients this
 | ||||
|      * is an integer division with rounding towards 0.  To do this portably | ||||
|      * in C, we shift after obtaining the absolute value; so the code is | ||||
|      * interwoven with finding the abs value (temp) and output bits (temp2). | ||||
|      */ | ||||
|     if (temp < 0) { | ||||
|       temp = -temp;		/* temp is abs value of input */ | ||||
|       temp >>= Al;		/* apply the point transform */ | ||||
|       /* For a negative coef, want temp2 = bitwise complement of abs(coef) */ | ||||
|       temp2 = ~temp; | ||||
|     } else { | ||||
|       temp >>= Al;		/* apply the point transform */ | ||||
|       temp2 = temp; | ||||
|     } | ||||
|     /* Watch out for case that nonzero coef is zero after point transform */ | ||||
|     if (temp == 0) { | ||||
|       r++; | ||||
|       continue; | ||||
|     } | ||||
| 
 | ||||
|     /* Emit any pending EOBRUN */ | ||||
|     if (entropy->EOBRUN > 0) | ||||
|       emit_eobrun(entropy); | ||||
|     /* if run length > 15, must emit special run-length-16 codes (0xF0) */ | ||||
|     while (r > 15) { | ||||
|       emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); | ||||
|       r -= 16; | ||||
|     } | ||||
| 
 | ||||
|     /* Find the number of bits needed for the magnitude of the coefficient */ | ||||
|     nbits = 1;			/* there must be at least one 1 bit */ | ||||
|     while ((temp >>= 1)) | ||||
|       nbits++; | ||||
|     /* Check for out-of-range coefficient values */ | ||||
|     if (nbits > MAX_COEF_BITS) | ||||
|       ERREXIT(cinfo, JERR_BAD_DCT_COEF); | ||||
| 
 | ||||
|     /* Count/emit Huffman symbol for run length / number of bits */ | ||||
|     emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + nbits); | ||||
| 
 | ||||
|     /* Emit that number of bits of the value, if positive, */ | ||||
|     /* or the complement of its magnitude, if negative. */ | ||||
|     emit_bits(entropy, (unsigned int) temp2, nbits); | ||||
| 
 | ||||
|     r = 0;			/* reset zero run length */ | ||||
|   } | ||||
| 
 | ||||
|   if (r > 0) {			/* If there are trailing zeroes, */ | ||||
|     entropy->EOBRUN++;		/* count an EOB */ | ||||
|     if (entropy->EOBRUN == 0x7FFF) | ||||
|       emit_eobrun(entropy);	/* force it out to avoid overflow */ | ||||
|   } | ||||
| 
 | ||||
|   cinfo->dest->next_output_byte = entropy->next_output_byte; | ||||
|   cinfo->dest->free_in_buffer = entropy->free_in_buffer; | ||||
| 
 | ||||
|   /* Update restart-interval state too */ | ||||
|   if (cinfo->restart_interval) { | ||||
|     if (entropy->restarts_to_go == 0) { | ||||
|       entropy->restarts_to_go = cinfo->restart_interval; | ||||
|       entropy->next_restart_num++; | ||||
|       entropy->next_restart_num &= 7; | ||||
|     } | ||||
|     entropy->restarts_to_go--; | ||||
|   } | ||||
| 
 | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * MCU encoding for DC successive approximation refinement scan. | ||||
|  * Note: we assume such scans can be multi-component, although the spec | ||||
|  * is not very clear on the point. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(boolean) | ||||
| encode_mcu_DC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) | ||||
| { | ||||
|   phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; | ||||
|   register int temp; | ||||
|   int blkn; | ||||
|   int Al = cinfo->Al; | ||||
|   JBLOCKROW block; | ||||
| 
 | ||||
|   entropy->next_output_byte = cinfo->dest->next_output_byte; | ||||
|   entropy->free_in_buffer = cinfo->dest->free_in_buffer; | ||||
| 
 | ||||
|   /* Emit restart marker if needed */ | ||||
|   if (cinfo->restart_interval) | ||||
|     if (entropy->restarts_to_go == 0) | ||||
|       emit_restart(entropy, entropy->next_restart_num); | ||||
| 
 | ||||
|   /* Encode the MCU data blocks */ | ||||
|   for (blkn = 0; blkn < cinfo->blocks_in_MCU; blkn++) { | ||||
|     block = MCU_data[blkn]; | ||||
| 
 | ||||
|     /* We simply emit the Al'th bit of the DC coefficient value. */ | ||||
|     temp = (*block)[0]; | ||||
|     emit_bits(entropy, (unsigned int) (temp >> Al), 1); | ||||
|   } | ||||
| 
 | ||||
|   cinfo->dest->next_output_byte = entropy->next_output_byte; | ||||
|   cinfo->dest->free_in_buffer = entropy->free_in_buffer; | ||||
| 
 | ||||
|   /* Update restart-interval state too */ | ||||
|   if (cinfo->restart_interval) { | ||||
|     if (entropy->restarts_to_go == 0) { | ||||
|       entropy->restarts_to_go = cinfo->restart_interval; | ||||
|       entropy->next_restart_num++; | ||||
|       entropy->next_restart_num &= 7; | ||||
|     } | ||||
|     entropy->restarts_to_go--; | ||||
|   } | ||||
| 
 | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * MCU encoding for AC successive approximation refinement scan. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(boolean) | ||||
| encode_mcu_AC_refine (j_compress_ptr cinfo, JBLOCKROW *MCU_data) | ||||
| { | ||||
|   phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; | ||||
|   register int temp; | ||||
|   register int r, k; | ||||
|   int EOB; | ||||
|   char *BR_buffer; | ||||
|   unsigned int BR; | ||||
|   int Se = cinfo->Se; | ||||
|   int Al = cinfo->Al; | ||||
|   JBLOCKROW block; | ||||
|   int absvalues[DCTSIZE2]; | ||||
| 
 | ||||
|   entropy->next_output_byte = cinfo->dest->next_output_byte; | ||||
|   entropy->free_in_buffer = cinfo->dest->free_in_buffer; | ||||
| 
 | ||||
|   /* Emit restart marker if needed */ | ||||
|   if (cinfo->restart_interval) | ||||
|     if (entropy->restarts_to_go == 0) | ||||
|       emit_restart(entropy, entropy->next_restart_num); | ||||
| 
 | ||||
|   /* Encode the MCU data block */ | ||||
|   block = MCU_data[0]; | ||||
| 
 | ||||
|   /* It is convenient to make a pre-pass to determine the transformed
 | ||||
|    * coefficients' absolute values and the EOB position. | ||||
|    */ | ||||
|   EOB = 0; | ||||
|   for (k = cinfo->Ss; k <= Se; k++) { | ||||
|     temp = (*block)[jpeg_natural_order[k]]; | ||||
|     /* We must apply the point transform by Al.  For AC coefficients this
 | ||||
|      * is an integer division with rounding towards 0.  To do this portably | ||||
|      * in C, we shift after obtaining the absolute value. | ||||
|      */ | ||||
|     if (temp < 0) | ||||
|       temp = -temp;		/* temp is abs value of input */ | ||||
|     temp >>= Al;		/* apply the point transform */ | ||||
|     absvalues[k] = temp;	/* save abs value for main pass */ | ||||
|     if (temp == 1) | ||||
|       EOB = k;			/* EOB = index of last newly-nonzero coef */ | ||||
|   } | ||||
| 
 | ||||
|   /* Encode the AC coefficients per section G.1.2.3, fig. G.7 */ | ||||
|    | ||||
|   r = 0;			/* r = run length of zeros */ | ||||
|   BR = 0;			/* BR = count of buffered bits added now */ | ||||
|   BR_buffer = entropy->bit_buffer + entropy->BE; /* Append bits to buffer */ | ||||
| 
 | ||||
|   for (k = cinfo->Ss; k <= Se; k++) { | ||||
|     if ((temp = absvalues[k]) == 0) { | ||||
|       r++; | ||||
|       continue; | ||||
|     } | ||||
| 
 | ||||
|     /* Emit any required ZRLs, but not if they can be folded into EOB */ | ||||
|     while (r > 15 && k <= EOB) { | ||||
|       /* emit any pending EOBRUN and the BE correction bits */ | ||||
|       emit_eobrun(entropy); | ||||
|       /* Emit ZRL */ | ||||
|       emit_symbol(entropy, entropy->ac_tbl_no, 0xF0); | ||||
|       r -= 16; | ||||
|       /* Emit buffered correction bits that must be associated with ZRL */ | ||||
|       emit_buffered_bits(entropy, BR_buffer, BR); | ||||
|       BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ | ||||
|       BR = 0; | ||||
|     } | ||||
| 
 | ||||
|     /* If the coef was previously nonzero, it only needs a correction bit.
 | ||||
|      * NOTE: a straight translation of the spec's figure G.7 would suggest | ||||
|      * that we also need to test r > 15.  But if r > 15, we can only get here | ||||
|      * if k > EOB, which implies that this coefficient is not 1. | ||||
|      */ | ||||
|     if (temp > 1) { | ||||
|       /* The correction bit is the next bit of the absolute value. */ | ||||
|       BR_buffer[BR++] = (char) (temp & 1); | ||||
|       continue; | ||||
|     } | ||||
| 
 | ||||
|     /* Emit any pending EOBRUN and the BE correction bits */ | ||||
|     emit_eobrun(entropy); | ||||
| 
 | ||||
|     /* Count/emit Huffman symbol for run length / number of bits */ | ||||
|     emit_symbol(entropy, entropy->ac_tbl_no, (r << 4) + 1); | ||||
| 
 | ||||
|     /* Emit output bit for newly-nonzero coef */ | ||||
|     temp = ((*block)[jpeg_natural_order[k]] < 0) ? 0 : 1; | ||||
|     emit_bits(entropy, (unsigned int) temp, 1); | ||||
| 
 | ||||
|     /* Emit buffered correction bits that must be associated with this code */ | ||||
|     emit_buffered_bits(entropy, BR_buffer, BR); | ||||
|     BR_buffer = entropy->bit_buffer; /* BE bits are gone now */ | ||||
|     BR = 0; | ||||
|     r = 0;			/* reset zero run length */ | ||||
|   } | ||||
| 
 | ||||
|   if (r > 0 || BR > 0) {	/* If there are trailing zeroes, */ | ||||
|     entropy->EOBRUN++;		/* count an EOB */ | ||||
|     entropy->BE += BR;		/* concat my correction bits to older ones */ | ||||
|     /* We force out the EOB if we risk either:
 | ||||
|      * 1. overflow of the EOB counter; | ||||
|      * 2. overflow of the correction bit buffer during the next MCU. | ||||
|      */ | ||||
|     if (entropy->EOBRUN == 0x7FFF || entropy->BE > (MAX_CORR_BITS-DCTSIZE2+1)) | ||||
|       emit_eobrun(entropy); | ||||
|   } | ||||
| 
 | ||||
|   cinfo->dest->next_output_byte = entropy->next_output_byte; | ||||
|   cinfo->dest->free_in_buffer = entropy->free_in_buffer; | ||||
| 
 | ||||
|   /* Update restart-interval state too */ | ||||
|   if (cinfo->restart_interval) { | ||||
|     if (entropy->restarts_to_go == 0) { | ||||
|       entropy->restarts_to_go = cinfo->restart_interval; | ||||
|       entropy->next_restart_num++; | ||||
|       entropy->next_restart_num &= 7; | ||||
|     } | ||||
|     entropy->restarts_to_go--; | ||||
|   } | ||||
| 
 | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Finish up at the end of a Huffman-compressed progressive scan. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| finish_pass_phuff (j_compress_ptr cinfo) | ||||
| {    | ||||
|   phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; | ||||
| 
 | ||||
|   entropy->next_output_byte = cinfo->dest->next_output_byte; | ||||
|   entropy->free_in_buffer = cinfo->dest->free_in_buffer; | ||||
| 
 | ||||
|   /* Flush out any buffered data */ | ||||
|   emit_eobrun(entropy); | ||||
|   flush_bits(entropy); | ||||
| 
 | ||||
|   cinfo->dest->next_output_byte = entropy->next_output_byte; | ||||
|   cinfo->dest->free_in_buffer = entropy->free_in_buffer; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Finish up a statistics-gathering pass and create the new Huffman tables. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| finish_pass_gather_phuff (j_compress_ptr cinfo) | ||||
| { | ||||
|   phuff_entropy_ptr entropy = (phuff_entropy_ptr) cinfo->entropy; | ||||
|   boolean is_DC_band; | ||||
|   int ci, tbl; | ||||
|   jpeg_component_info * compptr; | ||||
|   JHUFF_TBL **htblptr; | ||||
|   boolean did[NUM_HUFF_TBLS]; | ||||
| 
 | ||||
|   /* Flush out buffered data (all we care about is counting the EOB symbol) */ | ||||
|   emit_eobrun(entropy); | ||||
| 
 | ||||
|   is_DC_band = (cinfo->Ss == 0); | ||||
| 
 | ||||
|   /* It's important not to apply jpeg_gen_optimal_table more than once
 | ||||
|    * per table, because it clobbers the input frequency counts! | ||||
|    */ | ||||
|   MEMZERO(did, SIZEOF(did)); | ||||
| 
 | ||||
|   for (ci = 0; ci < cinfo->comps_in_scan; ci++) { | ||||
|     compptr = cinfo->cur_comp_info[ci]; | ||||
|     if (is_DC_band) { | ||||
|       if (cinfo->Ah != 0)	/* DC refinement needs no table */ | ||||
| 	continue; | ||||
|       tbl = compptr->dc_tbl_no; | ||||
|     } else { | ||||
|       tbl = compptr->ac_tbl_no; | ||||
|     } | ||||
|     if (! did[tbl]) { | ||||
|       if (is_DC_band) | ||||
|         htblptr = & cinfo->dc_huff_tbl_ptrs[tbl]; | ||||
|       else | ||||
|         htblptr = & cinfo->ac_huff_tbl_ptrs[tbl]; | ||||
|       if (*htblptr == NULL) | ||||
|         *htblptr = jpeg_alloc_huff_table((j_common_ptr) cinfo); | ||||
|       jpeg_gen_optimal_table(cinfo, *htblptr, entropy->count_ptrs[tbl]); | ||||
|       did[tbl] = TRUE; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Module initialization routine for progressive Huffman entropy encoding. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jinit_phuff_encoder (j_compress_ptr cinfo) | ||||
| { | ||||
|   phuff_entropy_ptr entropy; | ||||
|   int i; | ||||
| 
 | ||||
|   entropy = (phuff_entropy_ptr) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				SIZEOF(phuff_entropy_encoder)); | ||||
|   cinfo->entropy = (struct jpeg_entropy_encoder *) entropy; | ||||
|   entropy->pub.start_pass = start_pass_phuff; | ||||
| 
 | ||||
|   /* Mark tables unallocated */ | ||||
|   for (i = 0; i < NUM_HUFF_TBLS; i++) { | ||||
|     entropy->derived_tbls[i] = NULL; | ||||
|     entropy->count_ptrs[i] = NULL; | ||||
|   } | ||||
|   entropy->bit_buffer = NULL;	/* needed only in AC refinement scan */ | ||||
| } | ||||
| 
 | ||||
| #endif /* C_PROGRESSIVE_SUPPORTED */ | ||||
|  | @ -0,0 +1,354 @@ | |||
| /*
 | ||||
|  * jcprepct.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 the compression preprocessing controller. | ||||
|  * This controller manages the color conversion, downsampling, | ||||
|  * and edge expansion steps. | ||||
|  * | ||||
|  * Most of the complexity here is associated with buffering input rows | ||||
|  * as required by the downsampler.  See the comments at the head of | ||||
|  * jcsample.c for the downsampler's needs. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /* At present, jcsample.c can request context rows only for smoothing.
 | ||||
|  * In the future, we might also need context rows for CCIR601 sampling | ||||
|  * or other more-complex downsampling procedures.  The code to support | ||||
|  * context rows should be compiled only if needed. | ||||
|  */ | ||||
| #ifdef INPUT_SMOOTHING_SUPPORTED | ||||
| #define CONTEXT_ROWS_SUPPORTED | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * For the simple (no-context-row) case, we just need to buffer one | ||||
|  * row group's worth of pixels for the downsampling step.  At the bottom of | ||||
|  * the image, we pad to a full row group by replicating the last pixel row. | ||||
|  * The downsampler's last output row is then replicated if needed to pad | ||||
|  * out to a full iMCU row. | ||||
|  * | ||||
|  * When providing context rows, we must buffer three row groups' worth of | ||||
|  * pixels.  Three row groups are physically allocated, but the row pointer | ||||
|  * arrays are made five row groups high, with the extra pointers above and | ||||
|  * below "wrapping around" to point to the last and first real row groups. | ||||
|  * This allows the downsampler to access the proper context rows. | ||||
|  * At the top and bottom of the image, we create dummy context rows by | ||||
|  * copying the first or last real pixel row.  This copying could be avoided | ||||
|  * by pointer hacking as is done in jdmainct.c, but it doesn't seem worth the | ||||
|  * trouble on the compression side. | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| /* Private buffer controller object */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_c_prep_controller pub; /* public fields */ | ||||
| 
 | ||||
|   /* Downsampling input buffer.  This buffer holds color-converted data
 | ||||
|    * until we have enough to do a downsample step. | ||||
|    */ | ||||
|   JSAMPARRAY color_buf[MAX_COMPONENTS]; | ||||
| 
 | ||||
|   JDIMENSION rows_to_go;	/* counts rows remaining in source image */ | ||||
|   int next_buf_row;		/* index of next row to store in color_buf */ | ||||
| 
 | ||||
| #ifdef CONTEXT_ROWS_SUPPORTED	/* only needed for context case */ | ||||
|   int this_row_group;		/* starting row index of group to process */ | ||||
|   int next_buf_stop;		/* downsample when we reach this index */ | ||||
| #endif | ||||
| } my_prep_controller; | ||||
| 
 | ||||
| typedef my_prep_controller * my_prep_ptr; | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize for a processing pass. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| start_pass_prep (j_compress_ptr cinfo, J_BUF_MODE pass_mode) | ||||
| { | ||||
|   my_prep_ptr prep = (my_prep_ptr) cinfo->prep; | ||||
| 
 | ||||
|   if (pass_mode != JBUF_PASS_THRU) | ||||
|     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
| 
 | ||||
|   /* Initialize total-height counter for detecting bottom of image */ | ||||
|   prep->rows_to_go = cinfo->image_height; | ||||
|   /* Mark the conversion buffer empty */ | ||||
|   prep->next_buf_row = 0; | ||||
| #ifdef CONTEXT_ROWS_SUPPORTED | ||||
|   /* Preset additional state variables for context mode.
 | ||||
|    * These aren't used in non-context mode, so we needn't test which mode. | ||||
|    */ | ||||
|   prep->this_row_group = 0; | ||||
|   /* Set next_buf_stop to stop after two row groups have been read in. */ | ||||
|   prep->next_buf_stop = 2 * cinfo->max_v_samp_factor; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Expand an image vertically from height input_rows to height output_rows, | ||||
|  * by duplicating the bottom row. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| expand_bottom_edge (JSAMPARRAY image_data, JDIMENSION num_cols, | ||||
| 		    int input_rows, int output_rows) | ||||
| { | ||||
|   register int row; | ||||
| 
 | ||||
|   for (row = input_rows; row < output_rows; row++) { | ||||
|     jcopy_sample_rows(image_data, input_rows-1, image_data, row, | ||||
| 		      1, num_cols); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Process some data in the simple no-context case. | ||||
|  * | ||||
|  * Preprocessor output data is counted in "row groups".  A row group | ||||
|  * is defined to be v_samp_factor sample rows of each component. | ||||
|  * Downsampling will produce this much data from each max_v_samp_factor | ||||
|  * input rows. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| pre_process_data (j_compress_ptr cinfo, | ||||
| 		  JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, | ||||
| 		  JDIMENSION in_rows_avail, | ||||
| 		  JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, | ||||
| 		  JDIMENSION out_row_groups_avail) | ||||
| { | ||||
|   my_prep_ptr prep = (my_prep_ptr) cinfo->prep; | ||||
|   int numrows, ci; | ||||
|   JDIMENSION inrows; | ||||
|   jpeg_component_info * compptr; | ||||
| 
 | ||||
|   while (*in_row_ctr < in_rows_avail && | ||||
| 	 *out_row_group_ctr < out_row_groups_avail) { | ||||
|     /* Do color conversion to fill the conversion buffer. */ | ||||
|     inrows = in_rows_avail - *in_row_ctr; | ||||
|     numrows = cinfo->max_v_samp_factor - prep->next_buf_row; | ||||
|     numrows = (int) MIN((JDIMENSION) numrows, inrows); | ||||
|     (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, | ||||
| 				       prep->color_buf, | ||||
| 				       (JDIMENSION) prep->next_buf_row, | ||||
| 				       numrows); | ||||
|     *in_row_ctr += numrows; | ||||
|     prep->next_buf_row += numrows; | ||||
|     prep->rows_to_go -= numrows; | ||||
|     /* If at bottom of image, pad to fill the conversion buffer. */ | ||||
|     if (prep->rows_to_go == 0 && | ||||
| 	prep->next_buf_row < cinfo->max_v_samp_factor) { | ||||
|       for (ci = 0; ci < cinfo->num_components; ci++) { | ||||
| 	expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, | ||||
| 			   prep->next_buf_row, cinfo->max_v_samp_factor); | ||||
|       } | ||||
|       prep->next_buf_row = cinfo->max_v_samp_factor; | ||||
|     } | ||||
|     /* If we've filled the conversion buffer, empty it. */ | ||||
|     if (prep->next_buf_row == cinfo->max_v_samp_factor) { | ||||
|       (*cinfo->downsample->downsample) (cinfo, | ||||
| 					prep->color_buf, (JDIMENSION) 0, | ||||
| 					output_buf, *out_row_group_ctr); | ||||
|       prep->next_buf_row = 0; | ||||
|       (*out_row_group_ctr)++; | ||||
|     } | ||||
|     /* If at bottom of image, pad the output to a full iMCU height.
 | ||||
|      * Note we assume the caller is providing a one-iMCU-height output buffer! | ||||
|      */ | ||||
|     if (prep->rows_to_go == 0 && | ||||
| 	*out_row_group_ctr < out_row_groups_avail) { | ||||
|       for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
| 	   ci++, compptr++) { | ||||
| 	expand_bottom_edge(output_buf[ci], | ||||
| 			   compptr->width_in_blocks * DCTSIZE, | ||||
| 			   (int) (*out_row_group_ctr * compptr->v_samp_factor), | ||||
| 			   (int) (out_row_groups_avail * compptr->v_samp_factor)); | ||||
|       } | ||||
|       *out_row_group_ctr = out_row_groups_avail; | ||||
|       break;			/* can exit outer loop without test */ | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef CONTEXT_ROWS_SUPPORTED | ||||
| 
 | ||||
| /*
 | ||||
|  * Process some data in the context case. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| pre_process_context (j_compress_ptr cinfo, | ||||
| 		     JSAMPARRAY input_buf, JDIMENSION *in_row_ctr, | ||||
| 		     JDIMENSION in_rows_avail, | ||||
| 		     JSAMPIMAGE output_buf, JDIMENSION *out_row_group_ctr, | ||||
| 		     JDIMENSION out_row_groups_avail) | ||||
| { | ||||
|   my_prep_ptr prep = (my_prep_ptr) cinfo->prep; | ||||
|   int numrows, ci; | ||||
|   int buf_height = cinfo->max_v_samp_factor * 3; | ||||
|   JDIMENSION inrows; | ||||
| 
 | ||||
|   while (*out_row_group_ctr < out_row_groups_avail) { | ||||
|     if (*in_row_ctr < in_rows_avail) { | ||||
|       /* Do color conversion to fill the conversion buffer. */ | ||||
|       inrows = in_rows_avail - *in_row_ctr; | ||||
|       numrows = prep->next_buf_stop - prep->next_buf_row; | ||||
|       numrows = (int) MIN((JDIMENSION) numrows, inrows); | ||||
|       (*cinfo->cconvert->color_convert) (cinfo, input_buf + *in_row_ctr, | ||||
| 					 prep->color_buf, | ||||
| 					 (JDIMENSION) prep->next_buf_row, | ||||
| 					 numrows); | ||||
|       /* Pad at top of image, if first time through */ | ||||
|       if (prep->rows_to_go == cinfo->image_height) { | ||||
| 	for (ci = 0; ci < cinfo->num_components; ci++) { | ||||
| 	  int row; | ||||
| 	  for (row = 1; row <= cinfo->max_v_samp_factor; row++) { | ||||
| 	    jcopy_sample_rows(prep->color_buf[ci], 0, | ||||
| 			      prep->color_buf[ci], -row, | ||||
| 			      1, cinfo->image_width); | ||||
| 	  } | ||||
| 	} | ||||
|       } | ||||
|       *in_row_ctr += numrows; | ||||
|       prep->next_buf_row += numrows; | ||||
|       prep->rows_to_go -= numrows; | ||||
|     } else { | ||||
|       /* Return for more data, unless we are at the bottom of the image. */ | ||||
|       if (prep->rows_to_go != 0) | ||||
| 	break; | ||||
|       /* When at bottom of image, pad to fill the conversion buffer. */ | ||||
|       if (prep->next_buf_row < prep->next_buf_stop) { | ||||
| 	for (ci = 0; ci < cinfo->num_components; ci++) { | ||||
| 	  expand_bottom_edge(prep->color_buf[ci], cinfo->image_width, | ||||
| 			     prep->next_buf_row, prep->next_buf_stop); | ||||
| 	} | ||||
| 	prep->next_buf_row = prep->next_buf_stop; | ||||
|       } | ||||
|     } | ||||
|     /* If we've gotten enough data, downsample a row group. */ | ||||
|     if (prep->next_buf_row == prep->next_buf_stop) { | ||||
|       (*cinfo->downsample->downsample) (cinfo, | ||||
| 					prep->color_buf, | ||||
| 					(JDIMENSION) prep->this_row_group, | ||||
| 					output_buf, *out_row_group_ctr); | ||||
|       (*out_row_group_ctr)++; | ||||
|       /* Advance pointers with wraparound as necessary. */ | ||||
|       prep->this_row_group += cinfo->max_v_samp_factor; | ||||
|       if (prep->this_row_group >= buf_height) | ||||
| 	prep->this_row_group = 0; | ||||
|       if (prep->next_buf_row >= buf_height) | ||||
| 	prep->next_buf_row = 0; | ||||
|       prep->next_buf_stop = prep->next_buf_row + cinfo->max_v_samp_factor; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Create the wrapped-around downsampling input buffer needed for context mode. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| create_context_buffer (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_prep_ptr prep = (my_prep_ptr) cinfo->prep; | ||||
|   int rgroup_height = cinfo->max_v_samp_factor; | ||||
|   int ci, i; | ||||
|   jpeg_component_info * compptr; | ||||
|   JSAMPARRAY true_buffer, fake_buffer; | ||||
| 
 | ||||
|   /* Grab enough space for fake row pointers for all the components;
 | ||||
|    * we need five row groups' worth of pointers for each component. | ||||
|    */ | ||||
|   fake_buffer = (JSAMPARRAY) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				(cinfo->num_components * 5 * rgroup_height) * | ||||
| 				SIZEOF(JSAMPROW)); | ||||
| 
 | ||||
|   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
|        ci++, compptr++) { | ||||
|     /* Allocate the actual buffer space (3 row groups) for this component.
 | ||||
|      * We make the buffer wide enough to allow the downsampler to edge-expand | ||||
|      * horizontally within the buffer, if it so chooses. | ||||
|      */ | ||||
|     true_buffer = (*cinfo->mem->alloc_sarray) | ||||
|       ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
|        (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * | ||||
| 		      cinfo->max_h_samp_factor) / compptr->h_samp_factor), | ||||
|        (JDIMENSION) (3 * rgroup_height)); | ||||
|     /* Copy true buffer row pointers into the middle of the fake row array */ | ||||
|     MEMCOPY(fake_buffer + rgroup_height, true_buffer, | ||||
| 	    3 * rgroup_height * SIZEOF(JSAMPROW)); | ||||
|     /* Fill in the above and below wraparound pointers */ | ||||
|     for (i = 0; i < rgroup_height; i++) { | ||||
|       fake_buffer[i] = true_buffer[2 * rgroup_height + i]; | ||||
|       fake_buffer[4 * rgroup_height + i] = true_buffer[i]; | ||||
|     } | ||||
|     prep->color_buf[ci] = fake_buffer + rgroup_height; | ||||
|     fake_buffer += 5 * rgroup_height; /* point to space for next component */ | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #endif /* CONTEXT_ROWS_SUPPORTED */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize preprocessing controller. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jinit_c_prep_controller (j_compress_ptr cinfo, boolean need_full_buffer) | ||||
| { | ||||
|   my_prep_ptr prep; | ||||
|   int ci; | ||||
|   jpeg_component_info * compptr; | ||||
| 
 | ||||
|   if (need_full_buffer)		/* safety check */ | ||||
|     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
| 
 | ||||
|   prep = (my_prep_ptr) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				SIZEOF(my_prep_controller)); | ||||
|   cinfo->prep = (struct jpeg_c_prep_controller *) prep; | ||||
|   prep->pub.start_pass = start_pass_prep; | ||||
| 
 | ||||
|   /* Allocate the color conversion buffer.
 | ||||
|    * We make the buffer wide enough to allow the downsampler to edge-expand | ||||
|    * horizontally within the buffer, if it so chooses. | ||||
|    */ | ||||
|   if (cinfo->downsample->need_context_rows) { | ||||
|     /* Set up to provide context rows */ | ||||
| #ifdef CONTEXT_ROWS_SUPPORTED | ||||
|     prep->pub.pre_process_data = pre_process_context; | ||||
|     create_context_buffer(cinfo); | ||||
| #else | ||||
|     ERREXIT(cinfo, JERR_NOT_COMPILED); | ||||
| #endif | ||||
|   } else { | ||||
|     /* No context, just make it tall enough for one row group */ | ||||
|     prep->pub.pre_process_data = pre_process_data; | ||||
|     for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
| 	 ci++, compptr++) { | ||||
|       prep->color_buf[ci] = (*cinfo->mem->alloc_sarray) | ||||
| 	((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 	 (JDIMENSION) (((long) compptr->width_in_blocks * DCTSIZE * | ||||
| 			cinfo->max_h_samp_factor) / compptr->h_samp_factor), | ||||
| 	 (JDIMENSION) cinfo->max_v_samp_factor); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,519 @@ | |||
| /*
 | ||||
|  * jcsample.c | ||||
|  * | ||||
|  * Copyright (C) 1991-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 downsampling routines. | ||||
|  * | ||||
|  * Downsampling input data is counted in "row groups".  A row group | ||||
|  * is defined to be max_v_samp_factor pixel rows of each component, | ||||
|  * from which the downsampler produces v_samp_factor sample rows. | ||||
|  * A single row group is processed in each call to the downsampler module. | ||||
|  * | ||||
|  * The downsampler is responsible for edge-expansion of its output data | ||||
|  * to fill an integral number of DCT blocks horizontally.  The source buffer | ||||
|  * may be modified if it is helpful for this purpose (the source buffer is | ||||
|  * allocated wide enough to correspond to the desired output width). | ||||
|  * The caller (the prep controller) is responsible for vertical padding. | ||||
|  * | ||||
|  * The downsampler may request "context rows" by setting need_context_rows | ||||
|  * during startup.  In this case, the input arrays will contain at least | ||||
|  * one row group's worth of pixels above and below the passed-in data; | ||||
|  * the caller will create dummy rows at image top and bottom by replicating | ||||
|  * the first or last real pixel row. | ||||
|  * | ||||
|  * An excellent reference for image resampling is | ||||
|  *   Digital Image Warping, George Wolberg, 1990. | ||||
|  *   Pub. by IEEE Computer Society Press, Los Alamitos, CA. ISBN 0-8186-8944-7. | ||||
|  * | ||||
|  * The downsampling algorithm used here is a simple average of the source | ||||
|  * pixels covered by the output pixel.  The hi-falutin sampling literature | ||||
|  * refers to this as a "box filter".  In general the characteristics of a box | ||||
|  * filter are not very good, but for the specific cases we normally use (1:1 | ||||
|  * and 2:1 ratios) the box is equivalent to a "triangle filter" which is not | ||||
|  * nearly so bad.  If you intend to use other sampling ratios, you'd be well | ||||
|  * advised to improve this code. | ||||
|  * | ||||
|  * A simple input-smoothing capability is provided.  This is mainly intended | ||||
|  * for cleaning up color-dithered GIF input files (if you find it inadequate, | ||||
|  * we suggest using an external filtering program such as pnmconvol).  When | ||||
|  * enabled, each input pixel P is replaced by a weighted sum of itself and its | ||||
|  * eight neighbors.  P's weight is 1-8*SF and each neighbor's weight is SF, | ||||
|  * where SF = (smoothing_factor / 1024). | ||||
|  * Currently, smoothing is only supported for 2h2v sampling factors. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Pointer to routine to downsample a single component */ | ||||
| typedef JMETHOD(void, downsample1_ptr, | ||||
| 		(j_compress_ptr cinfo, jpeg_component_info * compptr, | ||||
| 		 JSAMPARRAY input_data, JSAMPARRAY output_data)); | ||||
| 
 | ||||
| /* Private subobject */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_downsampler pub;	/* public fields */ | ||||
| 
 | ||||
|   /* Downsampling method pointers, one per component */ | ||||
|   downsample1_ptr methods[MAX_COMPONENTS]; | ||||
| } my_downsampler; | ||||
| 
 | ||||
| typedef my_downsampler * my_downsample_ptr; | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize for a downsampling pass. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| start_pass_downsample (j_compress_ptr cinfo) | ||||
| { | ||||
|   /* no work for now */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Expand a component horizontally from width input_cols to width output_cols, | ||||
|  * by duplicating the rightmost samples. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| expand_right_edge (JSAMPARRAY image_data, int num_rows, | ||||
| 		   JDIMENSION input_cols, JDIMENSION output_cols) | ||||
| { | ||||
|   register JSAMPROW ptr; | ||||
|   register JSAMPLE pixval; | ||||
|   register int count; | ||||
|   int row; | ||||
|   int numcols = (int) (output_cols - input_cols); | ||||
| 
 | ||||
|   if (numcols > 0) { | ||||
|     for (row = 0; row < num_rows; row++) { | ||||
|       ptr = image_data[row] + input_cols; | ||||
|       pixval = ptr[-1];		/* don't need GETJSAMPLE() here */ | ||||
|       for (count = numcols; count > 0; count--) | ||||
| 	*ptr++ = pixval; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Do downsampling for a whole row group (all components). | ||||
|  * | ||||
|  * In this version we simply downsample each component independently. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| sep_downsample (j_compress_ptr cinfo, | ||||
| 		JSAMPIMAGE input_buf, JDIMENSION in_row_index, | ||||
| 		JSAMPIMAGE output_buf, JDIMENSION out_row_group_index) | ||||
| { | ||||
|   my_downsample_ptr downsample = (my_downsample_ptr) cinfo->downsample; | ||||
|   int ci; | ||||
|   jpeg_component_info * compptr; | ||||
|   JSAMPARRAY in_ptr, out_ptr; | ||||
| 
 | ||||
|   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
|        ci++, compptr++) { | ||||
|     in_ptr = input_buf[ci] + in_row_index; | ||||
|     out_ptr = output_buf[ci] + (out_row_group_index * compptr->v_samp_factor); | ||||
|     (*downsample->methods[ci]) (cinfo, compptr, in_ptr, out_ptr); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Downsample pixel values of a single component. | ||||
|  * One row group is processed per call. | ||||
|  * This version handles arbitrary integral sampling ratios, without smoothing. | ||||
|  * Note that this version is not actually used for customary sampling ratios. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| int_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, | ||||
| 		JSAMPARRAY input_data, JSAMPARRAY output_data) | ||||
| { | ||||
|   int inrow, outrow, h_expand, v_expand, numpix, numpix2, h, v; | ||||
|   JDIMENSION outcol, outcol_h;	/* outcol_h == outcol*h_expand */ | ||||
|   JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; | ||||
|   JSAMPROW inptr, outptr; | ||||
|   INT32 outvalue; | ||||
| 
 | ||||
|   h_expand = cinfo->max_h_samp_factor / compptr->h_samp_factor; | ||||
|   v_expand = cinfo->max_v_samp_factor / compptr->v_samp_factor; | ||||
|   numpix = h_expand * v_expand; | ||||
|   numpix2 = numpix/2; | ||||
| 
 | ||||
|   /* Expand input data enough to let all the output samples be generated
 | ||||
|    * by the standard loop.  Special-casing padded output would be more | ||||
|    * efficient. | ||||
|    */ | ||||
|   expand_right_edge(input_data, cinfo->max_v_samp_factor, | ||||
| 		    cinfo->image_width, output_cols * h_expand); | ||||
| 
 | ||||
|   inrow = 0; | ||||
|   for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { | ||||
|     outptr = output_data[outrow]; | ||||
|     for (outcol = 0, outcol_h = 0; outcol < output_cols; | ||||
| 	 outcol++, outcol_h += h_expand) { | ||||
|       outvalue = 0; | ||||
|       for (v = 0; v < v_expand; v++) { | ||||
| 	inptr = input_data[inrow+v] + outcol_h; | ||||
| 	for (h = 0; h < h_expand; h++) { | ||||
| 	  outvalue += (INT32) GETJSAMPLE(*inptr++); | ||||
| 	} | ||||
|       } | ||||
|       *outptr++ = (JSAMPLE) ((outvalue + numpix2) / numpix); | ||||
|     } | ||||
|     inrow += v_expand; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Downsample pixel values of a single component. | ||||
|  * This version handles the special case of a full-size component, | ||||
|  * without smoothing. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| fullsize_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, | ||||
| 		     JSAMPARRAY input_data, JSAMPARRAY output_data) | ||||
| { | ||||
|   /* Copy the data */ | ||||
|   jcopy_sample_rows(input_data, 0, output_data, 0, | ||||
| 		    cinfo->max_v_samp_factor, cinfo->image_width); | ||||
|   /* Edge-expand */ | ||||
|   expand_right_edge(output_data, cinfo->max_v_samp_factor, | ||||
| 		    cinfo->image_width, compptr->width_in_blocks * DCTSIZE); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Downsample pixel values of a single component. | ||||
|  * This version handles the common case of 2:1 horizontal and 1:1 vertical, | ||||
|  * without smoothing. | ||||
|  * | ||||
|  * A note about the "bias" calculations: when rounding fractional values to | ||||
|  * integer, we do not want to always round 0.5 up to the next integer. | ||||
|  * If we did that, we'd introduce a noticeable bias towards larger values. | ||||
|  * Instead, this code is arranged so that 0.5 will be rounded up or down at | ||||
|  * alternate pixel locations (a simple ordered dither pattern). | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| h2v1_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, | ||||
| 		 JSAMPARRAY input_data, JSAMPARRAY output_data) | ||||
| { | ||||
|   int outrow; | ||||
|   JDIMENSION outcol; | ||||
|   JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; | ||||
|   register JSAMPROW inptr, outptr; | ||||
|   register int bias; | ||||
| 
 | ||||
|   /* Expand input data enough to let all the output samples be generated
 | ||||
|    * by the standard loop.  Special-casing padded output would be more | ||||
|    * efficient. | ||||
|    */ | ||||
|   expand_right_edge(input_data, cinfo->max_v_samp_factor, | ||||
| 		    cinfo->image_width, output_cols * 2); | ||||
| 
 | ||||
|   for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { | ||||
|     outptr = output_data[outrow]; | ||||
|     inptr = input_data[outrow]; | ||||
|     bias = 0;			/* bias = 0,1,0,1,... for successive samples */ | ||||
|     for (outcol = 0; outcol < output_cols; outcol++) { | ||||
|       *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr) + GETJSAMPLE(inptr[1]) | ||||
| 			      + bias) >> 1); | ||||
|       bias ^= 1;		/* 0=>1, 1=>0 */ | ||||
|       inptr += 2; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Downsample pixel values of a single component. | ||||
|  * This version handles the standard case of 2:1 horizontal and 2:1 vertical, | ||||
|  * without smoothing. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| h2v2_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, | ||||
| 		 JSAMPARRAY input_data, JSAMPARRAY output_data) | ||||
| { | ||||
|   int inrow, outrow; | ||||
|   JDIMENSION outcol; | ||||
|   JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; | ||||
|   register JSAMPROW inptr0, inptr1, outptr; | ||||
|   register int bias; | ||||
| 
 | ||||
|   /* Expand input data enough to let all the output samples be generated
 | ||||
|    * by the standard loop.  Special-casing padded output would be more | ||||
|    * efficient. | ||||
|    */ | ||||
|   expand_right_edge(input_data, cinfo->max_v_samp_factor, | ||||
| 		    cinfo->image_width, output_cols * 2); | ||||
| 
 | ||||
|   inrow = 0; | ||||
|   for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { | ||||
|     outptr = output_data[outrow]; | ||||
|     inptr0 = input_data[inrow]; | ||||
|     inptr1 = input_data[inrow+1]; | ||||
|     bias = 1;			/* bias = 1,2,1,2,... for successive samples */ | ||||
|     for (outcol = 0; outcol < output_cols; outcol++) { | ||||
|       *outptr++ = (JSAMPLE) ((GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + | ||||
| 			      GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]) | ||||
| 			      + bias) >> 2); | ||||
|       bias ^= 3;		/* 1=>2, 2=>1 */ | ||||
|       inptr0 += 2; inptr1 += 2; | ||||
|     } | ||||
|     inrow += 2; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #ifdef INPUT_SMOOTHING_SUPPORTED | ||||
| 
 | ||||
| /*
 | ||||
|  * Downsample pixel values of a single component. | ||||
|  * This version handles the standard case of 2:1 horizontal and 2:1 vertical, | ||||
|  * with smoothing.  One row of context is required. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| h2v2_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info * compptr, | ||||
| 			JSAMPARRAY input_data, JSAMPARRAY output_data) | ||||
| { | ||||
|   int inrow, outrow; | ||||
|   JDIMENSION colctr; | ||||
|   JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; | ||||
|   register JSAMPROW inptr0, inptr1, above_ptr, below_ptr, outptr; | ||||
|   INT32 membersum, neighsum, memberscale, neighscale; | ||||
| 
 | ||||
|   /* Expand input data enough to let all the output samples be generated
 | ||||
|    * by the standard loop.  Special-casing padded output would be more | ||||
|    * efficient. | ||||
|    */ | ||||
|   expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, | ||||
| 		    cinfo->image_width, output_cols * 2); | ||||
| 
 | ||||
|   /* We don't bother to form the individual "smoothed" input pixel values;
 | ||||
|    * we can directly compute the output which is the average of the four | ||||
|    * smoothed values.  Each of the four member pixels contributes a fraction | ||||
|    * (1-8*SF) to its own smoothed image and a fraction SF to each of the three | ||||
|    * other smoothed pixels, therefore a total fraction (1-5*SF)/4 to the final | ||||
|    * output.  The four corner-adjacent neighbor pixels contribute a fraction | ||||
|    * SF to just one smoothed pixel, or SF/4 to the final output; while the | ||||
|    * eight edge-adjacent neighbors contribute SF to each of two smoothed | ||||
|    * pixels, or SF/2 overall.  In order to use integer arithmetic, these | ||||
|    * factors are scaled by 2^16 = 65536. | ||||
|    * Also recall that SF = smoothing_factor / 1024. | ||||
|    */ | ||||
| 
 | ||||
|   memberscale = 16384 - cinfo->smoothing_factor * 80; /* scaled (1-5*SF)/4 */ | ||||
|   neighscale = cinfo->smoothing_factor * 16; /* scaled SF/4 */ | ||||
| 
 | ||||
|   inrow = 0; | ||||
|   for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { | ||||
|     outptr = output_data[outrow]; | ||||
|     inptr0 = input_data[inrow]; | ||||
|     inptr1 = input_data[inrow+1]; | ||||
|     above_ptr = input_data[inrow-1]; | ||||
|     below_ptr = input_data[inrow+2]; | ||||
| 
 | ||||
|     /* Special case for first column: pretend column -1 is same as column 0 */ | ||||
|     membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + | ||||
| 		GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); | ||||
|     neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + | ||||
| 	       GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + | ||||
| 	       GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[2]) + | ||||
| 	       GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[2]); | ||||
|     neighsum += neighsum; | ||||
|     neighsum += GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[2]) + | ||||
| 		GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[2]); | ||||
|     membersum = membersum * memberscale + neighsum * neighscale; | ||||
|     *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); | ||||
|     inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; | ||||
| 
 | ||||
|     for (colctr = output_cols - 2; colctr > 0; colctr--) { | ||||
|       /* sum of pixels directly mapped to this output element */ | ||||
|       membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + | ||||
| 		  GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); | ||||
|       /* sum of edge-neighbor pixels */ | ||||
|       neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + | ||||
| 		 GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + | ||||
| 		 GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[2]) + | ||||
| 		 GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[2]); | ||||
|       /* The edge-neighbors count twice as much as corner-neighbors */ | ||||
|       neighsum += neighsum; | ||||
|       /* Add in the corner-neighbors */ | ||||
|       neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[2]) + | ||||
| 		  GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[2]); | ||||
|       /* form final output scaled up by 2^16 */ | ||||
|       membersum = membersum * memberscale + neighsum * neighscale; | ||||
|       /* round, descale and output it */ | ||||
|       *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); | ||||
|       inptr0 += 2; inptr1 += 2; above_ptr += 2; below_ptr += 2; | ||||
|     } | ||||
| 
 | ||||
|     /* Special case for last column */ | ||||
|     membersum = GETJSAMPLE(*inptr0) + GETJSAMPLE(inptr0[1]) + | ||||
| 		GETJSAMPLE(*inptr1) + GETJSAMPLE(inptr1[1]); | ||||
|     neighsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(above_ptr[1]) + | ||||
| 	       GETJSAMPLE(*below_ptr) + GETJSAMPLE(below_ptr[1]) + | ||||
| 	       GETJSAMPLE(inptr0[-1]) + GETJSAMPLE(inptr0[1]) + | ||||
| 	       GETJSAMPLE(inptr1[-1]) + GETJSAMPLE(inptr1[1]); | ||||
|     neighsum += neighsum; | ||||
|     neighsum += GETJSAMPLE(above_ptr[-1]) + GETJSAMPLE(above_ptr[1]) + | ||||
| 		GETJSAMPLE(below_ptr[-1]) + GETJSAMPLE(below_ptr[1]); | ||||
|     membersum = membersum * memberscale + neighsum * neighscale; | ||||
|     *outptr = (JSAMPLE) ((membersum + 32768) >> 16); | ||||
| 
 | ||||
|     inrow += 2; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Downsample pixel values of a single component. | ||||
|  * This version handles the special case of a full-size component, | ||||
|  * with smoothing.  One row of context is required. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| fullsize_smooth_downsample (j_compress_ptr cinfo, jpeg_component_info *compptr, | ||||
| 			    JSAMPARRAY input_data, JSAMPARRAY output_data) | ||||
| { | ||||
|   int outrow; | ||||
|   JDIMENSION colctr; | ||||
|   JDIMENSION output_cols = compptr->width_in_blocks * DCTSIZE; | ||||
|   register JSAMPROW inptr, above_ptr, below_ptr, outptr; | ||||
|   INT32 membersum, neighsum, memberscale, neighscale; | ||||
|   int colsum, lastcolsum, nextcolsum; | ||||
| 
 | ||||
|   /* Expand input data enough to let all the output samples be generated
 | ||||
|    * by the standard loop.  Special-casing padded output would be more | ||||
|    * efficient. | ||||
|    */ | ||||
|   expand_right_edge(input_data - 1, cinfo->max_v_samp_factor + 2, | ||||
| 		    cinfo->image_width, output_cols); | ||||
| 
 | ||||
|   /* Each of the eight neighbor pixels contributes a fraction SF to the
 | ||||
|    * smoothed pixel, while the main pixel contributes (1-8*SF).  In order | ||||
|    * to use integer arithmetic, these factors are multiplied by 2^16 = 65536. | ||||
|    * Also recall that SF = smoothing_factor / 1024. | ||||
|    */ | ||||
| 
 | ||||
|   memberscale = 65536L - cinfo->smoothing_factor * 512L; /* scaled 1-8*SF */ | ||||
|   neighscale = cinfo->smoothing_factor * 64; /* scaled SF */ | ||||
| 
 | ||||
|   for (outrow = 0; outrow < compptr->v_samp_factor; outrow++) { | ||||
|     outptr = output_data[outrow]; | ||||
|     inptr = input_data[outrow]; | ||||
|     above_ptr = input_data[outrow-1]; | ||||
|     below_ptr = input_data[outrow+1]; | ||||
| 
 | ||||
|     /* Special case for first column */ | ||||
|     colsum = GETJSAMPLE(*above_ptr++) + GETJSAMPLE(*below_ptr++) + | ||||
| 	     GETJSAMPLE(*inptr); | ||||
|     membersum = GETJSAMPLE(*inptr++); | ||||
|     nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + | ||||
| 		 GETJSAMPLE(*inptr); | ||||
|     neighsum = colsum + (colsum - membersum) + nextcolsum; | ||||
|     membersum = membersum * memberscale + neighsum * neighscale; | ||||
|     *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); | ||||
|     lastcolsum = colsum; colsum = nextcolsum; | ||||
| 
 | ||||
|     for (colctr = output_cols - 2; colctr > 0; colctr--) { | ||||
|       membersum = GETJSAMPLE(*inptr++); | ||||
|       above_ptr++; below_ptr++; | ||||
|       nextcolsum = GETJSAMPLE(*above_ptr) + GETJSAMPLE(*below_ptr) + | ||||
| 		   GETJSAMPLE(*inptr); | ||||
|       neighsum = lastcolsum + (colsum - membersum) + nextcolsum; | ||||
|       membersum = membersum * memberscale + neighsum * neighscale; | ||||
|       *outptr++ = (JSAMPLE) ((membersum + 32768) >> 16); | ||||
|       lastcolsum = colsum; colsum = nextcolsum; | ||||
|     } | ||||
| 
 | ||||
|     /* Special case for last column */ | ||||
|     membersum = GETJSAMPLE(*inptr); | ||||
|     neighsum = lastcolsum + (colsum - membersum) + colsum; | ||||
|     membersum = membersum * memberscale + neighsum * neighscale; | ||||
|     *outptr = (JSAMPLE) ((membersum + 32768) >> 16); | ||||
| 
 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| #endif /* INPUT_SMOOTHING_SUPPORTED */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Module initialization routine for downsampling. | ||||
|  * Note that we must select a routine for each component. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jinit_downsampler (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_downsample_ptr downsample; | ||||
|   int ci; | ||||
|   jpeg_component_info * compptr; | ||||
|   boolean smoothok = TRUE; | ||||
| 
 | ||||
|   downsample = (my_downsample_ptr) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				SIZEOF(my_downsampler)); | ||||
|   cinfo->downsample = (struct jpeg_downsampler *) downsample; | ||||
|   downsample->pub.start_pass = start_pass_downsample; | ||||
|   downsample->pub.downsample = sep_downsample; | ||||
|   downsample->pub.need_context_rows = FALSE; | ||||
| 
 | ||||
|   if (cinfo->CCIR601_sampling) | ||||
|     ERREXIT(cinfo, JERR_CCIR601_NOTIMPL); | ||||
| 
 | ||||
|   /* Verify we can handle the sampling factors, and set up method pointers */ | ||||
|   for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components; | ||||
|        ci++, compptr++) { | ||||
|     if (compptr->h_samp_factor == cinfo->max_h_samp_factor && | ||||
| 	compptr->v_samp_factor == cinfo->max_v_samp_factor) { | ||||
| #ifdef INPUT_SMOOTHING_SUPPORTED | ||||
|       if (cinfo->smoothing_factor) { | ||||
| 	downsample->methods[ci] = fullsize_smooth_downsample; | ||||
| 	downsample->pub.need_context_rows = TRUE; | ||||
|       } else | ||||
| #endif | ||||
| 	downsample->methods[ci] = fullsize_downsample; | ||||
|     } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && | ||||
| 	       compptr->v_samp_factor == cinfo->max_v_samp_factor) { | ||||
|       smoothok = FALSE; | ||||
|       downsample->methods[ci] = h2v1_downsample; | ||||
|     } else if (compptr->h_samp_factor * 2 == cinfo->max_h_samp_factor && | ||||
| 	       compptr->v_samp_factor * 2 == cinfo->max_v_samp_factor) { | ||||
| #ifdef INPUT_SMOOTHING_SUPPORTED | ||||
|       if (cinfo->smoothing_factor) { | ||||
| 	downsample->methods[ci] = h2v2_smooth_downsample; | ||||
| 	downsample->pub.need_context_rows = TRUE; | ||||
|       } else | ||||
| #endif | ||||
| 	downsample->methods[ci] = h2v2_downsample; | ||||
|     } else if ((cinfo->max_h_samp_factor % compptr->h_samp_factor) == 0 && | ||||
| 	       (cinfo->max_v_samp_factor % compptr->v_samp_factor) == 0) { | ||||
|       smoothok = FALSE; | ||||
|       downsample->methods[ci] = int_downsample; | ||||
|     } else | ||||
|       ERREXIT(cinfo, JERR_FRACT_SAMPLE_NOTIMPL); | ||||
|   } | ||||
| 
 | ||||
| #ifdef INPUT_SMOOTHING_SUPPORTED | ||||
|   if (cinfo->smoothing_factor && !smoothok) | ||||
|     TRACEMS(cinfo, 0, JTRC_SMOOTH_NOTIMPL); | ||||
| #endif | ||||
| } | ||||
|  | @ -0,0 +1,388 @@ | |||
| /*
 | ||||
|  * jctrans.c | ||||
|  * | ||||
|  * Copyright (C) 1995-1998, 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 library routines for transcoding compression, | ||||
|  * that is, writing raw DCT coefficient arrays to an output JPEG file. | ||||
|  * The routines in jcapimin.c will also be needed by a transcoder. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Forward declarations */ | ||||
| LOCAL(void) transencode_master_selection | ||||
| 	JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); | ||||
| LOCAL(void) transencode_coef_controller | ||||
| 	JPP((j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays)); | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Compression initialization for writing raw-coefficient data. | ||||
|  * Before calling this, all parameters and a data destination must be set up. | ||||
|  * Call jpeg_finish_compress() to actually write the data. | ||||
|  * | ||||
|  * The number of passed virtual arrays must match cinfo->num_components. | ||||
|  * Note that the virtual arrays need not be filled or even realized at | ||||
|  * the time write_coefficients is called; indeed, if the virtual arrays | ||||
|  * were requested from this compression object's memory manager, they | ||||
|  * typically will be realized during this routine and filled afterwards. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_write_coefficients (j_compress_ptr cinfo, jvirt_barray_ptr * coef_arrays) | ||||
| { | ||||
|   if (cinfo->global_state != CSTATE_START) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   /* Mark all tables to be written */ | ||||
|   jpeg_suppress_tables(cinfo, FALSE); | ||||
|   /* (Re)initialize error mgr and destination modules */ | ||||
|   (*cinfo->err->reset_error_mgr) ((j_common_ptr) cinfo); | ||||
|   (*cinfo->dest->init_destination) (cinfo); | ||||
|   /* Perform master selection of active modules */ | ||||
|   transencode_master_selection(cinfo, coef_arrays); | ||||
|   /* Wait for jpeg_finish_compress() call */ | ||||
|   cinfo->next_scanline = 0;	/* so jpeg_write_marker works */ | ||||
|   cinfo->global_state = CSTATE_WRCOEFS; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize the compression object with default parameters, | ||||
|  * then copy from the source object all parameters needed for lossless | ||||
|  * transcoding.  Parameters that can be varied without loss (such as | ||||
|  * scan script and Huffman optimization) are left in their default states. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_copy_critical_parameters (j_decompress_ptr srcinfo, | ||||
| 			       j_compress_ptr dstinfo) | ||||
| { | ||||
|   JQUANT_TBL ** qtblptr; | ||||
|   jpeg_component_info *incomp, *outcomp; | ||||
|   JQUANT_TBL *c_quant, *slot_quant; | ||||
|   int tblno, ci, coefi; | ||||
| 
 | ||||
|   /* Safety check to ensure start_compress not called yet. */ | ||||
|   if (dstinfo->global_state != CSTATE_START) | ||||
|     ERREXIT1(dstinfo, JERR_BAD_STATE, dstinfo->global_state); | ||||
|   /* Copy fundamental image dimensions */ | ||||
|   dstinfo->image_width = srcinfo->image_width; | ||||
|   dstinfo->image_height = srcinfo->image_height; | ||||
|   dstinfo->input_components = srcinfo->num_components; | ||||
|   dstinfo->in_color_space = srcinfo->jpeg_color_space; | ||||
|   /* Initialize all parameters to default values */ | ||||
|   jpeg_set_defaults(dstinfo); | ||||
|   /* jpeg_set_defaults may choose wrong colorspace, eg YCbCr if input is RGB.
 | ||||
|    * Fix it to get the right header markers for the image colorspace. | ||||
|    */ | ||||
|   jpeg_set_colorspace(dstinfo, srcinfo->jpeg_color_space); | ||||
|   dstinfo->data_precision = srcinfo->data_precision; | ||||
|   dstinfo->CCIR601_sampling = srcinfo->CCIR601_sampling; | ||||
|   /* Copy the source's quantization tables. */ | ||||
|   for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) { | ||||
|     if (srcinfo->quant_tbl_ptrs[tblno] != NULL) { | ||||
|       qtblptr = & dstinfo->quant_tbl_ptrs[tblno]; | ||||
|       if (*qtblptr == NULL) | ||||
| 	*qtblptr = jpeg_alloc_quant_table((j_common_ptr) dstinfo); | ||||
|       MEMCOPY((*qtblptr)->quantval, | ||||
| 	      srcinfo->quant_tbl_ptrs[tblno]->quantval, | ||||
| 	      SIZEOF((*qtblptr)->quantval)); | ||||
|       (*qtblptr)->sent_table = FALSE; | ||||
|     } | ||||
|   } | ||||
|   /* Copy the source's per-component info.
 | ||||
|    * Note we assume jpeg_set_defaults has allocated the dest comp_info array. | ||||
|    */ | ||||
|   dstinfo->num_components = srcinfo->num_components; | ||||
|   if (dstinfo->num_components < 1 || dstinfo->num_components > MAX_COMPONENTS) | ||||
|     ERREXIT2(dstinfo, JERR_COMPONENT_COUNT, dstinfo->num_components, | ||||
| 	     MAX_COMPONENTS); | ||||
|   for (ci = 0, incomp = srcinfo->comp_info, outcomp = dstinfo->comp_info; | ||||
|        ci < dstinfo->num_components; ci++, incomp++, outcomp++) { | ||||
|     outcomp->component_id = incomp->component_id; | ||||
|     outcomp->h_samp_factor = incomp->h_samp_factor; | ||||
|     outcomp->v_samp_factor = incomp->v_samp_factor; | ||||
|     outcomp->quant_tbl_no = incomp->quant_tbl_no; | ||||
|     /* Make sure saved quantization table for component matches the qtable
 | ||||
|      * slot.  If not, the input file re-used this qtable slot. | ||||
|      * IJG encoder currently cannot duplicate this. | ||||
|      */ | ||||
|     tblno = outcomp->quant_tbl_no; | ||||
|     if (tblno < 0 || tblno >= NUM_QUANT_TBLS || | ||||
| 	srcinfo->quant_tbl_ptrs[tblno] == NULL) | ||||
|       ERREXIT1(dstinfo, JERR_NO_QUANT_TABLE, tblno); | ||||
|     slot_quant = srcinfo->quant_tbl_ptrs[tblno]; | ||||
|     c_quant = incomp->quant_table; | ||||
|     if (c_quant != NULL) { | ||||
|       for (coefi = 0; coefi < DCTSIZE2; coefi++) { | ||||
| 	if (c_quant->quantval[coefi] != slot_quant->quantval[coefi]) | ||||
| 	  ERREXIT1(dstinfo, JERR_MISMATCHED_QUANT_TABLE, tblno); | ||||
|       } | ||||
|     } | ||||
|     /* Note: we do not copy the source's Huffman table assignments;
 | ||||
|      * instead we rely on jpeg_set_colorspace to have made a suitable choice. | ||||
|      */ | ||||
|   } | ||||
|   /* Also copy JFIF version and resolution information, if available.
 | ||||
|    * Strictly speaking this isn't "critical" info, but it's nearly | ||||
|    * always appropriate to copy it if available.  In particular, | ||||
|    * if the application chooses to copy JFIF 1.02 extension markers from | ||||
|    * the source file, we need to copy the version to make sure we don't | ||||
|    * emit a file that has 1.02 extensions but a claimed version of 1.01. | ||||
|    * We will *not*, however, copy version info from mislabeled "2.01" files. | ||||
|    */ | ||||
|   if (srcinfo->saw_JFIF_marker) { | ||||
|     if (srcinfo->JFIF_major_version == 1) { | ||||
|       dstinfo->JFIF_major_version = srcinfo->JFIF_major_version; | ||||
|       dstinfo->JFIF_minor_version = srcinfo->JFIF_minor_version; | ||||
|     } | ||||
|     dstinfo->density_unit = srcinfo->density_unit; | ||||
|     dstinfo->X_density = srcinfo->X_density; | ||||
|     dstinfo->Y_density = srcinfo->Y_density; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Master selection of compression modules for transcoding. | ||||
|  * This substitutes for jcinit.c's initialization of the full compressor. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| transencode_master_selection (j_compress_ptr cinfo, | ||||
| 			      jvirt_barray_ptr * coef_arrays) | ||||
| { | ||||
|   /* Although we don't actually use input_components for transcoding,
 | ||||
|    * jcmaster.c's initial_setup will complain if input_components is 0. | ||||
|    */ | ||||
|   cinfo->input_components = 1; | ||||
|   /* Initialize master control (includes parameter checking/processing) */ | ||||
|   jinit_c_master_control(cinfo, TRUE /* transcode only */); | ||||
| 
 | ||||
|   /* Entropy encoding: either Huffman or arithmetic coding. */ | ||||
|   if (cinfo->arith_code) { | ||||
|     ERREXIT(cinfo, JERR_ARITH_NOTIMPL); | ||||
|   } else { | ||||
|     if (cinfo->progressive_mode) { | ||||
| #ifdef C_PROGRESSIVE_SUPPORTED | ||||
|       jinit_phuff_encoder(cinfo); | ||||
| #else | ||||
|       ERREXIT(cinfo, JERR_NOT_COMPILED); | ||||
| #endif | ||||
|     } else | ||||
|       jinit_huff_encoder(cinfo); | ||||
|   } | ||||
| 
 | ||||
|   /* We need a special coefficient buffer controller. */ | ||||
|   transencode_coef_controller(cinfo, coef_arrays); | ||||
| 
 | ||||
|   jinit_marker_writer(cinfo); | ||||
| 
 | ||||
|   /* We can now tell the memory manager to allocate virtual arrays. */ | ||||
|   (*cinfo->mem->realize_virt_arrays) ((j_common_ptr) cinfo); | ||||
| 
 | ||||
|   /* Write the datastream header (SOI, JFIF) immediately.
 | ||||
|    * Frame and scan headers are postponed till later. | ||||
|    * This lets application insert special markers after the SOI. | ||||
|    */ | ||||
|   (*cinfo->marker->write_file_header) (cinfo); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * The rest of this file is a special implementation of the coefficient | ||||
|  * buffer controller.  This is similar to jccoefct.c, but it handles only | ||||
|  * output from presupplied virtual arrays.  Furthermore, we generate any | ||||
|  * dummy padding blocks on-the-fly rather than expecting them to be present | ||||
|  * in the arrays. | ||||
|  */ | ||||
| 
 | ||||
| /* Private buffer controller object */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_c_coef_controller pub; /* public fields */ | ||||
| 
 | ||||
|   JDIMENSION iMCU_row_num;	/* iMCU row # within image */ | ||||
|   JDIMENSION mcu_ctr;		/* counts MCUs processed in current row */ | ||||
|   int MCU_vert_offset;		/* counts MCU rows within iMCU row */ | ||||
|   int MCU_rows_per_iMCU_row;	/* number of such rows needed */ | ||||
| 
 | ||||
|   /* Virtual block array for each component. */ | ||||
|   jvirt_barray_ptr * whole_image; | ||||
| 
 | ||||
|   /* Workspace for constructing dummy blocks at right/bottom edges. */ | ||||
|   JBLOCKROW dummy_buffer[C_MAX_BLOCKS_IN_MCU]; | ||||
| } my_coef_controller; | ||||
| 
 | ||||
| typedef my_coef_controller * my_coef_ptr; | ||||
| 
 | ||||
| 
 | ||||
| LOCAL(void) | ||||
| start_iMCU_row (j_compress_ptr cinfo) | ||||
| /* Reset within-iMCU-row counters for a new row */ | ||||
| { | ||||
|   my_coef_ptr coef = (my_coef_ptr) cinfo->coef; | ||||
| 
 | ||||
|   /* In an interleaved scan, an MCU row is the same as an iMCU row.
 | ||||
|    * In a noninterleaved scan, an iMCU row has v_samp_factor MCU rows. | ||||
|    * But at the bottom of the image, process only what's left. | ||||
|    */ | ||||
|   if (cinfo->comps_in_scan > 1) { | ||||
|     coef->MCU_rows_per_iMCU_row = 1; | ||||
|   } else { | ||||
|     if (coef->iMCU_row_num < (cinfo->total_iMCU_rows-1)) | ||||
|       coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->v_samp_factor; | ||||
|     else | ||||
|       coef->MCU_rows_per_iMCU_row = cinfo->cur_comp_info[0]->last_row_height; | ||||
|   } | ||||
| 
 | ||||
|   coef->mcu_ctr = 0; | ||||
|   coef->MCU_vert_offset = 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize for a processing pass. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| start_pass_coef (j_compress_ptr cinfo, J_BUF_MODE pass_mode) | ||||
| { | ||||
|   my_coef_ptr coef = (my_coef_ptr) cinfo->coef; | ||||
| 
 | ||||
|   if (pass_mode != JBUF_CRANK_DEST) | ||||
|     ERREXIT(cinfo, JERR_BAD_BUFFER_MODE); | ||||
| 
 | ||||
|   coef->iMCU_row_num = 0; | ||||
|   start_iMCU_row(cinfo); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Process some data. | ||||
|  * We process the equivalent of one fully interleaved MCU row ("iMCU" row) | ||||
|  * per call, ie, v_samp_factor block rows for each component in the scan. | ||||
|  * The data is obtained from the virtual arrays and fed to the entropy coder. | ||||
|  * Returns TRUE if the iMCU row is completed, FALSE if suspended. | ||||
|  * | ||||
|  * NB: input_buf is ignored; it is likely to be a NULL pointer. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(boolean) | ||||
| compress_output (j_compress_ptr cinfo, JSAMPIMAGE input_buf) | ||||
| { | ||||
|   my_coef_ptr coef = (my_coef_ptr) cinfo->coef; | ||||
|   JDIMENSION MCU_col_num;	/* index of current MCU within row */ | ||||
|   JDIMENSION last_MCU_col = cinfo->MCUs_per_row - 1; | ||||
|   JDIMENSION last_iMCU_row = cinfo->total_iMCU_rows - 1; | ||||
|   int blkn, ci, xindex, yindex, yoffset, blockcnt; | ||||
|   JDIMENSION start_col; | ||||
|   JBLOCKARRAY buffer[MAX_COMPS_IN_SCAN]; | ||||
|   JBLOCKROW MCU_buffer[C_MAX_BLOCKS_IN_MCU]; | ||||
|   JBLOCKROW buffer_ptr; | ||||
|   jpeg_component_info *compptr; | ||||
| 
 | ||||
|   /* Align the virtual buffers for the components used in this scan. */ | ||||
|   for (ci = 0; ci < cinfo->comps_in_scan; ci++) { | ||||
|     compptr = cinfo->cur_comp_info[ci]; | ||||
|     buffer[ci] = (*cinfo->mem->access_virt_barray) | ||||
|       ((j_common_ptr) cinfo, coef->whole_image[compptr->component_index], | ||||
|        coef->iMCU_row_num * compptr->v_samp_factor, | ||||
|        (JDIMENSION) compptr->v_samp_factor, FALSE); | ||||
|   } | ||||
| 
 | ||||
|   /* Loop to process one whole iMCU row */ | ||||
|   for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row; | ||||
|        yoffset++) { | ||||
|     for (MCU_col_num = coef->mcu_ctr; MCU_col_num < cinfo->MCUs_per_row; | ||||
| 	 MCU_col_num++) { | ||||
|       /* Construct list of pointers to DCT blocks belonging to this MCU */ | ||||
|       blkn = 0;			/* index of current DCT block within MCU */ | ||||
|       for (ci = 0; ci < cinfo->comps_in_scan; ci++) { | ||||
| 	compptr = cinfo->cur_comp_info[ci]; | ||||
| 	start_col = MCU_col_num * compptr->MCU_width; | ||||
| 	blockcnt = (MCU_col_num < last_MCU_col) ? compptr->MCU_width | ||||
| 						: compptr->last_col_width; | ||||
| 	for (yindex = 0; yindex < compptr->MCU_height; yindex++) { | ||||
| 	  if (coef->iMCU_row_num < last_iMCU_row || | ||||
| 	      yindex+yoffset < compptr->last_row_height) { | ||||
| 	    /* Fill in pointers to real blocks in this row */ | ||||
| 	    buffer_ptr = buffer[ci][yindex+yoffset] + start_col; | ||||
| 	    for (xindex = 0; xindex < blockcnt; xindex++) | ||||
| 	      MCU_buffer[blkn++] = buffer_ptr++; | ||||
| 	  } else { | ||||
| 	    /* At bottom of image, need a whole row of dummy blocks */ | ||||
| 	    xindex = 0; | ||||
| 	  } | ||||
| 	  /* Fill in any dummy blocks needed in this row.
 | ||||
| 	   * Dummy blocks are filled in the same way as in jccoefct.c: | ||||
| 	   * all zeroes in the AC entries, DC entries equal to previous | ||||
| 	   * block's DC value.  The init routine has already zeroed the | ||||
| 	   * AC entries, so we need only set the DC entries correctly. | ||||
| 	   */ | ||||
| 	  for (; xindex < compptr->MCU_width; xindex++) { | ||||
| 	    MCU_buffer[blkn] = coef->dummy_buffer[blkn]; | ||||
| 	    MCU_buffer[blkn][0][0] = MCU_buffer[blkn-1][0][0]; | ||||
| 	    blkn++; | ||||
| 	  } | ||||
| 	} | ||||
|       } | ||||
|       /* Try to write the MCU. */ | ||||
|       if (! (*cinfo->entropy->encode_mcu) (cinfo, MCU_buffer)) { | ||||
| 	/* Suspension forced; update state counters and exit */ | ||||
| 	coef->MCU_vert_offset = yoffset; | ||||
| 	coef->mcu_ctr = MCU_col_num; | ||||
| 	return FALSE; | ||||
|       } | ||||
|     } | ||||
|     /* Completed an MCU row, but perhaps not an iMCU row */ | ||||
|     coef->mcu_ctr = 0; | ||||
|   } | ||||
|   /* Completed the iMCU row, advance counters for next one */ | ||||
|   coef->iMCU_row_num++; | ||||
|   start_iMCU_row(cinfo); | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize coefficient buffer controller. | ||||
|  * | ||||
|  * Each passed coefficient array must be the right size for that | ||||
|  * coefficient: width_in_blocks wide and height_in_blocks high, | ||||
|  * with unitheight at least v_samp_factor. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| transencode_coef_controller (j_compress_ptr cinfo, | ||||
| 			     jvirt_barray_ptr * coef_arrays) | ||||
| { | ||||
|   my_coef_ptr coef; | ||||
|   JBLOCKROW buffer; | ||||
|   int i; | ||||
| 
 | ||||
|   coef = (my_coef_ptr) | ||||
|     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				SIZEOF(my_coef_controller)); | ||||
|   cinfo->coef = (struct jpeg_c_coef_controller *) coef; | ||||
|   coef->pub.start_pass = start_pass_coef; | ||||
|   coef->pub.compress_data = compress_output; | ||||
| 
 | ||||
|   /* Save pointer to virtual arrays */ | ||||
|   coef->whole_image = coef_arrays; | ||||
| 
 | ||||
|   /* Allocate and pre-zero space for dummy DCT blocks. */ | ||||
|   buffer = (JBLOCKROW) | ||||
|     (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); | ||||
|   jzero_far((void FAR *) buffer, C_MAX_BLOCKS_IN_MCU * SIZEOF(JBLOCK)); | ||||
|   for (i = 0; i < C_MAX_BLOCKS_IN_MCU; i++) { | ||||
|     coef->dummy_buffer[i] = buffer + i; | ||||
|   } | ||||
| } | ||||
|  | @ -0,0 +1,395 @@ | |||
| /*
 | ||||
|  * jdapimin.c | ||||
|  * | ||||
|  * Copyright (C) 1994-1998, 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 application interface code for the decompression half | ||||
|  * of the JPEG library.  These are the "minimum" API routines that may be | ||||
|  * needed in either the normal full-decompression case or the | ||||
|  * transcoding-only case. | ||||
|  * | ||||
|  * Most of the routines intended to be called directly by an application | ||||
|  * are in this file or in jdapistd.c.  But also see jcomapi.c for routines | ||||
|  * shared by compression and decompression, and jdtrans.c for the transcoding | ||||
|  * case. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialization of a JPEG decompression object. | ||||
|  * The error manager must already be set up (in case memory manager fails). | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_CreateDecompress (j_decompress_ptr cinfo, int version, size_t structsize) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   /* Guard against version mismatches between library and caller. */ | ||||
|   cinfo->mem = NULL;		/* so jpeg_destroy knows mem mgr not called */ | ||||
|   if (version != JPEG_LIB_VERSION) | ||||
|     ERREXIT2(cinfo, JERR_BAD_LIB_VERSION, JPEG_LIB_VERSION, version); | ||||
|   if (structsize != SIZEOF(struct jpeg_decompress_struct)) | ||||
|     ERREXIT2(cinfo, JERR_BAD_STRUCT_SIZE,  | ||||
| 	     (int) SIZEOF(struct jpeg_decompress_struct), (int) structsize); | ||||
| 
 | ||||
|   /* For debugging purposes, we zero the whole master structure.
 | ||||
|    * But the application has already set the err pointer, and may have set | ||||
|    * client_data, so we have to save and restore those fields. | ||||
|    * Note: if application hasn't set client_data, tools like Purify may | ||||
|    * complain here. | ||||
|    */ | ||||
|   { | ||||
|     struct jpeg_error_mgr * err = cinfo->err; | ||||
|     void * client_data = cinfo->client_data; /* ignore Purify complaint here */ | ||||
|     MEMZERO(cinfo, SIZEOF(struct jpeg_decompress_struct)); | ||||
|     cinfo->err = err; | ||||
|     cinfo->client_data = client_data; | ||||
|   } | ||||
|   cinfo->is_decompressor = TRUE; | ||||
| 
 | ||||
|   /* Initialize a memory manager instance for this object */ | ||||
|   jinit_memory_mgr((j_common_ptr) cinfo); | ||||
| 
 | ||||
|   /* Zero out pointers to permanent structures. */ | ||||
|   cinfo->progress = NULL; | ||||
|   cinfo->src = NULL; | ||||
| 
 | ||||
|   for (i = 0; i < NUM_QUANT_TBLS; i++) | ||||
|     cinfo->quant_tbl_ptrs[i] = NULL; | ||||
| 
 | ||||
|   for (i = 0; i < NUM_HUFF_TBLS; i++) { | ||||
|     cinfo->dc_huff_tbl_ptrs[i] = NULL; | ||||
|     cinfo->ac_huff_tbl_ptrs[i] = NULL; | ||||
|   } | ||||
| 
 | ||||
|   /* Initialize marker processor so application can override methods
 | ||||
|    * for COM, APPn markers before calling jpeg_read_header. | ||||
|    */ | ||||
|   cinfo->marker_list = NULL; | ||||
|   jinit_marker_reader(cinfo); | ||||
| 
 | ||||
|   /* And initialize the overall input controller. */ | ||||
|   jinit_input_controller(cinfo); | ||||
| 
 | ||||
|   /* OK, I'm ready */ | ||||
|   cinfo->global_state = DSTATE_START; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Destruction of a JPEG decompression object | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_destroy_decompress (j_decompress_ptr cinfo) | ||||
| { | ||||
|   jpeg_destroy((j_common_ptr) cinfo); /* use common routine */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Abort processing of a JPEG decompression operation, | ||||
|  * but don't destroy the object itself. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_abort_decompress (j_decompress_ptr cinfo) | ||||
| { | ||||
|   jpeg_abort((j_common_ptr) cinfo); /* use common routine */ | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Set default decompression parameters. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(void) | ||||
| default_decompress_parms (j_decompress_ptr cinfo) | ||||
| { | ||||
|   /* Guess the input colorspace, and set output colorspace accordingly. */ | ||||
|   /* (Wish JPEG committee had provided a real way to specify this...) */ | ||||
|   /* Note application may override our guesses. */ | ||||
|   switch (cinfo->num_components) { | ||||
|   case 1: | ||||
|     cinfo->jpeg_color_space = JCS_GRAYSCALE; | ||||
|     cinfo->out_color_space = JCS_GRAYSCALE; | ||||
|     break; | ||||
|      | ||||
|   case 3: | ||||
|     if (cinfo->saw_JFIF_marker) { | ||||
|       cinfo->jpeg_color_space = JCS_YCbCr; /* JFIF implies YCbCr */ | ||||
|     } else if (cinfo->saw_Adobe_marker) { | ||||
|       switch (cinfo->Adobe_transform) { | ||||
|       case 0: | ||||
| 	cinfo->jpeg_color_space = JCS_RGB; | ||||
| 	break; | ||||
|       case 1: | ||||
| 	cinfo->jpeg_color_space = JCS_YCbCr; | ||||
| 	break; | ||||
|       default: | ||||
| 	WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); | ||||
| 	cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ | ||||
| 	break; | ||||
|       } | ||||
|     } else { | ||||
|       /* Saw no special markers, try to guess from the component IDs */ | ||||
|       int cid0 = cinfo->comp_info[0].component_id; | ||||
|       int cid1 = cinfo->comp_info[1].component_id; | ||||
|       int cid2 = cinfo->comp_info[2].component_id; | ||||
| 
 | ||||
|       if (cid0 == 1 && cid1 == 2 && cid2 == 3) | ||||
| 	cinfo->jpeg_color_space = JCS_YCbCr; /* assume JFIF w/out marker */ | ||||
|       else if (cid0 == 82 && cid1 == 71 && cid2 == 66) | ||||
| 	cinfo->jpeg_color_space = JCS_RGB; /* ASCII 'R', 'G', 'B' */ | ||||
|       else { | ||||
| 	TRACEMS3(cinfo, 1, JTRC_UNKNOWN_IDS, cid0, cid1, cid2); | ||||
| 	cinfo->jpeg_color_space = JCS_YCbCr; /* assume it's YCbCr */ | ||||
|       } | ||||
|     } | ||||
|     /* Always guess RGB is proper output colorspace. */ | ||||
|     cinfo->out_color_space = JCS_RGB; | ||||
|     break; | ||||
|      | ||||
|   case 4: | ||||
|     if (cinfo->saw_Adobe_marker) { | ||||
|       switch (cinfo->Adobe_transform) { | ||||
|       case 0: | ||||
| 	cinfo->jpeg_color_space = JCS_CMYK; | ||||
| 	break; | ||||
|       case 2: | ||||
| 	cinfo->jpeg_color_space = JCS_YCCK; | ||||
| 	break; | ||||
|       default: | ||||
| 	WARNMS1(cinfo, JWRN_ADOBE_XFORM, cinfo->Adobe_transform); | ||||
| 	cinfo->jpeg_color_space = JCS_YCCK; /* assume it's YCCK */ | ||||
| 	break; | ||||
|       } | ||||
|     } else { | ||||
|       /* No special markers, assume straight CMYK. */ | ||||
|       cinfo->jpeg_color_space = JCS_CMYK; | ||||
|     } | ||||
|     cinfo->out_color_space = JCS_CMYK; | ||||
|     break; | ||||
|      | ||||
|   default: | ||||
|     cinfo->jpeg_color_space = JCS_UNKNOWN; | ||||
|     cinfo->out_color_space = JCS_UNKNOWN; | ||||
|     break; | ||||
|   } | ||||
| 
 | ||||
|   /* Set defaults for other decompression parameters. */ | ||||
|   cinfo->scale_num = 1;		/* 1:1 scaling */ | ||||
|   cinfo->scale_denom = 1; | ||||
|   cinfo->output_gamma = 1.0; | ||||
|   cinfo->buffered_image = FALSE; | ||||
|   cinfo->raw_data_out = FALSE; | ||||
|   cinfo->dct_method = JDCT_DEFAULT; | ||||
|   cinfo->do_fancy_upsampling = TRUE; | ||||
|   cinfo->do_block_smoothing = TRUE; | ||||
|   cinfo->quantize_colors = FALSE; | ||||
|   /* We set these in case application only sets quantize_colors. */ | ||||
|   cinfo->dither_mode = JDITHER_FS; | ||||
| #ifdef QUANT_2PASS_SUPPORTED | ||||
|   cinfo->two_pass_quantize = TRUE; | ||||
| #else | ||||
|   cinfo->two_pass_quantize = FALSE; | ||||
| #endif | ||||
|   cinfo->desired_number_of_colors = 256; | ||||
|   cinfo->colormap = NULL; | ||||
|   /* Initialize for no mode change in buffered-image mode. */ | ||||
|   cinfo->enable_1pass_quant = FALSE; | ||||
|   cinfo->enable_external_quant = FALSE; | ||||
|   cinfo->enable_2pass_quant = FALSE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Decompression startup: read start of JPEG datastream to see what's there. | ||||
|  * Need only initialize JPEG object and supply a data source before calling. | ||||
|  * | ||||
|  * This routine will read as far as the first SOS marker (ie, actual start of | ||||
|  * compressed data), and will save all tables and parameters in the JPEG | ||||
|  * object.  It will also initialize the decompression parameters to default | ||||
|  * values, and finally return JPEG_HEADER_OK.  On return, the application may | ||||
|  * adjust the decompression parameters and then call jpeg_start_decompress. | ||||
|  * (Or, if the application only wanted to determine the image parameters, | ||||
|  * the data need not be decompressed.  In that case, call jpeg_abort or | ||||
|  * jpeg_destroy to release any temporary space.) | ||||
|  * If an abbreviated (tables only) datastream is presented, the routine will | ||||
|  * return JPEG_HEADER_TABLES_ONLY upon reaching EOI.  The application may then | ||||
|  * re-use the JPEG object to read the abbreviated image datastream(s). | ||||
|  * It is unnecessary (but OK) to call jpeg_abort in this case. | ||||
|  * The JPEG_SUSPENDED return code only occurs if the data source module | ||||
|  * requests suspension of the decompressor.  In this case the application | ||||
|  * should load more source data and then re-call jpeg_read_header to resume | ||||
|  * processing. | ||||
|  * If a non-suspending data source is used and require_image is TRUE, then the | ||||
|  * return code need not be inspected since only JPEG_HEADER_OK is possible. | ||||
|  * | ||||
|  * This routine is now just a front end to jpeg_consume_input, with some | ||||
|  * extra error checking. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(int) | ||||
| jpeg_read_header (j_decompress_ptr cinfo, boolean require_image) | ||||
| { | ||||
|   int retcode; | ||||
| 
 | ||||
|   if (cinfo->global_state != DSTATE_START && | ||||
|       cinfo->global_state != DSTATE_INHEADER) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
| 
 | ||||
|   retcode = jpeg_consume_input(cinfo); | ||||
| 
 | ||||
|   switch (retcode) { | ||||
|   case JPEG_REACHED_SOS: | ||||
|     retcode = JPEG_HEADER_OK; | ||||
|     break; | ||||
|   case JPEG_REACHED_EOI: | ||||
|     if (require_image)		/* Complain if application wanted an image */ | ||||
|       ERREXIT(cinfo, JERR_NO_IMAGE); | ||||
|     /* Reset to start state; it would be safer to require the application to
 | ||||
|      * call jpeg_abort, but we can't change it now for compatibility reasons. | ||||
|      * A side effect is to free any temporary memory (there shouldn't be any). | ||||
|      */ | ||||
|     jpeg_abort((j_common_ptr) cinfo); /* sets state = DSTATE_START */ | ||||
|     retcode = JPEG_HEADER_TABLES_ONLY; | ||||
|     break; | ||||
|   case JPEG_SUSPENDED: | ||||
|     /* no work */ | ||||
|     break; | ||||
|   } | ||||
| 
 | ||||
|   return retcode; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Consume data in advance of what the decompressor requires. | ||||
|  * This can be called at any time once the decompressor object has | ||||
|  * been created and a data source has been set up. | ||||
|  * | ||||
|  * This routine is essentially a state machine that handles a couple | ||||
|  * of critical state-transition actions, namely initial setup and | ||||
|  * transition from header scanning to ready-for-start_decompress. | ||||
|  * All the actual input is done via the input controller's consume_input | ||||
|  * method. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(int) | ||||
| jpeg_consume_input (j_decompress_ptr cinfo) | ||||
| { | ||||
|   int retcode = JPEG_SUSPENDED; | ||||
| 
 | ||||
|   /* NB: every possible DSTATE value should be listed in this switch */ | ||||
|   switch (cinfo->global_state) { | ||||
|   case DSTATE_START: | ||||
|     /* Start-of-datastream actions: reset appropriate modules */ | ||||
|     (*cinfo->inputctl->reset_input_controller) (cinfo); | ||||
|     /* Initialize application's data source module */ | ||||
|     (*cinfo->src->init_source) (cinfo); | ||||
|     cinfo->global_state = DSTATE_INHEADER; | ||||
|     /*FALLTHROUGH*/ | ||||
|   case DSTATE_INHEADER: | ||||
|     retcode = (*cinfo->inputctl->consume_input) (cinfo); | ||||
|     if (retcode == JPEG_REACHED_SOS) { /* Found SOS, prepare to decompress */ | ||||
|       /* Set up default parameters based on header data */ | ||||
|       default_decompress_parms(cinfo); | ||||
|       /* Set global state: ready for start_decompress */ | ||||
|       cinfo->global_state = DSTATE_READY; | ||||
|     } | ||||
|     break; | ||||
|   case DSTATE_READY: | ||||
|     /* Can't advance past first SOS until start_decompress is called */ | ||||
|     retcode = JPEG_REACHED_SOS; | ||||
|     break; | ||||
|   case DSTATE_PRELOAD: | ||||
|   case DSTATE_PRESCAN: | ||||
|   case DSTATE_SCANNING: | ||||
|   case DSTATE_RAW_OK: | ||||
|   case DSTATE_BUFIMAGE: | ||||
|   case DSTATE_BUFPOST: | ||||
|   case DSTATE_STOPPING: | ||||
|     retcode = (*cinfo->inputctl->consume_input) (cinfo); | ||||
|     break; | ||||
|   default: | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   } | ||||
|   return retcode; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Have we finished reading the input file? | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(boolean) | ||||
| jpeg_input_complete (j_decompress_ptr cinfo) | ||||
| { | ||||
|   /* Check for valid jpeg object */ | ||||
|   if (cinfo->global_state < DSTATE_START || | ||||
|       cinfo->global_state > DSTATE_STOPPING) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   return cinfo->inputctl->eoi_reached; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Is there more than one scan? | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(boolean) | ||||
| jpeg_has_multiple_scans (j_decompress_ptr cinfo) | ||||
| { | ||||
|   /* Only valid after jpeg_read_header completes */ | ||||
|   if (cinfo->global_state < DSTATE_READY || | ||||
|       cinfo->global_state > DSTATE_STOPPING) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   return cinfo->inputctl->has_multiple_scans; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Finish JPEG decompression. | ||||
|  * | ||||
|  * This will normally just verify the file trailer and release temp storage. | ||||
|  * | ||||
|  * Returns FALSE if suspended.  The return value need be inspected only if | ||||
|  * a suspending data source is used. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(boolean) | ||||
| jpeg_finish_decompress (j_decompress_ptr cinfo) | ||||
| { | ||||
|   if ((cinfo->global_state == DSTATE_SCANNING || | ||||
|        cinfo->global_state == DSTATE_RAW_OK) && ! cinfo->buffered_image) { | ||||
|     /* Terminate final pass of non-buffered mode */ | ||||
|     if (cinfo->output_scanline < cinfo->output_height) | ||||
|       ERREXIT(cinfo, JERR_TOO_LITTLE_DATA); | ||||
|     (*cinfo->master->finish_output_pass) (cinfo); | ||||
|     cinfo->global_state = DSTATE_STOPPING; | ||||
|   } else if (cinfo->global_state == DSTATE_BUFIMAGE) { | ||||
|     /* Finishing after a buffered-image operation */ | ||||
|     cinfo->global_state = DSTATE_STOPPING; | ||||
|   } else if (cinfo->global_state != DSTATE_STOPPING) { | ||||
|     /* STOPPING = repeat call after a suspension, anything else is error */ | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   } | ||||
|   /* Read until EOI */ | ||||
|   while (! cinfo->inputctl->eoi_reached) { | ||||
|     if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) | ||||
|       return FALSE;		/* Suspend, come back later */ | ||||
|   } | ||||
|   /* Do final cleanup */ | ||||
|   (*cinfo->src->term_source) (cinfo); | ||||
|   /* We can use jpeg_abort to release memory and reset global_state */ | ||||
|   jpeg_abort((j_common_ptr) cinfo); | ||||
|   return TRUE; | ||||
| } | ||||
|  | @ -0,0 +1,275 @@ | |||
| /*
 | ||||
|  * jdapistd.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 application interface code for the decompression half | ||||
|  * of the JPEG library.  These are the "standard" API routines that are | ||||
|  * used in the normal full-decompression case.  They are not used by a | ||||
|  * transcoding-only application.  Note that if an application links in | ||||
|  * jpeg_start_decompress, it will end up linking in the entire decompressor. | ||||
|  * We thus must separate this file from jdapimin.c to avoid linking the | ||||
|  * whole decompression library into a transcoder. | ||||
|  */ | ||||
| 
 | ||||
| #define JPEG_INTERNALS | ||||
| #include "jinclude.h" | ||||
| #include "jpeglib.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Forward declarations */ | ||||
| LOCAL(boolean) output_pass_setup JPP((j_decompress_ptr cinfo)); | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Decompression initialization. | ||||
|  * jpeg_read_header must be completed before calling this. | ||||
|  * | ||||
|  * If a multipass operating mode was selected, this will do all but the | ||||
|  * last pass, and thus may take a great deal of time. | ||||
|  * | ||||
|  * Returns FALSE if suspended.  The return value need be inspected only if | ||||
|  * a suspending data source is used. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(boolean) | ||||
| jpeg_start_decompress (j_decompress_ptr cinfo) | ||||
| { | ||||
|   if (cinfo->global_state == DSTATE_READY) { | ||||
|     /* First call: initialize master control, select active modules */ | ||||
|     jinit_master_decompress(cinfo); | ||||
|     if (cinfo->buffered_image) { | ||||
|       /* No more work here; expecting jpeg_start_output next */ | ||||
|       cinfo->global_state = DSTATE_BUFIMAGE; | ||||
|       return TRUE; | ||||
|     } | ||||
|     cinfo->global_state = DSTATE_PRELOAD; | ||||
|   } | ||||
|   if (cinfo->global_state == DSTATE_PRELOAD) { | ||||
|     /* If file has multiple scans, absorb them all into the coef buffer */ | ||||
|     if (cinfo->inputctl->has_multiple_scans) { | ||||
| #ifdef D_MULTISCAN_FILES_SUPPORTED | ||||
|       for (;;) { | ||||
| 	int retcode; | ||||
| 	/* Call progress monitor hook if present */ | ||||
| 	if (cinfo->progress != NULL) | ||||
| 	  (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); | ||||
| 	/* Absorb some more input */ | ||||
| 	retcode = (*cinfo->inputctl->consume_input) (cinfo); | ||||
| 	if (retcode == JPEG_SUSPENDED) | ||||
| 	  return FALSE; | ||||
| 	if (retcode == JPEG_REACHED_EOI) | ||||
| 	  break; | ||||
| 	/* Advance progress counter if appropriate */ | ||||
| 	if (cinfo->progress != NULL && | ||||
| 	    (retcode == JPEG_ROW_COMPLETED || retcode == JPEG_REACHED_SOS)) { | ||||
| 	  if (++cinfo->progress->pass_counter >= cinfo->progress->pass_limit) { | ||||
| 	    /* jdmaster underestimated number of scans; ratchet up one scan */ | ||||
| 	    cinfo->progress->pass_limit += (long) cinfo->total_iMCU_rows; | ||||
| 	  } | ||||
| 	} | ||||
|       } | ||||
| #else | ||||
|       ERREXIT(cinfo, JERR_NOT_COMPILED); | ||||
| #endif /* D_MULTISCAN_FILES_SUPPORTED */ | ||||
|     } | ||||
|     cinfo->output_scan_number = cinfo->input_scan_number; | ||||
|   } else if (cinfo->global_state != DSTATE_PRESCAN) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   /* Perform any dummy output passes, and set up for the final pass */ | ||||
|   return output_pass_setup(cinfo); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Set up for an output pass, and perform any dummy pass(es) needed. | ||||
|  * Common subroutine for jpeg_start_decompress and jpeg_start_output. | ||||
|  * Entry: global_state = DSTATE_PRESCAN only if previously suspended. | ||||
|  * Exit: If done, returns TRUE and sets global_state for proper output mode. | ||||
|  *       If suspended, returns FALSE and sets global_state = DSTATE_PRESCAN. | ||||
|  */ | ||||
| 
 | ||||
| LOCAL(boolean) | ||||
| output_pass_setup (j_decompress_ptr cinfo) | ||||
| { | ||||
|   if (cinfo->global_state != DSTATE_PRESCAN) { | ||||
|     /* First call: do pass setup */ | ||||
|     (*cinfo->master->prepare_for_output_pass) (cinfo); | ||||
|     cinfo->output_scanline = 0; | ||||
|     cinfo->global_state = DSTATE_PRESCAN; | ||||
|   } | ||||
|   /* Loop over any required dummy passes */ | ||||
|   while (cinfo->master->is_dummy_pass) { | ||||
| #ifdef QUANT_2PASS_SUPPORTED | ||||
|     /* Crank through the dummy pass */ | ||||
|     while (cinfo->output_scanline < cinfo->output_height) { | ||||
|       JDIMENSION last_scanline; | ||||
|       /* Call progress monitor hook if present */ | ||||
|       if (cinfo->progress != NULL) { | ||||
| 	cinfo->progress->pass_counter = (long) cinfo->output_scanline; | ||||
| 	cinfo->progress->pass_limit = (long) cinfo->output_height; | ||||
| 	(*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); | ||||
|       } | ||||
|       /* Process some data */ | ||||
|       last_scanline = cinfo->output_scanline; | ||||
|       (*cinfo->main->process_data) (cinfo, (JSAMPARRAY) NULL, | ||||
| 				    &cinfo->output_scanline, (JDIMENSION) 0); | ||||
|       if (cinfo->output_scanline == last_scanline) | ||||
| 	return FALSE;		/* No progress made, must suspend */ | ||||
|     } | ||||
|     /* Finish up dummy pass, and set up for another one */ | ||||
|     (*cinfo->master->finish_output_pass) (cinfo); | ||||
|     (*cinfo->master->prepare_for_output_pass) (cinfo); | ||||
|     cinfo->output_scanline = 0; | ||||
| #else | ||||
|     ERREXIT(cinfo, JERR_NOT_COMPILED); | ||||
| #endif /* QUANT_2PASS_SUPPORTED */ | ||||
|   } | ||||
|   /* Ready for application to drive output pass through
 | ||||
|    * jpeg_read_scanlines or jpeg_read_raw_data. | ||||
|    */ | ||||
|   cinfo->global_state = cinfo->raw_data_out ? DSTATE_RAW_OK : DSTATE_SCANNING; | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Read some scanlines of data from the JPEG decompressor. | ||||
|  * | ||||
|  * The return value will be the number of lines actually read. | ||||
|  * This may be less than the number requested in several cases, | ||||
|  * including bottom of image, data source suspension, and operating | ||||
|  * modes that emit multiple scanlines at a time. | ||||
|  * | ||||
|  * Note: we warn about excess calls to jpeg_read_scanlines() since | ||||
|  * this likely signals an application programmer error.  However, | ||||
|  * an oversize buffer (max_lines > scanlines remaining) is not an error. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(JDIMENSION) | ||||
| jpeg_read_scanlines (j_decompress_ptr cinfo, JSAMPARRAY scanlines, | ||||
| 		     JDIMENSION max_lines) | ||||
| { | ||||
|   JDIMENSION row_ctr; | ||||
| 
 | ||||
|   if (cinfo->global_state != DSTATE_SCANNING) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   if (cinfo->output_scanline >= cinfo->output_height) { | ||||
|     WARNMS(cinfo, JWRN_TOO_MUCH_DATA); | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   /* Call progress monitor hook if present */ | ||||
|   if (cinfo->progress != NULL) { | ||||
|     cinfo->progress->pass_counter = (long) cinfo->output_scanline; | ||||
|     cinfo->progress->pass_limit = (long) cinfo->output_height; | ||||
|     (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); | ||||
|   } | ||||
| 
 | ||||
|   /* Process some data */ | ||||
|   row_ctr = 0; | ||||
|   (*cinfo->main->process_data) (cinfo, scanlines, &row_ctr, max_lines); | ||||
|   cinfo->output_scanline += row_ctr; | ||||
|   return row_ctr; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Alternate entry point to read raw data. | ||||
|  * Processes exactly one iMCU row per call, unless suspended. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(JDIMENSION) | ||||
| jpeg_read_raw_data (j_decompress_ptr cinfo, JSAMPIMAGE data, | ||||
| 		    JDIMENSION max_lines) | ||||
| { | ||||
|   JDIMENSION lines_per_iMCU_row; | ||||
| 
 | ||||
|   if (cinfo->global_state != DSTATE_RAW_OK) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   if (cinfo->output_scanline >= cinfo->output_height) { | ||||
|     WARNMS(cinfo, JWRN_TOO_MUCH_DATA); | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   /* Call progress monitor hook if present */ | ||||
|   if (cinfo->progress != NULL) { | ||||
|     cinfo->progress->pass_counter = (long) cinfo->output_scanline; | ||||
|     cinfo->progress->pass_limit = (long) cinfo->output_height; | ||||
|     (*cinfo->progress->progress_monitor) ((j_common_ptr) cinfo); | ||||
|   } | ||||
| 
 | ||||
|   /* Verify that at least one iMCU row can be returned. */ | ||||
|   lines_per_iMCU_row = cinfo->max_v_samp_factor * cinfo->min_DCT_scaled_size; | ||||
|   if (max_lines < lines_per_iMCU_row) | ||||
|     ERREXIT(cinfo, JERR_BUFFER_SIZE); | ||||
| 
 | ||||
|   /* Decompress directly into user's buffer. */ | ||||
|   if (! (*cinfo->coef->decompress_data) (cinfo, data)) | ||||
|     return 0;			/* suspension forced, can do nothing more */ | ||||
| 
 | ||||
|   /* OK, we processed one iMCU row. */ | ||||
|   cinfo->output_scanline += lines_per_iMCU_row; | ||||
|   return lines_per_iMCU_row; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Additional entry points for buffered-image mode. */ | ||||
| 
 | ||||
| #ifdef D_MULTISCAN_FILES_SUPPORTED | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize for an output pass in buffered-image mode. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(boolean) | ||||
| jpeg_start_output (j_decompress_ptr cinfo, int scan_number) | ||||
| { | ||||
|   if (cinfo->global_state != DSTATE_BUFIMAGE && | ||||
|       cinfo->global_state != DSTATE_PRESCAN) | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   /* Limit scan number to valid range */ | ||||
|   if (scan_number <= 0) | ||||
|     scan_number = 1; | ||||
|   if (cinfo->inputctl->eoi_reached && | ||||
|       scan_number > cinfo->input_scan_number) | ||||
|     scan_number = cinfo->input_scan_number; | ||||
|   cinfo->output_scan_number = scan_number; | ||||
|   /* Perform any dummy output passes, and set up for the real pass */ | ||||
|   return output_pass_setup(cinfo); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Finish up after an output pass in buffered-image mode. | ||||
|  * | ||||
|  * Returns FALSE if suspended.  The return value need be inspected only if | ||||
|  * a suspending data source is used. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(boolean) | ||||
| jpeg_finish_output (j_decompress_ptr cinfo) | ||||
| { | ||||
|   if ((cinfo->global_state == DSTATE_SCANNING || | ||||
|        cinfo->global_state == DSTATE_RAW_OK) && cinfo->buffered_image) { | ||||
|     /* Terminate this pass. */ | ||||
|     /* We do not require the whole pass to have been completed. */ | ||||
|     (*cinfo->master->finish_output_pass) (cinfo); | ||||
|     cinfo->global_state = DSTATE_BUFPOST; | ||||
|   } else if (cinfo->global_state != DSTATE_BUFPOST) { | ||||
|     /* BUFPOST = repeat call after a suspension, anything else is error */ | ||||
|     ERREXIT1(cinfo, JERR_BAD_STATE, cinfo->global_state); | ||||
|   } | ||||
|   /* Read markers looking for SOS or EOI */ | ||||
|   while (cinfo->input_scan_number <= cinfo->output_scan_number && | ||||
| 	 ! cinfo->inputctl->eoi_reached) { | ||||
|     if ((*cinfo->inputctl->consume_input) (cinfo) == JPEG_SUSPENDED) | ||||
|       return FALSE;		/* Suspend, come back later */ | ||||
|   } | ||||
|   cinfo->global_state = DSTATE_BUFIMAGE; | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| #endif /* D_MULTISCAN_FILES_SUPPORTED */ | ||||
|  | @ -0,0 +1,151 @@ | |||
| /*
 | ||||
|  * jdatadst.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 compression data destination routines for the case of | ||||
|  * emitting JPEG data to a file (or any stdio stream).  While these routines | ||||
|  * are sufficient for most applications, some will want to use a different | ||||
|  * destination manager. | ||||
|  * IMPORTANT: we assume that fwrite() will correctly transcribe an array of | ||||
|  * JOCTETs into 8-bit-wide elements on external storage.  If char is wider | ||||
|  * than 8 bits on your machine, you may need to do some tweaking. | ||||
|  */ | ||||
| 
 | ||||
| /* 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 destination object for stdio output */ | ||||
| 
 | ||||
| typedef struct { | ||||
|   struct jpeg_destination_mgr pub; /* public fields */ | ||||
| 
 | ||||
|   FILE * outfile;		/* target stream */ | ||||
|   JOCTET * buffer;		/* start of buffer */ | ||||
| } my_destination_mgr; | ||||
| 
 | ||||
| typedef my_destination_mgr * my_dest_ptr; | ||||
| 
 | ||||
| #define OUTPUT_BUF_SIZE  4096	/* choose an efficiently fwrite'able size */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Initialize destination --- called by jpeg_start_compress | ||||
|  * before any data is actually written. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(void) | ||||
| init_destination (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_dest_ptr dest = (my_dest_ptr) cinfo->dest; | ||||
| 
 | ||||
|   /* Allocate the output buffer --- it will be released when done with image */ | ||||
|   dest->buffer = (JOCTET *) | ||||
|       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | ||||
| 				  OUTPUT_BUF_SIZE * SIZEOF(JOCTET)); | ||||
| 
 | ||||
|   dest->pub.next_output_byte = dest->buffer; | ||||
|   dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Empty the output buffer --- called whenever buffer fills up. | ||||
|  * | ||||
|  * In typical applications, this should write the entire output buffer | ||||
|  * (ignoring the current state of next_output_byte & free_in_buffer), | ||||
|  * reset the pointer & count to the start of the buffer, and return TRUE | ||||
|  * indicating that the buffer has been dumped. | ||||
|  * | ||||
|  * In applications that need to be able to suspend compression due to output | ||||
|  * overrun, a FALSE return indicates that the buffer cannot be emptied now. | ||||
|  * In this situation, the compressor will return to its caller (possibly with | ||||
|  * an indication that it has not accepted all the supplied scanlines).  The | ||||
|  * application should resume compression after it has made more room in the | ||||
|  * output buffer.  Note that there are substantial restrictions on the use of | ||||
|  * suspension --- see the documentation. | ||||
|  * | ||||
|  * When suspending, the compressor will back up to a convenient restart point | ||||
|  * (typically the start of the current MCU). next_output_byte & free_in_buffer | ||||
|  * indicate where the restart point will be if the current call returns FALSE. | ||||
|  * Data beyond this point will be regenerated after resumption, so do not | ||||
|  * write it out when emptying the buffer externally. | ||||
|  */ | ||||
| 
 | ||||
| METHODDEF(boolean) | ||||
| empty_output_buffer (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_dest_ptr dest = (my_dest_ptr) cinfo->dest; | ||||
| 
 | ||||
|   if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != | ||||
|       (size_t) OUTPUT_BUF_SIZE) | ||||
|     ERREXIT(cinfo, JERR_FILE_WRITE); | ||||
| 
 | ||||
|   dest->pub.next_output_byte = dest->buffer; | ||||
|   dest->pub.free_in_buffer = OUTPUT_BUF_SIZE; | ||||
| 
 | ||||
|   return TRUE; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Terminate destination --- called by jpeg_finish_compress | ||||
|  * after all data has been written.  Usually needs to flush buffer. | ||||
|  * | ||||
|  * 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_destination (j_compress_ptr cinfo) | ||||
| { | ||||
|   my_dest_ptr dest = (my_dest_ptr) cinfo->dest; | ||||
|   size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer; | ||||
| 
 | ||||
|   /* Write any data remaining in the buffer */ | ||||
|   if (datacount > 0) { | ||||
|     if (JFWRITE(dest->outfile, dest->buffer, datacount) != datacount) | ||||
|       ERREXIT(cinfo, JERR_FILE_WRITE); | ||||
|   } | ||||
|   fflush(dest->outfile); | ||||
|   /* Make sure we wrote the output file OK */ | ||||
|   if (ferror(dest->outfile)) | ||||
|     ERREXIT(cinfo, JERR_FILE_WRITE); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * Prepare for output to a stdio stream. | ||||
|  * The caller must have already opened the stream, and is responsible | ||||
|  * for closing it after finishing compression. | ||||
|  */ | ||||
| 
 | ||||
| GLOBAL(void) | ||||
| jpeg_stdio_dest (j_compress_ptr cinfo, FILE * outfile) | ||||
| { | ||||
|   my_dest_ptr dest; | ||||
| 
 | ||||
|   /* The destination object is made permanent so that multiple JPEG images
 | ||||
|    * can be written to the same file without re-executing jpeg_stdio_dest. | ||||
|    * This makes it dangerous to use this manager and a different destination | ||||
|    * manager serially with the same JPEG object, because their private object | ||||
|    * sizes may be different.  Caveat programmer. | ||||
|    */ | ||||
|   if (cinfo->dest == NULL) {	/* first time for this JPEG object? */ | ||||
|     cinfo->dest = (struct jpeg_destination_mgr *) | ||||
|       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, | ||||
| 				  SIZEOF(my_destination_mgr)); | ||||
|   } | ||||
| 
 | ||||
|   dest = (my_dest_ptr) cinfo->dest; | ||||
|   dest->pub.init_destination = init_destination; | ||||
|   dest->pub.empty_output_buffer = empty_output_buffer; | ||||
|   dest->pub.term_destination = term_destination; | ||||
|   dest->outfile = outfile; | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
		Reference in New Issue