mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-04 01:43:24 +00:00
plug-ins: bmp import - overhaul
This commit is contained in:
parent
b6be63eae3
commit
a261fdb91b
5 changed files with 1284 additions and 768 deletions
File diff suppressed because it is too large
Load diff
|
@ -25,9 +25,7 @@
|
|||
#define PLUG_IN_BINARY "file-bmp"
|
||||
#define PLUG_IN_ROLE "gimp-file-bmp"
|
||||
|
||||
#define MAXCOLORS 256
|
||||
|
||||
#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
|
||||
#define MAXCOLORS 256
|
||||
|
||||
#define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
|
||||
|
||||
|
@ -36,9 +34,17 @@
|
|||
#define BI_RLE8 1
|
||||
#define BI_RLE4 2
|
||||
#define BI_BITFIELDS 3
|
||||
#define BI_ALPHABITFIELDS 4
|
||||
#define BI_JPEG 4
|
||||
#define BI_PNG 5
|
||||
#define BI_ALPHABITFIELDS 6
|
||||
#endif
|
||||
|
||||
/* The following two are OS/2 BMP compression methods.
|
||||
* Their values (3 and 4) clash with MS values for
|
||||
* BI_BITFIELDS and BI_JPEG. We make up our own distinct
|
||||
* values and assign them as soon as we identify these
|
||||
* methods. */
|
||||
#define BI_OS2_HUFFMAN (100 + BI_BITFIELDS)
|
||||
#define BI_OS2_RLE24 (100 + BI_JPEG)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -63,6 +69,15 @@ typedef struct
|
|||
guint32 biClrUsed; /* 2E */
|
||||
guint32 biClrImp; /* 32 */
|
||||
guint32 masks[4]; /* 36 */
|
||||
guint32 bV4CSType;
|
||||
gdouble bV4Endpoints[9];
|
||||
gdouble bV4GammaRed;
|
||||
gdouble bV4GammaGreen;
|
||||
gdouble bV4GammaBlue;
|
||||
guint32 bV5Intent;
|
||||
guint32 bV5ProfileData;
|
||||
guint32 bV5ProfileSize;
|
||||
guint32 bV5Reserved;
|
||||
} BitmapHead;
|
||||
|
||||
typedef struct
|
||||
|
@ -70,6 +85,7 @@ typedef struct
|
|||
guint32 mask;
|
||||
guint32 shiftin;
|
||||
gfloat max_value;
|
||||
gint nbits;
|
||||
} BitmapChannel;
|
||||
|
||||
|
||||
|
|
209
plug-ins/file-bmp/generate-huffman.c
Normal file
209
plug-ins/file-bmp/generate-huffman.c
Normal file
|
@ -0,0 +1,209 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This program generates the header file "huffman.h".
|
||||
* huffman.h will contain an array of Huffnode structs which make up two
|
||||
* Huffman code trees for black and white pixels, respectively.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "generate-huffman.h"
|
||||
|
||||
#define ARR_SIZE(a) (sizeof a / sizeof a[0])
|
||||
|
||||
struct Node
|
||||
{
|
||||
int l;
|
||||
int r;
|
||||
int value;
|
||||
int leaf;
|
||||
int makeup;
|
||||
};
|
||||
|
||||
static int nnodes = 0;
|
||||
static struct Node nodebuffer[416];
|
||||
|
||||
static int blackroot = -1;
|
||||
static int whiteroot = -1;
|
||||
|
||||
static void s_buildtree (void);
|
||||
static void add_node (int *idx,
|
||||
const char *bits,
|
||||
int value,
|
||||
int makeup);
|
||||
static void find_empty_nodes (int idx,
|
||||
int depth);
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
struct Node *n = nodebuffer;
|
||||
FILE *file;
|
||||
|
||||
if (argc == 2)
|
||||
{
|
||||
if (! strcmp (argv[1], "-"))
|
||||
{
|
||||
file = stdout;
|
||||
}
|
||||
else if (! (file = fopen (argv[1], "w")))
|
||||
{
|
||||
perror (argv[1]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "Need filespec to save generated huffman header!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf (file, "/* This file was auto-generated by\n * %s\n */\n\n", argv[0]);
|
||||
|
||||
s_buildtree ();
|
||||
|
||||
/* sanity checks */
|
||||
find_empty_nodes (blackroot, 0);
|
||||
find_empty_nodes (whiteroot, 0);
|
||||
if (nnodes != 416)
|
||||
{
|
||||
fprintf (stderr, "*** have %d nodes, but should have 416.\n", nnodes);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf (file, "static const int blackroot = %d;\n", blackroot);
|
||||
fprintf (file, "static const int whiteroot = %d;\n\n", whiteroot);
|
||||
fprintf (file, "static const struct Huffnode nodebuffer[] = {\n ");
|
||||
for (i = 0; i < ARR_SIZE (nodebuffer); i++)
|
||||
{
|
||||
if ((i + 1) % 2 == 0 && i < ARR_SIZE (nodebuffer) - 1)
|
||||
{
|
||||
fprintf (file, "{ %3d, %3d, %4d, %2d, %2d },\n ", n[i].l, n[i].r,
|
||||
n[i].value, n[i].leaf, n[i].makeup);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (file, "{ %3d, %3d, %4d, %2d, %2d }, ", n[i].l, n[i].r,
|
||||
n[i].value, n[i].leaf, n[i].makeup);
|
||||
}
|
||||
}
|
||||
fprintf (file, "\n};\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
s_buildtree (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset (nodebuffer, 0, sizeof nodebuffer);
|
||||
|
||||
for (i = 0; i < ARR_SIZE (huff_term_black); i++)
|
||||
add_node (&blackroot, huff_term_black[i].bits, huff_term_black[i].number, 0);
|
||||
|
||||
for (i = 0; i < ARR_SIZE (huff_makeup_black); i++)
|
||||
add_node (&blackroot, huff_makeup_black[i].bits, huff_makeup_black[i].number, 1);
|
||||
|
||||
for (i = 0; i < ARR_SIZE (huff_term_white); i++)
|
||||
add_node (&whiteroot, huff_term_white[i].bits, huff_term_white[i].number, 0);
|
||||
|
||||
for (i = 0; i < ARR_SIZE (huff_makeup_white); i++)
|
||||
add_node (&whiteroot, huff_makeup_white[i].bits, huff_makeup_white[i].number, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
add_node (int *idx, const char *bits, int value, int makeup)
|
||||
{
|
||||
if (*idx == -1)
|
||||
{
|
||||
if (nnodes >= ARR_SIZE (nodebuffer))
|
||||
{
|
||||
fprintf (stderr, "*** too many nodes (have %d, max is %d)\n", nnodes,
|
||||
(int) ARR_SIZE (nodebuffer));
|
||||
exit (1);
|
||||
}
|
||||
*idx = nnodes++;
|
||||
nodebuffer[*idx].l = -1;
|
||||
nodebuffer[*idx].r = -1;
|
||||
}
|
||||
|
||||
if (! *bits)
|
||||
{
|
||||
/* we are on the final bit of the sequence */
|
||||
nodebuffer[*idx].value = value;
|
||||
nodebuffer[*idx].leaf = 1;
|
||||
nodebuffer[*idx].makeup = makeup;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (*bits)
|
||||
{
|
||||
case '0':
|
||||
add_node (&nodebuffer[*idx].l, bits + 1, value, makeup);
|
||||
break;
|
||||
case '1':
|
||||
add_node (&nodebuffer[*idx].r, bits + 1, value, makeup);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
find_empty_nodes (int idx, int depth)
|
||||
{
|
||||
static char str[30];
|
||||
const struct Node *node;
|
||||
|
||||
if (depth >= (int) sizeof str)
|
||||
{
|
||||
fprintf (stderr, "*** panic!, str[] is too short\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
str[depth] = 0;
|
||||
|
||||
node = &nodebuffer[idx];
|
||||
if (! node->leaf)
|
||||
{
|
||||
if (! (node->l != -1 && node->r != -1))
|
||||
{
|
||||
if (node->r != -1 && ! strcmp ("0000000", str))
|
||||
{
|
||||
; /* ok, that's eol */
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "*** node %s not full. l=%d r=%d\n", str, node->l, node->r);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
if (node->l != -1)
|
||||
{
|
||||
str[depth] = '0';
|
||||
find_empty_nodes (node->l, depth + 1);
|
||||
}
|
||||
if (node->r != -1)
|
||||
{
|
||||
str[depth] = '1';
|
||||
find_empty_nodes (node->r, depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
96
plug-ins/file-bmp/generate-huffman.h
Normal file
96
plug-ins/file-bmp/generate-huffman.h
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* GIMP - The GNU Image Manipulation Program
|
||||
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* This header file is used by generate-huffman.c to auto-generate
|
||||
* the actual "huffman.h".
|
||||
*
|
||||
* The bit sequences for terminating and make-up codes can be found in
|
||||
* ITU-T Rec T.4:
|
||||
* https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-T.4-200307-I!!PDF-E&type=items
|
||||
*/
|
||||
|
||||
struct Huffcode
|
||||
{
|
||||
int number;
|
||||
const char *bits;
|
||||
};
|
||||
|
||||
/* clang-format off */
|
||||
|
||||
static struct Huffcode huff_term_white[] = {
|
||||
{ 0, "00110101" }, { 1, "000111" }, { 2, "0111" }, { 3, "1000" },
|
||||
{ 4, "1011" }, { 5, "1100" }, { 6, "1110" }, { 7, "1111" },
|
||||
{ 8, "10011" }, { 9, "10100" }, { 10, "00111" }, { 11, "01000" },
|
||||
{ 12, "001000" }, { 13, "000011" }, { 14, "110100" }, { 15, "110101" },
|
||||
{ 16, "101010" }, { 17, "101011" }, { 18, "0100111" }, { 19, "0001100" },
|
||||
{ 20, "0001000" }, { 21, "0010111" }, { 22, "0000011" }, { 23, "0000100" },
|
||||
{ 24, "0101000" }, { 25, "0101011" }, { 26, "0010011" }, { 27, "0100100" },
|
||||
{ 28, "0011000" }, { 29, "00000010" }, { 30, "00000011" }, { 31, "00011010" },
|
||||
{ 32, "00011011" }, { 33, "00010010" }, { 34, "00010011" }, { 35, "00010100" },
|
||||
{ 36, "00010101" }, { 37, "00010110" }, { 38, "00010111" }, { 39, "00101000" },
|
||||
{ 40, "00101001" }, { 41, "00101010" }, { 42, "00101011" }, { 43, "00101100" },
|
||||
{ 44, "00101101" }, { 45, "00000100" }, { 46, "00000101" }, { 47, "00001010" },
|
||||
{ 48, "00001011" }, { 49, "01010010" }, { 50, "01010011" }, { 51, "01010100" },
|
||||
{ 52, "01010101" }, { 53, "00100100" }, { 54, "00100101" }, { 55, "01011000" },
|
||||
{ 56, "01011001" }, { 57, "01011010" }, { 58, "01011011" }, { 59, "01001010" },
|
||||
{ 60, "01001011" }, { 61, "00110010" }, { 62, "00110011" }, { 63, "00110100" },
|
||||
};
|
||||
|
||||
static struct Huffcode huff_term_black[] = {
|
||||
{ 0, "0000110111" }, { 1, "010" }, { 2, "11" }, { 3, "10" },
|
||||
{ 4, "011" }, { 5, "0011" }, { 6, "0010" }, { 7, "00011" },
|
||||
{ 8, "000101" }, { 9, "000100" }, { 10, "0000100" }, { 11, "0000101" },
|
||||
{ 12, "0000111" }, { 13, "00000100" }, { 14, "00000111" }, { 15, "000011000" },
|
||||
{ 16, "0000010111" }, { 17, "0000011000" }, { 18, "0000001000" }, { 19, "00001100111" },
|
||||
{ 20, "00001101000" }, { 21, "00001101100" }, { 22, "00000110111" }, { 23, "00000101000" },
|
||||
{ 24, "00000010111" }, { 25, "00000011000" }, { 26, "000011001010" }, { 27, "000011001011" },
|
||||
{ 28, "000011001100" }, { 29, "000011001101" }, { 30, "000001101000" }, { 31, "000001101001" },
|
||||
{ 32, "000001101010" }, { 33, "000001101011" }, { 34, "000011010010" }, { 35, "000011010011" },
|
||||
{ 36, "000011010100" }, { 37, "000011010101" }, { 38, "000011010110" }, { 39, "000011010111" },
|
||||
{ 40, "000001101100" }, { 41, "000001101101" }, { 42, "000011011010" }, { 43, "000011011011" },
|
||||
{ 44, "000001010100" }, { 45, "000001010101" }, { 46, "000001010110" }, { 47, "000001010111" },
|
||||
{ 48, "000001100100" }, { 49, "000001100101" }, { 50, "000001010010" }, { 51, "000001010011" },
|
||||
{ 52, "000000100100" }, { 53, "000000110111" }, { 54, "000000111000" }, { 55, "000000100111" },
|
||||
{ 56, "000000101000" }, { 57, "000001011000" }, { 58, "000001011001" }, { 59, "000000101011" },
|
||||
{ 60, "000000101100" }, { 61, "000001011010" }, { 62, "000001100110" }, { 63, "000001100111" },
|
||||
};
|
||||
|
||||
static struct Huffcode huff_makeup_white[] = {
|
||||
{ 64, "11011" }, { 128, "10010" }, { 192, "010111" }, { 256, "0110111" },
|
||||
{ 320, "00110110" }, { 384, "00110111" }, { 448, "01100100" }, { 512, "01100101" },
|
||||
{ 576, "01101000" }, { 640, "01100111" }, { 704, "011001100" }, { 768, "011001101" },
|
||||
{ 832, "011010010" }, { 896, "011010011" }, { 960, "011010100" }, { 1024, "011010101" },
|
||||
{ 1088, "011010110" }, { 1152, "011010111" }, { 1216, "011011000" }, { 1280, "011011001" },
|
||||
{ 1344, "011011010" }, { 1408, "011011011" }, { 1472, "010011000" }, { 1536, "010011001" },
|
||||
{ 1600, "010011010" }, { 1664, "011000" }, { 1728, "010011011" }, { 1792, "00000001000" },
|
||||
{ 1856, "00000001100" }, { 1920, "00000001101" }, { 1984, "000000010010" }, { 2048, "000000010011" },
|
||||
{ 2112, "000000010100" }, { 2176, "000000010101" }, { 2240, "000000010110" }, { 2304, "000000010111" },
|
||||
{ 2368, "000000011100" }, { 2432, "000000011101" }, { 2496, "000000011110" }, { 2560, "000000011111" },
|
||||
};
|
||||
|
||||
static struct Huffcode huff_makeup_black[] = {
|
||||
{ 64, "0000001111" }, { 128, "000011001000" }, { 192, "000011001001" }, { 256, "000001011011" },
|
||||
{ 320, "000000110011" }, { 384, "000000110100" }, { 448, "000000110101" }, { 512, "0000001101100" },
|
||||
{ 576, "0000001101101" }, { 640, "0000001001010" }, { 704, "0000001001011" }, { 768, "0000001001100" },
|
||||
{ 832, "0000001001101" }, { 896, "0000001110010" }, { 960, "0000001110011" }, { 1024, "0000001110100" },
|
||||
{ 1088, "0000001110101" }, { 1152, "0000001110110" }, { 1216, "0000001110111" }, { 1280, "0000001010010" },
|
||||
{ 1344, "0000001010011" }, { 1408, "0000001010100" }, { 1472, "0000001010101" }, { 1536, "0000001011010" },
|
||||
{ 1600, "0000001011011" }, { 1664, "0000001100100" }, { 1728, "0000001100101" }, { 1792, "00000001000" },
|
||||
{ 1856, "00000001100" }, { 1920, "00000001101" }, { 1984, "000000010010" }, { 2048, "000000010011" },
|
||||
{ 2112, "000000010100" }, { 2176, "000000010101" }, { 2240, "000000010110" }, { 2304, "000000010111" },
|
||||
{ 2368, "000000011100" }, { 2432, "000000011101" }, { 2496, "000000011110" }, { 2560, "000000011111" },
|
||||
};
|
|
@ -1,9 +1,19 @@
|
|||
plugin_name = 'file-bmp'
|
||||
|
||||
gen_huffman = executable('generate-huffman',
|
||||
'generate-huffman.c'
|
||||
)
|
||||
|
||||
huffman = custom_target('huffman.h',
|
||||
output: 'huffman.h',
|
||||
command: [gen_huffman, '@OUTPUT@'],
|
||||
)
|
||||
|
||||
plugin_sources = [
|
||||
'bmp-load.c',
|
||||
'bmp-export.c',
|
||||
'bmp.c',
|
||||
huffman,
|
||||
]
|
||||
|
||||
if platform_windows
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue