[gthumb] added ability to save images as WebP
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] added ability to save images as WebP
- Date: Sun, 26 Aug 2012 09:53:37 +0000 (UTC)
commit ebbcf1a90e8580abc6f5685eacdb471d7656c53d
Author: Paolo Bacchilega <paobac src gnome org>
Date: Sun Aug 26 10:16:47 2012 +0200
added ability to save images as WebP
[new feature]
data/org.gnome.gthumb.pixbuf-savers.gschema.xml.in | 31 ++-
extensions/cairo_io/Makefile.am | 4 +-
extensions/cairo_io/data/ui/Makefile.am | 3 +-
.../cairo_io/data/ui/save-options-preferences.ui | 2 +-
extensions/cairo_io/data/ui/tiff-options.ui | 367 +++++++++---------
extensions/cairo_io/data/ui/webp-options.ui | 121 ++++++
extensions/cairo_io/gth-image-saver-webp.c | 397 ++++++++++++++++++++
extensions/cairo_io/gth-image-saver-webp.h | 56 +++
extensions/cairo_io/main.c | 4 +-
extensions/cairo_io/preferences.h | 7 +
gthumb/cairo-utils.c | 29 +-
gthumb/glib-utils.c | 5 +-
12 files changed, 821 insertions(+), 205 deletions(-)
---
diff --git a/data/org.gnome.gthumb.pixbuf-savers.gschema.xml.in b/data/org.gnome.gthumb.pixbuf-savers.gschema.xml.in
index 8c13f56..220dae3 100644
--- a/data/org.gnome.gthumb.pixbuf-savers.gschema.xml.in
+++ b/data/org.gnome.gthumb.pixbuf-savers.gschema.xml.in
@@ -1,30 +1,31 @@
<!--
gThumb
-
+
Copyright  2011 Free Software Foundation, Inc.
-
+
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, see <http://www.gnu.org/licenses/>.
-->
<schemalist>
-
+
<schema id="org.gnome.gthumb.pixbuf-savers" path="/org/gnome/gthumb/pixbuf-savers/">
<child name="jpeg" schema="org.gnome.gthumb.pixbuf-savers.jpeg" />
<child name="png" schema="org.gnome.gthumb.pixbuf-savers.png" />
<child name="tga" schema="org.gnome.gthumb.pixbuf-savers.tga" />
<child name="tiff" schema="org.gnome.gthumb.pixbuf-savers.tiff" />
+ <child name="webp" schema="org.gnome.gthumb.pixbuf-savers.webp" />
</schema>
-
+
<schema id="org.gnome.gthumb.pixbuf-savers.jpeg" path="/org/gnome/gthumb/pixbuf-savers/jpeg/">
<key name="default-ext" type="s">
<default>'jpeg'</default>
@@ -43,19 +44,19 @@
<default>false</default>
</key>
</schema>
-
+
<schema id="org.gnome.gthumb.pixbuf-savers.png" path="/org/gnome/gthumb/pixbuf-savers/png/">
<key name="compression-level" type="i">
<default>6</default>
</key>
</schema>
-
+
<schema id="org.gnome.gthumb.pixbuf-savers.tga" path="/org/gnome/gthumb/pixbuf-savers/tga/">
<key name="rle-compression" type="b">
<default>true</default>
</key>
</schema>
-
+
<schema id="org.gnome.gthumb.pixbuf-savers.tiff" path="/org/gnome/gthumb/pixbuf-savers/tiff/">
<key name="default-ext" type="s">
<default>'tiff'</default>
@@ -72,4 +73,16 @@
</key>
</schema>
+ <schema id="org.gnome.gthumb.pixbuf-savers.webp" path="/org/gnome/gthumb/pixbuf-savers/webp/">
+ <key name="lossless" type="b">
+ <default>true</default>
+ </key>
+ <key name="quality" type="i">
+ <default>75</default>
+ </key>
+ <key name="method" type="i">
+ <default>4</default>
+ </key>
+ </schema>
+
</schemalist>
diff --git a/extensions/cairo_io/Makefile.am b/extensions/cairo_io/Makefile.am
index 9e822d1..a33dacc 100644
--- a/extensions/cairo_io/Makefile.am
+++ b/extensions/cairo_io/Makefile.am
@@ -58,7 +58,9 @@ endif
if ENABLE_LIBWEBP
libcairo_io_la_SOURCES += \
cairo-image-surface-webp.c \
- cairo-image-surface-webp.h
+ cairo-image-surface-webp.h \
+ gth-image-saver-webp.c \
+ gth-image-saver-webp.h
endif
libcairo_io_la_CFLAGS = $(GTHUMB_CFLAGS) $(JPEG_CFLAGS) $(LIBRSVG_CFLAGS) -I$(top_srcdir) -I$(top_builddir)/gthumb
diff --git a/extensions/cairo_io/data/ui/Makefile.am b/extensions/cairo_io/data/ui/Makefile.am
index f4eede8..17d86bc 100644
--- a/extensions/cairo_io/data/ui/Makefile.am
+++ b/extensions/cairo_io/data/ui/Makefile.am
@@ -4,7 +4,8 @@ ui_DATA = \
png-options.ui \
save-options-preferences.ui \
tga-options.ui \
- tiff-options.ui
+ tiff-options.ui \
+ webp-options.ui
EXTRA_DIST = $(ui_DATA)
-include $(top_srcdir)/git.mk
diff --git a/extensions/cairo_io/data/ui/save-options-preferences.ui b/extensions/cairo_io/data/ui/save-options-preferences.ui
index 459ac69..fb72872 100644
--- a/extensions/cairo_io/data/ui/save-options-preferences.ui
+++ b/extensions/cairo_io/data/ui/save-options-preferences.ui
@@ -16,7 +16,7 @@
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="orientation">vertical</property>
- <property name="spacing">6</property>
+ <property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
diff --git a/extensions/cairo_io/data/ui/tiff-options.ui b/extensions/cairo_io/data/ui/tiff-options.ui
index ebaf764..e836345 100644
--- a/extensions/cairo_io/data/ui/tiff-options.ui
+++ b/extensions/cairo_io/data/ui/tiff-options.ui
@@ -65,93 +65,98 @@
</packing>
</child>
<child>
- <object class="GtkFrame" id="frame1">
+ <object class="GtkBox" id="box5">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
<child>
- <object class="GtkAlignment" id="alignment1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="top_padding">6</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkBox" id="box2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkRadioButton" id="tiff_comp_none_radiobutton">
- <property name="label" translatable="yes">_No compression</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
- <property name="use_underline">True</property>
- <property name="xalign">0</property>
- <property name="active">True</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkRadioButton" id="tiff_comp_deflate_radiobutton">
- <property name="label" translatable="yes">No_rmal (Deflate)</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
- <property name="use_underline">True</property>
- <property name="xalign">0</property>
- <property name="active">True</property>
- <property name="draw_indicator">True</property>
- <property name="group">tiff_comp_none_radiobutton</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkRadioButton" id="tiff_comp_jpeg_radiobutton">
- <property name="label" translatable="yes">_Loss compression (JPEG)</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
- <property name="use_underline">True</property>
- <property name="xalign">0</property>
- <property name="active">True</property>
- <property name="draw_indicator">True</property>
- <property name="group">tiff_comp_none_radiobutton</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="xalign">0</property>
<property name="label" translatable="yes">Compression</property>
<property name="use_markup">True</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">12</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="tiff_comp_none_radiobutton">
+ <property name="label" translatable="yes">_No compression</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="tiff_comp_deflate_radiobutton">
+ <property name="label" translatable="yes">No_rmal (Deflate)</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">tiff_comp_none_radiobutton</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="tiff_comp_jpeg_radiobutton">
+ <property name="label" translatable="yes">_Loss compression (JPEG)</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">tiff_comp_none_radiobutton</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
</child>
</object>
<packing>
@@ -161,147 +166,151 @@
</packing>
</child>
<child>
- <object class="GtkFrame" id="frame2">
+ <object class="GtkBox" id="box6">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
<child>
- <object class="GtkAlignment" id="alignment2">
+ <object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="top_padding">6</property>
- <property name="left_padding">12</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Resolution</property>
+ <property name="use_markup">True</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_left">12</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Horizontal:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">tiff_hdpi_spinbutton</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Vertical:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">tiff_vdpi_spinbutton</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
<child>
- <object class="GtkGrid" id="grid1">
+ <object class="GtkBox" id="box3">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="row_spacing">6</property>
- <property name="column_spacing">6</property>
- <property name="n_rows">2</property>
- <property name="n_columns">2</property>
+ <property name="spacing">6</property>
<child>
- <object class="GtkLabel" id="label4">
+ <object class="GtkSpinButton" id="tiff_hdpi_spinbutton">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">_Horizontal:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">tiff_hdpi_spinbutton</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="invisible_char_set">True</property>
+ <property name="adjustment">tiff_hdpi_adjustment</property>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkLabel" id="label5">
+ <object class="GtkLabel" id="label6">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">_Vertical:</property>
- <property name="use_underline">True</property>
- <property name="mnemonic_widget">tiff_vdpi_spinbutton</property>
+ <property name="label" translatable="yes">dpi</property>
</object>
<packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">6</property>
<child>
- <object class="GtkBox" id="box3">
+ <object class="GtkSpinButton" id="tiff_vdpi_spinbutton">
<property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkSpinButton" id="tiff_hdpi_spinbutton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">â</property>
- <property name="adjustment">tiff_hdpi_adjustment</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label6">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">dpi</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">â</property>
+ <property name="invisible_char_set">True</property>
+ <property name="adjustment">tiff_vdpi_adjustment</property>
</object>
<packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
- <object class="GtkBox" id="box4">
+ <object class="GtkLabel" id="label7">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkSpinButton" id="tiff_vdpi_spinbutton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">â</property>
- <property name="adjustment">tiff_vdpi_adjustment</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label7">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">dpi</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
+ <property name="label" translatable="yes">dpi</property>
</object>
<packing>
- <property name="left_attach">1</property>
- <property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
</packing>
</child>
</object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
</child>
</object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Resolution</property>
- <property name="use_markup">True</property>
- <attributes>
- <attribute name="weight" value="bold"/>
- </attributes>
- </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
</child>
</object>
<packing>
diff --git a/extensions/cairo_io/data/ui/webp-options.ui b/extensions/cairo_io/data/ui/webp-options.ui
new file mode 100644
index 0000000..d5ae6ec
--- /dev/null
+++ b/extensions/cairo_io/data/ui/webp-options.ui
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.0 -->
+ <object class="GtkAdjustment" id="method_adjustment">
+ <property name="upper">6</property>
+ <property name="value">4</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">1</property>
+ </object>
+ <object class="GtkAdjustment" id="quality_adjustment">
+ <property name="upper">100</property>
+ <property name="value">75</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="webp_options">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Quality:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">quality_scale</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">_Method:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">method_scale</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="lossless_checkbutton">
+ <property name="label" translatable="yes">_Lossless</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ <property name="width">2</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScale" id="quality_scale">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="adjustment">quality_adjustment</property>
+ <property name="round_digits">1</property>
+ <property name="digits">0</property>
+ <property name="value_pos">left</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScale" id="method_scale">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="adjustment">method_adjustment</property>
+ <property name="round_digits">1</property>
+ <property name="digits">0</property>
+ <property name="value_pos">left</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ <property name="width">1</property>
+ <property name="height">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/extensions/cairo_io/gth-image-saver-webp.c b/extensions/cairo_io/gth-image-saver-webp.c
new file mode 100644
index 0000000..0de77bd
--- /dev/null
+++ b/extensions/cairo_io/gth-image-saver-webp.c
@@ -0,0 +1,397 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <webp/encode.h>
+#include <glib/gi18n.h>
+#include <gthumb.h>
+#include "gth-image-saver-webp.h"
+#include "preferences.h"
+
+
+#define GET_WIDGET(x) (_gtk_builder_get_widget (self->priv->builder, (x)))
+
+
+G_DEFINE_TYPE (GthImageSaverWebp, gth_image_saver_webp, GTH_TYPE_IMAGE_SAVER)
+
+
+struct _GthImageSaverWebpPrivate {
+ GtkBuilder *builder;
+ GSettings *settings;
+};
+
+
+static void
+gth_image_saver_webp_finalize (GObject *object)
+{
+ GthImageSaverWebp *self = GTH_IMAGE_SAVER_WEBP (object);
+
+ _g_object_unref (self->priv->builder);
+ _g_object_unref (self->priv->settings);
+ G_OBJECT_CLASS (gth_image_saver_webp_parent_class)->finalize (object);
+}
+
+
+static GtkWidget *
+gth_image_saver_webp_get_control (GthImageSaver *base)
+{
+ GthImageSaverWebp *self = GTH_IMAGE_SAVER_WEBP (base);
+
+ if (self->priv->builder == NULL)
+ self->priv->builder = _gtk_builder_new_from_file ("webp-options.ui", "cairo_io");
+
+ gtk_adjustment_set_value (GTK_ADJUSTMENT (GET_WIDGET ("quality_adjustment")),
+ g_settings_get_int (self->priv->settings, PREF_WEBP_QUALITY));
+ gtk_adjustment_set_value (GTK_ADJUSTMENT (GET_WIDGET ("method_adjustment")),
+ g_settings_get_int (self->priv->settings, PREF_WEBP_METHOD));
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("lossless_checkbutton")),
+ g_settings_get_boolean (self->priv->settings, PREF_WEBP_LOSSLESS));
+
+ return GET_WIDGET ("webp_options");
+}
+
+
+static void
+gth_image_saver_webp_save_options (GthImageSaver *base)
+{
+ GthImageSaverWebp *self = GTH_IMAGE_SAVER_WEBP (base);
+
+ g_settings_set_int (self->priv->settings, PREF_WEBP_QUALITY, (int) gtk_adjustment_get_value (GTK_ADJUSTMENT (GET_WIDGET ("quality_adjustment"))));
+ g_settings_set_int (self->priv->settings, PREF_WEBP_METHOD, (int) gtk_adjustment_get_value (GTK_ADJUSTMENT (GET_WIDGET ("method_adjustment"))));
+ g_settings_set_boolean (self->priv->settings, PREF_WEBP_LOSSLESS, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("lossless_checkbutton"))));
+}
+
+
+static gboolean
+gth_image_saver_webp_can_save (GthImageSaver *self,
+ const char *mime_type)
+{
+ return g_content_type_equals (mime_type, "image/webp");
+}
+
+
+typedef struct {
+ GError **error;
+ GthBufferData *buffer_data;
+ int success;
+} CairoWebpData;
+
+
+static void
+_cairo_webp_data_destroy (CairoWebpData *cairo_webp_data)
+{
+ gth_buffer_data_free (cairo_webp_data->buffer_data, ! cairo_webp_data->success);
+ g_free (cairo_webp_data);
+}
+
+
+static int
+cairo_webp_writer_func (const uint8_t *data,
+ size_t data_size,
+ const WebPPicture *picture)
+{
+ CairoWebpData *cairo_webp_data = picture->custom_ptr;
+
+ cairo_webp_data->success = gth_buffer_data_write (cairo_webp_data->buffer_data,
+ (void *) data,
+ data_size,
+ cairo_webp_data->error);
+
+ return cairo_webp_data->success;
+}
+
+
+static int
+_WebPPictureImportCairoSurface (WebPPicture *const picture,
+ cairo_surface_t *image)
+{
+ int stride;
+ guchar *src_row;
+ uint32_t *dest_row;
+ int y, x;
+ guchar r, g, b, a;
+
+ if (_cairo_image_surface_get_has_alpha (image))
+ picture->colorspace |= WEBP_CSP_ALPHA_BIT;
+ else
+ picture->colorspace &= ~WEBP_CSP_ALPHA_BIT;
+
+ if (! WebPPictureAlloc (picture))
+ return 0;
+
+ stride = cairo_image_surface_get_stride (image);
+ src_row = cairo_image_surface_get_data (image);
+ dest_row = picture->argb;
+
+ for (y= 0; y < cairo_image_surface_get_height (image); y++) {
+ guchar *pixel = src_row;
+
+ for (x = 0; x < cairo_image_surface_get_width (image); x++) {
+ CAIRO_GET_RGBA (pixel, r, g, b, a);
+ dest_row[x] = ((a << 24) | (r << 16) | (g << 8) | b);
+
+ pixel += 4;
+ }
+
+ src_row += stride;
+ dest_row += picture->argb_stride;
+ }
+
+ return 1;
+}
+
+
+static gboolean
+_cairo_surface_write_as_webp (cairo_surface_t *image,
+ char **buffer,
+ gsize *buffer_size,
+ char **keys,
+ char **values,
+ GError **error)
+{
+ gboolean lossless;
+ int quality;
+ int method;
+ WebPConfig config;
+ CairoWebpData *cairo_webp_data;
+ WebPPicture pic;
+
+ lossless = TRUE;
+ quality = 75;
+ method = 4;
+
+ if (keys && *keys) {
+ char **kiter = keys;
+ char **viter = values;
+
+ while (*kiter) {
+ if (strcmp (*kiter, "lossless") == 0) {
+ if (*viter == NULL) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "Must specify a value for the 'lossless' option");
+ return FALSE;
+ }
+
+ lossless = atoi (*viter);
+
+ if (lossless < 0 || lossless > 1) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "Invalid value set for the 'lossless' option of the WebP saver");
+ return FALSE;
+ }
+ }
+ else if (strcmp (*kiter, "quality") == 0) {
+ if (*viter == NULL) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "Must specify a quality value to the WebP saver");
+ return FALSE;
+ }
+
+ quality = atoi (*viter);
+
+ if (quality < 0 || quality > 100) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "Unsupported quality value passed to the WebP saver");
+ return FALSE;
+ }
+ }
+ else if (strcmp (*kiter, "method") == 0) {
+ if (*viter == NULL) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "Must specify a method value to the WebP saver");
+ return FALSE;
+ }
+
+ method = atoi (*viter);
+
+ if (method < 0 || method > 6) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "Unsupported method value passed to the WebP saver");
+ return FALSE;
+ }
+ }
+ else {
+ g_warning ("Bad option name '%s' passed to the WebP saver", *kiter);
+ return FALSE;
+ }
+
+ ++kiter;
+ ++viter;
+ }
+ }
+
+ if (! WebPConfigInit (&config)) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "Version error");
+ return FALSE;
+ }
+
+ config.lossless = lossless;
+ config.quality = quality;
+ config.method = method;
+
+ if (! WebPValidateConfig (&config)) {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "Config error");
+ return FALSE;
+ }
+
+ cairo_webp_data = g_new0 (CairoWebpData, 1);
+ cairo_webp_data->error = error;
+ cairo_webp_data->buffer_data = gth_buffer_data_new ();
+ cairo_webp_data->success = FALSE;
+
+ WebPPictureInit (&pic);
+ pic.width = cairo_image_surface_get_width (image);
+ pic.height = cairo_image_surface_get_height (image);
+ pic.writer = cairo_webp_writer_func;
+ pic.custom_ptr = cairo_webp_data;
+ pic.use_argb = TRUE;
+
+ if (_WebPPictureImportCairoSurface (&pic, image)) {
+ int ok = WebPEncode (&config, &pic);
+ WebPPictureFree (&pic);
+
+ if (cairo_webp_data->success && ! ok) {
+ g_set_error (cairo_webp_data->error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "Encoding error: %d", pic.error_code);
+ cairo_webp_data->success = FALSE;
+ }
+ }
+ else {
+ g_set_error (cairo_webp_data->error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_DATA,
+ "Memory error");
+ cairo_webp_data->success = FALSE;
+ }
+
+ if (cairo_webp_data->success)
+ gth_buffer_data_get (cairo_webp_data->buffer_data, buffer, buffer_size);
+
+ _cairo_webp_data_destroy (cairo_webp_data);
+
+ return TRUE;
+}
+
+
+static gboolean
+gth_image_saver_webp_save_image (GthImageSaver *base,
+ GthImage *image,
+ char **buffer,
+ gsize *buffer_size,
+ const char *mime_type,
+ GError **error)
+{
+ GthImageSaverWebp *self = GTH_IMAGE_SAVER_WEBP (base);
+ cairo_surface_t *surface;
+ char **option_keys;
+ char **option_values;
+ int i = -1;
+ int i_value;
+ gboolean result;
+
+ option_keys = g_new (char *, 4);
+ option_values = g_new (char *, 4);
+
+ i++;
+ i_value = g_settings_get_boolean (self->priv->settings, PREF_WEBP_LOSSLESS);
+ option_keys[i] = g_strdup ("lossless");;
+ option_values[i] = g_strdup_printf ("%d", i_value);
+
+ i++;
+ i_value = g_settings_get_int (self->priv->settings, PREF_WEBP_QUALITY);
+ option_keys[i] = g_strdup ("quality");;
+ option_values[i] = g_strdup_printf ("%d", i_value);
+
+ i++;
+ i_value = g_settings_get_int (self->priv->settings, PREF_WEBP_METHOD);
+ option_keys[i] = g_strdup ("method");;
+ option_values[i] = g_strdup_printf ("%d", i_value);
+
+ i++;
+ option_keys[i] = NULL;
+ option_values[i] = NULL;
+
+ surface = gth_image_get_cairo_surface (image);
+ result = _cairo_surface_write_as_webp (surface,
+ buffer,
+ buffer_size,
+ option_keys,
+ option_values,
+ error);
+
+ cairo_surface_destroy (surface);
+ g_strfreev (option_keys);
+ g_strfreev (option_values);
+
+ return result;
+}
+
+
+static void
+gth_image_saver_webp_class_init (GthImageSaverWebpClass *klass)
+{
+ GObjectClass *object_class;
+ GthImageSaverClass *image_saver_class;
+
+ g_type_class_add_private (klass, sizeof (GthImageSaverWebpPrivate));
+
+ object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = gth_image_saver_webp_finalize;
+
+ image_saver_class = GTH_IMAGE_SAVER_CLASS (klass);
+ image_saver_class->id = "webp";
+ image_saver_class->display_name = _("WebP");
+ image_saver_class->mime_type = "image/webp";
+ image_saver_class->extensions = "webp";
+ image_saver_class->get_default_ext = NULL;
+ image_saver_class->get_control = gth_image_saver_webp_get_control;
+ image_saver_class->save_options = gth_image_saver_webp_save_options;
+ image_saver_class->can_save = gth_image_saver_webp_can_save;
+ image_saver_class->save_image = gth_image_saver_webp_save_image;
+}
+
+
+static void
+gth_image_saver_webp_init (GthImageSaverWebp *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_IMAGE_SAVER_WEBP, GthImageSaverWebpPrivate);
+ self->priv->settings = g_settings_new (GTHUMB_IMAGE_SAVERS_WEBP_SCHEMA);
+}
diff --git a/extensions/cairo_io/gth-image-saver-webp.h b/extensions/cairo_io/gth-image-saver-webp.h
new file mode 100644
index 0000000..c353b04
--- /dev/null
+++ b/extensions/cairo_io/gth-image-saver-webp.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_IMAGE_SAVER_WEBP_H
+#define GTH_IMAGE_SAVER_WEBP_H
+
+#include <gtk/gtk.h>
+#include <gthumb.h>
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_IMAGE_SAVER_WEBP (gth_image_saver_webp_get_type ())
+#define GTH_IMAGE_SAVER_WEBP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_IMAGE_SAVER_WEBP, GthImageSaverWebp))
+#define GTH_IMAGE_SAVER_WEBP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTH_IMAGE_SAVER_WEBP_TYPE, GthImageSaverWebpClass))
+#define GTH_IS_IMAGE_SAVER_WEBP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTH_TYPE_IMAGE_SAVER_WEBP))
+#define GTH_IS_IMAGE_SAVER_WEBP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_IMAGE_SAVER_WEBP))
+#define GTH_IMAGE_SAVER_WEBP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_IMAGE_SAVER_WEBP, GthImageSaverWebpClass))
+
+typedef struct _GthImageSaverWebp GthImageSaverWebp;
+typedef struct _GthImageSaverWebpClass GthImageSaverWebpClass;
+typedef struct _GthImageSaverWebpPrivate GthImageSaverWebpPrivate;
+
+struct _GthImageSaverWebp
+{
+ GthImageSaver __parent;
+ GthImageSaverWebpPrivate *priv;
+};
+
+struct _GthImageSaverWebpClass
+{
+ GthImageSaverClass __parent_class;
+};
+
+GType gth_image_saver_webp_get_type (void);
+
+G_END_DECLS
+
+#endif /* GTH_IMAGE_SAVER_WEBP_H */
diff --git a/extensions/cairo_io/main.c b/extensions/cairo_io/main.c
index a685ecc..27564de 100644
--- a/extensions/cairo_io/main.c
+++ b/extensions/cairo_io/main.c
@@ -30,7 +30,7 @@
#include "gth-image-saver-png.h"
#include "gth-image-saver-tga.h"
#include "gth-image-saver-tiff.h"
-/*#include "gth-image-saver-webp.h"*/
+#include "gth-image-saver-webp.h"
#include "preferences.h"
@@ -66,7 +66,7 @@ gthumb_extension_activate (void)
GTH_IMAGE_FORMAT_CAIRO_SURFACE,
"image/webp",
NULL);
- /*gth_main_register_type ("image-saver", GTH_TYPE_IMAGE_SAVER_WEBP);*/
+ gth_main_register_type ("image-saver", GTH_TYPE_IMAGE_SAVER_WEBP);
#endif
gth_hook_add_callback ("dlg-preferences-construct", 30, G_CALLBACK (ci__dlg_preferences_construct_cb), NULL);
diff --git a/extensions/cairo_io/preferences.h b/extensions/cairo_io/preferences.h
index 1d48bcc..798275f 100644
--- a/extensions/cairo_io/preferences.h
+++ b/extensions/cairo_io/preferences.h
@@ -39,6 +39,7 @@ typedef enum {
#define GTHUMB_IMAGE_SAVERS_PNG_SCHEMA GTHUMB_IMAGE_SAVERS ".png"
#define GTHUMB_IMAGE_SAVERS_TGA_SCHEMA GTHUMB_IMAGE_SAVERS ".tga"
#define GTHUMB_IMAGE_SAVERS_TIFF_SCHEMA GTHUMB_IMAGE_SAVERS ".tiff"
+#define GTHUMB_IMAGE_SAVERS_WEBP_SCHEMA GTHUMB_IMAGE_SAVERS ".webp"
/* keys: jpeg */
@@ -63,6 +64,12 @@ typedef enum {
#define PREF_TIFF_HORIZONTAL_RES "horizontal-resolution"
#define PREF_TIFF_VERTICAL_RES "vertical-resolution"
+/* keys: webp */
+
+#define PREF_WEBP_LOSSLESS "lossless"
+#define PREF_WEBP_QUALITY "quality"
+#define PREF_WEBP_METHOD "method"
+
void ci__dlg_preferences_construct_cb (GtkWidget *dialog,
GthBrowser *browser,
diff --git a/gthumb/cairo-utils.c b/gthumb/cairo-utils.c
index d635f5e..3d78475 100644
--- a/gthumb/cairo-utils.c
+++ b/gthumb/cairo-utils.c
@@ -566,20 +566,29 @@ _cairo_image_surface_color_shift (cairo_surface_t *image,
void
_cairo_copy_line_as_rgba (guchar *dest,
- guchar *src,
- guint width,
- guint alpha)
+ guchar *src,
+ guint width,
+ guint alpha)
{
guint x;
- for (x = 0; x < width; x++) {
- *(dest++) = src[CAIRO_RED];
- *(dest++) = src[CAIRO_GREEN];
- *(dest++) = src[CAIRO_BLUE];
- if (alpha)
- *(dest++) = src[CAIRO_ALPHA];
+ if (alpha) {
+ for (x = 0; x < width; x++) {
+ CAIRO_GET_RGBA (src, dest[0], dest[1], dest[2], dest[3]);
- src += 4;
+ src += 4;
+ dest += 4;
+ }
+ }
+ else {
+ for (x = 0; x < width; x++) {
+ dest[0] = src[CAIRO_RED];
+ dest[1] = src[CAIRO_GREEN];
+ dest[2] = src[CAIRO_BLUE];
+
+ src += 4;
+ dest += 3;
+ }
}
}
diff --git a/gthumb/glib-utils.c b/gthumb/glib-utils.c
index c25df62..d380ecd 100644
--- a/gthumb/glib-utils.c
+++ b/gthumb/glib-utils.c
@@ -2877,8 +2877,9 @@ get_mime_type_from_magic_numbers (void *buffer,
const struct magic * const magic = &magic_ids[i];
if ((magic->off + magic->len) > buffer_size)
- g_warning ("buffer underrun for mime-type '%s' magic", magic->mime_type);
- else if (! memcmp (buffer + magic->off, magic->id, magic->len))
+ continue;
+
+ if (! memcmp (buffer + magic->off, magic->id, magic->len))
return magic->mime_type;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]