summaryrefslogtreecommitdiff
path: root/image
diff options
context:
space:
mode:
authorJohn Mark Bell <jmb@netsurf-browser.org>2004-09-04 16:41:28 +0000
committerJohn Mark Bell <jmb@netsurf-browser.org>2004-09-04 16:41:28 +0000
commit101c87958dfeb769c697136d221a2a1c63929e65 (patch)
tree99108a4a5c4b182ca9d385a9fa0330a9a6e3ea03 /image
parente223757e3504586f8c260991b81f8f62c3b75ffc (diff)
downloadnetsurf-101c87958dfeb769c697136d221a2a1c63929e65.tar.gz
netsurf-101c87958dfeb769c697136d221a2a1c63929e65.tar.bz2
[project @ 2004-09-04 16:41:28 by jmb]
Fix jpeg redraw Move png.c/h to /image and rework to use the bitmap code Make RISC OS bitmap struct publically accessible (via riscos/bitmap.h) Draw export now embeds JPEGs and PNGs/MNGs/JNGs correctly again. Background images are now plotted correctly again. svn path=/import/netsurf/; revision=1268
Diffstat (limited to 'image')
-rw-r--r--image/jpeg.c7
-rw-r--r--image/png.c245
-rw-r--r--image/png.h27
3 files changed, 278 insertions, 1 deletions
diff --git a/image/jpeg.c b/image/jpeg.c
index 85711bd2e..47a8f4b5e 100644
--- a/image/jpeg.c
+++ b/image/jpeg.c
@@ -122,7 +122,12 @@ bool nsjpeg_convert(struct content *c, int w, int h)
scanlines[0][i * 4 + 2] = b;
scanlines[0][i * 4 + 3] = 0xff;
}
-
+#else
+ /* make fully opaque for alpha plotting
+ * (is there a better way?) */
+ for (int i = width - 1; 0 <= i; i--) {
+ scanlines[0][i * 4 + 3] = 0xff;
+ }
#endif
} while (cinfo.output_scanline != cinfo.output_height);
diff --git a/image/png.c b/image/png.c
new file mode 100644
index 000000000..5fa4d9af7
--- /dev/null
+++ b/image/png.c
@@ -0,0 +1,245 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2004 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2004 Richard Wilson <not_ginger_matt@hotmail.com>
+ */
+
+#include <assert.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include "libpng/png.h"
+#include "netsurf/utils/config.h"
+#include "netsurf/content/content.h"
+#include "netsurf/image/bitmap.h"
+#include "netsurf/image/png.h"
+#include "netsurf/utils/log.h"
+#include "netsurf/utils/messages.h"
+#include "netsurf/utils/utils.h"
+
+#ifdef WITH_PNG
+/* libpng uses names starting png_, so use nspng_ here to avoid clashes */
+
+static void info_callback(png_structp png, png_infop info);
+static void row_callback(png_structp png, png_bytep new_row,
+ png_uint_32 row_num, int pass);
+static void end_callback(png_structp png, png_infop info);
+
+
+bool nspng_create(struct content *c, const char *params[])
+{
+ union content_msg_data msg_data;
+
+ c->data.png.png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ 0, 0, 0);
+ if (!c->data.png.png) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ warn_user("NoMemory", 0);
+ return false;
+ }
+ c->data.png.info = png_create_info_struct(c->data.png.png);
+ if (!c->data.png.info) {
+ png_destroy_read_struct(&c->data.png.png,
+ &c->data.png.info, 0);
+
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ warn_user("NoMemory", 0);
+ return false;
+ }
+
+ if (setjmp(png_jmpbuf(c->data.png.png))) {
+ png_destroy_read_struct(&c->data.png.png,
+ &c->data.png.info, 0);
+ LOG(("Failed to set callbacks"));
+ c->data.png.png = NULL;
+ c->data.png.info = NULL;
+
+ msg_data.error = messages_get("PNGError");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ png_set_progressive_read_fn(c->data.png.png, c,
+ info_callback, row_callback, end_callback);
+
+ return true;
+}
+
+
+bool nspng_process_data(struct content *c, char *data, unsigned int size)
+{
+ union content_msg_data msg_data;
+
+ if (setjmp(png_jmpbuf(c->data.png.png))) {
+ png_destroy_read_struct(&c->data.png.png,
+ &c->data.png.info, 0);
+ LOG(("Failed to process data"));
+ c->data.png.png = NULL;
+ c->data.png.info = NULL;
+
+ msg_data.error = messages_get("PNGError");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ return false;
+ }
+
+ png_process_data(c->data.png.png, c->data.png.info, data, size);
+
+ return true;
+}
+
+
+/**
+ * info_callback -- PNG header has been completely received, prepare to process
+ * image data
+ */
+
+void info_callback(png_structp png, png_infop info)
+{
+ int bit_depth, color_type, interlace, intent;
+ double gamma;
+ unsigned int rowbytes;
+ unsigned long width, height;
+ struct content *c = png_get_progressive_ptr(png);
+ union content_msg_data msg_data;
+
+ /* Read the PNG details
+ */
+ png_get_IHDR(png, info, &width, &height, &bit_depth,
+ &color_type, &interlace, 0, 0);
+
+ /* Claim the required memory for the converted PNG
+ */
+ c->bitmap = bitmap_create(width, height);
+ if (!c->bitmap) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ LOG(("Insufficient memory to create canvas."));
+ return;
+ }
+
+ /* Set up our transformations
+ */
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png);
+ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ png_set_gray_1_2_4_to_8(png);
+ if (png_get_valid(png, info, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png);
+ if (bit_depth == 16)
+ png_set_strip_16(png);
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png);
+ if (!(color_type & PNG_COLOR_MASK_ALPHA))
+ png_set_filler(png, 0xff, PNG_FILLER_AFTER);
+ /* gamma correction - we use 2.2 as our screen gamma
+ * this appears to be correct (at least in respect to !Browse)
+ * see http://www.w3.org/Graphics/PNG/all_seven.html for a test case
+ */
+ if (png_get_sRGB(png, info, &intent))
+ png_set_gamma(png, 2.2, 0.45455);
+ else {
+ if (png_get_gAMA(png, info, &gamma))
+ png_set_gamma(png, 2.2, gamma);
+ else
+ png_set_gamma(png, 2.2, 0.45455);
+ }
+
+
+ png_read_update_info(png, info);
+
+ c->data.png.rowbytes = rowbytes = png_get_rowbytes(png, info);
+ c->data.png.interlace = (interlace == PNG_INTERLACE_ADAM7);
+ c->width = width;
+ c->height = height;
+
+ LOG(("size %li * %li, bpp %i, rowbytes %u", width,
+ height, bit_depth, rowbytes));
+}
+
+
+static unsigned int interlace_start[8] = {0, 16, 0, 8, 0, 4, 0};
+static unsigned int interlace_step[8] = {28, 28, 12, 12, 4, 4, 0};
+static unsigned int interlace_row_start[8] = {0, 0, 4, 0, 2, 0, 1};
+static unsigned int interlace_row_step[8] = {8, 8, 8, 4, 4, 2, 2};
+
+void row_callback(png_structp png, png_bytep new_row,
+ png_uint_32 row_num, int pass)
+{
+ struct content *c = png_get_progressive_ptr(png);
+ unsigned long i, j, rowbytes = c->data.png.rowbytes;
+ unsigned int start, step;
+ char *row = bitmap_get_buffer(c->bitmap) +
+ bitmap_get_rowstride(c->bitmap) * row_num;
+
+ /* Abort if we've not got any data
+ */
+ if (new_row == 0)
+ return;
+
+ /* Handle interlaced sprites using the Adam7 algorithm
+ */
+ if (c->data.png.interlace) {
+ start = interlace_start[pass];
+ step = interlace_step[pass];
+ row_num = interlace_row_start[pass] +
+ interlace_row_step[pass] * row_num;
+
+ /* Copy the data to our current row taking into consideration interlacing
+ */
+ row = bitmap_get_buffer(c->bitmap) +
+ bitmap_get_rowstride(c->bitmap) * row_num;
+ for (j = 0, i = start; i < rowbytes; i += step) {
+ row[i++] = new_row[j++];
+ row[i++] = new_row[j++];
+ row[i++] = new_row[j++];
+ row[i++] = new_row[j++];
+ }
+ } else {
+ /* Do a fast memcpy of the row data
+ */
+ memcpy(row, new_row, rowbytes);
+ }
+}
+
+
+void end_callback(png_structp png, png_infop info)
+{
+ /*struct content *c = png_get_progressive_ptr(png);*/
+
+ LOG(("PNG end"));
+
+ /*xosspriteop_save_sprite_file(osspriteop_USER_AREA, c->data.png.sprite_area,
+ "png");*/
+}
+
+
+
+bool nspng_convert(struct content *c, int width, int height)
+{
+ assert(c->data.png.png);
+ assert(c->data.png.info);
+
+ png_destroy_read_struct(&c->data.png.png, &c->data.png.info, 0);
+
+ c->title = malloc(100);
+ if (c->title)
+ snprintf(c->title, 100, messages_get("PNGTitle"),
+ c->width, c->height, c->source_size);
+ c->size += (c->width * c->height * 4) + 16 + 44 + 100;
+ c->status = CONTENT_STATUS_DONE;
+ return true;
+}
+
+
+void nspng_destroy(struct content *c)
+{
+ free(c->title);
+ if (c->bitmap)
+ bitmap_destroy(c->bitmap);
+}
+#endif
diff --git a/image/png.h b/image/png.h
new file mode 100644
index 000000000..5cf0eb3c1
--- /dev/null
+++ b/image/png.h
@@ -0,0 +1,27 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2003 James Bursa <bursa@users.sourceforge.net>
+ */
+
+#ifndef _NETSURF_IMAGE_PNG_H_
+#define _NETSURF_IMAGE_PNG_H_
+
+#include "libpng/png.h"
+
+struct content;
+
+struct content_png_data {
+ png_structp png;
+ png_infop info;
+ unsigned long rowbytes;
+ int interlace;
+};
+
+bool nspng_create(struct content *c, const char *params[]);
+bool nspng_process_data(struct content *c, char *data, unsigned int size);
+bool nspng_convert(struct content *c, int width, int height);
+void nspng_destroy(struct content *c);
+
+#endif