static cairo_test_status_t test_cairo_image_surface_get_height (cairo_surface_t *surface) { unsigned int height = cairo_image_surface_get_height (surface); return height == 0 || surface_has_type (surface, CAIRO_SURFACE_TYPE_IMAGE) ? CAIRO_TEST_SUCCESS : CAIRO_TEST_ERROR; }
static GtkWidget * gth_file_tool_grayscale_get_options (GthFileTool *base) { GthFileToolGrayscale *self; GtkWidget *window; GtkWidget *viewer_page; GtkWidget *viewer; cairo_surface_t *source; GtkWidget *options; int width, height; GtkAllocation allocation; self = (GthFileToolGrayscale *) base; window = gth_file_tool_get_window (base); viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window)); if (! GTH_IS_IMAGE_VIEWER_PAGE (viewer_page)) return NULL; cairo_surface_destroy (self->priv->destination); cairo_surface_destroy (self->priv->preview); viewer = gth_image_viewer_page_get_image_viewer (GTH_IMAGE_VIEWER_PAGE (viewer_page)); source = gth_image_viewer_page_tool_get_source (GTH_IMAGE_VIEWER_PAGE_TOOL (self)); if (source == NULL) return NULL; width = cairo_image_surface_get_width (source); height = cairo_image_surface_get_height (source); gtk_widget_get_allocation (GTK_WIDGET (viewer), &allocation); if (scale_keeping_ratio (&width, &height, PREVIEW_SIZE * allocation.width, PREVIEW_SIZE * allocation.height, FALSE)) self->priv->preview = _cairo_image_surface_scale_bilinear (source, width, height); else self->priv->preview = cairo_surface_reference (source); self->priv->destination = cairo_surface_reference (self->priv->preview); self->priv->apply_to_original = FALSE; self->priv->closing = FALSE; self->priv->builder = _gtk_builder_new_from_file ("grayscale-options.ui", "file_tools"); options = _gtk_builder_get_widget (self->priv->builder, "options"); gtk_widget_show (options); g_signal_connect (GET_WIDGET ("ok_button"), "clicked", G_CALLBACK (ok_button_clicked_cb), self); g_signal_connect_swapped (GET_WIDGET ("cancel_button"), "clicked", G_CALLBACK (gth_file_tool_cancel), self); g_signal_connect (GET_WIDGET ("brightness_radiobutton"), "clicked", G_CALLBACK (method_changed_cb), self); g_signal_connect (GET_WIDGET ("saturation_radiobutton"), "clicked", G_CALLBACK (method_changed_cb), self); g_signal_connect (GET_WIDGET ("average_radiobutton"), "clicked", G_CALLBACK (method_changed_cb), self); g_signal_connect (GET_WIDGET ("preview_checkbutton"), "toggled", G_CALLBACK (preview_checkbutton_toggled_cb), self); self->priv->preview_tool = gth_preview_tool_new (); gth_preview_tool_set_image (GTH_PREVIEW_TOOL (self->priv->preview_tool), self->priv->preview); gth_image_viewer_set_tool (GTH_IMAGE_VIEWER (viewer), self->priv->preview_tool); apply_changes (self); return options; }
static std::size_t height(data_type_t const& data_in) { return cairo_image_surface_get_height(data_in); }
void _gtk_9slice_render (Gtk9Slice *slice, cairo_t *cr, gdouble x, gdouble y, gdouble width, gdouble height) { int img_width, img_height; cairo_surface_t *surface; cairo_save (cr); /* Top side */ surface = slice->surfaces[BORDER_MIDDLE][BORDER_TOP]; img_height = cairo_image_surface_get_height (surface); render_border (cr, surface, SIDE_TOP, x + slice->distances[SIDE_LEFT], y, width - slice->distances[SIDE_LEFT] - slice->distances[SIDE_RIGHT], (gdouble) img_height, slice->modifiers[SIDE_TOP]); /* Bottom side */ surface = slice->surfaces[BORDER_MIDDLE][BORDER_BOTTOM]; img_height = cairo_image_surface_get_height (surface); render_border (cr, surface, SIDE_BOTTOM, x + slice->distances[SIDE_LEFT], y + height - img_height, width - slice->distances[SIDE_LEFT] - slice->distances[SIDE_RIGHT], (gdouble) img_height, slice->modifiers[SIDE_BOTTOM]); /* Left side */ surface = slice->surfaces[BORDER_LEFT][BORDER_MIDDLE]; img_width = cairo_image_surface_get_width (surface); render_border (cr, surface, SIDE_LEFT, x, y + slice->distances[SIDE_TOP], (gdouble) img_width, height - slice->distances[SIDE_TOP] - slice->distances[SIDE_BOTTOM], slice->modifiers[SIDE_LEFT]); /* Right side */ surface = slice->surfaces[BORDER_RIGHT][BORDER_MIDDLE]; img_width = cairo_image_surface_get_width (surface); render_border (cr, surface, SIDE_RIGHT, x + width - img_width, y + slice->distances[SIDE_TOP], (gdouble) img_width, height - slice->distances[SIDE_TOP] - slice->distances[SIDE_BOTTOM], slice->modifiers[SIDE_RIGHT]); /* Top/Left corner */ surface = slice->surfaces[BORDER_LEFT][BORDER_TOP]; img_width = cairo_image_surface_get_width (surface); img_height = cairo_image_surface_get_height (surface); render_corner (cr, surface, x, y, (gdouble) img_width, (gdouble) img_height); /* Top/right corner */ surface = slice->surfaces[BORDER_RIGHT][BORDER_TOP]; img_width = cairo_image_surface_get_width (surface); img_height = cairo_image_surface_get_height (surface); render_corner (cr, surface, x + width - img_width, y, (gdouble) img_width, (gdouble) img_height); /* Bottom/left corner */ surface = slice->surfaces[BORDER_LEFT][BORDER_BOTTOM]; img_width = cairo_image_surface_get_width (surface); img_height = cairo_image_surface_get_height (surface); render_corner (cr, surface, x, y + height - img_height, (gdouble) img_width, (gdouble) img_height); /* Bottom/right corner */ surface = slice->surfaces[BORDER_RIGHT][BORDER_BOTTOM]; img_width = cairo_image_surface_get_width (surface); img_height = cairo_image_surface_get_height (surface); render_corner (cr, surface, x + width - img_width, y + height - img_height, (gdouble) img_width, (gdouble) img_height); cairo_restore (cr); }
void render_image(struct window *window, cairo_surface_t *image, enum scaling_mode scaling_mode) { double width = cairo_image_surface_get_width(image); double height = cairo_image_surface_get_height(image); switch (scaling_mode) { case SCALING_MODE_STRETCH: cairo_scale(window->cairo, (double) window->width / width, (double) window->height / height); cairo_set_source_surface(window->cairo, image, 0, 0); break; case SCALING_MODE_FILL: { double window_ratio = (double) window->width / window->height; double bg_ratio = width / height; if (window_ratio > bg_ratio) { double scale = (double) window->width / width; cairo_scale(window->cairo, scale, scale); cairo_set_source_surface(window->cairo, image, 0, (double) window->height/2 / scale - height/2); } else { double scale = (double) window->height / height; cairo_scale(window->cairo, scale, scale); cairo_set_source_surface(window->cairo, image, (double) window->width/2 / scale - width/2, 0); } break; } case SCALING_MODE_FIT: { double window_ratio = (double) window->width / window->height; double bg_ratio = width / height; if (window_ratio > bg_ratio) { double scale = (double) window->height / height; cairo_scale(window->cairo, scale, scale); cairo_set_source_surface(window->cairo, image, (double) window->width/2 / scale - width/2, 0); } else { double scale = (double) window->width / width; cairo_scale(window->cairo, scale, scale); cairo_set_source_surface(window->cairo, image, 0, (double) window->height/2 / scale - height/2); } break; } case SCALING_MODE_CENTER: cairo_set_source_surface(window->cairo, image, (double) window->width/2 - width/2, (double) window->height/2 - height/2); break; case SCALING_MODE_TILE: { cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); cairo_set_source(window->cairo, pattern); break; } } cairo_paint(window->cairo); }
static int surface_get_gdk_pixbuf (lua_State *L) { cairo_surface_t **surface; cairo_format_t format; int width, height, stridei, strideo; unsigned char *buffer, *rowpo, *po; const char *rowpi, *pi; size_t buffer_len; int x, y; int has_alpha; surface = luaL_checkudata(L, 1, OOCAIRO_MT_NAME_SURFACE); if (cairo_surface_get_type(*surface) != CAIRO_SURFACE_TYPE_IMAGE) return luaL_error(L, "pixbufs can only be made from image surfaces"); format = cairo_image_surface_get_format(*surface); if (format != CAIRO_FORMAT_ARGB32 && format != CAIRO_FORMAT_RGB24) return luaL_error(L, "can't make pixbuf from this image format"); has_alpha = (format == CAIRO_FORMAT_ARGB32); width = cairo_image_surface_get_width(*surface); height = cairo_image_surface_get_height(*surface); stridei = cairo_image_surface_get_stride(*surface); if (has_alpha) strideo = stridei; /* might as well keep Cairo stride */ else strideo = ((3 * width) + 7) & ~7; /* align to 8 bytes */ buffer_len = strideo * height; buffer = malloc(buffer_len); assert(buffer); rowpi = (const char *) cairo_image_surface_get_data(*surface); rowpo = buffer; /* Copy pixels from Cairo's pixel format to GdkPixbuf's, which is slightly * different. */ if (IS_BIG_ENDIAN) { for (y = 0; y < height; ++y) { pi = rowpi; po = rowpo; for (x = 0; x < width; ++x) { *po++ = pi[1]; *po++ = pi[2]; *po++ = pi[3]; if (has_alpha) *po++ = pi[0]; pi += 4; } rowpi += stridei; rowpo += strideo; } } else { for (y = 0; y < height; ++y) { pi = rowpi; po = rowpo; for (x = 0; x < width; ++x) { *po++ = pi[2]; *po++ = pi[1]; *po++ = pi[0]; if (has_alpha) *po++ = pi[3]; pi += 4; } rowpi += stridei; rowpo += strideo; } } /* The buffer needs to be copied in to a Lua string so that it can * be passed to Lua-Gnome. */ lua_pushlstring(L, (const char *) buffer, buffer_len); free(buffer); /* Use Lua-Gnome function to construct the GdkPixbuf object, so that we * don't have to link directly with GDK, and so that the resulting object * can be used with the rest of Lua-Gnome. */ get_gtk_module_function(L, "gdk_pixbuf_new_from_data"); lua_pushvalue(L, -2); get_gtk_module_function(L, "GDK_COLORSPACE_RGB"); lua_pushboolean(L, has_alpha); lua_pushnumber(L, 8); lua_pushnumber(L, width); lua_pushnumber(L, height); lua_pushnumber(L, strideo); lua_pushnil(L); lua_pushnil(L); lua_call(L, 9, 1); /* Keep a reference to the Lua string used to store the data, since * it needs to be kept around for as long as the object is in use. */ lua_pushvalue(L, -2); lua_setfield(L, -2, "_pixbuf_buffer_string"); return 1; }
static void render_spect_border (cairo_surface_t * surface, const char * filename, double left, double width, double seconds, double top, double height, double min_freq, double max_freq, bool log_freq) { char text [512] ; cairo_t * cr ; cairo_text_extents_t extents ; cairo_matrix_t matrix ; TICKS ticks ; int k, tick_count ; cr = cairo_create (surface) ; cairo_set_source_rgb (cr, 1.0, 1.0, 1.0) ; cairo_set_line_width (cr, BORDER_LINE_WIDTH) ; /* Print title. */ cairo_select_font_face (cr, font_family, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL) ; cairo_set_font_size (cr, 1.0 * TITLE_FONT_SIZE) ; snprintf (text, sizeof (text), "Spectrogram: %s", filename) ; cairo_text_extents (cr, text, &extents) ; cairo_move_to (cr, left + 2, top - extents.height / 2) ; cairo_show_text (cr, text) ; /* Print labels. */ cairo_select_font_face (cr, font_family, CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL) ; cairo_set_font_size (cr, 1.0 * NORMAL_FONT_SIZE) ; /* Border around actual spectrogram. */ cairo_rectangle (cr, left, top, width, height) ; /* Put ticks on Time axis */ tick_count = calculate_ticks (0.0, seconds, width, false, &ticks) ; for (k = 0 ; k < tick_count ; k++) { y_line (cr, left + ticks.distance [k], top + height, TICK_LEN) ; if (JUST_A_TICK (ticks, k)) continue ; str_print_value (text, sizeof (text), ticks.value [k], ticks.decimal_places_to_print) ; cairo_text_extents (cr, text, &extents) ; cairo_move_to (cr, left + ticks.distance [k] - extents.width / 2, top + height + 8 + extents.height) ; cairo_show_text (cr, text) ; } ; /* Put ticks on Frequency axis */ tick_count = calculate_ticks (min_freq, max_freq, height, log_freq, &ticks) ; for (k = 0 ; k < tick_count ; k++) { x_line (cr, left + width, top + height - ticks.distance [k], TICK_LEN) ; if (JUST_A_TICK (ticks, k)) continue ; str_print_value (text, sizeof (text), ticks.value [k], ticks.decimal_places_to_print) ; cairo_text_extents (cr, text, &extents) ; cairo_move_to (cr, left + width + 12, top + height - ticks.distance [k] + extents.height / 4.5) ; cairo_show_text (cr, text) ; } ; cairo_set_font_size (cr, 1.0 * NORMAL_FONT_SIZE) ; /* Label X axis. */ snprintf (text, sizeof (text), "Time (secs)") ; cairo_text_extents (cr, text, &extents) ; cairo_move_to (cr, left + (width - extents.width) / 2, cairo_image_surface_get_height (surface) - 8) ; cairo_show_text (cr, text) ; /* Label Y axis (rotated). */ snprintf (text, sizeof (text), "Frequency (Hz)") ; cairo_text_extents (cr, text, &extents) ; cairo_get_font_matrix (cr, &matrix) ; cairo_matrix_rotate (&matrix, -0.5 * M_PI) ; cairo_set_font_matrix (cr, &matrix) ; cairo_move_to (cr, cairo_image_surface_get_width (surface) - 12, top + (height + extents.width) / 2) ; cairo_show_text (cr, text) ; cairo_destroy (cr) ; } /* render_spect_border */
void draw_shadow (cairo_t* cr, gdouble width, gdouble height, gint shadow_radius, gint corner_radius) { cairo_surface_t* tmp_surface = NULL; cairo_surface_t* new_surface = NULL; cairo_pattern_t* pattern = NULL; cairo_t* cr_surf = NULL; cairo_matrix_t matrix; raico_blur_t* blur = NULL; tmp_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 4 * shadow_radius, 4 * shadow_radius); if (cairo_surface_status (tmp_surface) != CAIRO_STATUS_SUCCESS) return; cr_surf = cairo_create (tmp_surface); if (cairo_status (cr_surf) != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy (tmp_surface); return; } cairo_scale (cr_surf, 1.0f, 1.0f); cairo_set_operator (cr_surf, CAIRO_OPERATOR_CLEAR); cairo_paint (cr_surf); cairo_set_operator (cr_surf, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (cr_surf, 0.0f, 0.0f, 0.0f, 0.75f); cairo_arc (cr_surf, 2 * shadow_radius, 2 * shadow_radius, 2.0f * corner_radius, 0.0f, 360.0f * (G_PI / 180.f)); cairo_fill (cr_surf); cairo_destroy (cr_surf); // create and setup blur blur = raico_blur_create (RAICO_BLUR_QUALITY_LOW); raico_blur_set_radius (blur, shadow_radius); // now blur it raico_blur_apply (blur, tmp_surface); // blur no longer needed raico_blur_destroy (blur); new_surface = cairo_image_surface_create_for_data ( cairo_image_surface_get_data (tmp_surface), cairo_image_surface_get_format (tmp_surface), cairo_image_surface_get_width (tmp_surface) / 2, cairo_image_surface_get_height (tmp_surface) / 2, cairo_image_surface_get_stride (tmp_surface)); pattern = cairo_pattern_create_for_surface (new_surface); if (cairo_pattern_status (pattern) != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy (tmp_surface); cairo_surface_destroy (new_surface); return; } // top left cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD); cairo_set_source (cr, pattern); cairo_rectangle (cr, 0.0f, 0.0f, width - 2 * shadow_radius, 2 * shadow_radius); cairo_fill (cr); // bottom left cairo_matrix_init_scale (&matrix, 1.0f, -1.0f); cairo_matrix_translate (&matrix, 0.0f, -height); cairo_pattern_set_matrix (pattern, &matrix); cairo_rectangle (cr, 0.0f, 2 * shadow_radius, 2 * shadow_radius, height - 2 * shadow_radius); cairo_fill (cr); // top right cairo_matrix_init_scale (&matrix, -1.0f, 1.0f); cairo_matrix_translate (&matrix, -width, 0.0f); cairo_pattern_set_matrix (pattern, &matrix); cairo_rectangle (cr, width - 2 * shadow_radius, 0.0f, 2 * shadow_radius, height - 2 * shadow_radius); cairo_fill (cr); // bottom right cairo_matrix_init_scale (&matrix, -1.0f, -1.0f); cairo_matrix_translate (&matrix, -width, -height); cairo_pattern_set_matrix (pattern, &matrix); cairo_rectangle (cr, 2 * shadow_radius, height - 2 * shadow_radius, width - 2 * shadow_radius, 2 * shadow_radius); cairo_fill (cr); // clean up cairo_pattern_destroy (pattern); cairo_surface_destroy (tmp_surface); cairo_surface_destroy (new_surface); }
static cairo_surface_t* _cairocks_create_embossed_surface( cairo_surface_t* surface, double azimuth, double elevation, double height, double ambient, double diffuse ) { unsigned char* src = cairo_image_surface_get_data(surface); int w = cairo_image_surface_get_width(surface); int h = cairo_image_surface_get_height(surface); int stride = cairo_image_surface_get_stride(surface); cairo_surface_t* dst_surface = cairo_image_surface_create(CAIRO_FORMAT_A8, w, h); unsigned char* dst = cairo_image_surface_get_data(dst_surface); double scale = height / (4.0f * 255.0f); double Lx = cos(azimuth) * cos(elevation); double Ly = sin(azimuth) * cos(elevation); double Lz = sin(elevation); int y; int x; memset(dst, minc(ambient + diffuse * Lz), stride * h); /* I'm going to set a minimum requirement size for embossing here for now, since the matrix "d" below assumes 3x3. Later, if it's necessary for such small surfaces, we could rectify this. */ if(w < 4 || h < 4) goto dirty_ret; for(y = 0; y < h; y++) { for(x = 0; x < w; x++) { double Nx; double Ny; double Nz; double NdotL; double d[3][3]; int i; int j; for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) { d[i][j] = (unsigned char)(src[OFFSET(x + i - 1, y + j - 1, w, h, stride)]); } } /* Compute the normal from the source. */ Nx = d[2][0] + (2.0f * d[2][1]) + d[2][2]; Nx -= d[0][0] + (2.0f * d[0][1]) + d[0][2]; Nx /= 9; Nx *= scale; Ny = d[0][2] + (2.0f * d[1][2]) + d[2][2]; Ny -= d[0][0] + (2.0f * d[1][0]) + d[2][0]; Ny /= 9; Ny *= scale; Nz = 0.5; NdotL = (Nx * Lx) + (Ny * Ly) + (Nz * Lz); NdotL = (NdotL > 0.0) ? NdotL : 0.0; dst[(y * stride) + x] = minc(ambient + (diffuse * NdotL)); } } dirty_ret: cairo_surface_mark_dirty(dst_surface); return dst_surface; }
bool wxGTKCairoDCImpl::DoStretchBlit(int xdest, int ydest, int dstWidth, int dstHeight, wxDC* source, int xsrc, int ysrc, int srcWidth, int srcHeight, wxRasterOperationMode rop, bool useMask, int xsrcMask, int ysrcMask) { wxCHECK_MSG(IsOk(), false, "invalid DC"); wxCHECK_MSG(source && source->IsOk(), false, "invalid source DC"); cairo_t* cr = NULL; if (m_graphicContext) cr = static_cast<cairo_t*>(m_graphicContext->GetNativeContext()); cairo_t* cr_src = NULL; wxGraphicsContext* gc_src = source->GetGraphicsContext(); if (gc_src) cr_src = static_cast<cairo_t*>(gc_src->GetNativeContext()); if (cr == NULL || cr_src == NULL) return false; const int xsrc_dev = source->LogicalToDeviceX(xsrc); const int ysrc_dev = source->LogicalToDeviceY(ysrc); cairo_surface_t* surfaceSrc = cairo_get_target(cr_src); cairo_surface_flush(surfaceSrc); cairo_surface_t* surfaceTmp = NULL; // If destination (this) and source wxDC refer to the same Cairo context // it means that we operate on one surface and results of drawing // can be invalid if destination and source regions overlap. // In such situation we have to copy source surface to the temporary // surface and use this copy in the drawing operations. if ( cr == cr_src ) { // Check if destination and source regions overlap. // If necessary, copy source surface to the temporary one. if (wxRect(xdest, ydest, dstWidth, dstHeight) .Intersects(wxRect(xsrc, ysrc, srcWidth, srcHeight))) { const int w = cairo_image_surface_get_width(surfaceSrc); const int h = cairo_image_surface_get_height(surfaceSrc); #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0) if ( cairo_version() >= CAIRO_VERSION_ENCODE(1, 12, 0) ) { surfaceTmp = cairo_surface_create_similar_image(surfaceSrc, cairo_image_surface_get_format(surfaceSrc), w, h); } else #endif // Cairo 1.12 { surfaceTmp = cairo_surface_create_similar(surfaceSrc, CAIRO_CONTENT_COLOR_ALPHA, w, h); } cairo_t* crTmp = cairo_create(surfaceTmp); cairo_set_source_surface(crTmp, surfaceSrc, 0, 0); cairo_rectangle(crTmp, 0.0, 0.0, w, h); cairo_set_operator(crTmp, CAIRO_OPERATOR_SOURCE); cairo_fill(crTmp); cairo_destroy(crTmp); cairo_surface_flush(surfaceTmp); surfaceSrc = surfaceTmp; } } cairo_save(cr); cairo_translate(cr, xdest, ydest); cairo_rectangle(cr, 0, 0, dstWidth, dstHeight); double sx, sy; source->GetUserScale(&sx, &sy); cairo_scale(cr, dstWidth / (sx * srcWidth), dstHeight / (sy * srcHeight)); cairo_set_source_surface(cr, surfaceSrc, -xsrc_dev, -ysrc_dev); const wxRasterOperationMode rop_save = m_logicalFunction; SetLogicalFunction(rop); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); cairo_surface_t* maskSurf = NULL; if (useMask) { const wxBitmap& bitmap = source->GetImpl()->GetSelectedBitmap(); if (bitmap.IsOk()) { wxMask* mask = bitmap.GetMask(); if (mask) maskSurf = *mask; } } if (maskSurf) { int xsrcMask_dev = xsrc_dev; int ysrcMask_dev = ysrc_dev; if (xsrcMask != -1) xsrcMask_dev = source->LogicalToDeviceX(xsrcMask); if (ysrcMask != -1) ysrcMask_dev = source->LogicalToDeviceY(ysrcMask); cairo_clip(cr); cairo_mask_surface(cr, maskSurf, -xsrcMask_dev, -ysrcMask_dev); } else { cairo_fill(cr); } cairo_restore(cr); if ( surfaceTmp ) { cairo_surface_destroy(surfaceTmp); } m_logicalFunction = rop_save; return true; }
static GtkWidget * gth_file_tool_resize_get_options (GthFileTool *base) { GthFileToolResize *self = (GthFileToolResize *) base; cairo_surface_t *source; GtkWidget *window; GtkWidget *viewer_page; GtkWidget *viewer; GtkAllocation allocation; int preview_width; int preview_height; GtkWidget *options; char *text; source = gth_image_viewer_page_tool_get_source (GTH_IMAGE_VIEWER_PAGE_TOOL (self)); if (source == NULL) return NULL; self->priv->original_width = cairo_image_surface_get_width (source); self->priv->original_height = cairo_image_surface_get_height (source); window = gth_file_tool_get_window (base); viewer_page = gth_browser_get_viewer_page (GTH_BROWSER (window)); viewer = gth_image_viewer_page_get_image_viewer (GTH_IMAGE_VIEWER_PAGE (viewer_page)); gtk_widget_get_allocation (GTK_WIDGET (viewer), &allocation); preview_width = self->priv->original_width; preview_height = self->priv->original_height; if (scale_keeping_ratio (&preview_width, &preview_height, allocation.width, allocation.height, FALSE)) self->priv->preview = _cairo_image_surface_scale_fast (source, preview_width, preview_height); else self->priv->preview = cairo_surface_reference (source); _gtk_widget_get_screen_size (window, &self->priv->screen_width, &self->priv->screen_height); self->priv->new_image = NULL; self->priv->new_width = self->priv->original_width; self->priv->new_height = self->priv->original_height; self->priv->high_quality = g_settings_get_boolean (self->priv->settings, PREF_RESIZE_HIGH_QUALITY); self->priv->unit = g_settings_get_enum (self->priv->settings, PREF_RESIZE_UNIT); self->priv->builder = _gtk_builder_new_from_file ("resize-options.ui", "file_tools"); self->priv->apply_to_original = FALSE; update_dimensione_info_label (self, "original_dimensions_label", self->priv->original_width, self->priv->original_height, TRUE); options = _gtk_builder_get_widget (self->priv->builder, "options"); gtk_widget_show (options); if (self->priv->unit == GTH_UNIT_PIXELS) { gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("resize_width_spinbutton")), 0); gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("resize_height_spinbutton")), 0); gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("resize_width_spinbutton")), g_settings_get_double (self->priv->settings, PREF_RESIZE_WIDTH)); gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("resize_height_spinbutton")), g_settings_get_double (self->priv->settings, PREF_RESIZE_HEIGHT)); } else if (self->priv->unit == GTH_UNIT_PERCENTAGE) { gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("resize_width_spinbutton")), 2); gtk_spin_button_set_digits (GTK_SPIN_BUTTON (GET_WIDGET ("resize_height_spinbutton")), 2); gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("resize_width_spinbutton")), g_settings_get_double (self->priv->settings, PREF_RESIZE_WIDTH)); gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("resize_height_spinbutton")), g_settings_get_double (self->priv->settings, PREF_RESIZE_HEIGHT)); } gtk_combo_box_set_active (GTK_COMBO_BOX (GET_WIDGET ("unit_combobox")), self->priv->unit); self->priv->ratio_combobox = _gtk_combo_box_new_with_texts (_("None"), _("Square"), NULL); text = g_strdup_printf (_("%d x %d (Image)"), self->priv->original_width, self->priv->original_height); gtk_label_set_text (GTK_LABEL (GET_WIDGET ("image_size_label")), text); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->priv->ratio_combobox), text); g_free (text); text = g_strdup_printf (_("%d x %d (Screen)"), self->priv->screen_width, self->priv->screen_height); gtk_label_set_text (GTK_LABEL (GET_WIDGET ("screen_size_label")), text); gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->priv->ratio_combobox), text); g_free (text); _gtk_combo_box_append_texts (GTK_COMBO_BOX_TEXT (self->priv->ratio_combobox), _("5:4"), _("4:3 (DVD, Book)"), _("7:5"), _("3:2 (Postcard)"), _("16:10"), _("16:9 (DVD)"), _("1.85:1"), _("2.39:1"), _("Custom"), NULL); gtk_widget_show (self->priv->ratio_combobox); gtk_box_pack_start (GTK_BOX (GET_WIDGET ("ratio_combobox_box")), self->priv->ratio_combobox, TRUE, TRUE, 0); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("high_quality_checkbutton")), self->priv->high_quality); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("invert_ratio_checkbutton")), g_settings_get_boolean (self->priv->settings, PREF_RESIZE_ASPECT_RATIO_INVERT)); gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("ratio_w_spinbutton")), MAX (g_settings_get_int (self->priv->settings, PREF_RESIZE_ASPECT_RATIO_WIDTH), 1)); gtk_spin_button_set_value (GTK_SPIN_BUTTON (GET_WIDGET ("ratio_h_spinbutton")), MAX (g_settings_get_int (self->priv->settings, PREF_RESIZE_ASPECT_RATIO_HEIGHT), 1)); g_signal_connect_swapped (GET_WIDGET ("options_close_button"), "clicked", G_CALLBACK (gtk_widget_hide), GET_WIDGET ("options_dialog")); g_signal_connect (GET_WIDGET ("options_dialog"), "delete-event", G_CALLBACK (gtk_widget_hide_on_delete), NULL); g_signal_connect (GET_WIDGET ("resize_width_spinbutton"), "value-changed", G_CALLBACK (selection_width_value_changed_cb), self); g_signal_connect (GET_WIDGET ("resize_height_spinbutton"), "value-changed", G_CALLBACK (selection_height_value_changed_cb), self); g_signal_connect (GET_WIDGET ("high_quality_checkbutton"), "toggled", G_CALLBACK (high_quality_checkbutton_toggled_cb), self); g_signal_connect (GET_WIDGET ("unit_combobox"), "changed", G_CALLBACK (unit_combobox_changed_cb), self); g_signal_connect (self->priv->ratio_combobox, "changed", G_CALLBACK (ratio_combobox_changed_cb), self); g_signal_connect (GET_WIDGET ("ratio_w_spinbutton"), "value_changed", G_CALLBACK (ratio_value_changed_cb), self); g_signal_connect (GET_WIDGET ("ratio_h_spinbutton"), "value_changed", G_CALLBACK (ratio_value_changed_cb), self); g_signal_connect (GET_WIDGET ("invert_ratio_checkbutton"), "toggled", G_CALLBACK (invert_ratio_changed_cb), self); g_signal_connect (GET_WIDGET ("image_size_button"), "clicked", G_CALLBACK (image_size_button_clicked_cb), self); g_signal_connect (GET_WIDGET ("screen_size_button"), "clicked", G_CALLBACK (screen_size_button_clicked_cb), self); gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->ratio_combobox), g_settings_get_enum (self->priv->settings, PREF_RESIZE_ASPECT_RATIO)); gth_image_viewer_set_zoom_quality (GTH_IMAGE_VIEWER (viewer), GTH_ZOOM_QUALITY_HIGH); return options; }
int main(int argc, char **argv) { char *image_path = NULL; char *scaling_mode_str = "fit"; init_log(L_INFO); static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"image", required_argument, NULL, 'i'}, {"scaling", required_argument, NULL, 's'}, {"tiling", no_argument, NULL, 't'}, {"version", no_argument, NULL, 'v'}, {0, 0, 0, 0} }; const char *usage = "Usage: swaylock [options...]\n" "\n" " -h, --help Show help message and quit.\n" " -s, --scaling Scaling mode: stretch, fill, fit, center, tile.\n" " -t, --tiling Same as --scaling=tile.\n" " -v, --version Show the version number and quit.\n" " -i, --image <path> Display the given image.\n"; int c; while (1) { int option_index = 0; c = getopt_long(argc, argv, "hi:s:tv", long_options, &option_index); if (c == -1) { break; } switch (c) { case 'i': image_path = optarg; break; case 's': scaling_mode_str = optarg; break; case 't': scaling_mode_str = "tile"; break; case 'v': #if defined SWAY_GIT_VERSION && defined SWAY_GIT_BRANCH && defined SWAY_VERSION_DATE fprintf(stdout, "swaylock version %s (%s, branch \"%s\")\n", SWAY_GIT_VERSION, SWAY_VERSION_DATE, SWAY_GIT_BRANCH); #else fprintf(stdout, "version not detected\n"); #endif exit(EXIT_SUCCESS); break; default: fprintf(stderr, "%s", usage); exit(EXIT_FAILURE); } } // TODO: support locking without image if (!image_path) { fprintf(stderr, "No image specified!\n"); exit(EXIT_FAILURE); } password = malloc(1024); // TODO: Let this grow password[0] = '\0'; surfaces = create_list(); registry = registry_poll(); if (!registry->swaylock) { sway_abort("swaylock requires the compositor to support the swaylock extension."); } int i; for (i = 0; i < registry->outputs->length; ++i) { struct output_state *output = registry->outputs->items[i]; struct window *window = window_setup(registry, output->width, output->height, true); if (!window) { sway_abort("Failed to create surfaces."); } list_add(surfaces, window); } registry->input->notify = notify_key; #ifdef WITH_GDK_PIXBUF GError *err = NULL; GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(image_path, &err); if (!pixbuf) { sway_abort("Failed to load background image."); } cairo_surface_t *image = gdk_cairo_image_surface_create_from_pixbuf(pixbuf); g_object_unref(pixbuf); #else cairo_surface_t *image = cairo_image_surface_create_from_png(argv[1]); #endif //WITH_GDK_PIXBUF if (!image) { sway_abort("Failed to read background image."); } double width = cairo_image_surface_get_width(image); double height = cairo_image_surface_get_height(image); enum scaling_mode scaling_mode = SCALING_MODE_STRETCH; if (strcmp(scaling_mode_str, "stretch") == 0) { scaling_mode = SCALING_MODE_STRETCH; } else if (strcmp(scaling_mode_str, "fill") == 0) { scaling_mode = SCALING_MODE_FILL; } else if (strcmp(scaling_mode_str, "fit") == 0) { scaling_mode = SCALING_MODE_FIT; } else if (strcmp(scaling_mode_str, "center") == 0) { scaling_mode = SCALING_MODE_CENTER; } else if (strcmp(scaling_mode_str, "tile") == 0) { scaling_mode = SCALING_MODE_TILE; } else { sway_abort("Unsupported scaling mode: %s", scaling_mode_str); } for (i = 0; i < surfaces->length; ++i) { struct window *window = surfaces->items[i]; if (window_prerender(window) && window->cairo) { switch (scaling_mode) { case SCALING_MODE_STRETCH: cairo_scale(window->cairo, (double) window->width / width, (double) window->height / height); cairo_set_source_surface(window->cairo, image, 0, 0); break; case SCALING_MODE_FILL: { double window_ratio = (double) window->width / window->height; double bg_ratio = width / height; if (window_ratio > bg_ratio) { double scale = (double) window->width / width; cairo_scale(window->cairo, scale, scale); cairo_set_source_surface(window->cairo, image, 0, (double) window->height/2 / scale - height/2); } else { double scale = (double) window->height / height; cairo_scale(window->cairo, scale, scale); cairo_set_source_surface(window->cairo, image, (double) window->width/2 / scale - width/2, 0); } break; } case SCALING_MODE_FIT: { double window_ratio = (double) window->width / window->height; double bg_ratio = width / height; if (window_ratio > bg_ratio) { double scale = (double) window->height / height; cairo_scale(window->cairo, scale, scale); cairo_set_source_surface(window->cairo, image, (double) window->width/2 / scale - width/2, 0); } else { double scale = (double) window->width / width; cairo_scale(window->cairo, scale, scale); cairo_set_source_surface(window->cairo, image, 0, (double) window->height/2 / scale - height/2); } break; } case SCALING_MODE_CENTER: cairo_set_source_surface(window->cairo, image, (double) window->width/2 - width/2, (double) window->height/2 - height/2); break; case SCALING_MODE_TILE: { cairo_pattern_t *pattern = cairo_pattern_create_for_surface(image); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); cairo_set_source(window->cairo, pattern); break; } default: sway_abort("Scaling mode '%s' not implemented yet!", scaling_mode_str); } cairo_paint(window->cairo); window_render(window); } } cairo_surface_destroy(image); bool locked = false; while (wl_display_dispatch(registry->display) != -1) { if (!locked) { for (i = 0; i < registry->outputs->length; ++i) { struct output_state *output = registry->outputs->items[i]; struct window *window = surfaces->items[i]; lock_set_lock_surface(registry->swaylock, output->output, window->surface); } locked = true; } } for (i = 0; i < surfaces->length; ++i) { struct window *window = surfaces->items[i]; window_teardown(window); } list_free(surfaces); registry_teardown(registry); return 0; }
void flush() { cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_A8, _totalWidth, _maxHeight); cairo_t *cr = cairo_create(surface); int pos = 0; cairo_set_source_rgba (cr, 0., 0., 0., 0); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_font_options_t *fontOptions = cairo_font_options_create(); cairo_get_font_options(cr, fontOptions); cairo_font_options_set_hint_style(fontOptions, CAIRO_HINT_STYLE_FULL); cairo_font_options_set_antialias(fontOptions, CAIRO_ANTIALIAS_GRAY); cairo_set_font_options(cr, fontOptions); cairo_font_options_destroy(fontOptions); cairo_set_source_rgba(cr, 1, 1, 1, 1); for(std::vector<element>::iterator it = _elements.begin(); it != _elements.end(); ++it) { cairo_move_to(cr, pos - it->xBearing, -it->yBearing); cairo_set_font_size(cr, it->fontSize); cairo_set_font_face(cr, it->fontFace); cairo_show_text(cr, it->text.c_str()); cairo_font_face_destroy(it->fontFace); pos += it->width; } cairo_destroy(cr); //setup matrices GLint matrixMode; GLuint textureId; glGetIntegerv (GL_MATRIX_MODE, &matrixMode); glMatrixMode (GL_PROJECTION); glPushMatrix(); glLoadIdentity (); glMatrixMode (GL_MODELVIEW); glPushMatrix(); glLoadIdentity (); float winw = Fl_Window::current()->w(); float winh = Fl_Window::current()->h(); glScalef (2.0f / winw, 2.0f / winh, 1.0f); glTranslatef (-winw / 2.0f, -winh / 2.0f, 0.0f); //write the texture on screen glEnable(GL_TEXTURE_RECTANGLE_ARB); glPushAttrib(GL_ENABLE_BIT | GL_TEXTURE_BIT | GL_COLOR_BUFFER_BIT); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_RECTANGLE_ARB, textureId); glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_ALPHA, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface), 0, GL_ALPHA, GL_UNSIGNED_BYTE, cairo_image_surface_get_data(surface)); //glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_SRC0_ALPHA); //printf("error %i %s\n", __LINE__, gluErrorString(glGetError())); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); pos = 0; for(std::vector<element>::iterator it = _elements.begin(); it != _elements.end(); ++it) { glTranslatef(it->x, it->y, it->z); glColor4f(it->r, it->g, it->b, it->alpha); int Lx = it->width; int Ly = it->height; glBegin (GL_QUADS); glTexCoord2f (pos, 0); glVertex2f (0.0f, Ly); glTexCoord2f (pos + Lx, 0); glVertex2f (Lx, Ly); glTexCoord2f (pos + Lx, Ly); glVertex2f (Lx, 0.0f); glTexCoord2f (pos, Ly); glVertex2f (0.0f, 0.0f); glEnd (); pos += Lx; glTranslatef(-it->x, -it->y, -it->z); } glDeleteTextures(1, &textureId); glPopAttrib(); // reset original matrices glPopMatrix(); // GL_MODELVIEW glMatrixMode (GL_PROJECTION); glPopMatrix(); glMatrixMode (matrixMode); _elements.clear(); _maxHeight = 0; _totalWidth = 0; cairo_surface_destroy(surface); }
GtkWidget *create_class_page (void) { #if 1 GtkWidget *vbox; gchar *path; vbox = gtk_vbox_new (FALSE, 0); priv->kb = utt_keyboard_new (); path = g_build_filename (PKGDATADIR, "keyboard_wubi.png", NULL); utt_keyboard_set_image (UTT_KEYBOARD (priv->kb), path); g_free (path); gtk_box_pack_start (GTK_BOX (vbox), priv->kb, FALSE, FALSE, 0); return vbox; #else GtkWidget *vbox; GtkWidget *frame, *hbox, *hbox2, *align; GtkWidget *ch_draw[6]; GtkWidget *kb_draw; cairo_surface_t *kb_image; gint i; gchar *path; vbox = gtk_vbox_new (FALSE, 0); frame = gtk_frame_new (_("Display Zone")); hbox = gtk_hbox_new (FALSE, 0); gtk_container_add (GTK_CONTAINER (frame), hbox); gtk_container_set_border_width (GTK_CONTAINER (frame), 4); gtk_container_set_border_width (GTK_CONTAINER (hbox), 4); gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); /* padding */ hbox2 = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), hbox2, TRUE, TRUE, 0); for (i = 0; i < 6; i++) { ch_draw[i] = gtk_drawing_area_new (); gtk_widget_set_size_request (ch_draw[i], 48, 48); hbox2 = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), hbox2, TRUE, TRUE, 0); align = gtk_alignment_new (0.5, 0.5, 0, 0); gtk_container_add (GTK_CONTAINER (align), ch_draw[i]); gtk_box_pack_start (GTK_BOX (hbox2), align, TRUE, TRUE, 0); } /* padding */ hbox2 = gtk_hbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (hbox), hbox2, TRUE, TRUE, 0); kb_draw = gtk_drawing_area_new (); path = g_build_filename (PKGDATADIR, "keyboard_wubi.png", NULL); if (!g_file_test (path, G_FILE_TEST_EXISTS)) { g_error (G_STRLOC ": %s doesn't exists.", path); } kb_image = cairo_image_surface_create_from_png (path); g_free (path); gtk_widget_add_events (kb_draw, GDK_KEY_PRESS_MASK); /* set can focus and grab focus, so we can receive key press event */ gtk_widget_set_can_focus (kb_draw, TRUE); gtk_widget_set_size_request (kb_draw, cairo_image_surface_get_width (kb_image), cairo_image_surface_get_height (kb_image)); align = gtk_alignment_new (0.5, 0.5, 0, 0); gtk_container_add (GTK_CONTAINER (align), kb_draw); gtk_container_set_border_width (GTK_CONTAINER (align), 4); gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0); return vbox; #endif }
guac_palette* guac_palette_alloc(cairo_surface_t* surface) { int x, y; int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); int stride = cairo_image_surface_get_stride(surface); unsigned char* data = cairo_image_surface_get_data(surface); /* Allocate palette */ guac_palette* palette = (guac_palette*) malloc(sizeof(guac_palette)); memset(palette, 0, sizeof(guac_palette)); for (y=0; y<height; y++) { for (x=0; x<width; x++) { /* Get pixel color */ int color = ((uint32_t*) data)[x] & 0xFFFFFF; /* Calculate hash code */ int hash = ((color & 0xFFF000) >> 12) ^ (color & 0xFFF); guac_palette_entry* entry; /* Search for open palette entry */ for (;;) { entry = &(palette->entries[hash]); /* If we've found a free space, use it */ if (entry->index == 0) { png_color* c; /* Stop if already at capacity */ if (palette->size == 256) { guac_palette_free(palette); return NULL; } /* Store in palette */ c = &(palette->colors[palette->size]); c->blue = (color ) & 0xFF; c->green = (color >> 8 ) & 0xFF; c->red = (color >> 16) & 0xFF; /* Add color to map */ entry->index = ++palette->size; entry->color = color; break; } /* Otherwise, if already stored here, done */ if (entry->color == color) break; /* Otherwise, collision. Move on to another bucket */ hash = (hash+1) & 0xFFF; } } /* Advance to next data row */ data += stride; }
static gpointer equalize_exec (GthAsyncTask *task, gpointer user_data) { EqualizeData *equalize_data = user_data; cairo_surface_t *source; cairo_format_t format; int width; int height; int source_stride; cairo_surface_t *destination; int destination_stride; unsigned char *p_source_line; unsigned char *p_destination_line; unsigned char *p_source; unsigned char *p_destination; gboolean cancelled; double progress; int x, y; unsigned char red, green, blue, alpha; /* initialize the extra data */ source = gth_image_task_get_source_surface (GTH_IMAGE_TASK (task)); equalize_histogram_setup (equalize_data, source); /* convert the image */ format = cairo_image_surface_get_format (source); width = cairo_image_surface_get_width (source); height = cairo_image_surface_get_height (source); source_stride = cairo_image_surface_get_stride (source); destination = cairo_image_surface_create (format, width, height); destination_stride = cairo_image_surface_get_stride (destination); p_source_line = _cairo_image_surface_flush_and_get_data (source); p_destination_line = _cairo_image_surface_flush_and_get_data (destination); for (y = 0; y < height; y++) { gth_async_task_get_data (task, NULL, &cancelled, NULL); if (cancelled) return NULL; progress = (double) y / height; gth_async_task_set_data (task, NULL, NULL, &progress); p_source = p_source_line; p_destination = p_destination_line; for (x = 0; x < width; x++) { CAIRO_GET_RGBA (p_source, red, green, blue, alpha); red = equalize_func (equalize_data, GTH_HISTOGRAM_CHANNEL_RED, red); green = equalize_func (equalize_data, GTH_HISTOGRAM_CHANNEL_GREEN, green); blue = equalize_func (equalize_data, GTH_HISTOGRAM_CHANNEL_BLUE, blue); CAIRO_SET_RGBA (p_destination, red, green, blue, alpha); p_source += 4; p_destination += 4; } p_source_line += source_stride; p_destination_line += destination_stride; } cairo_surface_mark_dirty (destination); gth_image_task_set_destination_surface (GTH_IMAGE_TASK (task), destination); cairo_surface_destroy (destination); cairo_surface_destroy (source); return NULL; }
/** * _st_create_shadow_cairo_pattern: * @shadow_spec: the definition of the shadow * @src_pattern: surface pattern for which we create the shadow * (must be a surface pattern) * * This is a utility function for creating shadows used by * st-theme-node.c; it's in this file to share the gaussian * blur implementation. The usage of this function is quite different * depending on whether shadow_spec->inset is %TRUE or not. If * shadow_spec->inset is %TRUE, the caller should pass in a @src_pattern * which is the <i>inverse</i> of what they want shadowed, and must take * care of the spread and offset from the shadow spec themselves. If * shadow_spec->inset is %FALSE then the caller should pass in what they * want shadowed directly, and this function takes care of the spread and * the offset. */ cairo_pattern_t * _st_create_shadow_cairo_pattern (StShadow *shadow_spec, cairo_pattern_t *src_pattern) { static cairo_user_data_key_t shadow_pattern_user_data; cairo_t *cr; cairo_surface_t *src_surface; cairo_surface_t *surface_in; cairo_surface_t *surface_out; cairo_pattern_t *dst_pattern; guchar *pixels_in, *pixels_out; gint width_in, height_in, rowstride_in; gint width_out, height_out, rowstride_out; cairo_matrix_t shadow_matrix; int i, j; g_return_val_if_fail (shadow_spec != NULL, NULL); g_return_val_if_fail (src_pattern != NULL, NULL); cairo_pattern_get_surface (src_pattern, &src_surface); width_in = cairo_image_surface_get_width (src_surface); height_in = cairo_image_surface_get_height (src_surface); /* We want the output to be a color agnostic alpha mask, * so we need to strip the color channels from the input */ if (cairo_image_surface_get_format (src_surface) != CAIRO_FORMAT_A8) { surface_in = cairo_image_surface_create (CAIRO_FORMAT_A8, width_in, height_in); cr = cairo_create (surface_in); cairo_set_source_surface (cr, src_surface, 0, 0); cairo_paint (cr); cairo_destroy (cr); } else { surface_in = cairo_surface_reference (src_surface); } pixels_in = cairo_image_surface_get_data (surface_in); rowstride_in = cairo_image_surface_get_stride (surface_in); pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in, shadow_spec->blur, &width_out, &height_out, &rowstride_out); cairo_surface_destroy (surface_in); /* Invert pixels for inset shadows */ if (shadow_spec->inset) { for (j = 0; j < height_out; j++) { guchar *p = pixels_out + rowstride_out * j; for (i = 0; i < width_out; i++, p++) *p = ~*p; } } surface_out = cairo_image_surface_create_for_data (pixels_out, CAIRO_FORMAT_A8, width_out, height_out, rowstride_out); cairo_surface_set_user_data (surface_out, &shadow_pattern_user_data, pixels_out, (cairo_destroy_func_t) g_free); dst_pattern = cairo_pattern_create_for_surface (surface_out); cairo_surface_destroy (surface_out); cairo_pattern_get_matrix (src_pattern, &shadow_matrix); if (shadow_spec->inset) { /* For inset shadows, offsets and spread radius have already been * applied to the original pattern, so all left to do is shift the * blurred image left, so that it aligns centered under the * unblurred one */ cairo_matrix_translate (&shadow_matrix, (width_out - width_in) / 2.0, (height_out - height_in) / 2.0); cairo_pattern_set_matrix (dst_pattern, &shadow_matrix); return dst_pattern; } /* Read all the code from the cairo_pattern_set_matrix call * at the end of this function to here from bottom to top, * because each new affine transformation is applied in * front of all the previous ones */ /* 6. Invert the matrix back */ cairo_matrix_invert (&shadow_matrix); /* 5. Adjust based on specified offsets */ cairo_matrix_translate (&shadow_matrix, shadow_spec->xoffset, shadow_spec->yoffset); /* 4. Recenter the newly scaled image */ cairo_matrix_translate (&shadow_matrix, - shadow_spec->spread, - shadow_spec->spread); /* 3. Scale up the blurred image to fill the spread */ cairo_matrix_scale (&shadow_matrix, (width_in + 2.0 * shadow_spec->spread) / width_in, (height_in + 2.0 * shadow_spec->spread) / height_in); /* 2. Shift the blurred image left, so that it aligns centered * under the unblurred one */ cairo_matrix_translate (&shadow_matrix, - (width_out - width_in) / 2.0, - (height_out - height_in) / 2.0); /* 1. Invert the matrix so we can work with it in pattern space */ cairo_matrix_invert (&shadow_matrix); cairo_pattern_set_matrix (dst_pattern, &shadow_matrix); return dst_pattern; }
int ink_cairo_surface_get_height(cairo_surface_t *surface) { assert(cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE); return cairo_image_surface_get_height(surface); }
static gpointer negative_exec (GthAsyncTask *task, gpointer user_data) { cairo_surface_t *source; cairo_format_t format; int width; int height; int source_stride; cairo_surface_t *destination; int destination_stride; unsigned char *p_source_line; unsigned char *p_destination_line; unsigned char *p_source; unsigned char *p_destination; gboolean cancelled; double progress; int x, y; unsigned char red, green, blue, alpha; source = gth_image_task_get_source_surface (GTH_IMAGE_TASK (task)); format = cairo_image_surface_get_format (source); width = cairo_image_surface_get_width (source); height = cairo_image_surface_get_height (source); source_stride = cairo_image_surface_get_stride (source); destination = cairo_image_surface_create (format, width, height); destination_stride = cairo_image_surface_get_stride (destination); p_source_line = _cairo_image_surface_flush_and_get_data (source); p_destination_line = _cairo_image_surface_flush_and_get_data (destination); for (y = 0; y < height; y++) { gth_async_task_get_data (task, NULL, &cancelled, NULL); if (cancelled) return NULL; progress = (double) y / height; gth_async_task_set_data (task, NULL, NULL, &progress); p_source = p_source_line; p_destination = p_destination_line; for (x = 0; x < width; x++) { CAIRO_GET_RGBA (p_source, red, green, blue, alpha); CAIRO_SET_RGBA (p_destination, 255 - red, 255 - green, 255 - blue, alpha); p_source += 4; p_destination += 4; } p_source_line += source_stride; p_destination_line += destination_stride; } cairo_surface_mark_dirty (destination); gth_image_task_set_destination_surface (GTH_IMAGE_TASK (task), destination); cairo_surface_destroy (destination); cairo_surface_destroy (source); return NULL; }
static gint get_surface_size (cairo_surface_t *surface) { return MAX (cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface)); }
static void render_to_surface (const RENDER * render, SNDFILE *infile, int samplerate, sf_count_t filelen, cairo_surface_t * surface) { float ** mag_spec = NULL ; // Indexed by [w][h] spectrum *spec ; double max_mag = 0.0 ; int width, height, w, speclen ; if (render->border) { width = lrint (cairo_image_surface_get_width (surface) - LEFT_BORDER - RIGHT_BORDER) ; height = lrint (cairo_image_surface_get_height (surface) - TOP_BORDER - BOTTOM_BORDER) ; } else { width = render->width ; height = render->height ; } if (width < 1) { printf ("Error : 'width' parameter must be >= %d\n", render->border ? (int) (LEFT_BORDER + RIGHT_BORDER) + 1 : 1) ; exit (1) ; } ; if (height < 1) { printf ("Error : 'height' parameter must be >= %d\n", render->border ? (int) (TOP_BORDER + BOTTOM_BORDER) + 1 : 1) ; exit (1) ; } ; /* ** Choose a speclen value, the spectrum length. ** The FFT window size is twice this. */ if (render->fft_freq != 0.0) /* Choose an FFT window size of 1/fft_freq seconds of audio */ speclen = (samplerate / render->fft_freq + 1) / 2 ; else /* Long enough to represent frequencies down to 20Hz. */ speclen = height * (samplerate / 20 / height + 1) ; /* Find the nearest fast value for the FFT size. */ { int d ; /* difference */ for (d = 0 ; /* Will terminate */ ; d++) { /* Logarithmically, the integer above is closer than ** the integer below, so prefer it to the one below. */ if (is_good_speclen (speclen + d)) { speclen += d ; break ; } /* FFT length must also be >= the output height, ** otherwise repeated pixel rows occur in the output. */ if (speclen - d >= height && is_good_speclen (speclen - d)) { speclen -= d ; break ; } } } mag_spec = calloc (width, sizeof (float *)) ; if (mag_spec == NULL) { printf ("%s : Not enough memory.\n", __func__) ; exit (1) ; } ; for (w = 0 ; w < width ; w++) { if ((mag_spec [w] = calloc (height, sizeof (float))) == NULL) { printf ("%s : Not enough memory.\n", __func__) ; exit (1) ; } ; } ; spec = create_spectrum (speclen, render->window_function) ; if (spec == NULL) { printf ("%s : line %d : create plan failed.\n", __FILE__, __LINE__) ; exit (1) ; } ; for (w = 0 ; w < width ; w++) { double single_max ; read_mono_audio (infile, filelen, spec->time_domain, 2 * speclen, w, width) ; single_max = calc_magnitude_spectrum (spec) ; max_mag = MAX (max_mag, single_max) ; interp_spec (mag_spec [w], height, spec->mag_spec, speclen, render, samplerate) ; } ; destroy_spectrum (spec) ; if (render->border) { RECT heat_rect ; heat_rect.left = 12 ; heat_rect.top = TOP_BORDER + TOP_BORDER / 2 ; heat_rect.width = 12 ; heat_rect.height = height - TOP_BORDER / 2 ; render_spectrogram (surface, render->spec_floor_db, mag_spec, max_mag, LEFT_BORDER, TOP_BORDER, width, height, render->gray_scale) ; render_heat_map (surface, render->spec_floor_db, &heat_rect, render->gray_scale) ; render_spect_border (surface, render->filename, LEFT_BORDER, width, filelen / (1.0 * samplerate), TOP_BORDER, height, render->min_freq, render->max_freq, render->log_freq) ; render_heat_border (surface, render->spec_floor_db, &heat_rect) ; } else render_spectrogram (surface, render->spec_floor_db, mag_spec, max_mag, 0, 0, width, height, render->gray_scale) ; for (w = 0 ; w < width ; w++) free (mag_spec [w]) ; free (mag_spec) ; return ; } /* render_to_surface */
bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool ignoreGammaAndColorProfile) { // This implementation is taken from GraphicsContext3DCairo. if (!m_image) return false; // We need this to stay in scope because the native image is just a shallow copy of the data. m_decoder = new ImageSource(premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied, ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied); if (!m_decoder) return false; ImageSource& decoder = *m_decoder; m_alphaOp = AlphaDoNothing; if (m_image->data()) { decoder.setData(m_image->data(), true); if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0)) return false; m_imageSurface = decoder.createFrameAtIndex(0); } else { m_imageSurface = m_image->nativeImageForCurrentFrame(); // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value is 0xFF for each pixel, // which is true at present and may be changed in the future and needs adjustment accordingly. // 2. For texImage2D with HTMLCanvasElement input in which Alpha is already Premultiplied in this port, // do AlphaDoUnmultiply if UNPACK_PREMULTIPLY_ALPHA_WEBGL is set to false. if (!premultiplyAlpha && m_imageHtmlDomSource != HtmlDomVideo) m_alphaOp = AlphaDoUnmultiply; } if (!m_imageSurface) return false; m_imageWidth = cairo_image_surface_get_width(m_imageSurface.get()); m_imageHeight = cairo_image_surface_get_height(m_imageSurface.get()); if (!m_imageWidth || !m_imageHeight) return false; if (cairo_image_surface_get_format(m_imageSurface.get()) != CAIRO_FORMAT_ARGB32) return false; uint srcUnpackAlignment = 1; size_t bytesPerRow = cairo_image_surface_get_stride(m_imageSurface.get()); size_t bitsPerPixel = 32; unsigned padding = bytesPerRow - bitsPerPixel / 8 * m_imageWidth; if (padding) { srcUnpackAlignment = padding + 1; while (bytesPerRow % srcUnpackAlignment) ++srcUnpackAlignment; } m_imagePixelData = cairo_image_surface_get_data(m_imageSurface.get()); m_imageSourceFormat = DataFormatBGRA8; m_imageSourceUnpackAlignment = srcUnpackAlignment; return true; }
void gui_init(dt_lib_module_t *self) { char filename[PATH_MAX] = { 0 }; char datadir[PATH_MAX] = { 0 }; /* initialize ui widgets */ dt_lib_darktable_t *d = (dt_lib_darktable_t *)g_malloc0(sizeof(dt_lib_darktable_t)); self->data = (void *)d; /* create drawing area */ self->widget = gtk_event_box_new(); /* connect callbacks */ g_signal_connect(G_OBJECT(self->widget), "draw", G_CALLBACK(_lib_darktable_draw_callback), self); g_signal_connect(G_OBJECT(self->widget), "button-press-event", G_CALLBACK(_lib_darktable_button_press_callback), self); /* create a cairo surface of dt icon */ char *logo; dt_logo_season_t season = get_logo_season(); if(season != DT_LOGO_SEASON_NONE) logo = g_strdup_printf("%%s/pixmaps/idbutton-%d.%%s", (int)season); else logo = g_strdup("%s/pixmaps/idbutton.%s"); dt_loc_get_datadir(datadir, sizeof(datadir)); snprintf(filename, sizeof(filename), logo, datadir, "svg"); // first we try the SVG { GError *error = NULL; RsvgHandle *svg = rsvg_handle_new_from_file(filename, &error); if(!svg || error) { fprintf(stderr, "warning: can't load darktable logo from SVG file `%s', falling back to PNG version\n%s\n", filename, error->message); g_error_free(error); error = NULL; goto png_fallback; } cairo_surface_t *surface; cairo_t *cr; RsvgDimensionData dimension; rsvg_handle_get_dimensions(svg, &dimension); int width = DT_PIXEL_APPLY_DPI(dimension.width) * darktable.gui->ppd, height = DT_PIXEL_APPLY_DPI(dimension.height) * darktable.gui->ppd; int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); d->image_buffer = (guint8 *)calloc(stride * height, sizeof(guint8)); surface = dt_cairo_image_surface_create_for_data(d->image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride); if(cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) { free(d->image_buffer); d->image_buffer = NULL; g_object_unref(svg); fprintf(stderr, "warning: can't load darktable logo from SVG file `%s', falling back to PNG version\n", filename); goto png_fallback; } cr = cairo_create(surface); cairo_scale(cr, darktable.gui->dpi_factor, darktable.gui->dpi_factor); rsvg_handle_render_cairo(svg, cr); cairo_destroy(cr); cairo_surface_flush(surface); d->image = surface; g_object_unref(svg); } goto done; png_fallback: // let's fall back to the PNG { cairo_surface_t *surface; cairo_t *cr; snprintf(filename, sizeof(filename), logo, datadir, "png"); surface = cairo_image_surface_create_from_png(filename); if(cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "warning: can't load darktable logo from PNG file `%s'\n", filename); d->image = NULL; goto done; } int png_width = cairo_image_surface_get_width(surface), png_height = cairo_image_surface_get_height(surface); // blow up the PNG. Ugly, but at least it has the correct size afterwards :-/ int width = DT_PIXEL_APPLY_DPI(png_width) * darktable.gui->ppd, height = DT_PIXEL_APPLY_DPI(png_height) * darktable.gui->ppd; int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width); d->image_buffer = (guint8 *)calloc(stride * height, sizeof(guint8)); d->image = dt_cairo_image_surface_create_for_data(d->image_buffer, CAIRO_FORMAT_ARGB32, width, height, stride); if(cairo_surface_status(d->image) != CAIRO_STATUS_SUCCESS) { free(d->image_buffer); d->image_buffer = NULL; cairo_surface_destroy(surface); fprintf(stderr, "warning: can't load darktable logo from PNG file `%s'\n", filename); d->image = NULL; goto done; } cr = cairo_create(d->image); cairo_rectangle(cr, 0, 0, width, height); cairo_scale(cr, darktable.gui->dpi_factor, darktable.gui->dpi_factor); cairo_set_source_surface(cr, surface, 0, 0); cairo_fill(cr); cairo_destroy(cr); cairo_surface_flush(d->image); cairo_surface_destroy(surface); } done: g_free(logo); d->image_width = d->image ? dt_cairo_image_surface_get_width(d->image) : 0; d->image_height = d->image ? dt_cairo_image_surface_get_height(d->image) : 0; /* set size of drawing area */ gtk_widget_set_size_request(self->widget, d->image_width + (int)DT_PIXEL_APPLY_DPI(180), d->image_height + (int)DT_PIXEL_APPLY_DPI(8)); }
/* * function to draw the rectangular selection */ static void paint_selection (cairo_t *ci, Detect * d) { double t = microtime(); int w = cairo_image_surface_get_width (surface); int h = cairo_image_surface_get_height (surface); /** draw brush */ /* cairo_surface_t* test; cairo_t *cb; double brush_w = 70, brush_h = 70; int w = cairo_image_surface_get_width (image); int h = cairo_image_surface_get_height (image); test = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, w, h ); cb = cairo_create(test); cairo_scale (cb, brush_w/w, brush_h/h); cairo_set_source_surface (cb, image, 0, 0); cairo_mask_surface(cb, test, 0, 0); cairo_paint(cb); cairo_destroy (cb); // cairo_set_source_rgb (ci, 0.5,0.5,0.5); cairo_paint(ci); cairo_set_source_surface (ci, test, mouse->x-(brush_w/2),mouse->y-(brush_h/2)); cairo_paint(ci); */ d_events * events; d_events::iterator it_events; events = d->GetEvents(); MousePosition mouse; /* mouse->x = 100; mouse->y = 100; mouse->prev_x = 250; mouse->prev_y = 100;*/ //cairo_save (ci); //printf("size %d \n",events->size()); for(it_events = events->begin(); it_events!= events->end(); it_events++){ if(it_events->second.live ){ mouse.x = (gint) (w*(1-it_events->second.x)); mouse.y = (gint) (h*it_events->second.y); mouse.prev_x = (gint) (w*(1-it_events->second.last[1].x)); mouse.prev_y = (gint) (h*(it_events->second.last[1].y)); mouse.bold = it_events->second.size; // printf("mouse: %d %d %d | ", mouse.x, mouse.y, mouse.bold); //printf("mouse: %d %d %d | ", mouse.prev_x, mouse.prev_y, mouse.bold); //printf("mouse: %f %f | %f %f \n", it_events->second.x, it_events->second.y, it_events->second.last[1].x, it_events->second.last[1].y); /*cairo_set_source_rgba (ci, 255,0,0, 1.); cairo_arc (ci, mouse.x,mouse.y, 20, 0, 2 * M_PI); cairo_fill_preserve (ci); cairo_stroke (ci);*/ //printf("%f %f\n",mouse->f_x,mouse->f_y); //if(!(mouse->f_x>0 && mouse->f_y > 0)) return; //mouse->x = (int) (w-mouse->f_x*w); //mouse->y = (int) (mouse->f_y*h); //printf("(%d %d) %d %d < %f %f\n",w,h,mouse->x,mouse->y,mouse->f_x,mouse->f_y); /* proložení vykreslování */ float test_t = sqrt(pow(mouse.x-mouse.prev_x,2) + pow(mouse.y-mouse.prev_y,2)); int size_brush; //omezení pokud jsou velké skoky if(test_t==0 || test_t > 100) break; if(brush_type == 0 || brush_type==3){ size_brush = (mouse.bold / 2) - 5; if(size_brush < 5) size_brush = 5; if(size_brush > 20) size_brush = 20; cairo_set_line_width (ci, 0.); } else { size_brush = mouse.bold / 10; if(size_brush > 5) size_brush = 5; if(size_brush < 1) size_brush = 1; } // printf("brush %d \n", size_brush); int step = int (test_t/size_brush); int rate_rand = 10; //printf("%d %d\n",size_brush, mouse->bold); //délka jednoho tahu double step_x = (mouse.x - mouse.prev_x)/(double) step; double step_y = (mouse.y - mouse.prev_y)/(double) step; float aplha = 1.; if (brush_type == 3) aplha = 0.3; if(brush_type == 2) { aplha = 0.2; // size_brush = 5; } // printf("color: %f %f %f\n",color.r, color.g, color.b); /* proložení ploch */ if(brush_type == 0){ for(int i=0; i < step+1; i++){ if(brush_type == 0){ cairo_set_source_rgba (ci, color.r, color.g, color.b, 1.); cairo_arc (ci, mouse.prev_x+step_x*i,mouse.prev_y+step_y*i, size_brush, 0, 2 * M_PI); cairo_fill_preserve (ci); cairo_stroke (ci); } else { cairo_set_source_rgba (ci, color.r, color.g, color.b, aplha); for(int j=0; j < 5; j++){ // printf("%f ",10*(drand48()*2.-1.)); cairo_arc (ci, (mouse.prev_x+step_x*i)+rate_rand*(drand48()*2.-1.), (mouse.prev_y+step_y*i)+rate_rand*(drand48()*2.-1.), size_brush, 0, 2 * M_PI); cairo_fill_preserve (ci); cairo_stroke (ci); } } } } //vykreslení plochy if(brush_type == 0){ cairo_set_source_rgba (ci, color.r, color.g, color.b, 1.); cairo_arc (ci, mouse.x, mouse.y, size_brush, 0, 2 * M_PI); cairo_fill_preserve (ci); cairo_stroke (ci); } else { cairo_set_source_rgba (ci, color.r, color.g, color.b, aplha); for(int j=0; j < 8; j++){ // printf("%f ",10*(drand48()*2.-1.)); cairo_arc (ci, mouse.x+rate_rand*(drand48()*2.5-1.), mouse.y+rate_rand*(drand48()*2.5-1.), ((int) size_brush), 0, 2 * M_PI); cairo_fill_preserve (ci); cairo_stroke (ci); } } } } // cairo_restore (ci); if(image!=NULL){ int _w = cairo_image_surface_get_width (image); int _h = cairo_image_surface_get_height (image); //cairo_surface_t* test; //cairo_t *cb; //test = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, _w, _h ); //printf("%d %d\n",_w,_h); //cb = cairo_create(test); cairo_scale (ci, w/(double)_w, h/(double)_h); cairo_set_source_surface (ci, image, 0, 0); cairo_paint(ci); } cairo_restore (ci); timer[1] = microtime() - t; }
int main(int argc, char** argv) { int c; float col_r, col_g, col_b = -1.0f; Options opt; while ((c = getopt(argc, argv, "a:x:y:f:s:t:n:w:r:g:b:c:")) != -1) { switch(c) { /* color */ /* ------------------------------------------------------- */ case 'r': { col_r = convert_type<float>(optarg); break; } case 'g': { col_g = convert_type<float>(optarg); break; } case 'b': { col_b = convert_type<float>(optarg); break; } /* ------------------------------------------------------- */ /* foreground */ case 'c': { opt.foreground_file = convert_type<std::string>(optarg); break; } /* ------------------------------------------------------- */ /* background */ case 'x': { opt.background_x = convert_type<int>(optarg); break; } case 'y': { opt.background_y = convert_type<int>(optarg); break; } case 'f': { //printf("Got: %s", optarg); opt.background_file = convert_type<std::string>(optarg); break; } /* ------------------------------------------------------- */ /* visible size */ case 'a': { opt.visible_size = convert_type<float>(optarg); break; } /* ------------------------------------------------------- */ /* name */ case 'n': { opt.name = convert_type<std::string>(optarg); /* we expect that r,g,b has been set */ if (0 > col_r) { printf("Error: you haven't set -r -g -b for the name.\n"); exit(EXIT_FAILURE); } opt.name_r = col_r; opt.name_g = col_g; opt.name_b = col_b; break; } /* name x position */ case 's': { opt.name_x = convert_type<int>(optarg); break; } /* name y position */ case 't': { opt.name_y = convert_type<int>(optarg); break; } /* name font size */ case 'w': { opt.name_font_size = convert_type<float>(optarg); break; } default: { printf("Unkown option\n"); break; } } } if (false == opt.validate()) { printf("+ error: cannot validate the given options.\n"); exit(EXIT_FAILURE); } opt.print(); /* ------------------------------------------------------------------------------------ */ Image img; std::string path; std::string ext; cairo_surface_t* surf_bg = NULL; cairo_format_t img_format = CAIRO_FORMAT_INVALID; path = opt.foreground_file; if (false == rx_file_exists(path)) { printf("+ error: cannot find the file: %s\n", path.c_str()); exit(EXIT_FAILURE); } cairo_surface_t* surf_overlay = cairo_image_surface_create_from_png(path.c_str()); if (NULL == surf_overlay) { printf("Error: cannot create s1\n"); exit(EXIT_FAILURE); } path = opt.background_file; if (false == rx_file_exists(path)) { printf("Error: file doesn't exist: %s\n", path.c_str()); exit(EXIT_FAILURE); } /* check what file type was given. */ ext = rx_get_file_ext(path); if (ext == "jpg") { printf("+ warning: jpg as input doesn't seem to work\n"); /* cairo doesn't have support for PNG? */ if (0 > rx_load_jpg(path, &img.pixels, img.width, img.height, img.channels)) { printf("Error: failed to load: %s\n", path.c_str()); exit(EXIT_FAILURE); } if (0 == img.width || 0 == img.height || 0 == img.channels) { printf("Error: image has invalid flags: %d x %d, channels: %d\n", img.width, img.height, img.channels); exit(EXIT_FAILURE); } if (3 == img.channels) { img_format = CAIRO_FORMAT_RGB24; printf("+ Using RGB24\n"); } else if(4 == img.channels) { img_format = CAIRO_FORMAT_ARGB32; printf("+ Using ARGB32\n"); } else { printf("Error: unsupported number of channels: %d.\n", img.channels); exit(EXIT_FAILURE); } if (NULL != img.pixels && NULL == surf_bg) { printf("Stride: %d\n", cairo_format_stride_for_width(img_format, img.width)); printf("Info: creating %d x %d, channels: %d\n", img.width, img.height, img.channels); surf_bg = cairo_image_surface_create_for_data(img.pixels, img_format, img.width, img.height, cairo_format_stride_for_width(img_format, img.width)); #if 0 /* TESTING */ cairo_t* cr = cairo_create(surf_bg); if (NULL == cr) { printf("Error: cannot create the cairo"); exit(EXIT_FAILURE); } path = rx_get_exe_path() +"/generated_polaroid.png"; cairo_surface_write_to_png(surf_bg, path.c_str()); printf("Created\n"); exit(0); /* END TESTING */ #endif } } else if (ext == "png") { /* use cairo png load feature. */ surf_bg = cairo_image_surface_create_from_png(path.c_str()); if (NULL == surf_bg) { printf("Error: cannot create s2\n"); exit(EXIT_FAILURE); } } else { printf("Error: unsupported file format: %s\n", ext.c_str()); exit(EXIT_FAILURE); } /* make sure the background is loaded correctly (aka the photo) */ if (NULL == surf_bg) { printf("Error: cannot create background surface.\n"); exit(EXIT_FAILURE); } if (CAIRO_STATUS_SUCCESS != cairo_surface_status(surf_bg)) { printf("Error: something went wrong: %d\n", cairo_surface_status(surf_bg)); exit(EXIT_FAILURE); } float source_width = cairo_image_surface_get_width(surf_bg); float source_height = cairo_image_surface_get_height(surf_bg); /* create output */ int dest_width = cairo_image_surface_get_width(surf_overlay); int dest_height = cairo_image_surface_get_height(surf_overlay); printf("+ Output size: %d x %d\n", dest_width, dest_height); cairo_surface_t* surf_out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dest_width, dest_height); if (NULL == surf_out) { printf("Error: cannot create cairo_surface_t\n"); exit(EXIT_FAILURE); } printf("+ Info: creating output surface: %d x %d\n", dest_width, dest_height); cairo_t* cr = cairo_create(surf_out); if (NULL == cr) { printf("Error: cannot create the cairo"); exit(EXIT_FAILURE); } /* fill background. */ cairo_set_source_rgba(cr, 1, 1, 1, 1); cairo_paint(cr); float scale_factor = opt.visible_size / source_width; printf("+ Scale factor: %f\n", scale_factor); /* paint background */ cairo_save(cr); cairo_scale(cr, scale_factor, scale_factor); cairo_set_source_surface(cr, surf_bg, opt.background_x, opt.background_y); cairo_rectangle(cr, 0, 0, img.width, img.height); cairo_paint(cr); cairo_restore(cr); /* paint overlay */ cairo_set_source_surface(cr, surf_overlay, 0, 0); cairo_paint(cr); cairo_surface_flush(surf_out); /* font */ cairo_select_font_face(cr, "Open Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_set_source_rgba(cr, opt.name_r, opt.name_g, opt.name_b, 1.0); cairo_move_to(cr, opt.name_x, opt.name_y); cairo_set_font_size(cr, opt.name_font_size); cairo_show_text(cr, opt.name.c_str()); cairo_stroke(cr); cairo_fill(cr); cairo_surface_flush(surf_out); /* write out */ path = rx_get_exe_path() +"/generated_polaroid.png"; cairo_surface_write_to_png(surf_out, path.c_str()); /* cleanup */ cairo_surface_destroy(surf_out); cairo_surface_destroy(surf_bg); cairo_surface_destroy(surf_overlay); cairo_destroy(cr); printf("\n"); return 0; }
static cairo_status_t png_diff (const char *filename_a, const char *filename_b, const char *filename_diff, int ax, int ay, int bx, int by, buffer_diff_result_t *result) { cairo_surface_t *surface_a; cairo_surface_t *surface_b; cairo_surface_t *surface_diff; cairo_status_t status; surface_a = cairo_image_surface_create_from_png (filename_a); status = cairo_surface_status (surface_a); if (status) { fprintf (stderr, "Error: Failed to create surface from %s: %s\n", filename_a, cairo_status_to_string (status)); return status; } surface_b = cairo_image_surface_create_from_png (filename_b); status = cairo_surface_status (surface_b); if (status) { fprintf (stderr, "Error: Failed to create surface from %s: %s\n", filename_b, cairo_status_to_string (status)); cairo_surface_destroy (surface_a); return status; } if (ax || ay) { extract_sub_surface (&surface_a, ax, ay); ax = ay = 0; } if (bx || by) { extract_sub_surface (&surface_b, bx, by); bx = by = 0; } status = cairo_surface_status (surface_a); if (status) { fprintf (stderr, "Error: Failed to extract surface from %s: %s\n", filename_a, cairo_status_to_string (status)); cairo_surface_destroy (surface_a); cairo_surface_destroy (surface_b); return status; } status = cairo_surface_status (surface_b); if (status) { fprintf (stderr, "Error: Failed to extract surface from %s: %s\n", filename_b, cairo_status_to_string (status)); cairo_surface_destroy (surface_a); cairo_surface_destroy (surface_b); return status; } surface_diff = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, cairo_image_surface_get_width (surface_a), cairo_image_surface_get_height (surface_a)); status = cairo_surface_status (surface_diff); if (status) { fprintf (stderr, "Error: Failed to allocate surface to hold differences\n"); cairo_surface_destroy (surface_a); cairo_surface_destroy (surface_b); return CAIRO_STATUS_NO_MEMORY; } status = image_diff (NULL, surface_a, surface_b, surface_diff, result); cairo_surface_destroy (surface_a); cairo_surface_destroy (surface_b); cairo_surface_destroy (surface_diff); _xunlink (filename_diff); if (status == CAIRO_STATUS_SUCCESS && result->pixels_changed) { status = write_png (surface_diff, filename_diff); } return status; }
static gpointer grayscale_exec (GthAsyncTask *task, gpointer user_data) { GrayscaleData *grayscale_data = user_data; cairo_surface_t *source; cairo_format_t format; int width; int height; int source_stride; cairo_surface_t *destination; int destination_stride; unsigned char *p_source_line; unsigned char *p_destination_line; unsigned char *p_source; unsigned char *p_destination; gboolean cancelled; double progress; int x, y; unsigned char red, green, blue, alpha; unsigned char min, max, value; source = gth_image_task_get_source_surface (GTH_IMAGE_TASK (task)); format = cairo_image_surface_get_format (source); width = cairo_image_surface_get_width (source); height = cairo_image_surface_get_height (source); source_stride = cairo_image_surface_get_stride (source); destination = cairo_image_surface_create (format, width, height); destination_stride = cairo_image_surface_get_stride (destination); p_source_line = _cairo_image_surface_flush_and_get_data (source); p_destination_line = _cairo_image_surface_flush_and_get_data (destination); for (y = 0; y < height; y++) { gth_async_task_get_data (task, NULL, &cancelled, NULL); if (cancelled) return NULL; progress = (double) y / height; gth_async_task_set_data (task, NULL, NULL, &progress); p_source = p_source_line; p_destination = p_destination_line; for (x = 0; x < width; x++) { CAIRO_GET_RGBA (p_source, red, green, blue, alpha); switch (grayscale_data->method) { case METHOD_BRIGHTNESS: value = (0.2125 * red + 0.7154 * green + 0.072 * blue); break; case METHOD_SATURATION: max = MAX (MAX (red, green), blue); min = MIN (MIN (red, green), blue); value = (max + min) / 2; break; case METHOD_AVARAGE: value = (0.3333 * red + 0.3333 * green + 0.3333 * blue); break; default: g_assert_not_reached (); } CAIRO_SET_RGBA (p_destination, value, value, value, alpha); p_source += 4; p_destination += 4; } p_source_line += source_stride; p_destination_line += destination_stride; } cairo_surface_mark_dirty (destination); gth_image_task_set_destination_surface (GTH_IMAGE_TASK (task), destination); cairo_surface_destroy (destination); cairo_surface_destroy (source); return NULL; }
BufferData * _create_buffer_similar (BufferData *buffer) { return _create_buffer (cairo_image_surface_get_width (buffer->surface), cairo_image_surface_get_height (buffer->surface)); }
static const char * write_ppm (cairo_surface_t *surface, int fd) { char buf[4096]; cairo_format_t format; const char *format_str; const unsigned char *data; int len; int width, height, stride; int i, j; data = cairo_image_surface_get_data (surface); height = cairo_image_surface_get_height (surface); width = cairo_image_surface_get_width (surface); stride = cairo_image_surface_get_stride (surface); format = cairo_image_surface_get_format (surface); if (format == CAIRO_FORMAT_ARGB32) { /* see if we can convert to a standard ppm type and trim a few bytes */ const unsigned char *alpha = data; for (j = height; j--; alpha += stride) { for (i = 0; i < width; i++) { if ((*(unsigned int *) (alpha+4*i) & 0xff000000) != 0xff000000) goto done; } } format = CAIRO_FORMAT_RGB24; done: ; } switch (format) { case CAIRO_FORMAT_ARGB32: /* XXX need true alpha for svg */ format_str = "P7"; break; case CAIRO_FORMAT_RGB24: format_str = "P6"; break; case CAIRO_FORMAT_A8: format_str = "P5"; break; case CAIRO_FORMAT_A1: case CAIRO_FORMAT_RGB16_565: case CAIRO_FORMAT_RGB30: case CAIRO_FORMAT_INVALID: default: return "unhandled image format"; } len = sprintf (buf, "%s %d %d 255\n", format_str, width, height); for (j = 0; j < height; j++) { const unsigned int *row = (unsigned int *) (data + stride * j); switch ((int) format) { case CAIRO_FORMAT_ARGB32: len = _cairo_write (fd, buf, sizeof (buf), len, (unsigned char *) row, 4 * width); break; case CAIRO_FORMAT_RGB24: for (i = 0; i < width; i++) { unsigned char rgb[3]; unsigned int p = *row++; rgb[0] = (p & 0xff0000) >> 16; rgb[1] = (p & 0x00ff00) >> 8; rgb[2] = (p & 0x0000ff) >> 0; len = _cairo_write (fd, buf, sizeof (buf), len, rgb, 3); } break; case CAIRO_FORMAT_A8: len = _cairo_write (fd, buf, sizeof (buf), len, (unsigned char *) row, width); break; } if (len < 0) return "write failed"; } if (len && ! _cairo_writen (fd, buf, len)) return "write failed"; return NULL; }
static VALUE cr_image_surface_get_height (VALUE self) { return INT2NUM (cairo_image_surface_get_height (_SELF)); }