/* Write the BMP file header. */ int write_bmp_header(gx_device_printer *pdev, FILE *file) { int depth = pdev->color_info.depth; bmp_quad palette[256]; if (depth <= 8) { int i; gx_color_value rgb[3]; bmp_quad q; q.reserved = 0; for (i = 0; i != 1 << depth; i++) { /* Note that the use of map_color_rgb is deprecated in favor of decode_color. This should work, though, because backwards compatibility is preserved. */ (*dev_proc(pdev, map_color_rgb))((gx_device *)pdev, (gx_color_index)i, rgb); q.red = gx_color_value_to_byte(rgb[0]); q.green = gx_color_value_to_byte(rgb[1]); q.blue = gx_color_value_to_byte(rgb[2]); palette[i] = q; } } return write_bmp_depth_header(pdev, file, depth, (const byte *)palette, gdev_prn_raster(pdev)); }
/* Map a r-g-b color to a color index. */ gx_color_index bmp_map_16m_rgb_color(gx_device * dev, const gx_color_value cv[]) { gx_color_value r, g, b; r = cv[0]; g = cv[1]; b = cv[2]; return gx_color_value_to_byte(r) + ((uint) gx_color_value_to_byte(g) << 8) + ((ulong) gx_color_value_to_byte(b) << 16); }
/* Encode a r-g-b color to a color index. */ static gx_color_index os2prn_map_rgb_color(gx_device * dev, const gx_color_value cv[]) { gx_color_value r = cv[0]; gx_color_value g = cv[1]; gx_color_value b = cv[2]; return gx_color_value_to_byte(r) + ((uint) gx_color_value_to_byte(g) << 8) + ((ulong) gx_color_value_to_byte(b) << 16); }
/* Map a r-g-b color to a color index. */ static gx_color_index cp50_rgb_color(gx_device *dev, const gx_color_value cv[]) { gx_color_value red, green, blue; red = cv[0]; green = cv[1]; blue = cv[2]; return ((ulong)gx_color_value_to_byte(red) << 16)+ ((uint)gx_color_value_to_byte(green) << 8) + gx_color_value_to_byte(blue); }
static gx_color_index pngalpha_encode_color(gx_device * dev, const gx_color_value cv[]) { /* bits 0-7 are alpha, stored inverted to avoid white/opaque * being 0xffffffff which is also gx_no_color_index. * So 0xff is transparent and 0x00 is opaque. * We always return opaque colors (bits 0-7 = 0). * Return value is 0xRRGGBB00. */ return ((uint) gx_color_value_to_byte(cv[2]) << 8) + ((ulong) gx_color_value_to_byte(cv[1]) << 16) + ((ulong) gx_color_value_to_byte(cv[0]) << 24); }
static gx_color_index dca_map_rgb_alpha_color(gx_device * dev, gx_color_value red, gx_color_value green, gx_color_value blue, gx_color_value alpha) { /* * We work exclusively with premultiplied color values, so we * have to premultiply the color components by alpha here. */ byte a = gx_color_value_to_byte(alpha); #define premult_(c)\ (((c) * a + gx_max_color_value / 2) / gx_max_color_value) #ifdef PREMULTIPLY_TOWARDS_WHITE byte bias = ~a; # define premult(c) (premult_(c) + bias) #else # define premult(c) premult_(c) #endif gx_color_index color; if (dev->color_info.num_components == 1) { uint lum = (red * lum_red_weight + green * lum_green_weight + blue * lum_blue_weight + lum_all_weights / 2) / lum_all_weights; if (a == 0xff) color = gx_color_value_to_byte(lum); else /* Premultiplication is necessary. */ color = premult(lum); } else { if (a == 0xff) color = ((uint) gx_color_value_to_byte(red) << 16) + ((uint) gx_color_value_to_byte(green) << 8) + gx_color_value_to_byte(blue); else /* Premultiplication is necessary. */ color = (premult(red) << 16) + (premult(green) << 8) + premult(blue); } #undef premult return (color << 8) + a; }
/* Map a r-g-b color to a color index. */ static gx_color_index win_pr2_map_rgb_color(gx_device * dev, const gx_color_value cv[]) { gx_color_value r = cv[0]; gx_color_value g = cv[1]; gx_color_value b = cv[2]; switch (dev->color_info.depth) { case 1: return gdev_prn_map_rgb_color(dev, cv); case 4: /* use only 8 colors */ return (r > (gx_max_color_value / 2 + 1) ? 4 : 0) + (g > (gx_max_color_value / 2 + 1) ? 2 : 0) + (b > (gx_max_color_value / 2 + 1) ? 1 : 0); case 8: return pc_8bit_map_rgb_color(dev, cv); case 24: return gx_color_value_to_byte(r) + ((uint) gx_color_value_to_byte(g) << 8) + ((ulong) gx_color_value_to_byte(b) << 16); } return 0; /* error */ }
/* Get the color map for a device. Return true if there is one. */ static bool param_HWColorMap(gx_device * dev, byte * palette /* 3 << 8 */ ) { int depth = dev->color_info.depth; int colors = dev->color_info.num_components; if (depth <= 8 && colors <= 3) { byte *p = palette; gx_color_value rgb[3]; gx_color_index i; fill_dev_proc(dev, map_color_rgb, gx_default_map_color_rgb); for (i = 0; (i >> depth) == 0; i++) { int j; if ((*dev_proc(dev, map_color_rgb)) (dev, i, rgb) < 0) return false; for (j = 0; j < colors; j++) *p++ = gx_color_value_to_byte(rgb[j]); } return true; }
/* This routine is used for all formats. */ static int png_print_page(gx_device_printer * pdev, FILE * file) { gs_memory_t *mem = pdev->memory; int raster = gdev_prn_raster(pdev); /* PNG structures */ byte *row = gs_alloc_bytes(mem, raster, "png raster buffer"); png_struct *png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); png_info *info_ptr = png_create_info_struct(png_ptr); int height = pdev->height; int depth = pdev->color_info.depth; int y; int code; /* return code */ char software_key[80]; char software_text[256]; png_text text_png; if (row == 0 || png_ptr == 0 || info_ptr == 0) { code = gs_note_error(gs_error_VMerror); goto done; } /* set error handling */ if (setjmp(png_ptr->jmpbuf)) { /* If we get here, we had a problem reading the file */ code = gs_note_error(gs_error_VMerror); goto done; } code = 0; /* for normal path */ /* set up the output control */ png_init_io(png_ptr, file); /* set the file information here */ info_ptr->width = pdev->width; info_ptr->height = pdev->height; /* resolution is in pixels per meter vs. dpi */ info_ptr->x_pixels_per_unit = (png_uint_32) (pdev->HWResolution[0] * (100.0 / 2.54)); info_ptr->y_pixels_per_unit = (png_uint_32) (pdev->HWResolution[1] * (100.0 / 2.54)); info_ptr->phys_unit_type = PNG_RESOLUTION_METER; info_ptr->valid |= PNG_INFO_pHYs; switch (depth) { case 32: info_ptr->bit_depth = 8; info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA; png_set_invert_alpha(png_ptr); { gx_device_pngalpha *ppdev = (gx_device_pngalpha *)pdev; png_color_16 background; background.index = 0; background.red = (ppdev->background >> 16) & 0xff; background.green = (ppdev->background >> 8) & 0xff; background.blue = (ppdev->background) & 0xff; background.gray = 0; png_set_bKGD(png_ptr, info_ptr, &background); } break; case 48: info_ptr->bit_depth = 16; info_ptr->color_type = PNG_COLOR_TYPE_RGB; #if defined(ARCH_IS_BIG_ENDIAN) && (!ARCH_IS_BIG_ENDIAN) png_set_swap(png_ptr); #endif break; case 24: info_ptr->bit_depth = 8; info_ptr->color_type = PNG_COLOR_TYPE_RGB; break; case 8: info_ptr->bit_depth = 8; if (gx_device_has_color(pdev)) info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; else info_ptr->color_type = PNG_COLOR_TYPE_GRAY; break; case 4: info_ptr->bit_depth = 4; info_ptr->color_type = PNG_COLOR_TYPE_PALETTE; break; case 1: info_ptr->bit_depth = 1; info_ptr->color_type = PNG_COLOR_TYPE_GRAY; /* invert monocrome pixels */ png_set_invert_mono(png_ptr); break; } /* set the palette if there is one */ if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { int i; int num_colors = 1 << depth; gx_color_value rgb[3]; info_ptr->palette = (void *)gs_alloc_bytes(mem, 256 * sizeof(png_color), "png palette"); if (info_ptr->palette == 0) { code = gs_note_error(gs_error_VMerror); goto done; } info_ptr->num_palette = num_colors; info_ptr->valid |= PNG_INFO_PLTE; for (i = 0; i < num_colors; i++) { (*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev, (gx_color_index) i, rgb); info_ptr->palette[i].red = gx_color_value_to_byte(rgb[0]); info_ptr->palette[i].green = gx_color_value_to_byte(rgb[1]); info_ptr->palette[i].blue = gx_color_value_to_byte(rgb[2]); } } /* add comment */ strncpy(software_key, "Software", sizeof(software_key)); sprintf(software_text, "%s %d.%02d", gs_product, (int)(gs_revision / 100), (int)(gs_revision % 100)); text_png.compression = -1; /* uncompressed */ text_png.key = software_key; text_png.text = software_text; text_png.text_length = strlen(software_text); info_ptr->text = &text_png; info_ptr->num_text = 1; /* write the file information */ png_write_info(png_ptr, info_ptr); /* don't write the comments twice */ info_ptr->num_text = 0; info_ptr->text = NULL; /* Write the contents of the image. */ for (y = 0; y < height; y++) { gdev_prn_copy_scan_lines(pdev, y, row, raster); png_write_rows(png_ptr, &row, 1); } /* write the rest of the file */ png_write_end(png_ptr, info_ptr); /* if you alloced the palette, free it here */ gs_free_object(mem, info_ptr->palette, "png palette"); done: /* free the structures */ png_destroy_write_struct(&png_ptr, &info_ptr); gs_free_object(mem, row, "png raster buffer"); return code; }
/* one scan line at a time */ static int win_pr2_print_page(gx_device_printer * pdev, FILE * file) { int raster = gdev_prn_raster(pdev); /* BMP scan lines are padded to 32 bits. */ ulong bmp_raster = raster + (-raster & 3); ulong bmp_raster_multi; int scan_lines, yslice, lines, i; int width; int depth = pdev->color_info.depth; byte *row; int y; int code = 0; /* return code */ MSG msg; char dlgtext[32]; HGLOBAL hrow; int ratio = ((gx_device_win_pr2 *)pdev)->ratio; struct bmi_s { BITMAPINFOHEADER h; RGBQUAD pal[256]; } bmi; scan_lines = dev_print_scan_lines(pdev); width = (int)(pdev->width - ((dev_l_margin(pdev) + dev_r_margin(pdev) - dev_x_offset(pdev)) * pdev->x_pixels_per_inch)); yslice = 65535 / bmp_raster; /* max lines in 64k */ bmp_raster_multi = bmp_raster * yslice; hrow = GlobalAlloc(0, bmp_raster_multi); row = GlobalLock(hrow); if (row == 0) /* can't allocate row buffer */ return_error(gs_error_VMerror); /* Write the info header. */ bmi.h.biSize = sizeof(bmi.h); bmi.h.biWidth = pdev->width; /* wdev->mdev.width; */ bmi.h.biHeight = yslice; bmi.h.biPlanes = 1; bmi.h.biBitCount = pdev->color_info.depth; bmi.h.biCompression = 0; bmi.h.biSizeImage = 0; /* default */ bmi.h.biXPelsPerMeter = 0; /* default */ bmi.h.biYPelsPerMeter = 0; /* default */ StartPage(wdev->hdcprn); /* Write the palette. */ if (depth <= 8) { int i; gx_color_value rgb[3]; LPRGBQUAD pq; bmi.h.biClrUsed = 1 << depth; bmi.h.biClrImportant = 1 << depth; for (i = 0; i != 1 << depth; i++) { (*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev, (gx_color_index) i, rgb); pq = &bmi.pal[i]; pq->rgbRed = gx_color_value_to_byte(rgb[0]); pq->rgbGreen = gx_color_value_to_byte(rgb[1]); pq->rgbBlue = gx_color_value_to_byte(rgb[2]); pq->rgbReserved = 0; } } else { bmi.h.biClrUsed = 0; bmi.h.biClrImportant = 0; } if (!wdev->nocancel) { sprintf(dlgtext, "Printing page %d", (int)(pdev->PageCount) + 1); SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PRINTING), dlgtext); ShowWindow(wdev->hDlgModeless, SW_SHOW); } for (y = 0; y < scan_lines;) { /* copy slice to row buffer */ if (y > scan_lines - yslice) lines = scan_lines - y; else lines = yslice; for (i = 0; i < lines; i++) gdev_prn_copy_scan_lines(pdev, y + i, row + (bmp_raster * (lines - 1 - i)), raster); if (ratio > 1) { StretchDIBits(wdev->hdcprn, 0, y*ratio, pdev->width*ratio, lines*ratio, 0, 0, pdev->width, lines, row, (BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS, SRCCOPY); } else { SetDIBitsToDevice(wdev->hdcprn, 0, y, pdev->width, lines, 0, 0, 0, lines, row, (BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS); } y += lines; if (!wdev->nocancel) { /* inform user of progress */ sprintf(dlgtext, "%d%% done", (int)(y * 100L / scan_lines)); SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE), dlgtext); } /* process message loop */ while (PeekMessage(&msg, wdev->hDlgModeless, 0, 0, PM_REMOVE)) { if ((wdev->hDlgModeless == 0) || !IsDialogMessage(wdev->hDlgModeless, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } if ((!wdev->nocancel) && (wdev->hDlgModeless == 0)) { /* user pressed cancel button */ break; } } if ((!wdev->nocancel) && (wdev->hDlgModeless == 0)) code = gs_error_Fatal; /* exit Ghostscript cleanly */ else { /* push out the page */ if (!wdev->nocancel) SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE), "Ejecting page..."); EndPage(wdev->hdcprn); if (!wdev->nocancel) ShowWindow(wdev->hDlgModeless, SW_HIDE); } GlobalUnlock(hrow); GlobalFree(hrow); return code; }
/* one scan line at a time */ static int os2prn_print_page(gx_device_printer * pdev, FILE * file) { int raster = gdev_prn_raster(pdev); /* BMP scan lines are padded to 32 bits. */ ulong bmp_raster = (raster + 3) & (~3); ulong bmp_raster_multi; int height = pdev->height; int depth = pdev->color_info.depth; byte *row; int y; int code = 0; /* return code */ POINTL apts[4]; APIRET rc; POINTL aptsb[4]; HBITMAP hbmp, hbmr; int i, lines; int ystart, yend; int yslice; struct bmi_s { BITMAPINFOHEADER2 h; RGB2 pal[256]; } bmi; yslice = 65535 / bmp_raster; bmp_raster_multi = bmp_raster * yslice; row = (byte *) gs_malloc(pdev->memory, bmp_raster_multi, 1, "bmp file buffer"); if (row == 0) /* can't allocate row buffer */ return_error(gs_error_VMerror); if (opdev->newframe) DevEscape(opdev->hdc, DEVESC_NEWFRAME, 0L, NULL, NULL, NULL); opdev->newframe = 1; /* Write the info header. */ memset(&bmi.h, 0, sizeof(bmi.h)); bmi.h.cbFix = sizeof(bmi.h); bmi.h.cx = pdev->width; /* opdev->mdev.width; */ /* bmi.h.cy = height; */ bmi.h.cy = yslice; /* size for memory PS */ bmi.h.cPlanes = 1; bmi.h.cBitCount = pdev->color_info.depth; /* Write the palette. */ if (depth <= 8) { int i; gx_color_value rgb[3]; PRGB2 pq; bmi.h.cclrUsed = 1 << depth; bmi.h.cclrImportant = 1 << depth; for (i = 0; i != 1 << depth; i++) { (*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev, (gx_color_index) i, rgb); pq = &bmi.pal[i]; pq->bRed = gx_color_value_to_byte(rgb[0]); pq->bGreen = gx_color_value_to_byte(rgb[1]); pq->bBlue = gx_color_value_to_byte(rgb[2]); pq->fcOptions = 0; } } else { bmi.h.cclrUsed = 0; bmi.h.cclrImportant = 0; } /* for GpiDrawBits */ /* target is inclusive */ apts[0].x = 0; apts[0].y = 0; /* filled in later */ apts[1].x = pdev->width - 1; apts[1].y = 0; /* filled in later */ /* source is not inclusive of top & right borders */ apts[2].x = 0; apts[2].y = 0; apts[3].x = pdev->width; apts[3].y = 0; /* filled in later */ /* for GpiBitBlt */ /* target is not inclusive */ aptsb[0].x = opdev->clipbox[0]; aptsb[0].y = 0; /* filled in later */ aptsb[1].x = opdev->clipbox[2]; aptsb[1].y = 0; /* filled in later */ /* source is not inclusive */ aptsb[2].x = opdev->clipbox[0]; aptsb[2].y = 0; aptsb[3].x = opdev->clipbox[2]; aptsb[3].y = 0; /* filled in later */ /* write the bits */ ystart = opdev->clipbox[3]; yend = opdev->clipbox[1]; y = ystart; while (y > yend) { /* create a bitmap for the memory DC */ hbmp = GpiCreateBitmap(opdev->hpsMem, &bmi.h, 0L, NULL, NULL); if (hbmp == GPI_ERROR) goto bmp_done; hbmr = GpiSetBitmap(opdev->hpsMem, hbmp); /* copy slice to memory bitmap */ if (y > yend + yslice) lines = yslice; else lines = y - yend; y -= lines; for (i = lines - 1; i >= 0; i--) gdev_prn_copy_scan_lines(pdev, ystart - 1 - (y + i), row + (bmp_raster * i), raster); apts[0].y = 0; /* target */ apts[1].y = lines; apts[3].y = lines - 1; /* source */ /* copy DIB bitmap to memory bitmap */ rc = GpiDrawBits(opdev->hpsMem, row, (BITMAPINFO2 *) & bmi, 4, apts, (depth != 1) ? ROP_SRCCOPY : ROP_NOTSRCCOPY, 0); /* copy slice to printer */ aptsb[0].y = y; aptsb[1].y = y + lines; aptsb[3].y = lines; rc = GpiBitBlt(opdev->hps, opdev->hpsMem, 4, aptsb, ROP_SRCCOPY, BBO_IGNORE); /* delete bitmap */ if (hbmr != HBM_ERROR) GpiSetBitmap(opdev->hpsMem, (ULONG) 0); hbmr = HBM_ERROR; if (hbmp != GPI_ERROR) GpiDeleteBitmap(hbmp); hbmp = GPI_ERROR; } bmp_done: if (row) gs_free(pdev->memory, (char *)row, bmp_raster_multi, 1, "bmp file buffer"); return code; }