mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-21 12:02:32 +00:00
Yet another intermediate version.
This commit is contained in:
parent
770d8cad3e
commit
5d6799eb6d
|
@ -36,8 +36,8 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h> /* We want glib.h first for some pretty obscure
|
||||
* Win32 compilation issues.
|
||||
#include <glib.h> /* We want glib.h first because of some
|
||||
* pretty obscure Win32 compilation issues.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -277,9 +277,10 @@ typedef struct
|
|||
{
|
||||
guint32 width, height;
|
||||
gdouble resolution;
|
||||
PSPCompression compression;
|
||||
guchar metric;
|
||||
guint16 compression;
|
||||
guint16 depth;
|
||||
gboolean greyscale;
|
||||
guchar greyscale;
|
||||
guint32 active_layer;
|
||||
guint16 layer_count;
|
||||
} PSPimage;
|
||||
|
@ -331,7 +332,7 @@ static PSPSaveInterface psint =
|
|||
};
|
||||
|
||||
static guint16 major, minor;
|
||||
|
||||
static guint tile_height;
|
||||
|
||||
MAIN()
|
||||
|
||||
|
@ -573,7 +574,7 @@ read_block_header (FILE *f,
|
|||
long header_start;
|
||||
guint32 len;
|
||||
|
||||
IFDBG(2) header_start = ftell (f);
|
||||
IFDBG(3) header_start = ftell (f);
|
||||
|
||||
if (fread (buf, 4, 1, f) < 1
|
||||
|| fread (&id, 2, 1, f) < 1
|
||||
|
@ -591,7 +592,7 @@ read_block_header (FILE *f,
|
|||
return -1;
|
||||
}
|
||||
|
||||
IFDBG(2) gimp_message_printf (("PSP: %s at %d", block_name (id),
|
||||
IFDBG(3) gimp_message_printf (("PSP: %s at %d", block_name (id),
|
||||
header_start));
|
||||
|
||||
if (major < 4)
|
||||
|
@ -604,7 +605,8 @@ read_block_header (FILE *f,
|
|||
/* Version 4.0 seems to have dropped the initial data chunk length
|
||||
* field.
|
||||
*/
|
||||
*total_len = *init_len = GUINT32_FROM_LE (len);
|
||||
*init_len = 0xDEADBEEF; /* Intentionally bogus, should not be used */
|
||||
*total_len = GUINT32_FROM_LE (len);
|
||||
}
|
||||
|
||||
return id;
|
||||
|
@ -622,9 +624,6 @@ read_general_image_attribute_block (FILE *f,
|
|||
#else
|
||||
guchar res[8];
|
||||
#endif
|
||||
guchar metric;
|
||||
guint16 compression;
|
||||
guchar greyscale;
|
||||
|
||||
if (init_len < 38 || total_len < 38)
|
||||
{
|
||||
|
@ -639,11 +638,11 @@ read_general_image_attribute_block (FILE *f,
|
|||
if (fread (&ia->width, 4, 1, f) < 1
|
||||
|| fread (&ia->height, 4, 1, f) < 1
|
||||
|| fread (res, 8, 1, f) < 1
|
||||
|| fread (&metric, 1, 1, f) < 1
|
||||
|| fread (&compression, 1, 1, f) < 1
|
||||
|| fread (&ia->metric, 1, 1, f) < 1
|
||||
|| fread (&ia->compression, 2, 1, f) < 1
|
||||
|| fread (&ia->depth, 2, 1, f) < 1
|
||||
|| fread (buf, 2+4, 1, f) < 1 /* Skip plane and colour count */
|
||||
|| fread (&greyscale, 1, 1, f) < 1
|
||||
|| fread (&ia->greyscale, 1, 1, f) < 1
|
||||
|| fread (buf, 4, 1, f) < 1 /* Skip total image size */
|
||||
|| fread (&ia->active_layer, 4, 1, f) < 1
|
||||
|| fread (&ia->layer_count, 2, 1, f) < 1)
|
||||
|
@ -654,7 +653,7 @@ read_general_image_attribute_block (FILE *f,
|
|||
}
|
||||
ia->height = GUINT32_FROM_LE (ia->height);
|
||||
ia->width = GUINT32_FROM_LE (ia->width);
|
||||
ia->width = GUINT32_FROM_LE (ia->width);
|
||||
ia->depth = GUINT16_FROM_LE (ia->depth);
|
||||
|
||||
#ifdef G_HAVE_GINT64
|
||||
res[0] = GUINT64_FROM_LE (res[0]);
|
||||
|
@ -679,10 +678,19 @@ read_general_image_attribute_block (FILE *f,
|
|||
#endif
|
||||
#endif
|
||||
memcpy (&ia->resolution, res, 8);
|
||||
if (metric == PSP_METRIC_CM)
|
||||
if (ia->metric == PSP_METRIC_CM)
|
||||
ia->resolution /= 2.54;
|
||||
|
||||
ia->compression = compression;
|
||||
ia->compression = GUINT16_FROM_LE (ia->compression);
|
||||
if (ia->compression > PSP_COMP_LZ77)
|
||||
{
|
||||
gimp_message_printf (("PSP: Unknown compression type %d",
|
||||
ia->compression));
|
||||
fclose (f);
|
||||
return -1;
|
||||
}
|
||||
ia->active_layer = GUINT32_FROM_LE (ia->active_layer);
|
||||
ia->layer_count = GUINT16_FROM_LE (ia->layer_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -849,6 +857,8 @@ gimp_layer_mode_from_psp_blend_mode (PSPLayerBlendModes mode)
|
|||
return NORMAL_MODE;
|
||||
case PSP_BLEND_DARKEN:
|
||||
return DARKEN_ONLY_MODE;
|
||||
case PSP_BLEND_LIGHTEN:
|
||||
return LIGHTEN_ONLY_MODE;
|
||||
case PSP_BLEND_HUE:
|
||||
return HUE_MODE;
|
||||
case PSP_BLEND_SATURATION:
|
||||
|
@ -907,17 +917,120 @@ blend_mode_name (PSPLayerBlendModes mode)
|
|||
return blend_mode_names[mode];
|
||||
|
||||
g_free (err_name);
|
||||
err_name = g_strdup_printf ("%d", mode);
|
||||
err_name = g_strdup_printf ("unknown layer blend mode %d", mode);
|
||||
|
||||
return err_name;
|
||||
}
|
||||
|
||||
static char *
|
||||
bitmap_type_name (int type)
|
||||
{
|
||||
static char *bitmap_type_names[] =
|
||||
{
|
||||
"IMAGE",
|
||||
"TRANS_MASK",
|
||||
"USER_MASK",
|
||||
"SELECTION",
|
||||
"ALPHA_MASK",
|
||||
"THUMBNAIL"
|
||||
};
|
||||
static gchar *err_name = NULL;
|
||||
|
||||
if (type >= 0 && type <= PSP_DIB_THUMBNAIL)
|
||||
return bitmap_type_names[type];
|
||||
|
||||
g_free (err_name);
|
||||
err_name = g_strdup_printf ("unknown bitmap type %d", type);
|
||||
|
||||
return err_name;
|
||||
}
|
||||
|
||||
static char *
|
||||
channel_type_name (int type)
|
||||
{
|
||||
static char *channel_type_names[] =
|
||||
{
|
||||
"COMPOSITE",
|
||||
"RED",
|
||||
"GREEN",
|
||||
"BLUE"
|
||||
};
|
||||
static gchar *err_name = NULL;
|
||||
|
||||
if (type >= 0 && type <= PSP_DIB_THUMBNAIL)
|
||||
return channel_type_names[type];
|
||||
|
||||
g_free (err_name);
|
||||
err_name = g_strdup_printf ("unknown channel type %d", type);
|
||||
|
||||
return err_name;
|
||||
}
|
||||
|
||||
static void
|
||||
read_channel_data (FILE *f,
|
||||
PSPCompression compression,
|
||||
guchar **pixels,
|
||||
guint bpp,
|
||||
GDrawable *drawable,
|
||||
GPixelRgn *pixel_rgn,
|
||||
PSPDIBType bitmap_type,
|
||||
PSPChannelType channel_type,
|
||||
guint32 compressed_len)
|
||||
{
|
||||
gint i, k, y, width = drawable->width, height = drawable->height;
|
||||
guchar *scanline, *p, *q;
|
||||
|
||||
switch (compression)
|
||||
{
|
||||
case PSP_COMP_NONE:
|
||||
if (bpp == 1)
|
||||
{
|
||||
gimp_tile_cache_size (tile_height * width);
|
||||
y = 0;
|
||||
while (y < height)
|
||||
{
|
||||
fread (pixels[y], width, 1, f);
|
||||
if (width % 4)
|
||||
fseek (f, 4 - (width % 4), SEEK_CUR);
|
||||
y++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_tile_cache_size (height * width * bpp);
|
||||
scanline = g_malloc (width);
|
||||
if (channel_type == PSP_CHANNEL_COMPOSITE)
|
||||
k = 3;
|
||||
else
|
||||
k = channel_type - PSP_CHANNEL_RED;
|
||||
y = 0;
|
||||
while (y < height)
|
||||
{
|
||||
fread (scanline, width, 1, f);
|
||||
if (width % 4)
|
||||
fseek (f, 4 - (width % 4), SEEK_CUR);
|
||||
p = scanline;
|
||||
q = pixels[y] + k;
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
*q = *p;
|
||||
q += bpp;
|
||||
p++;
|
||||
}
|
||||
y++;
|
||||
}
|
||||
g_free (scanline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
read_layer_block (FILE *f,
|
||||
gint image_ID,
|
||||
guint total_len,
|
||||
PSPimage *ia)
|
||||
{
|
||||
int i;
|
||||
long block_start, sub_block_start, channel_start;
|
||||
int sub_id;
|
||||
guint32 sub_init_len, sub_total_len;
|
||||
|
@ -926,13 +1039,18 @@ read_layer_block (FILE *f,
|
|||
guchar type, opacity, blend_mode, visibility, transparency_protected;
|
||||
guchar link_group_id, mask_linked, mask_disabled;
|
||||
guint32 image_rect[4], saved_image_rect[4], mask_rect[4], saved_mask_rect[4];
|
||||
gboolean width_bumped = FALSE, height_bumped = FALSE;
|
||||
gboolean null_layer = FALSE;
|
||||
guint16 bitmap_count, channel_count;
|
||||
GDrawableType drawable_type;
|
||||
guint32 layer_ID;
|
||||
GLayerMode layer_mode;
|
||||
guint32 channel_init_len, channel_total_len;
|
||||
guint32 compressed_len, uncompressed_len;
|
||||
guint16 bitmap_type, channel_type;
|
||||
gint width, height, bpp;
|
||||
guchar **pixels, *pixel;
|
||||
GDrawable *drawable;
|
||||
GPixelRgn pixel_rgn;
|
||||
|
||||
block_start = ftell (f);
|
||||
|
||||
|
@ -977,9 +1095,9 @@ read_layer_block (FILE *f,
|
|||
|| fread (&saved_mask_rect, 16, 1, f) < 1
|
||||
|| fread (&mask_linked, 1, 1, f) < 1
|
||||
|| fread (&mask_disabled, 1, 1, f) < 1
|
||||
|| fseek (f, 43, SEEK_CUR) < 0
|
||||
|| fread (&bitmap_count, 1, 1, f) < 1
|
||||
|| fread (&channel_count, 1, 1, f) < 1)
|
||||
|| fseek (f, 47, SEEK_CUR) < 0
|
||||
|| fread (&bitmap_count, 2, 1, f) < 1
|
||||
|| fread (&channel_count, 2, 1, f) < 1)
|
||||
{
|
||||
gimp_message ("PSP: Error reading layer information chunk");
|
||||
fclose (f);
|
||||
|
@ -1007,10 +1125,11 @@ read_layer_block (FILE *f,
|
|||
|| fread (&mask_linked, 1, 1, f) < 1
|
||||
|| fread (&mask_disabled, 1, 1, f) < 1
|
||||
|| fseek (f, 43, SEEK_CUR) < 0
|
||||
|| fread (&bitmap_count, 1, 1, f) < 1
|
||||
|| fread (&channel_count, 1, 1, f) < 1)
|
||||
|| fread (&bitmap_count, 2, 1, f) < 1
|
||||
|| fread (&channel_count, 2, 1, f) < 1)
|
||||
{
|
||||
gimp_message ("PSP: Error reading layer information chunk");
|
||||
g_free (name);
|
||||
fclose (f);
|
||||
gimp_image_delete (image_ID);
|
||||
return -1;
|
||||
|
@ -1024,6 +1143,8 @@ read_layer_block (FILE *f,
|
|||
swab_rect (saved_image_rect);
|
||||
swab_rect (mask_rect);
|
||||
swab_rect (saved_mask_rect);
|
||||
bitmap_count = GUINT16_FROM_LE (bitmap_count);
|
||||
channel_count = GUINT16_FROM_LE (channel_count);
|
||||
|
||||
layer_mode = gimp_layer_mode_from_psp_blend_mode (blend_mode);
|
||||
if ((int) layer_mode == -1)
|
||||
|
@ -1035,32 +1156,44 @@ read_layer_block (FILE *f,
|
|||
visibility = FALSE;
|
||||
}
|
||||
|
||||
IFDBG(2) gimp_message_printf
|
||||
(("PSP: layer: %s %dx%d (%dx%d) opacity %d blend_mode %d", name,
|
||||
image_rect[2] - image_rect[0],
|
||||
image_rect[3] - image_rect[1],
|
||||
saved_image_rect[2] - saved_image_rect[0],
|
||||
saved_image_rect[3] - saved_image_rect[1],
|
||||
opacity, blend_mode));
|
||||
width = saved_image_rect[2] - saved_image_rect[0];
|
||||
height = saved_image_rect[3] - saved_image_rect[1];
|
||||
|
||||
if (saved_image_rect[0] == saved_image_rect[2])
|
||||
IFDBG(2) gimp_message_printf
|
||||
(("PSP: layer: %s %dx%d (%dx%d) opacity %d blend_mode %s "
|
||||
"%d bitmaps %d channels",
|
||||
name,
|
||||
image_rect[2] - image_rect[0], image_rect[3] - image_rect[1],
|
||||
width, height,
|
||||
opacity, blend_mode_name (blend_mode),
|
||||
bitmap_count, channel_count));
|
||||
|
||||
if (width == 0)
|
||||
{
|
||||
saved_image_rect[2]++;
|
||||
width_bumped = TRUE;
|
||||
width++;
|
||||
null_layer = TRUE;
|
||||
}
|
||||
if (saved_image_rect[1] == saved_image_rect[3])
|
||||
if (height == 0)
|
||||
{
|
||||
saved_image_rect[3]++;
|
||||
height_bumped = TRUE;
|
||||
height++;
|
||||
null_layer = TRUE;
|
||||
}
|
||||
|
||||
if (ia->greyscale)
|
||||
if (!null_layer && bitmap_count == 1)
|
||||
drawable_type = GRAY_IMAGE, bpp = 1;
|
||||
else
|
||||
drawable_type = GRAYA_IMAGE, bpp = 1;
|
||||
else
|
||||
if (!null_layer && bitmap_count == 1)
|
||||
drawable_type = RGB_IMAGE, bpp = 3;
|
||||
else
|
||||
drawable_type = RGBA_IMAGE, bpp = 4;
|
||||
|
||||
layer_ID = gimp_layer_new (image_ID, name,
|
||||
saved_image_rect[2] - saved_image_rect[0],
|
||||
saved_image_rect[3] - saved_image_rect[1],
|
||||
/* XXX */
|
||||
ia->greyscale ? GRAYA_IMAGE : RGBA_IMAGE,
|
||||
width, height,
|
||||
drawable_type,
|
||||
opacity / 255.0,
|
||||
/* XXX */
|
||||
layer_mode);
|
||||
if (layer_ID == -1)
|
||||
{
|
||||
|
@ -1070,6 +1203,7 @@ read_layer_block (FILE *f,
|
|||
return -1;
|
||||
}
|
||||
|
||||
g_free (name);
|
||||
if (saved_image_rect[0] != 0 || saved_image_rect[1] != 0)
|
||||
gimp_layer_set_offsets (layer_ID,
|
||||
saved_image_rect[0], saved_image_rect[1]);
|
||||
|
@ -1081,11 +1215,25 @@ read_layer_block (FILE *f,
|
|||
|
||||
gimp_image_add_layer (image_ID, layer_ID, -1);
|
||||
|
||||
if (try_fseek (f, sub_block_start + sub_init_len, SEEK_SET) < 0)
|
||||
{
|
||||
gimp_image_delete (image_ID);
|
||||
return -1;
|
||||
}
|
||||
if (major < 4)
|
||||
if (try_fseek (f, sub_block_start + sub_init_len, SEEK_SET) < 0)
|
||||
{
|
||||
gimp_image_delete (image_ID);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (null_layer)
|
||||
pixel = g_malloc0 (height * width * bpp);
|
||||
else
|
||||
pixel = g_malloc0 (height * width * bpp);
|
||||
|
||||
pixels = g_new(guchar *, height);
|
||||
for (i = 0; i < height; i++)
|
||||
pixels[i] = pixel + width * bpp * i;
|
||||
|
||||
drawable = gimp_drawable_get (layer_ID);
|
||||
gimp_pixel_rgn_init (&pixel_rgn, drawable, 0, 0,
|
||||
width, height, TRUE, FALSE);
|
||||
|
||||
/* Read the layer channel sub-blocks */
|
||||
while (ftell (f) < sub_block_start + sub_total_len)
|
||||
|
@ -1110,6 +1258,9 @@ read_layer_block (FILE *f,
|
|||
|
||||
channel_start = ftell (f);
|
||||
|
||||
if (major == 4)
|
||||
fseek (f, 4, SEEK_CUR); /* Unknown field */
|
||||
|
||||
if (fread (&compressed_len, 4, 1, f) < 1
|
||||
|| fread (&uncompressed_len, 4, 1, f) < 1
|
||||
|| fread (&bitmap_type, 2, 1, f) < 1
|
||||
|
@ -1121,33 +1272,48 @@ read_layer_block (FILE *f,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (GUINT16_FROM_LE (bitmap_type) > PSP_DIB_USER_MASK)
|
||||
compressed_len = GUINT32_FROM_LE (compressed_len);
|
||||
uncompressed_len = GUINT32_FROM_LE (uncompressed_len);
|
||||
bitmap_type = GUINT16_FROM_LE (bitmap_type);
|
||||
channel_type = GUINT16_FROM_LE (channel_type);
|
||||
|
||||
if (bitmap_type > PSP_DIB_USER_MASK)
|
||||
{
|
||||
gimp_message ("PSP: Invalid bitmap type "
|
||||
"in channel information chunk");
|
||||
gimp_message_printf (("PSP: Invalid bitmap type %d "
|
||||
"in channel information chunk",
|
||||
bitmap_type));
|
||||
fclose (f);
|
||||
gimp_image_delete (image_ID);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (GUINT16_FROM_LE (channel_type) > PSP_CHANNEL_BLUE)
|
||||
if (channel_type > PSP_CHANNEL_BLUE)
|
||||
{
|
||||
gimp_message ("PSP: Invalid channel type "
|
||||
"in channel information chunk");
|
||||
gimp_message_printf (("PSP: Invalid channel type %d "
|
||||
"in channel information chunk",
|
||||
channel_type));
|
||||
fclose (f);
|
||||
gimp_image_delete (image_ID);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (try_fseek (f, channel_start + channel_init_len, SEEK_SET) < 0)
|
||||
{
|
||||
gimp_image_delete (image_ID);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read channel data */
|
||||
IFDBG(2) gimp_message_printf (("PSP: channel: %s %s %d (%d) bytes",
|
||||
bitmap_type_name (bitmap_type),
|
||||
channel_type_name (channel_type),
|
||||
uncompressed_len, compressed_len));
|
||||
|
||||
if (major < 4)
|
||||
if (try_fseek (f, channel_start + channel_init_len, SEEK_SET) < 0)
|
||||
{
|
||||
gimp_image_delete (image_ID);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!null_layer)
|
||||
read_channel_data (f, ia->compression, pixels,
|
||||
bpp, drawable, &pixel_rgn,
|
||||
bitmap_type, channel_type,
|
||||
compressed_len);
|
||||
|
||||
if (try_fseek (f, channel_start + channel_total_len, SEEK_SET) < 0)
|
||||
{
|
||||
|
@ -1155,15 +1321,36 @@ read_layer_block (FILE *f,
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
gimp_pixel_rgn_set_rect (&pixel_rgn, pixel, 0, 0, width, height);
|
||||
|
||||
g_free (pixels);
|
||||
g_free (pixel);
|
||||
}
|
||||
if (try_fseek (f, block_start + total_len, SEEK_SET) < 0)
|
||||
{
|
||||
gimp_image_delete (image_ID);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return layer_ID;
|
||||
}
|
||||
|
||||
static char *
|
||||
compression_name (int compression)
|
||||
{
|
||||
switch (compression)
|
||||
{
|
||||
case PSP_COMP_NONE:
|
||||
return "no compression";
|
||||
case PSP_COMP_RLE:
|
||||
return "RLE";
|
||||
case PSP_COMP_LZ77:
|
||||
return "LZ77";
|
||||
}
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static gint32
|
||||
load_image (char *filename)
|
||||
{
|
||||
|
@ -1256,10 +1443,10 @@ load_image (char *filename)
|
|||
block_total_len, &ia) == -1)
|
||||
return -1;
|
||||
|
||||
IFDBG(2) gimp_message_printf (("PSP: resolution: %d dpi "
|
||||
"width: %d height %d",
|
||||
IFDBG(3) gimp_message_printf (("PSP: %d dpi %dx%d %s",
|
||||
(int) ia.resolution,
|
||||
ia.width, ia.height));
|
||||
ia.width, ia.height,
|
||||
compression_name (ia.compression)));
|
||||
|
||||
image_ID = gimp_image_new (ia.width, ia.height,
|
||||
ia.greyscale ? GRAY : RGB);
|
||||
|
@ -1359,6 +1546,8 @@ run (char *name,
|
|||
GStatusType status = STATUS_SUCCESS;
|
||||
gint32 image_ID;
|
||||
|
||||
tile_height = gimp_tile_height ();
|
||||
|
||||
run_mode = param[0].data.d_int32;
|
||||
|
||||
*nreturn_vals = 1;
|
||||
|
|
Loading…
Reference in a new issue