00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "config.h"
00028 #include <gtk/gtk.h>
00029 #include <libermetadb/ermetadb.h>
00030
00031 #include "log.h"
00032 #include "notepad_utils.h"
00033 #include "notepad_thumbnail.h"
00034
00035 #include "notepad_filestore.h"
00036 #include "notepad_doc.h"
00037 #include "notepad_ipc.h"
00038
00039 #include "notepad_pages.h"
00040
00041
00042 namespace notepad
00043 {
00044
00045
00046 static const char* THUMBNAIL_COLUMNS[CThumbnail::THUMBNAIL_COUNT] =
00047 {
00048 "thumb_data_mini",
00049 "thumb_data_small",
00050 "thumb_data_medium",
00051 "thumb_data_large"
00052 };
00053
00054
00055
00056 void CThumbnail::storeThumbnail(CFileStore& filestore, CNotepadPages& pages, gint margin)
00057 {
00058 LOGPRINTF("entry");
00059
00060
00061 metadata_table* values = metadata_table_new();
00062 int values_index = -1;
00063 if (values == NULL)
00064 {
00065 WARNPRINTF("exit failed metadata_table");
00066 return;
00067 }
00068
00069
00070 GdkImage* cover = pages.get_page(1);
00071
00072 if (cover == 0 || cover->width == 0 || cover->height == 0)
00073 {
00074 WARNPRINTF("trying to thumbnail an uninitialized page");
00075 return;
00076 }
00077
00078 GdkPixbuf* raw_bmp = gdk_pixbuf_get_from_image(NULL,
00079 cover,
00080 gdk_colormap_get_system(),
00081 margin, margin,
00082 0, 0,
00083 #if MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00084 cover->width - margin,
00085 #endif
00086 #if MACHINE_IS_DR800S || MACHINE_IS_DR800SG || MACHINE_IS_DR800SW
00087 cover->width - 2*margin,
00088 #endif
00089 cover->height - margin);
00090
00091 if (raw_bmp == NULL)
00092 {
00093 WARNPRINTF("Error creating pixbuf.");
00094 return;
00095 }
00096
00097
00098 np_rotation rotation = ipc_get_rotation();
00099 GdkPixbuf* rotated_bmp = 0;
00100 switch (rotation)
00101 {
00102 case NP_CLOCKWISE:
00103 rotated_bmp = gdk_pixbuf_rotate_simple(raw_bmp, GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE);
00104 g_object_unref(raw_bmp);
00105 raw_bmp = rotated_bmp;
00106 break;
00107 case NP_ANTICLOCKWISE:
00108 rotated_bmp = gdk_pixbuf_rotate_simple(raw_bmp, GDK_PIXBUF_ROTATE_CLOCKWISE);
00109 g_object_unref(raw_bmp);
00110 raw_bmp = rotated_bmp;
00111 break;
00112 case NP_PORTRAIT:
00113 default:
00114 break;
00115 }
00116
00117
00118 for (int size = 0; size <= THUMBNAIL_COUNT; size++)
00119 {
00120 if (size != THUMBNAIL_SMALL && size != THUMBNAIL_MEDIUM)
00121 {
00122 continue;
00123 }
00124
00125
00126 int w = getWidth(static_cast<ThumbnailSize>(size));
00127 int h = getHeight(static_cast<ThumbnailSize>(size));
00128 int raw_w = gdk_pixbuf_get_width(raw_bmp);
00129 int raw_h = gdk_pixbuf_get_height(raw_bmp);
00130 float zoom_w = ((float)w) / ((float)raw_w);
00131 float zoom_h = ((float)h) / ((float)raw_h);
00132 if (zoom_w < zoom_h)
00133 {
00134 h = static_cast<int> (( ((float)raw_h) * zoom_w) + 0.5);
00135 }
00136 else
00137 {
00138 w = static_cast<int> (( ((float)raw_w) * zoom_h) + 0.5);
00139 }
00140
00141
00142 GdkPixbuf* scaled_bmp = gdk_pixbuf_scale_simple(raw_bmp, w, h, GDK_INTERP_BILINEAR);
00143
00144
00145 enhance(scaled_bmp, w, h);
00146
00147
00148 drawRectangle(scaled_bmp, w, h);
00149
00150 gchar* blob = NULL;
00151 gsize blob_size = 0;
00152
00153
00154 if (gdk_pixbuf_save_to_buffer(scaled_bmp, &blob, &blob_size, "png", NULL, NULL))
00155 {
00156 metadata_table_add_column(values, THUMBNAIL_COLUMNS[size]);
00157 values_index++;
00158
00159 metadata_table_set_blob(values, values_index, blob, blob_size);
00160 }
00161
00162 g_object_unref(scaled_bmp);
00163 }
00164
00165
00166 const char* mountpoint = ipc_get_mountpoint();
00167 erMetadb global_db = ermetadb_global_open(mountpoint, FALSE);
00168 if (global_db == 0)
00169 {
00170 WARNPRINTF("open globaldb for writing thumbnail failed.");
00171 return;
00172 }
00173 gchar* dir = filestore.getFileNameDirPart();
00174 gchar* file = filestore.getFileNameFilePart();
00175
00176 int rc = ermetadb_global_change_file(global_db, dir, file, values);
00177 if (rc != ER_OK)
00178 {
00179 WARNPRINTF("cannot update global db");
00180 }
00181 ermetadb_close(global_db);
00182 g_free(dir);
00183 g_free(file);
00184
00185
00186 if (raw_bmp)
00187 {
00188 g_object_unref(raw_bmp);
00189 }
00190 metadata_table_free(values);
00191
00192 LOGPRINTF("exit");
00193 return;
00194 }
00195
00196
00197
00198 void CThumbnail::putPixel(GdkPixbuf* pixbuf, gint x, gint y)
00199 {
00200 gint channel = gdk_pixbuf_get_n_channels(pixbuf);
00201 gint rowstride = gdk_pixbuf_get_rowstride(pixbuf);
00202 guchar* pixel = gdk_pixbuf_get_pixels(pixbuf);
00203 guchar* p = pixel + y * rowstride + x * channel;
00204 p[0] = 0;
00205 p[1] = 0;
00206 p[2] = 0;
00207 }
00208
00209 void CThumbnail::enhance(GdkPixbuf* pixbuf, gint width, gint height)
00210 {
00211 gint channel = gdk_pixbuf_get_n_channels(pixbuf);
00212 gint rowstride = gdk_pixbuf_get_rowstride(pixbuf);
00213 guchar* pixel = gdk_pixbuf_get_pixels(pixbuf);
00214
00215 for (gint x = 0; x < width; x++)
00216 {
00217 for (gint y = 0; y < height; y++)
00218 {
00219 guchar* p = pixel + y * rowstride + x * channel;
00220
00221
00222 if (p[0] + p[1] + p[2] < 3*0xFF)
00223 {
00224 p[0] = 0;
00225 p[1] = 0;
00226 p[2] = 0;
00227 }
00228 }
00229 }
00230 }
00231
00232 void CThumbnail::drawRectangle(GdkPixbuf* pixbuf, gint width, gint height)
00233 {
00234 g_assert(pixbuf != 0);
00235 gint w = width -1;
00236 gint h = height -1;
00237 for (gint x = 0; x < width; x++)
00238 {
00239 putPixel(pixbuf, x, 0);
00240 putPixel(pixbuf, x, h);
00241 }
00242 for (gint y = 0; y < height; y++)
00243 {
00244 putPixel(pixbuf, 0, y);
00245 putPixel(pixbuf, w, y);
00246 }
00247 }
00248
00249 gint CThumbnail::getWidth(const ThumbnailSize size)
00250 {
00251 switch (size)
00252 {
00253 case THUMBNAIL_SMALL:
00254 return 60;
00255 case THUMBNAIL_MEDIUM:
00256 return 120;
00257 case THUMBNAIL_LARGE:
00258 return 300;
00259 default:
00260 return 300;
00261 }
00262 }
00263
00264 gint CThumbnail::getHeight(const ThumbnailSize size)
00265 {
00266 switch (size)
00267 {
00268 case THUMBNAIL_SMALL:
00269 return 60;
00270 case THUMBNAIL_MEDIUM:
00271 return 120;
00272 case THUMBNAIL_LARGE:
00273 return 300;
00274 default:
00275 return 300;
00276 }
00277 }
00278
00279 }
00280
00281