summaryrefslogtreecommitdiffstats
path: root/io-psd.c
diff options
context:
space:
mode:
authorGravatar jan.dudek2008-12-19 18:39:36 +0000
committerGravatar jan.dudek2008-12-19 18:39:36 +0000
commit83047774827f8d737e2de8193af75931259ba1c1 (patch)
treed27a71b69a67c6543d8b768f5c7734f7a6d48200 /io-psd.c
parent74ee904fedfb68265863a61bd4e5dc4ebb4fc0b6 (diff)
downloadgdk-pixbuf-psd-83047774827f8d737e2de8193af75931259ba1c1.tar.gz
gdk-pixbuf-psd-83047774827f8d737e2de8193af75931259ba1c1.tar.bz2
Fixed uncompressed images. Reenabling CMYK. Support for Grayscale and
16-bit color depth. git-svn-id: http://gdk-pixbuf-psd.googlecode.com/svn/trunk@16 c5539ac3-5556-0410-9a1f-7faf0b045682
Diffstat (limited to 'io-psd.c')
-rw-r--r--io-psd.c62
1 files changed, 39 insertions, 23 deletions
diff --git a/io-psd.c b/io-psd.c
index 2cdb688..ccc7db0 100644
--- a/io-psd.c
+++ b/io-psd.c
@@ -22,7 +22,6 @@
22 22
23/* 23/*
24 * TODO 24 * TODO
25 * - use http://library.gnome.org/devel/glib/unstable/glib-Byte-Order-Macros.html
26 * - report errors from parse_psd_header 25 * - report errors from parse_psd_header
27 * - other color modes (CMYK at least) 26 * - other color modes (CMYK at least)
28 * - i18n 27 * - i18n
@@ -43,7 +42,7 @@ typedef struct
43 guint16 channels; /* number of color channels (1-24) */ 42 guint16 channels; /* number of color channels (1-24) */
44 guint32 rows; /* height of image in pixels (1-30000) */ 43 guint32 rows; /* height of image in pixels (1-30000) */
45 guint32 columns; /* width of image in pixels (1-30000) */ 44 guint32 columns; /* width of image in pixels (1-30000) */
46 guint16 depth; /* number of bits per channel (1, 8, and 16) */ 45 guint16 depth; /* number of bits per channel (1, 8, 16 or 32) */
47 guint16 color_mode; /* color mode as defined below */ 46 guint16 color_mode; /* color mode as defined below */
48} PsdHeader; 47} PsdHeader;
49 48
@@ -95,10 +94,11 @@ typedef struct
95 guint32 bytes_to_skip; 94 guint32 bytes_to_skip;
96 gboolean bytes_to_skip_known; 95 gboolean bytes_to_skip_known;
97 96
98 guint32 width; /* width of image in pixels (1-30000) */ 97 guint32 width;
99 guint32 height; /* height of image in pixels (1-30000) */ 98 guint32 height;
100 guint16 channels; /* number of color channels (1-24) */ 99 guint16 channels;
101 guint16 depth; /* number of bits per channel (1/8/16) */ 100 guint16 depth;
101 guint16 depth_bytes;
102 PsdColorMode color_mode; 102 PsdColorMode color_mode;
103 PsdCompressionType compression; 103 PsdCompressionType compression;
104 104
@@ -336,6 +336,7 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr,
336 ctx->height = hd.rows; 336 ctx->height = hd.rows;
337 ctx->channels = hd.channels; 337 ctx->channels = hd.channels;
338 ctx->depth = hd.depth; 338 ctx->depth = hd.depth;
339 ctx->depth_bytes = (ctx->depth/8 > 0 ? ctx->depth/8 : 1);
339 ctx->color_mode = hd.color_mode; 340 ctx->color_mode = hd.color_mode;
340 341
341 /* 342 /*
@@ -347,7 +348,8 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr,
347 // ctx->color_mode, ctx->channels, ctx->depth); 348 // ctx->color_mode, ctx->channels, ctx->depth);
348 349
349 if (ctx->color_mode != PSD_MODE_RGB 350 if (ctx->color_mode != PSD_MODE_RGB
350 //&& ctx->color_mode != PSD_MODE_CMYK 351 && ctx->color_mode != PSD_MODE_GRAYSCALE
352 && ctx->color_mode != PSD_MODE_CMYK
351 ) { 353 ) {
352 g_set_error (error, GDK_PIXBUF_ERROR, 354 g_set_error (error, GDK_PIXBUF_ERROR,
353 GDK_PIXBUF_ERROR_UNKNOWN_TYPE, 355 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
@@ -355,7 +357,7 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr,
355 return FALSE; 357 return FALSE;
356 } 358 }
357 359
358 if (ctx->depth != 8) { 360 if (ctx->depth != 8 && ctx->depth != 16) {
359 g_set_error (error, GDK_PIXBUF_ERROR, 361 g_set_error (error, GDK_PIXBUF_ERROR,
360 GDK_PIXBUF_ERROR_UNKNOWN_TYPE, 362 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
361 ("Unsupported color depth")); 363 ("Unsupported color depth"));
@@ -371,10 +373,10 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr,
371 } 373 }
372 } 374 }
373 375
374 // we need buffer that can contain one channel data of one 376 // we need buffer that can contain one channel data for one
375 // row in RLE compressed format. 2*width should be enough 377 // row in RLE compressed format. 2*width should be enough
376 g_free(ctx->buffer); 378 g_free(ctx->buffer);
377 ctx->buffer = g_malloc(ctx->width * 2); 379 ctx->buffer = g_malloc(ctx->width * 2 * ctx->depth_bytes);
378 380
379 // this will be needed for RLE decompression 381 // this will be needed for RLE decompression
380 ctx->lines_lengths = 382 ctx->lines_lengths =
@@ -396,7 +398,7 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr,
396 ctx->ch_bufs = g_malloc(sizeof(guchar*) * ctx->channels); 398 ctx->ch_bufs = g_malloc(sizeof(guchar*) * ctx->channels);
397 for (int i = 0; i < ctx->channels; i++) { 399 for (int i = 0; i < ctx->channels; i++) {
398 ctx->ch_bufs[i] = 400 ctx->ch_bufs[i] =
399 g_malloc(ctx->width * ctx->height); 401 g_malloc(ctx->width*ctx->height*ctx->depth_bytes);
400 402
401 if (ctx->ch_bufs[i] == NULL) { 403 if (ctx->ch_bufs[i] == NULL) {
402 g_set_error (error, GDK_PIXBUF_ERROR, 404 g_set_error (error, GDK_PIXBUF_ERROR,
@@ -440,6 +442,7 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr,
440 reset_context_buffer(ctx); 442 reset_context_buffer(ctx);
441 } else if (ctx->compression == PSD_COMPRESSION_NONE) { 443 } else if (ctx->compression == PSD_COMPRESSION_NONE) {
442 ctx->state = PSD_STATE_CHANNEL_DATA; 444 ctx->state = PSD_STATE_CHANNEL_DATA;
445 reset_context_buffer(ctx);
443 } else { 446 } else {
444 g_set_error (error, GDK_PIXBUF_ERROR, 447 g_set_error (error, GDK_PIXBUF_ERROR,
445 GDK_PIXBUF_ERROR_UNKNOWN_TYPE, 448 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
@@ -464,7 +467,7 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr,
464 break; 467 break;
465 case PSD_STATE_CHANNEL_DATA: 468 case PSD_STATE_CHANNEL_DATA:
466 { 469 {
467 guint line_length = ctx->width; 470 guint line_length = ctx->width * ctx->depth_bytes;
468 if (ctx->compression == PSD_COMPRESSION_RLE) { 471 if (ctx->compression == PSD_COMPRESSION_RLE) {
469 line_length = ctx->lines_lengths[ 472 line_length = ctx->lines_lengths[
470 ctx->curr_ch * ctx->height + ctx->curr_row]; 473 ctx->curr_ch * ctx->height + ctx->curr_row];
@@ -473,18 +476,16 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr,
473 if (feed_buffer(ctx->buffer, &ctx->bytes_read, &data, &size, 476 if (feed_buffer(ctx->buffer, &ctx->bytes_read, &data, &size,
474 line_length)) 477 line_length))
475 { 478 {
476 reset_context_buffer(ctx);
477
478 if (ctx->compression == PSD_COMPRESSION_RLE) { 479 if (ctx->compression == PSD_COMPRESSION_RLE) {
479 decompress_line(ctx->buffer, line_length, 480 decompress_line(ctx->buffer, line_length,
480 ctx->ch_bufs[ctx->curr_ch] + ctx->pos 481 ctx->ch_bufs[ctx->curr_ch] + ctx->pos
481 ); 482 );
482 } else { 483 } else {
483 memcpy(ctx->ch_bufs[ctx->curr_ch] + ctx->pos, 484 memcpy(ctx->ch_bufs[ctx->curr_ch] + ctx->pos,
484 ctx->buffer, ctx->width); 485 ctx->buffer, line_length);
485 } 486 }
486 487
487 ctx->pos += ctx->width; 488 ctx->pos += ctx->width * ctx->depth_bytes;
488 ++ctx->curr_row; 489 ++ctx->curr_row;
489 490
490 if (ctx->curr_row >= ctx->height) { 491 if (ctx->curr_row >= ctx->height) {
@@ -495,6 +496,8 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr,
495 ctx->state = PSD_STATE_DONE; 496 ctx->state = PSD_STATE_DONE;
496 } 497 }
497 } 498 }
499
500 reset_context_buffer(ctx);
498 } 501 }
499 } 502 }
500 break; 503 break;
@@ -507,17 +510,29 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr,
507 510
508 if (ctx->state == PSD_STATE_DONE && !ctx->finalized) { 511 if (ctx->state == PSD_STATE_DONE && !ctx->finalized) {
509 // convert or copy channel buffers to our GdkPixbuf 512 // convert or copy channel buffers to our GdkPixbuf
513 guchar* pixels = gdk_pixbuf_get_pixels(ctx->pixbuf);
514 guint b = ctx->depth_bytes;
515
510 if (ctx->color_mode == PSD_MODE_RGB && !ctx->use_alpha) { 516 if (ctx->color_mode == PSD_MODE_RGB && !ctx->use_alpha) {
511 guchar* pixels = gdk_pixbuf_get_pixels(ctx->pixbuf);
512 for (int i = 0; i < ctx->height; i++) { 517 for (int i = 0; i < ctx->height; i++) {
513 for (int j = 0; j < ctx->width; j++) { 518 for (int j = 0; j < ctx->width; j++) {
514 pixels[3*j+0] = ctx->ch_bufs[0][ctx->width*i + j]; 519 pixels[3*j+0] = ctx->ch_bufs[0][ctx->width*i*b + j*b];
515 pixels[3*j+1] = ctx->ch_bufs[1][ctx->width*i + j]; 520 pixels[3*j+1] = ctx->ch_bufs[1][ctx->width*i*b + j*b];
516 pixels[3*j+2] = ctx->ch_bufs[2][ctx->width*i + j]; 521 pixels[3*j+2] = ctx->ch_bufs[2][ctx->width*i*b + j*b];
517 } 522 }
518 pixels += gdk_pixbuf_get_rowstride(ctx->pixbuf); 523 pixels += gdk_pixbuf_get_rowstride(ctx->pixbuf);
519 } 524 }
520 } else if (ctx->color_mode == PSD_MODE_RGB && ctx->use_alpha) { 525 } else if (ctx->color_mode == PSD_MODE_GRAYSCALE) {
526 for (int i = 0; i < ctx->height; i++) {
527 for (int j = 0; j < ctx->width; j++) {
528 pixels[3*j+0] = pixels[3*j+1] = pixels[3*j+2] =
529 ctx->ch_bufs[0][ctx->width*i*b + j*b];
530 }
531 pixels += gdk_pixbuf_get_rowstride(ctx->pixbuf);
532 }
533 }
534#if 0
535 else if (ctx->color_mode == PSD_MODE_RGB && ctx->use_alpha) {
521 guchar* pixels = gdk_pixbuf_get_pixels(ctx->pixbuf); 536 guchar* pixels = gdk_pixbuf_get_pixels(ctx->pixbuf);
522 for (int i = 0; i < ctx->height; i++) { 537 for (int i = 0; i < ctx->height; i++) {
523 for (int j = 0; j < ctx->width; j++) { 538 for (int j = 0; j < ctx->width; j++) {
@@ -528,7 +543,8 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr,
528 } 543 }
529 pixels += gdk_pixbuf_get_rowstride(ctx->pixbuf); 544 pixels += gdk_pixbuf_get_rowstride(ctx->pixbuf);
530 } 545 }
531 } else if (ctx->color_mode == PSD_MODE_CMYK) { 546#endif
547 else if (ctx->color_mode == PSD_MODE_CMYK) {
532 // unfortunately, this doesn't seem to work correctly... 548 // unfortunately, this doesn't seem to work correctly...
533 549
534 guchar* pixels = gdk_pixbuf_get_pixels(ctx->pixbuf); 550 guchar* pixels = gdk_pixbuf_get_pixels(ctx->pixbuf);