mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-27 20:37:11 +00:00
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> -->
|
||||
|
27
data/jids/confscr.jid
Normal file
27
data/jids/confscr.jid
Normal file
@ -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_selected(widget))
|
||||
jwidget_deselect(widget);
|
||||
else
|
||||
jwidget_select(widget);
|
||||
|
||||
jwidget_capture_mouse(widget);
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
case JI_RADIO:
|
||||
if (jwidget_is_deselected(widget)) {
|
||||
jwidget_signal_off(widget);
|
||||
jwidget_select(widget);
|
||||
jwidget_signal_on(widget);
|
||||
if (jwidget_is_enabled(widget)) {
|
||||
if (jwidget_is_selected(widget))
|
||||
jwidget_deselect(widget);
|
||||
else
|
||||
jwidget_select(widget);
|
||||
|
||||
jwidget_capture_mouse(widget);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
return TRUE;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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,45 +105,50 @@ 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;
|
||||
slider_press_left = msg->mouse.left;
|
||||
|
||||
|
||||
if (slider_press_left)
|
||||
jmouse_set_cursor(JI_CURSOR_HAND);
|
||||
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,19 +160,19 @@ static bool slider_msg_proc (JWidget widget, JMessage msg)
|
||||
}
|
||||
/* with right click */
|
||||
else {
|
||||
accuracy = MID (1,
|
||||
jrect_w(widget->rc) / range,
|
||||
jrect_w(widget->rc));
|
||||
accuracy = MID(1,
|
||||
jrect_w(widget->rc) / range,
|
||||
jrect_w(widget->rc));
|
||||
|
||||
value = slider_press_value +
|
||||
(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,
|
||||
widget->rc->x1+req_w,
|
||||
widget->rc->y1+req_h);
|
||||
jwidget_set_rect (widget, rect);
|
||||
jrect_free (rect);
|
||||
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_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,
|
||||
jrect_w(manager->rc)/2 - jrect_w(widget->rc)/2,
|
||||
jrect_h(manager->rc)/2 - jrect_h(widget->rc)/2);
|
||||
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,
|
||||
FALSE, FALSE);
|
||||
_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,
|
||||
x+jrect_w(widget->rc),
|
||||
y+jrect_h(widget->rc));
|
||||
move_window (widget, rect, TRUE);
|
||||
jrect_free (rect);
|
||||
JRect rect = jrect_new(x, y,
|
||||
x+jrect_w(widget->rc),
|
||||
y+jrect_h(widget->rc));
|
||||
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,10 +220,10 @@ 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_data[c].data, cmap);
|
||||
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))
|
||||
draw_sprite(ji_screen, icon_bmp, icon.x1, icon.y1);
|
||||
/* 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)
|
||||
|
220
makefile.lst
220
makefile.lst
@ -173,57 +173,13 @@ 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
|
||||
|
||||
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)))))
|
||||
ASE_OBJS = $(addprefix $(OBJ_DIR)/, \
|
||||
$(addsuffix $(OBJ), \
|
||||
$(notdir $(basename $(ASE_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,9 +392,9 @@ LIBPNG_SOURCES = \
|
||||
$(LIBPNG_DIR)/pngwtran.c \
|
||||
$(LIBPNG_DIR)/pngwutil.c
|
||||
|
||||
LIBPNG_OBJS = $(addprefix $(OBJ_DIR)/, \
|
||||
$(addsuffix $(OBJ), \
|
||||
$(notdir $(basename $(LIBPNG_SOURCES)))))
|
||||
LIBPNG_OBJS = $(addprefix $(OBJ_DIR)/png., \
|
||||
$(addsuffix $(OBJ), \
|
||||
$(notdir $(basename $(LIBPNG_SOURCES)))))
|
||||
|
||||
######################################################################
|
||||
# ZLib
|
||||
@ -318,9 +415,9 @@ ZLIB_SOURCES = \
|
||||
$(ZLIB_DIR)/uncompr.c \
|
||||
$(ZLIB_DIR)/zutil.c
|
||||
|
||||
ZLIB_OBJS = $(addprefix $(OBJ_DIR)/, \
|
||||
$(addsuffix $(OBJ), \
|
||||
$(notdir $(basename $(ZLIB_SOURCES)))))
|
||||
ZLIB_OBJS = $(addprefix $(OBJ_DIR)/zlib., \
|
||||
$(addsuffix $(OBJ), \
|
||||
$(notdir $(basename $(ZLIB_SOURCES)))))
|
||||
|
||||
######################################################################
|
||||
# All objects and libraries
|
||||
@ -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) {
|
||||
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;
|
||||
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
|
||||
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);
|
||||
|
||||
/* rebuild the menu list of sprites */
|
||||
if (is_interactive())
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
518
src/widgets/tabs.c
Normal file
518
src/widgets/tabs.c
Normal file
@ -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);
|
||||
}
|
33
src/widgets/tabs.h
Normal file
33
src/widgets/tabs.h
Normal file
@ -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 */
|
45
third_party/README.txt
vendored
45
third_party/README.txt
vendored
@ -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/
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
385
third_party/jpeg/README.txt
vendored
Normal file
385
third_party/jpeg/README.txt
vendored
Normal file
@ -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.
|
132
third_party/jpeg/cderror.h
vendored
Normal file
132
third_party/jpeg/cderror.h
vendored
Normal file
@ -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
|
181
third_party/jpeg/cdjpeg.c
vendored
Normal file
181
third_party/jpeg/cdjpeg.c
vendored
Normal file
@ -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;
|
||||
}
|
184
third_party/jpeg/cdjpeg.h
vendored
Normal file
184
third_party/jpeg/cdjpeg.h
vendored
Normal 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
|
217
third_party/jpeg/change.log
vendored
Normal file
217
third_party/jpeg/change.log
vendored
Normal file
@ -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.
|
402
third_party/jpeg/ckconfig.c
vendored
Normal file
402
third_party/jpeg/ckconfig.c
vendored
Normal file
@ -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;
|
||||
}
|
118
third_party/jpeg/coderules.doc
vendored
Normal file
118
third_party/jpeg/coderules.doc
vendored
Normal file
@ -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.
|
433
third_party/jpeg/example.c
vendored
Normal file
433
third_party/jpeg/example.c
vendored
Normal file
@ -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.
|
||||
*/
|
210
third_party/jpeg/filelist.doc
vendored
Normal file
210
third_party/jpeg/filelist.doc
vendored
Normal file
@ -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.
|
280
third_party/jpeg/jcapimin.c
vendored
Normal file
280
third_party/jpeg/jcapimin.c
vendored
Normal file
@ -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().
|
||||
*/
|
||||
}
|
161
third_party/jpeg/jcapistd.c
vendored
Normal file
161
third_party/jpeg/jcapistd.c
vendored
Normal file
@ -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;
|
||||
}
|
449
third_party/jpeg/jccoefct.c
vendored
Normal file
449
third_party/jpeg/jccoefct.c
vendored
Normal file
@ -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 */
|
||||
}
|
||||
}
|
459
third_party/jpeg/jccolor.c
vendored
Normal file
459
third_party/jpeg/jccolor.c
vendored
Normal file
@ -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;
|
||||
}
|
||||
}
|
387
third_party/jpeg/jcdctmgr.c
vendored
Normal file
387
third_party/jpeg/jcdctmgr.c
vendored
Normal file
@ -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
|
||||
}
|
||||
}
|
909
third_party/jpeg/jchuff.c
vendored
Normal file
909
third_party/jpeg/jchuff.c
vendored
Normal file
@ -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
|
||||
}
|
||||
}
|
47
third_party/jpeg/jchuff.h
vendored
Normal file
47
third_party/jpeg/jchuff.h
vendored
Normal file
@ -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[]));
|
72
third_party/jpeg/jcinit.c
vendored
Normal file
72
third_party/jpeg/jcinit.c
vendored
Normal file
@ -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);
|
||||
}
|
293
third_party/jpeg/jcmainct.c
vendored
Normal file
293
third_party/jpeg/jcmainct.c
vendored
Normal file
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
664
third_party/jpeg/jcmarker.c
vendored
Normal file
664
third_party/jpeg/jcmarker.c
vendored
Normal file
@ -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;
|
||||
}
|
590
third_party/jpeg/jcmaster.c
vendored
Normal file
590
third_party/jpeg/jcmaster.c
vendored
Normal file
@ -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;
|
||||
}
|
106
third_party/jpeg/jcomapi.c
vendored
Normal file
106
third_party/jpeg/jcomapi.c
vendored
Normal file
@ -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;
|
||||
}
|
155
third_party/jpeg/jconfig.doc
vendored
Normal file
155
third_party/jpeg/jconfig.doc
vendored
Normal file
@ -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 */
|
45
third_party/jpeg/jconfig.h
vendored
Normal file
45
third_party/jpeg/jconfig.h
vendored
Normal file
@ -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 */
|
610
third_party/jpeg/jcparam.c
vendored
Normal file
610
third_party/jpeg/jcparam.c
vendored
Normal file
@ -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 */
|
833
third_party/jpeg/jcphuff.c
vendored
Normal file
833
third_party/jpeg/jcphuff.c
vendored
Normal file
@ -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 */
|
354
third_party/jpeg/jcprepct.c
vendored
Normal file
354
third_party/jpeg/jcprepct.c
vendored
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
519
third_party/jpeg/jcsample.c
vendored
Normal file
519
third_party/jpeg/jcsample.c
vendored
Normal file
@ -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
|
||||
}
|
388
third_party/jpeg/jctrans.c
vendored
Normal file
388
third_party/jpeg/jctrans.c
vendored
Normal file
@ -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;
|
||||
}
|
||||
}
|
395
third_party/jpeg/jdapimin.c
vendored
Normal file
395
third_party/jpeg/jdapimin.c
vendored
Normal file
@ -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;
|
||||
}
|
275
third_party/jpeg/jdapistd.c
vendored
Normal file
275
third_party/jpeg/jdapistd.c
vendored
Normal file
@ -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 */
|
151
third_party/jpeg/jdatadst.c
vendored
Normal file
151
third_party/jpeg/jdatadst.c
vendored
Normal file
@ -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…
x
Reference in New Issue
Block a user