13ff48bf5SDavid du Colombier /* Copyright (C) 1995, 2000 Aladdin Enterprises. All rights reserved.
27dd7cddfSDavid du Colombier
3*593dc095SDavid du Colombier This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier implied.
57dd7cddfSDavid du Colombier
6*593dc095SDavid du Colombier This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier
10*593dc095SDavid du Colombier For more information about licensing, please refer to
11*593dc095SDavid du Colombier http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier San Rafael, CA 94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier
17*593dc095SDavid du Colombier /* $Id: gdevtfnx.c,v 1.7 2002/02/21 22:24:52 giles Exp $ */
187dd7cddfSDavid du Colombier /* 12-bit & 24-bit RGB uncompressed TIFF driver */
197dd7cddfSDavid du Colombier #include "gdevprn.h"
207dd7cddfSDavid du Colombier #include "gdevtifs.h"
217dd7cddfSDavid du Colombier
227dd7cddfSDavid du Colombier /*
237dd7cddfSDavid du Colombier * Thanks to Alan Barclay <alan@escribe.co.uk> for donating the original
247dd7cddfSDavid du Colombier * version of this code to Ghostscript.
257dd7cddfSDavid du Colombier */
267dd7cddfSDavid du Colombier
277dd7cddfSDavid du Colombier /* ------ The device descriptors ------ */
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier /* Default X and Y resolution */
307dd7cddfSDavid du Colombier #define X_DPI 72
317dd7cddfSDavid du Colombier #define Y_DPI 72
327dd7cddfSDavid du Colombier
337dd7cddfSDavid du Colombier typedef struct gx_device_tiff_s {
347dd7cddfSDavid du Colombier gx_device_common;
357dd7cddfSDavid du Colombier gx_prn_device_common;
367dd7cddfSDavid du Colombier gdev_tiff_state tiff;
377dd7cddfSDavid du Colombier } gx_device_tiff;
387dd7cddfSDavid du Colombier
397dd7cddfSDavid du Colombier private dev_proc_print_page(tiff12_print_page);
407dd7cddfSDavid du Colombier private dev_proc_print_page(tiff24_print_page);
417dd7cddfSDavid du Colombier
427dd7cddfSDavid du Colombier private const gx_device_procs tiff12_procs =
437dd7cddfSDavid du Colombier prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
447dd7cddfSDavid du Colombier gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb);
457dd7cddfSDavid du Colombier private const gx_device_procs tiff24_procs =
467dd7cddfSDavid du Colombier prn_color_procs(gdev_prn_open, gdev_prn_output_page, gdev_prn_close,
477dd7cddfSDavid du Colombier gx_default_rgb_map_rgb_color, gx_default_rgb_map_color_rgb);
487dd7cddfSDavid du Colombier
493ff48bf5SDavid du Colombier const gx_device_printer gs_tiff12nc_device = {
503ff48bf5SDavid du Colombier prn_device_std_body(gx_device_tiff, tiff12_procs, "tiff12nc",
517dd7cddfSDavid du Colombier DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
527dd7cddfSDavid du Colombier X_DPI, Y_DPI,
537dd7cddfSDavid du Colombier 0, 0, 0, 0,
547dd7cddfSDavid du Colombier 24, tiff12_print_page)
557dd7cddfSDavid du Colombier };
567dd7cddfSDavid du Colombier
573ff48bf5SDavid du Colombier const gx_device_printer gs_tiff24nc_device = {
583ff48bf5SDavid du Colombier prn_device_std_body(gx_device_tiff, tiff24_procs, "tiff24nc",
597dd7cddfSDavid du Colombier DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS,
607dd7cddfSDavid du Colombier X_DPI, Y_DPI,
617dd7cddfSDavid du Colombier 0, 0, 0, 0,
627dd7cddfSDavid du Colombier 24, tiff24_print_page)
637dd7cddfSDavid du Colombier };
647dd7cddfSDavid du Colombier
657dd7cddfSDavid du Colombier /* ------ Private definitions ------ */
667dd7cddfSDavid du Colombier
677dd7cddfSDavid du Colombier /* Define our TIFF directory - sorted by tag number */
687dd7cddfSDavid du Colombier typedef struct tiff_rgb_directory_s {
697dd7cddfSDavid du Colombier TIFF_dir_entry BitsPerSample;
707dd7cddfSDavid du Colombier TIFF_dir_entry Compression;
717dd7cddfSDavid du Colombier TIFF_dir_entry Photometric;
727dd7cddfSDavid du Colombier TIFF_dir_entry FillOrder;
737dd7cddfSDavid du Colombier TIFF_dir_entry SamplesPerPixel;
747dd7cddfSDavid du Colombier } tiff_rgb_directory;
757dd7cddfSDavid du Colombier typedef struct tiff_rgb_values_s {
767dd7cddfSDavid du Colombier TIFF_ushort bps[3];
777dd7cddfSDavid du Colombier } tiff_rgb_values;
787dd7cddfSDavid du Colombier
797dd7cddfSDavid du Colombier private const tiff_rgb_directory dir_rgb_template =
807dd7cddfSDavid du Colombier {
817dd7cddfSDavid du Colombier /* C's ridiculous rules about & and arrays require bps[0] here: */
827dd7cddfSDavid du Colombier {TIFFTAG_BitsPerSample, TIFF_SHORT | TIFF_INDIRECT, 3, offset_of(tiff_rgb_values, bps[0])},
837dd7cddfSDavid du Colombier {TIFFTAG_Compression, TIFF_SHORT, 1, Compression_none},
847dd7cddfSDavid du Colombier {TIFFTAG_Photometric, TIFF_SHORT, 1, Photometric_RGB},
857dd7cddfSDavid du Colombier {TIFFTAG_FillOrder, TIFF_SHORT, 1, FillOrder_MSB2LSB},
867dd7cddfSDavid du Colombier {TIFFTAG_SamplesPerPixel, TIFF_SHORT, 1, 3},
877dd7cddfSDavid du Colombier };
887dd7cddfSDavid du Colombier
893ff48bf5SDavid du Colombier private const tiff_rgb_values val_12_template = {
907dd7cddfSDavid du Colombier {4, 4, 4}
917dd7cddfSDavid du Colombier };
927dd7cddfSDavid du Colombier
933ff48bf5SDavid du Colombier private const tiff_rgb_values val_24_template = {
947dd7cddfSDavid du Colombier {8, 8, 8}
957dd7cddfSDavid du Colombier };
967dd7cddfSDavid du Colombier
977dd7cddfSDavid du Colombier /* ------ Private functions ------ */
987dd7cddfSDavid du Colombier
997dd7cddfSDavid du Colombier private int
tiff12_print_page(gx_device_printer * pdev,FILE * file)1007dd7cddfSDavid du Colombier tiff12_print_page(gx_device_printer * pdev, FILE * file)
1017dd7cddfSDavid du Colombier {
1023ff48bf5SDavid du Colombier gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
1037dd7cddfSDavid du Colombier int code;
1047dd7cddfSDavid du Colombier
1057dd7cddfSDavid du Colombier /* Write the page directory. */
1067dd7cddfSDavid du Colombier code = gdev_tiff_begin_page(pdev, &tfdev->tiff, file,
1077dd7cddfSDavid du Colombier (const TIFF_dir_entry *)&dir_rgb_template,
1087dd7cddfSDavid du Colombier sizeof(dir_rgb_template) / sizeof(TIFF_dir_entry),
1097dd7cddfSDavid du Colombier (const byte *)&val_12_template,
1103ff48bf5SDavid du Colombier sizeof(val_12_template), 0);
1117dd7cddfSDavid du Colombier if (code < 0)
1127dd7cddfSDavid du Colombier return code;
1137dd7cddfSDavid du Colombier
1147dd7cddfSDavid du Colombier /* Write the page data. */
1157dd7cddfSDavid du Colombier {
1167dd7cddfSDavid du Colombier int y;
1177dd7cddfSDavid du Colombier int raster = gdev_prn_raster(pdev);
1187dd7cddfSDavid du Colombier byte *line = gs_alloc_bytes(pdev->memory, raster, "tiff12_print_page");
1197dd7cddfSDavid du Colombier byte *row;
1207dd7cddfSDavid du Colombier
1217dd7cddfSDavid du Colombier if (line == 0)
1227dd7cddfSDavid du Colombier return_error(gs_error_VMerror);
1237dd7cddfSDavid du Colombier
1247dd7cddfSDavid du Colombier for (y = 0; y < pdev->height; ++y) {
1257dd7cddfSDavid du Colombier const byte *src;
1267dd7cddfSDavid du Colombier byte *dest;
1277dd7cddfSDavid du Colombier int x;
1287dd7cddfSDavid du Colombier
1297dd7cddfSDavid du Colombier code = gdev_prn_get_bits(pdev, y, line, &row);
1307dd7cddfSDavid du Colombier if (code < 0)
1317dd7cddfSDavid du Colombier break;
1327dd7cddfSDavid du Colombier
1337dd7cddfSDavid du Colombier for (src = row, dest = line, x = 0; x < raster;
1347dd7cddfSDavid du Colombier src += 6, dest += 3, x += 6
1357dd7cddfSDavid du Colombier ) {
1367dd7cddfSDavid du Colombier dest[0] = (src[0] & 0xf0) | (src[1] >> 4);
1377dd7cddfSDavid du Colombier dest[1] = (src[2] & 0xf0) | (src[3] >> 4);
1387dd7cddfSDavid du Colombier dest[2] = (src[4] & 0xf0) | (src[5] >> 4);
1397dd7cddfSDavid du Colombier }
1403ff48bf5SDavid du Colombier fwrite(line, 1, (pdev->width * 3 + 1) >> 1, file);
1417dd7cddfSDavid du Colombier }
1427dd7cddfSDavid du Colombier
1433ff48bf5SDavid du Colombier gdev_tiff_end_strip(&tfdev->tiff, file);
1447dd7cddfSDavid du Colombier gdev_tiff_end_page(&tfdev->tiff, file);
1457dd7cddfSDavid du Colombier gs_free_object(pdev->memory, line, "tiff12_print_page");
1467dd7cddfSDavid du Colombier }
1477dd7cddfSDavid du Colombier
1487dd7cddfSDavid du Colombier return code;
1497dd7cddfSDavid du Colombier }
1507dd7cddfSDavid du Colombier
1517dd7cddfSDavid du Colombier private int
tiff24_print_page(gx_device_printer * pdev,FILE * file)1527dd7cddfSDavid du Colombier tiff24_print_page(gx_device_printer * pdev, FILE * file)
1537dd7cddfSDavid du Colombier {
1543ff48bf5SDavid du Colombier gx_device_tiff *const tfdev = (gx_device_tiff *)pdev;
1557dd7cddfSDavid du Colombier int code;
1567dd7cddfSDavid du Colombier
1577dd7cddfSDavid du Colombier /* Write the page directory. */
1587dd7cddfSDavid du Colombier code = gdev_tiff_begin_page(pdev, &tfdev->tiff, file,
1597dd7cddfSDavid du Colombier (const TIFF_dir_entry *)&dir_rgb_template,
1607dd7cddfSDavid du Colombier sizeof(dir_rgb_template) / sizeof(TIFF_dir_entry),
1617dd7cddfSDavid du Colombier (const byte *)&val_24_template,
1623ff48bf5SDavid du Colombier sizeof(val_24_template), 0);
1637dd7cddfSDavid du Colombier if (code < 0)
1647dd7cddfSDavid du Colombier return code;
1657dd7cddfSDavid du Colombier
1667dd7cddfSDavid du Colombier /* Write the page data. */
1677dd7cddfSDavid du Colombier {
1687dd7cddfSDavid du Colombier int y;
1697dd7cddfSDavid du Colombier int raster = gdev_prn_raster(pdev);
1707dd7cddfSDavid du Colombier byte *line = gs_alloc_bytes(pdev->memory, raster, "tiff24_print_page");
1717dd7cddfSDavid du Colombier byte *row;
1727dd7cddfSDavid du Colombier
1737dd7cddfSDavid du Colombier if (line == 0)
1747dd7cddfSDavid du Colombier return_error(gs_error_VMerror);
1757dd7cddfSDavid du Colombier for (y = 0; y < pdev->height; ++y) {
1767dd7cddfSDavid du Colombier code = gdev_prn_get_bits(pdev, y, line, &row);
1777dd7cddfSDavid du Colombier if (code < 0)
1787dd7cddfSDavid du Colombier break;
1797dd7cddfSDavid du Colombier fwrite((char *)row, raster, 1, file);
1807dd7cddfSDavid du Colombier }
1813ff48bf5SDavid du Colombier gdev_tiff_end_strip(&tfdev->tiff, file);
1827dd7cddfSDavid du Colombier gdev_tiff_end_page(&tfdev->tiff, file);
1837dd7cddfSDavid du Colombier gs_free_object(pdev->memory, line, "tiff24_print_page");
1847dd7cddfSDavid du Colombier }
1857dd7cddfSDavid du Colombier
1867dd7cddfSDavid du Colombier return code;
1877dd7cddfSDavid du Colombier }
188