| File: | _build/../thumbnailer/gnome-thumbnailer-skeleton.c |
| Warning: | line 334, column 3 This statement is never executed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* |
| 2 | * Copyright (C) 2013 Bastien Nocera <hadess@hadess.net> |
| 3 | * |
| 4 | * Authors: Bastien Nocera <hadess@hadess.net> |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; either version 2 of the License, or |
| 9 | * (at your option) any later version. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License |
| 17 | * along with this program; if not, write to the Free Software |
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 19 | * |
| 20 | */ |
| 21 | |
| 22 | #include <string.h> |
| 23 | #include <glib.h> |
| 24 | #include <gio/gio.h> |
| 25 | #include <cdk-pixbuf/cdk-pixbuf.h> |
| 26 | |
| 27 | #include <locale.h> |
| 28 | #include <math.h> |
| 29 | #include <stdlib.h> |
| 30 | |
| 31 | #include "gnome-thumbnailer-skeleton.h" |
| 32 | |
| 33 | #ifndef THUMBNAILER_USAGE"Thumbnail images" |
| 34 | #error "THUMBNAILER_USAGE must be set" |
| 35 | #endif |
| 36 | |
| 37 | static int output_size = 256; |
| 38 | static gboolean g_fatal_warnings = FALSE(0); |
| 39 | static char **filenames = NULL((void*)0); |
| 40 | |
| 41 | #if !CDK_PIXBUF_CHECK_VERSION(2,36,5)((2) > (2) || ((2) == (2) && (45) > (36)) || (( 2) == (2) && (45) == (36) && (1) >= (5))) |
| 42 | /** |
| 43 | * gnome_desktop_thumbnail_scale_down_pixbuf: |
| 44 | * @pixbuf: a #CdkPixbuf |
| 45 | * @dest_width: the desired new width |
| 46 | * @dest_height: the desired new height |
| 47 | * |
| 48 | * Scales the pixbuf to the desired size. This function |
| 49 | * is a lot faster than cdk-pixbuf when scaling down by |
| 50 | * large amounts. |
| 51 | * |
| 52 | * Return value: (transfer full): a scaled pixbuf |
| 53 | * |
| 54 | * Since: 2.2 |
| 55 | **/ |
| 56 | CdkPixbuf * |
| 57 | gnome_desktop_thumbnail_scale_down_pixbuf (CdkPixbuf *pixbuf, |
| 58 | int dest_width, |
| 59 | int dest_height) |
| 60 | { |
| 61 | int source_width, source_height; |
| 62 | int s_x1, s_y1, s_x2, s_y2; |
| 63 | int s_xfrac, s_yfrac; |
| 64 | int dx, dx_frac, dy, dy_frac; |
| 65 | div_t ddx, ddy; |
| 66 | int x, y; |
| 67 | int r, g, b, a; |
| 68 | int n_pixels; |
| 69 | gboolean has_alpha; |
| 70 | guchar *dest, *src, *xsrc, *src_pixels; |
| 71 | CdkPixbuf *dest_pixbuf; |
| 72 | int pixel_stride; |
| 73 | int source_rowstride, dest_rowstride; |
| 74 | |
| 75 | if (dest_width == 0 || dest_height == 0) { |
| 76 | return NULL((void*)0); |
| 77 | } |
| 78 | |
| 79 | source_width = cdk_pixbuf_get_width (pixbuf); |
| 80 | source_height = cdk_pixbuf_get_height (pixbuf); |
| 81 | |
| 82 | g_assert (source_width >= dest_width)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_10 = 0; if (source_width >= dest_width) _g_boolean_var_10 = 1 ; _g_boolean_var_10; }), 1)) ; else g_assertion_message_expr ( ((gchar*) 0), "../thumbnailer/gnome-thumbnailer-skeleton.c", 82 , ((const char*) (__func__)), "source_width >= dest_width" ); } while (0); |
| 83 | g_assert (source_height >= dest_height)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_11 = 0; if (source_height >= dest_height) _g_boolean_var_11 = 1; _g_boolean_var_11; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "../thumbnailer/gnome-thumbnailer-skeleton.c" , 83, ((const char*) (__func__)), "source_height >= dest_height" ); } while (0); |
| 84 | |
| 85 | ddx = div (source_width, dest_width); |
| 86 | dx = ddx.quot; |
| 87 | dx_frac = ddx.rem; |
| 88 | |
| 89 | ddy = div (source_height, dest_height); |
| 90 | dy = ddy.quot; |
| 91 | dy_frac = ddy.rem; |
| 92 | |
| 93 | g_assert (dx >= 1)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_12 = 0; if (dx >= 1) _g_boolean_var_12 = 1; _g_boolean_var_12 ; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "../thumbnailer/gnome-thumbnailer-skeleton.c" , 93, ((const char*) (__func__)), "dx >= 1"); } while (0); |
| 94 | g_assert (dy >= 1)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_13 = 0; if (dy >= 1) _g_boolean_var_13 = 1; _g_boolean_var_13 ; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "../thumbnailer/gnome-thumbnailer-skeleton.c" , 94, ((const char*) (__func__)), "dy >= 1"); } while (0); |
| 95 | |
| 96 | has_alpha = cdk_pixbuf_get_has_alpha (pixbuf); |
| 97 | source_rowstride = cdk_pixbuf_get_rowstride (pixbuf); |
| 98 | src_pixels = cdk_pixbuf_get_pixels (pixbuf); |
| 99 | |
| 100 | dest_pixbuf = cdk_pixbuf_new (CDK_COLORSPACE_RGB, has_alpha, 8, |
| 101 | dest_width, dest_height); |
| 102 | dest = cdk_pixbuf_get_pixels (dest_pixbuf); |
| 103 | dest_rowstride = cdk_pixbuf_get_rowstride (dest_pixbuf); |
| 104 | |
| 105 | pixel_stride = (has_alpha)?4:3; |
| 106 | |
| 107 | s_y1 = 0; |
| 108 | s_yfrac = -dest_height/2; |
| 109 | while (s_y1 < source_height) { |
| 110 | s_y2 = s_y1 + dy; |
| 111 | s_yfrac += dy_frac; |
| 112 | if (s_yfrac > 0) { |
| 113 | s_y2++; |
| 114 | s_yfrac -= dest_height; |
| 115 | } |
| 116 | |
| 117 | s_x1 = 0; |
| 118 | s_xfrac = -dest_width/2; |
| 119 | while (s_x1 < source_width) { |
| 120 | s_x2 = s_x1 + dx; |
| 121 | s_xfrac += dx_frac; |
| 122 | if (s_xfrac > 0) { |
| 123 | s_x2++; |
| 124 | s_xfrac -= dest_width; |
| 125 | } |
| 126 | |
| 127 | /* Average block of [x1,x2[ x [y1,y2[ and store in dest */ |
| 128 | r = g = b = a = 0; |
| 129 | n_pixels = 0; |
| 130 | |
| 131 | src = src_pixels + s_y1 * source_rowstride + s_x1 * pixel_stride; |
| 132 | for (y = s_y1; y < s_y2; y++) { |
| 133 | xsrc = src; |
| 134 | if (has_alpha) { |
| 135 | for (x = 0; x < s_x2-s_x1; x++) { |
| 136 | n_pixels++; |
| 137 | |
| 138 | r += xsrc[3] * xsrc[0]; |
| 139 | g += xsrc[3] * xsrc[1]; |
| 140 | b += xsrc[3] * xsrc[2]; |
| 141 | a += xsrc[3]; |
| 142 | xsrc += 4; |
| 143 | } |
| 144 | } else { |
| 145 | for (x = 0; x < s_x2-s_x1; x++) { |
| 146 | n_pixels++; |
| 147 | r += *xsrc++; |
| 148 | g += *xsrc++; |
| 149 | b += *xsrc++; |
| 150 | } |
| 151 | } |
| 152 | src += source_rowstride; |
| 153 | } |
| 154 | |
| 155 | g_assert (n_pixels > 0)do { if (__builtin_expect (__extension__ ({ int _g_boolean_var_14 = 0; if (n_pixels > 0) _g_boolean_var_14 = 1; _g_boolean_var_14 ; }), 1)) ; else g_assertion_message_expr (((gchar*) 0), "../thumbnailer/gnome-thumbnailer-skeleton.c" , 155, ((const char*) (__func__)), "n_pixels > 0"); } while (0); |
| 156 | |
| 157 | if (has_alpha) { |
| 158 | if (a != 0) { |
| 159 | *dest++ = r / a; |
| 160 | *dest++ = g / a; |
| 161 | *dest++ = b / a; |
| 162 | *dest++ = a / n_pixels; |
| 163 | } else { |
| 164 | *dest++ = 0; |
| 165 | *dest++ = 0; |
| 166 | *dest++ = 0; |
| 167 | *dest++ = 0; |
| 168 | } |
| 169 | } else { |
| 170 | *dest++ = r / n_pixels; |
| 171 | *dest++ = g / n_pixels; |
| 172 | *dest++ = b / n_pixels; |
| 173 | } |
| 174 | |
| 175 | s_x1 = s_x2; |
| 176 | } |
| 177 | s_y1 = s_y2; |
| 178 | dest += dest_rowstride - dest_width * pixel_stride; |
| 179 | } |
| 180 | |
| 181 | return dest_pixbuf; |
| 182 | } |
| 183 | #endif |
| 184 | |
| 185 | static char * |
| 186 | get_target_uri (GFile *file) |
| 187 | { |
| 188 | GFileInfo *info; |
| 189 | char *target; |
| 190 | |
| 191 | info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI"standard::target-uri", G_FILE_QUERY_INFO_NONE, NULL((void*)0), NULL((void*)0)); |
| 192 | if (info == NULL((void*)0)) |
| 193 | return NULL((void*)0); |
| 194 | target = g_strdup (g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_TARGET_URI))g_strdup_inline (g_file_info_get_attribute_string (info, "standard::target-uri" )); |
| 195 | g_object_unref (info); |
| 196 | |
| 197 | return target; |
| 198 | } |
| 199 | |
| 200 | static char * |
| 201 | get_target_path (GFile *input) |
| 202 | { |
| 203 | if (g_file_has_uri_scheme (input, "trash") != FALSE(0) || |
| 204 | g_file_has_uri_scheme (input, "recent") != FALSE(0)) { |
| 205 | GFile *file; |
| 206 | char *input_uri; |
| 207 | char *input_path; |
| 208 | |
| 209 | input_uri = get_target_uri (input); |
| 210 | file = g_file_new_for_uri (input_uri); |
| 211 | g_free (input_uri)(__builtin_object_size ((input_uri), 0) != ((size_t) - 1)) ? g_free_sized (input_uri, __builtin_object_size ((input_uri), 0)) : (g_free ) (input_uri); |
| 212 | input_path = g_file_get_path (file); |
| 213 | g_object_unref (file); |
| 214 | return input_path; |
| 215 | } |
| 216 | return g_file_get_path (input); |
| 217 | } |
| 218 | |
| 219 | static const GOptionEntry entries[] = { |
| 220 | { "size", 's', 0, G_OPTION_ARG_INT, &output_size, "Size of the thumbnail in pixels", NULL((void*)0) }, |
| 221 | {"g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &g_fatal_warnings, "Make all warnings fatal", NULL((void*)0)}, |
| 222 | { G_OPTION_REMAINING"", '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL((void*)0), "[INPUT FILE] [OUTPUT FILE]" }, |
| 223 | { NULL((void*)0) } |
| 224 | }; |
| 225 | |
| 226 | int main (int argc, char **argv) |
| 227 | { |
| 228 | char *input_filename; |
| 229 | CdkPixbuf *pixbuf; |
| 230 | GError *error = NULL((void*)0); |
| 231 | GOptionContext *context; |
| 232 | GFile *input; |
| 233 | const char *output; |
| 234 | |
| 235 | #ifdef THUMBNAILER_RETURNS_PIXBUF1 |
| 236 | /* Nothing */ |
| 237 | #elif THUMBNAILER_RETURNS_DATA |
| 238 | char *data = NULL((void*)0); |
| 239 | gsize length; |
| 240 | #endif |
| 241 | |
| 242 | setlocale (LC_ALL6, ""); |
| 243 | |
| 244 | #if !GLIB_CHECK_VERSION(2, 36, 0)(2 > (2) || (2 == (2) && 88 > (36)) || (2 == (2 ) && 88 == (36) && 3 >= (0))) |
| 245 | g_type_init (); |
| 246 | #endif |
| 247 | |
| 248 | /* Options parsing */ |
| 249 | context = g_option_context_new (THUMBNAILER_USAGE"Thumbnail images"); |
| 250 | g_option_context_add_main_entries (context, entries, NULL((void*)0)); |
| 251 | |
| 252 | if (g_option_context_parse (context, &argc, &argv, &error) == FALSE(0)) { |
| 253 | g_warning ("Couldn't parse command-line options: %s", error->message); |
| 254 | g_error_free (error); |
| 255 | g_option_context_free (context); |
| 256 | return 1; |
| 257 | } |
| 258 | |
| 259 | g_option_context_free (context); |
| 260 | |
| 261 | /* Set fatal warnings if required */ |
| 262 | if (g_fatal_warnings) { |
| 263 | GLogLevelFlags fatal_mask; |
| 264 | |
| 265 | fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK(G_LOG_FLAG_RECURSION | G_LOG_LEVEL_ERROR)); |
| 266 | fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL; |
| 267 | g_log_set_always_fatal (fatal_mask); |
| 268 | } |
| 269 | |
| 270 | if (filenames == NULL((void*)0) || g_strv_length (filenames) != 2) { |
| 271 | g_print ("Expects an input and an output file\n"); |
| 272 | return 1; |
| 273 | } |
| 274 | |
| 275 | input = g_file_new_for_commandline_arg (filenames[0]); |
| 276 | input_filename = get_target_path (input); |
| 277 | g_object_unref (input); |
| 278 | |
| 279 | if (input_filename == NULL((void*)0)) { |
| 280 | g_warning ("Could not get file path for %s", filenames[0]); |
| 281 | return 1; |
| 282 | } |
| 283 | |
| 284 | output = filenames[1]; |
| 285 | |
| 286 | #ifdef THUMBNAILER_RETURNS_PIXBUF1 |
| 287 | pixbuf = file_to_pixbuf (input_filename, output_size, &error); |
| 288 | if (pixbuf != NULL((void*)0)) { |
| 289 | int width, height; |
| 290 | |
| 291 | width = cdk_pixbuf_get_width (pixbuf); |
| 292 | height = cdk_pixbuf_get_height (pixbuf); |
| 293 | |
| 294 | /* Handle naive thumbnailers that don't resize */ |
| 295 | if (output_size != 0 && |
| 296 | (height > output_size || width > output_size)) { |
| 297 | CdkPixbuf *scaled; |
| 298 | double scale; |
| 299 | |
| 300 | scale = (double)output_size / MAX (width, height)(((width) > (height)) ? (width) : (height)); |
| 301 | |
| 302 | #if !CDK_PIXBUF_CHECK_VERSION(2,36,5)((2) > (2) || ((2) == (2) && (45) > (36)) || (( 2) == (2) && (45) == (36) && (1) >= (5))) |
| 303 | scaled = gnome_desktop_thumbnail_scale_down_pixbuf (pixbuf, |
| 304 | floor (width * scale + 0.5), |
| 305 | floor (height * scale + 0.5)); |
| 306 | #else |
| 307 | scaled = cdk_pixbuf_scale_simple (pixbuf, |
| 308 | floor (width * scale + 0.5), |
| 309 | floor (height * scale + 0.5), |
| 310 | CDK_INTERP_BILINEAR); |
| 311 | #endif |
| 312 | cdk_pixbuf_copy_options (pixbuf, scaled); |
| 313 | g_object_unref (pixbuf); |
| 314 | pixbuf = scaled; |
| 315 | } |
| 316 | } |
| 317 | #elif THUMBNAILER_RETURNS_DATA |
| 318 | data = file_to_data (input_filename, &length, &error); |
| 319 | if (data) { |
| 320 | GInputStream *mem_stream; |
| 321 | |
| 322 | mem_stream = g_memory_input_stream_new_from_data (data, length, g_free); |
| 323 | pixbuf = cdk_pixbuf_new_from_stream_at_scale (mem_stream, output_size, -1, TRUE(!(0)), NULL((void*)0), &error); |
| 324 | g_object_unref (mem_stream); |
| 325 | } else { |
| 326 | pixbuf = NULL((void*)0); |
| 327 | } |
| 328 | #else |
| 329 | #error "One of THUMBNAILER_RETURNS_PIXBUF or THUMBNAILER_RETURNS_DATA must be set" |
| 330 | #endif |
| 331 | g_free (input_filename)(__builtin_object_size ((input_filename), 0) != ((size_t) - 1 )) ? g_free_sized (input_filename, __builtin_object_size ((input_filename ), 0)) : (g_free) (input_filename); |
| 332 | |
| 333 | if (!pixbuf) { |
| 334 | g_warning ("Could not thumbnail '%s': %s", filenames[0], |
This statement is never executed | |
| 335 | error ? error->message : "Thumbnailer failed without returning an error"); |
| 336 | g_clear_error (&error); |
| 337 | g_strfreev (filenames); |
| 338 | return 1; |
| 339 | } |
| 340 | |
| 341 | if (cdk_pixbuf_save (pixbuf, output, "png", &error, NULL((void*)0)) == FALSE(0)) { |
| 342 | g_warning ("Couldn't save the thumbnail '%s' for file '%s': %s", output, filenames[0], error->message); |
| 343 | g_error_free (error); |
| 344 | return 1; |
| 345 | } |
| 346 | |
| 347 | g_object_unref (pixbuf); |
| 348 | |
| 349 | return 0; |
| 350 | } |