Added libjpeg in the repository.

Fixed some bugs in the GUI system.
Added tabs, and removed the list-menu.
This commit is contained in:
David Capello 2007-11-28 14:19:36 +00:00
parent 4c980d3e46
commit df0104734f
157 changed files with 38356 additions and 1158 deletions

View File

@ -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/>

View File

@ -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

View File

@ -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:

View File

@ -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"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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
View 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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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 />

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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" />

View File

@ -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

View File

@ -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
View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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 */
}

View File

@ -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(); */

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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"

View File

@ -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);

View File

@ -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());

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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;
}

View File

@ -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"));
}
}

View File

@ -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

View File

@ -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);
}

View File

@ -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,
};

View File

@ -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,
" # "
" ## "
" ### "
" #### "
" ### "
" ## "
" # "
" " },
};

View File

@ -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) {

View File

@ -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))

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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
View 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
View 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 */

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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