diff options
Diffstat (limited to 'io-psd.c')
| -rw-r--r-- | io-psd.c | 301 |
1 files changed, 75 insertions, 226 deletions
| @@ -26,6 +26,7 @@ | |||
| 26 | * - report errors from parse_psd_header | 26 | * - report errors from parse_psd_header |
| 27 | * - other color modes | 27 | * - other color modes |
| 28 | * - ... | 28 | * - ... |
| 29 | * - MODULE_ENTRY stuff | ||
| 29 | */ | 30 | */ |
| 30 | 31 | ||
| 31 | #include <stdlib.h> | 32 | #include <stdlib.h> |
| @@ -39,7 +40,7 @@ typedef struct | |||
| 39 | { | 40 | { |
| 40 | guchar signature[4]; /* file ID, always "8BPS" */ | 41 | guchar signature[4]; /* file ID, always "8BPS" */ |
| 41 | guint16 version; /* version number, always 1 */ | 42 | guint16 version; /* version number, always 1 */ |
| 42 | guchar reserved[6]; | 43 | guchar resetved[6]; |
| 43 | guint16 channels; /* number of color channels (1-24) */ | 44 | guint16 channels; /* number of color channels (1-24) */ |
| 44 | guint32 rows; /* height of image in pixels (1-30000) */ | 45 | guint32 rows; /* height of image in pixels (1-30000) */ |
| 45 | guint32 columns; /* width of image in pixels (1-30000) */ | 46 | guint32 columns; /* width of image in pixels (1-30000) */ |
| @@ -95,7 +96,6 @@ typedef struct | |||
| 95 | guint32 bytes_to_skip; | 96 | guint32 bytes_to_skip; |
| 96 | gboolean bytes_to_skip_known; | 97 | gboolean bytes_to_skip_known; |
| 97 | 98 | ||
| 98 | //PsdHeader hd; | ||
| 99 | guint32 width; /* width of image in pixels (1-30000) */ | 99 | guint32 width; /* width of image in pixels (1-30000) */ |
| 100 | guint32 height; /* height of image in pixels (1-30000) */ | 100 | guint32 height; /* height of image in pixels (1-30000) */ |
| 101 | guint16 channels; /* number of color channels (1-24) */ | 101 | guint16 channels; /* number of color channels (1-24) */ |
| @@ -103,79 +103,31 @@ typedef struct | |||
| 103 | PsdColorMode color_mode; | 103 | PsdColorMode color_mode; |
| 104 | PsdCompressionType compression; | 104 | PsdCompressionType compression; |
| 105 | 105 | ||
| 106 | guchar** channels_buffers; | 106 | guchar** ch_bufs; /* channels buffers */ |
| 107 | guint current_channel; | 107 | guint curr_ch; /* current channel */ |
| 108 | guint current_row; | 108 | guint curr_row; |
| 109 | guint position; // ? redundant? | 109 | guint pos; // redundant? |
| 110 | guint16* lines_lengths; | 110 | guint16* lines_lengths; |
| 111 | gboolean finalized; | 111 | gboolean finalized; |
| 112 | } PsdContext; | 112 | } PsdContext; |
| 113 | 113 | ||
| 114 | static guint16 | ||
| 115 | read_uint16 (FILE *fp) | ||
| 116 | { | ||
| 117 | guint16 t; | ||
| 118 | t = fgetc(fp) << 8; | ||
| 119 | t |= fgetc(fp); | ||
| 120 | return t; | ||
| 121 | } | ||
| 122 | |||
| 123 | static guint32 | ||
| 124 | read_uint32 (FILE *fp) | ||
| 125 | { | ||
| 126 | guint32 t; | ||
| 127 | t = fgetc(fp) << 24; | ||
| 128 | t |= fgetc(fp) << 16; | ||
| 129 | t |= fgetc(fp) << 8; | ||
| 130 | t |= fgetc(fp); | ||
| 131 | return t; | ||
| 132 | } | ||
| 133 | 114 | ||
| 134 | static guint16 | 115 | static guint16 |
| 135 | parse_uint16 (guchar* buf) | 116 | read_uint16 (guchar* buf) |
| 136 | { | 117 | { |
| 137 | return (buf[0] << 8) | buf[1]; | 118 | return (buf[0] << 8) | buf[1]; |
| 138 | } | 119 | } |
| 139 | 120 | ||
| 140 | static guint32 | 121 | static guint32 |
| 141 | parse_uint32 (guchar* buf) | 122 | read_uint32 (guchar* buf) |
| 142 | { | 123 | { |
| 143 | return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; | 124 | return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; |
| 144 | } | 125 | } |
| 145 | 126 | ||
| 146 | 127 | ||
| 147 | static PsdHeader | ||
| 148 | psd_read_header (FILE *fp) | ||
| 149 | { | ||
| 150 | PsdHeader hd; | ||
| 151 | int t; | ||
| 152 | |||
| 153 | fread(hd.signature, 1, 4, fp); | ||
| 154 | hd.version = read_uint16(fp); | ||
| 155 | fread(hd.reserved, 1, 6, fp); | ||
| 156 | hd.channels = read_uint16(fp); | ||
| 157 | hd.rows = read_uint32(fp); | ||
| 158 | hd.columns = read_uint32(fp); | ||
| 159 | hd.depth = read_uint16(fp); | ||
| 160 | hd.color_mode = read_uint16(fp); | ||
| 161 | |||
| 162 | // skip Color Mode Data Block | ||
| 163 | t = read_uint32(fp); | ||
| 164 | fseek(fp, t, SEEK_CUR); | ||
| 165 | |||
| 166 | // skip Image Resources Block | ||
| 167 | t = read_uint32(fp); | ||
| 168 | fseek(fp, t, SEEK_CUR); | ||
| 169 | |||
| 170 | // skip Layer and Mask Information Block | ||
| 171 | t = read_uint32(fp); | ||
| 172 | fseek(fp, t, SEEK_CUR); | ||
| 173 | |||
| 174 | return hd; | ||
| 175 | } | ||
| 176 | |||
| 177 | /* | 128 | /* |
| 178 | * Parse Psdheader from buffer | 129 | * Parse Psdheader from buffer |
| 130 | * | ||
| 179 | * str is expected to be at least PSD_HEADER_SIZE long | 131 | * str is expected to be at least PSD_HEADER_SIZE long |
| 180 | */ | 132 | */ |
| 181 | static PsdHeader | 133 | static PsdHeader |
| @@ -184,130 +136,22 @@ psd_parse_header (guchar* str) | |||
| 184 | PsdHeader hd; | 136 | PsdHeader hd; |
| 185 | 137 | ||
| 186 | memcpy(hd.signature, str, 4); | 138 | memcpy(hd.signature, str, 4); |
| 187 | hd.version = parse_uint16(str + 4); | 139 | hd.version = read_uint16(str + 4); |
| 188 | hd.channels = parse_uint16(str + 12); | 140 | hd.channels = read_uint16(str + 12); |
| 189 | hd.rows = parse_uint32(str + 14); | 141 | hd.rows = read_uint32(str + 14); |
| 190 | hd.columns = parse_uint32(str + 18); | 142 | hd.columns = read_uint32(str + 18); |
| 191 | hd.depth = parse_uint16(str + 22); | 143 | hd.depth = read_uint16(str + 22); |
| 192 | hd.color_mode = parse_uint16(str + 24); | 144 | hd.color_mode = read_uint16(str + 24); |
| 193 | 145 | ||
| 194 | return hd; | 146 | return hd; |
| 195 | } | 147 | } |
| 196 | 148 | ||
| 197 | // -- non-progressive loading -------------------------------------------------- | 149 | /* |
| 198 | 150 | * Attempts to read bytes_needed bytes from data and stores them in buffer. | |
| 199 | static GdkPixbuf* | 151 | * |
| 200 | gdk_pixbuf__psd_image_load (FILE *fp, | 152 | * Returns true if there were enough bytes and false otherwise |
| 201 | GError **error) | 153 | * (which means we need to call feed_buffer again) |
| 202 | { | 154 | */ |
| 203 | guint rowstride; | ||
| 204 | guint16 compression_type; | ||
| 205 | guchar *pixels; | ||
| 206 | GdkPixbuf *pixbuf; | ||
| 207 | guchar **buffers; | ||
| 208 | |||
| 209 | PsdHeader hd = psd_read_header(fp); | ||
| 210 | pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, hd.columns, hd.rows); | ||
| 211 | |||
| 212 | if (pixbuf == NULL) { | ||
| 213 | g_set_error (error, GDK_PIXBUF_ERROR, | ||
| 214 | GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, | ||
| 215 | ("Insufficient memory to load PSD image file")); | ||
| 216 | return NULL; | ||
| 217 | } | ||
| 218 | |||
| 219 | pixels = gdk_pixbuf_get_pixels (pixbuf); | ||
| 220 | rowstride = gdk_pixbuf_get_rowstride (pixbuf); | ||
| 221 | |||
| 222 | compression_type = read_uint16(fp); | ||
| 223 | |||
| 224 | if (compression_type != PSD_COMPRESSION_NONE && | ||
| 225 | compression_type != PSD_COMPRESSION_RLE) { | ||
| 226 | g_set_error (error, GDK_PIXBUF_ERROR, | ||
| 227 | GDK_PIXBUF_ERROR_UNKNOWN_TYPE, | ||
| 228 | ("Unsupported compression type")); | ||
| 229 | return NULL; | ||
| 230 | } | ||
| 231 | |||
| 232 | if (hd.color_mode != PSD_MODE_RGB) { | ||
| 233 | g_set_error (error, GDK_PIXBUF_ERROR, | ||
| 234 | GDK_PIXBUF_ERROR_UNKNOWN_TYPE, | ||
| 235 | ("Unsupported color mode")); | ||
| 236 | return NULL; | ||
| 237 | } | ||
| 238 | |||
| 239 | //g_message("mode=%d, channels=%d", hd.color_mode, hd.channels); | ||
| 240 | |||
| 241 | buffers = g_malloc(sizeof(guchar*) * hd.channels); | ||
| 242 | |||
| 243 | if (compression_type == PSD_COMPRESSION_RLE) { | ||
| 244 | guint16 *line_lengths = g_malloc(2 * hd.rows * hd.channels); | ||
| 245 | |||
| 246 | for (int i = 0; i < hd.rows * hd.channels; ++i) { | ||
| 247 | line_lengths[i] = read_uint16(fp); | ||
| 248 | } | ||
| 249 | |||
| 250 | for (int i = 0; i < hd.channels; ++i) { | ||
| 251 | buffers[i] = g_malloc(hd.rows * hd.columns); | ||
| 252 | gint position = 0; | ||
| 253 | |||
| 254 | for (int j = 0; j < hd.rows; ++j) { | ||
| 255 | guint16 bytes_read = 0; | ||
| 256 | while (bytes_read < line_lengths[i * hd.rows + j]) { | ||
| 257 | gchar byte = fgetc(fp); | ||
| 258 | ++bytes_read; | ||
| 259 | |||
| 260 | if (byte == -128) { | ||
| 261 | continue; | ||
| 262 | } else if (byte > -1) { | ||
| 263 | gint count = byte + 1; | ||
| 264 | |||
| 265 | // copy next count bytes | ||
| 266 | for (int k = 0; k < count; ++k) { | ||
| 267 | buffers[i][position] = fgetc(fp); | ||
| 268 | ++bytes_read; | ||
| 269 | ++position; | ||
| 270 | } | ||
| 271 | } else { | ||
| 272 | gint count = -byte + 1; | ||
| 273 | |||
| 274 | // copy next byte count times | ||
| 275 | guchar next_byte = fgetc(fp); | ||
| 276 | ++bytes_read; | ||
| 277 | for (int k = 0; k < count; ++k) { | ||
| 278 | buffers[i][position] = next_byte; | ||
| 279 | ++position; | ||
| 280 | } | ||
| 281 | } | ||
| 282 | } | ||
| 283 | } | ||
| 284 | } | ||
| 285 | |||
| 286 | g_free(line_lengths); | ||
| 287 | } | ||
| 288 | |||
| 289 | if (hd.color_mode == PSD_MODE_RGB) { | ||
| 290 | for (int i = 0; i < hd.rows; ++i) { | ||
| 291 | for (int j = 0; j < hd.columns; ++j) { | ||
| 292 | pixels[i*rowstride + 3*j + 0] = buffers[0][i*hd.columns + j]; | ||
| 293 | pixels[i*rowstride + 3*j + 1] = buffers[1][i*hd.columns + j]; | ||
| 294 | pixels[i*rowstride + 3*j + 2] = buffers[2][i*hd.columns + j]; | ||
| 295 | } | ||
| 296 | } | ||
| 297 | } | ||
| 298 | // TODO: other color modes, CMYK at least | ||
| 299 | |||
| 300 | return pixbuf; | ||
| 301 | } | ||
| 302 | |||
| 303 | |||
| 304 | // --- progressive loading ----------------------------------------------------- | ||
| 305 | |||
| 306 | // Attempts to read bytes_needed bytes from data and stores them | ||
| 307 | // in buffer. | ||
| 308 | // Returns true if there were enough bytes and false otherwise | ||
| 309 | // (which means we need to call feed_buffer again) | ||
| 310 | |||
| 311 | static gboolean | 155 | static gboolean |
| 312 | feed_buffer (guchar* buffer, | 156 | feed_buffer (guchar* buffer, |
| 313 | guint* bytes_read, | 157 | guint* bytes_read, |
| @@ -326,10 +170,12 @@ feed_buffer (guchar* buffer, | |||
| 326 | return (*bytes_read == bytes_needed); | 170 | return (*bytes_read == bytes_needed); |
| 327 | } | 171 | } |
| 328 | 172 | ||
| 329 | // Attempts to read size of the block and then skip this block. | 173 | /* |
| 330 | // Returns true when finishes consuming block data, otherwise false | 174 | * Attempts to read size of the block and then skip this block. |
| 331 | // (false means we must call skip_block once again) | 175 | * |
| 332 | 176 | * Returns true when finishes consuming block data, otherwise false | |
| 177 | * (false means we must call skip_block once again) | ||
| 178 | */ | ||
| 333 | static gboolean | 179 | static gboolean |
| 334 | skip_block (PsdContext* context, const guchar** data, guint* size) | 180 | skip_block (PsdContext* context, const guchar** data, guint* size) |
| 335 | { | 181 | { |
| @@ -338,7 +184,7 @@ skip_block (PsdContext* context, const guchar** data, guint* size) | |||
| 338 | if (!context->bytes_to_skip_known) { | 184 | if (!context->bytes_to_skip_known) { |
| 339 | context->bytes_read = 0; | 185 | context->bytes_read = 0; |
| 340 | if (feed_buffer(context->buffer, &context->bytes_read, data, size, 4)) { | 186 | if (feed_buffer(context->buffer, &context->bytes_read, data, size, 4)) { |
| 341 | context->bytes_to_skip = parse_uint32(context->buffer); | 187 | context->bytes_to_skip = read_uint32(context->buffer); |
| 342 | context->bytes_to_skip_known = TRUE; | 188 | context->bytes_to_skip_known = TRUE; |
| 343 | counter = 0; | 189 | counter = 0; |
| 344 | } else { | 190 | } else { |
| @@ -359,7 +205,9 @@ skip_block (PsdContext* context, const guchar** data, guint* size) | |||
| 359 | } | 205 | } |
| 360 | } | 206 | } |
| 361 | 207 | ||
| 362 | // Decodes RLE-compressed data | 208 | /* |
| 209 | * Decodes RLE-compressed data | ||
| 210 | */ | ||
| 363 | static void | 211 | static void |
| 364 | decompress_line(const guchar* src, guint line_length, guchar* dest) | 212 | decompress_line(const guchar* src, guint line_length, guchar* dest) |
| 365 | { | 213 | { |
| @@ -394,7 +242,7 @@ decompress_line(const guchar* src, guint line_length, guchar* dest) | |||
| 394 | } | 242 | } |
| 395 | 243 | ||
| 396 | static void | 244 | static void |
| 397 | reset_context(PsdContext* ctx) | 245 | reset_context_buffer(PsdContext* ctx) |
| 398 | { | 246 | { |
| 399 | ctx->bytes_read = 0; | 247 | ctx->bytes_read = 0; |
| 400 | ctx->bytes_to_skip = 0; | 248 | ctx->bytes_to_skip = 0; |
| @@ -426,12 +274,12 @@ gdk_pixbuf__psd_image_begin_load (GdkPixbufModuleSizeFunc size_func, | |||
| 426 | 274 | ||
| 427 | // we'll allocate larger buffer once we know image size | 275 | // we'll allocate larger buffer once we know image size |
| 428 | context->buffer = g_malloc(PSD_HEADER_SIZE); | 276 | context->buffer = g_malloc(PSD_HEADER_SIZE); |
| 429 | reset_context(context); | 277 | reset_context_buffer(context); |
| 430 | 278 | ||
| 431 | context->channels_buffers = NULL; | 279 | context->ch_bufs = NULL; |
| 432 | context->current_channel = 0; | 280 | context->curr_ch = 0; |
| 433 | context->current_row = 0; | 281 | context->curr_row = 0; |
| 434 | context->position = 0; | 282 | context->pos = 0; |
| 435 | context->lines_lengths = NULL; | 283 | context->lines_lengths = NULL; |
| 436 | context->finalized = FALSE; | 284 | context->finalized = FALSE; |
| 437 | 285 | ||
| @@ -449,12 +297,16 @@ gdk_pixbuf__psd_image_stop_load (gpointer context_ptr, GError **error) | |||
| 449 | error, | 297 | error, |
| 450 | GDK_PIXBUF_ERROR, | 298 | GDK_PIXBUF_ERROR, |
| 451 | GDK_PIXBUF_ERROR_CORRUPT_IMAGE, | 299 | GDK_PIXBUF_ERROR_CORRUPT_IMAGE, |
| 452 | ("PSD file was corrupted or incomplete. (not PSD_STATE_DONE)")); | 300 | ("PSD file was corrupted or incomplete.")); |
| 453 | retval = FALSE; | 301 | retval = FALSE; |
| 454 | } | 302 | } |
| 455 | 303 | ||
| 456 | g_free (ctx->buffer); // TODO a few more buffers need freeing | 304 | g_free(ctx->buffer); |
| 457 | g_free (ctx); | 305 | g_free(ctx->lines_lengths); |
| 306 | for (int i = 0; i < ctx->channels; i++) { | ||
| 307 | g_free(ctx->ch_bufs[i]); | ||
| 308 | } | ||
| 309 | g_free(ctx); | ||
| 458 | 310 | ||
| 459 | return retval; | 311 | return retval; |
| 460 | } | 312 | } |
| @@ -467,14 +319,13 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr, | |||
| 467 | GError **error) | 319 | GError **error) |
| 468 | { | 320 | { |
| 469 | 321 | ||
| 470 | PsdContext* context = (PsdContext*) context_ptr; | 322 | PsdContext* ctx = (PsdContext*) context_ptr; |
| 471 | PsdContext* ctx = context; | ||
| 472 | 323 | ||
| 473 | while (size > 0) { | 324 | while (size > 0) { |
| 474 | switch (context->state) { | 325 | switch (ctx->state) { |
| 475 | case PSD_STATE_HEADER: | 326 | case PSD_STATE_HEADER: |
| 476 | if (feed_buffer( | 327 | if (feed_buffer( |
| 477 | context->buffer, &context->bytes_read, | 328 | ctx->buffer, &ctx->bytes_read, |
| 478 | &data, &size, PSD_HEADER_SIZE)) | 329 | &data, &size, PSD_HEADER_SIZE)) |
| 479 | { | 330 | { |
| 480 | PsdHeader hd = psd_parse_header(ctx->buffer); | 331 | PsdHeader hd = psd_parse_header(ctx->buffer); |
| @@ -485,8 +336,8 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr, | |||
| 485 | ctx->depth = hd.depth; | 336 | ctx->depth = hd.depth; |
| 486 | ctx->color_mode = hd.color_mode; | 337 | ctx->color_mode = hd.color_mode; |
| 487 | 338 | ||
| 488 | g_message("color_mode=%d, channels=%d, depth=%d", | 339 | //g_message("color_mode=%d, channels=%d, depth=%d", |
| 489 | ctx->color_mode, ctx->channels, ctx->depth); | 340 | // ctx->color_mode, ctx->channels, ctx->depth); |
| 490 | 341 | ||
| 491 | if (ctx->color_mode != PSD_MODE_RGB/* && | 342 | if (ctx->color_mode != PSD_MODE_RGB/* && |
| 492 | ctx->color_mode != PSD_MODE_CMYK*/ | 343 | ctx->color_mode != PSD_MODE_CMYK*/ |
| @@ -535,13 +386,12 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr, | |||
| 535 | } | 386 | } |
| 536 | 387 | ||
| 537 | // create separate buffers for each channel | 388 | // create separate buffers for each channel |
| 538 | context->channels_buffers = | 389 | ctx->ch_bufs = g_malloc(sizeof(guchar*) * ctx->channels); |
| 539 | g_malloc(sizeof(guchar*) * ctx->channels); | ||
| 540 | for (int i = 0; i < ctx->channels; i++) { | 390 | for (int i = 0; i < ctx->channels; i++) { |
| 541 | ctx->channels_buffers[i] = | 391 | ctx->ch_bufs[i] = |
| 542 | g_malloc(ctx->width * ctx->height); | 392 | g_malloc(ctx->width * ctx->height); |
| 543 | 393 | ||
| 544 | if (ctx->channels_buffers[i] == NULL) { | 394 | if (ctx->ch_bufs[i] == NULL) { |
| 545 | g_set_error (error, GDK_PIXBUF_ERROR, | 395 | g_set_error (error, GDK_PIXBUF_ERROR, |
| 546 | GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, | 396 | GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, |
| 547 | ("Insufficient memory to load PSD image file")); | 397 | ("Insufficient memory to load PSD image file")); |
| @@ -552,35 +402,35 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr, | |||
| 552 | ctx->prepared_func(ctx->pixbuf, NULL, ctx->user_data); | 402 | ctx->prepared_func(ctx->pixbuf, NULL, ctx->user_data); |
| 553 | 403 | ||
| 554 | ctx->state = PSD_STATE_COLOR_MODE_BLOCK; | 404 | ctx->state = PSD_STATE_COLOR_MODE_BLOCK; |
| 555 | reset_context(ctx); | 405 | reset_context_buffer(ctx); |
| 556 | } | 406 | } |
| 557 | break; | 407 | break; |
| 558 | case PSD_STATE_COLOR_MODE_BLOCK: | 408 | case PSD_STATE_COLOR_MODE_BLOCK: |
| 559 | if (skip_block(ctx, &data, &size)) { | 409 | if (skip_block(ctx, &data, &size)) { |
| 560 | ctx->state = PSD_STATE_RESOURCES_BLOCK; | 410 | ctx->state = PSD_STATE_RESOURCES_BLOCK; |
| 561 | reset_context(ctx); | 411 | reset_context_buffer(ctx); |
| 562 | } | 412 | } |
| 563 | break; | 413 | break; |
| 564 | case PSD_STATE_RESOURCES_BLOCK: | 414 | case PSD_STATE_RESOURCES_BLOCK: |
| 565 | if (skip_block(ctx, &data, &size)) { | 415 | if (skip_block(ctx, &data, &size)) { |
| 566 | ctx->state = PSD_STATE_LAYERS_BLOCK; | 416 | ctx->state = PSD_STATE_LAYERS_BLOCK; |
| 567 | reset_context(ctx); | 417 | reset_context_buffer(ctx); |
| 568 | } | 418 | } |
| 569 | break; | 419 | break; |
| 570 | case PSD_STATE_LAYERS_BLOCK: | 420 | case PSD_STATE_LAYERS_BLOCK: |
| 571 | if (skip_block(ctx, &data, &size)) { | 421 | if (skip_block(ctx, &data, &size)) { |
| 572 | ctx->state = PSD_STATE_COMPRESSION; | 422 | ctx->state = PSD_STATE_COMPRESSION; |
| 573 | reset_context(ctx); | 423 | reset_context_buffer(ctx); |
| 574 | } | 424 | } |
| 575 | break; | 425 | break; |
| 576 | case PSD_STATE_COMPRESSION: | 426 | case PSD_STATE_COMPRESSION: |
| 577 | if (feed_buffer(ctx->buffer, &ctx->bytes_read, &data, &size, 2)) | 427 | if (feed_buffer(ctx->buffer, &ctx->bytes_read, &data, &size, 2)) |
| 578 | { | 428 | { |
| 579 | ctx->compression = parse_uint16(ctx->buffer); | 429 | ctx->compression = read_uint16(ctx->buffer); |
| 580 | 430 | ||
| 581 | if (ctx->compression == PSD_COMPRESSION_RLE) { | 431 | if (ctx->compression == PSD_COMPRESSION_RLE) { |
| 582 | ctx->state = PSD_STATE_LINES_LENGTHS; | 432 | ctx->state = PSD_STATE_LINES_LENGTHS; |
| 583 | reset_context(ctx); | 433 | reset_context_buffer(ctx); |
| 584 | } else if (ctx->compression == PSD_COMPRESSION_NONE) { | 434 | } else if (ctx->compression == PSD_COMPRESSION_NONE) { |
| 585 | ctx->state = PSD_STATE_CHANNEL_DATA; | 435 | ctx->state = PSD_STATE_CHANNEL_DATA; |
| 586 | } else { | 436 | } else { |
| @@ -598,11 +448,11 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr, | |||
| 598 | { | 448 | { |
| 599 | // convert from different endianness | 449 | // convert from different endianness |
| 600 | for (int i = 0; i < ctx->height * ctx->channels; i++) { | 450 | for (int i = 0; i < ctx->height * ctx->channels; i++) { |
| 601 | ctx->lines_lengths[i] = parse_uint16( | 451 | ctx->lines_lengths[i] = read_uint16( |
| 602 | (guchar*) &ctx->lines_lengths[i]); | 452 | (guchar*) &ctx->lines_lengths[i]); |
| 603 | } | 453 | } |
| 604 | ctx->state = PSD_STATE_CHANNEL_DATA; | 454 | ctx->state = PSD_STATE_CHANNEL_DATA; |
| 605 | reset_context(ctx); | 455 | reset_context_buffer(ctx); |
| 606 | } | 456 | } |
| 607 | break; | 457 | break; |
| 608 | case PSD_STATE_CHANNEL_DATA: | 458 | case PSD_STATE_CHANNEL_DATA: |
| @@ -610,32 +460,31 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr, | |||
| 610 | guint line_length = ctx->width; | 460 | guint line_length = ctx->width; |
| 611 | if (ctx->compression == PSD_COMPRESSION_RLE) { | 461 | if (ctx->compression == PSD_COMPRESSION_RLE) { |
| 612 | line_length = ctx->lines_lengths[ | 462 | line_length = ctx->lines_lengths[ |
| 613 | ctx->current_channel * ctx->height + ctx->current_row]; | 463 | ctx->curr_ch * ctx->height + ctx->curr_row]; |
| 614 | } | 464 | } |
| 615 | 465 | ||
| 616 | if (feed_buffer(ctx->buffer, &ctx->bytes_read, &data, &size, | 466 | if (feed_buffer(ctx->buffer, &ctx->bytes_read, &data, &size, |
| 617 | line_length)) | 467 | line_length)) |
| 618 | { | 468 | { |
| 619 | ctx->bytes_read = 0; | 469 | reset_context_buffer(ctx); |
| 620 | 470 | ||
| 621 | if (ctx->compression == PSD_COMPRESSION_RLE) { | 471 | if (ctx->compression == PSD_COMPRESSION_RLE) { |
| 622 | decompress_line(ctx->buffer, line_length, | 472 | decompress_line(ctx->buffer, line_length, |
| 623 | ctx->channels_buffers[ctx->current_channel] | 473 | ctx->ch_bufs[ctx->curr_ch] + ctx->pos |
| 624 | + ctx->position | ||
| 625 | ); | 474 | ); |
| 626 | } else { | 475 | } else { |
| 627 | memcpy(ctx->channels_buffers[ctx->current_channel] | 476 | memcpy(ctx->ch_bufs[ctx->curr_ch] + ctx->pos, |
| 628 | + ctx->position, ctx->buffer, ctx->width); | 477 | ctx->buffer, ctx->width); |
| 629 | } | 478 | } |
| 630 | 479 | ||
| 631 | ctx->position += ctx->width; | 480 | ctx->pos += ctx->width; |
| 632 | ++ctx->current_row; | 481 | ++ctx->curr_row; |
| 633 | 482 | ||
| 634 | if (ctx->current_row >= ctx->height) { | 483 | if (ctx->curr_row >= ctx->height) { |
| 635 | ++ctx->current_channel; | 484 | ++ctx->curr_ch; |
| 636 | ctx->current_row = 0; | 485 | ctx->curr_row = 0; |
| 637 | ctx->position = 0; | 486 | ctx->pos = 0; |
| 638 | if (ctx->current_channel >= ctx->channels) { | 487 | if (ctx->curr_ch >= ctx->channels) { |
| 639 | ctx->state = PSD_STATE_DONE; | 488 | ctx->state = PSD_STATE_DONE; |
| 640 | } | 489 | } |
| 641 | } | 490 | } |
| @@ -655,9 +504,9 @@ gdk_pixbuf__psd_image_load_increment (gpointer context_ptr, | |||
| 655 | guchar* pixels = gdk_pixbuf_get_pixels(ctx->pixbuf); | 504 | guchar* pixels = gdk_pixbuf_get_pixels(ctx->pixbuf); |
| 656 | for (int i = 0; i < ctx->height; i++) { | 505 | for (int i = 0; i < ctx->height; i++) { |
| 657 | for (int j = 0; j < ctx->width; j++) { | 506 | for (int j = 0; j < ctx->width; j++) { |
| 658 | pixels[3*j+0] = ctx->channels_buffers[0][ctx->width*i + j]; | 507 | pixels[3*j+0] = ctx->ch_bufs[0][ctx->width*i + j]; |
| 659 | pixels[3*j+1] = ctx->channels_buffers[1][ctx->width*i + j]; | 508 | pixels[3*j+1] = ctx->ch_bufs[1][ctx->width*i + j]; |
| 660 | pixels[3*j+2] = ctx->channels_buffers[2][ctx->width*i + j]; | 509 | pixels[3*j+2] = ctx->ch_bufs[2][ctx->width*i + j]; |
| 661 | } | 510 | } |
| 662 | pixels += gdk_pixbuf_get_rowstride(ctx->pixbuf); | 511 | pixels += gdk_pixbuf_get_rowstride(ctx->pixbuf); |
| 663 | } | 512 | } |
